graphic design tool
git clone https://git.lucas.co/cce-designer.git
refactor: TreeScope is public, with a constructor, for the wrangle's ch()
A script on a node reads channels through the scope its parameters use,
so an expression-valued parameter is evaluated before the script sees it.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
src/geometry.rs | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/geometry.rs b/src/geometry.rs
index b672fc9..12bba38 100644
--- a/src/geometry.rs
+++ b/src/geometry.rs
@@ -720,13 +720,25 @@ fn find_ref_param<'a>(node: &'a FsNode, name: &str) -> Option<(&'a ParamDef, Opt
/// What an expression on `node` sees: the tree for its channels, the frame
/// for `$F`, and the chain of parameters being evaluated, so a reference
/// that comes back round to itself is an error rather than a stack overflow.
-struct TreeScope<'a> {
+///
+/// Public so a SCRIPT on a node (the wrangle) can read channels through
+/// the same scope its parameters do: a `ch("../a/Radius")` in a script
+/// then sees an expression-valued Radius evaluated, not its text.
+pub struct TreeScope<'a> {
root: &'a FsNode,
node: &'a FsNode,
frame: i32,
stack: Vec<(String, String)>,
}
+impl<'a> TreeScope<'a> {
+ /// A scope for something on `node` — an expression on one of its
+ /// parameters, or a script it runs — evaluated at `frame`.
+ pub fn new(root: &'a FsNode, node: &'a FsNode, frame: i32) -> Self {
+ TreeScope { root, node, frame, stack: Vec::new() }
+ }
+}
+
impl<'a> crate::expr::Scope for TreeScope<'a> {
fn channel(&mut self, path: &str, kind: ChKind) -> Result<Value, String> {
let (absolute, segs, pname) = split_ref_path(path);