From f00b9e22e75bb0a4812a6adade8df5a5537df0f2 Mon Sep 17 00:00:00 2001 From: John Doty Date: Sat, 3 Feb 2024 09:54:46 -0800 Subject: [PATCH] [fine] Bindings in if remain in scope! --- fine/src/semantics.rs | 28 ++++++++++++++++++++++++++++ fine/tests/expression/is.fine | 9 ++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/fine/src/semantics.rs b/fine/src/semantics.rs index 2722463d..0c3e726f 100644 --- a/fine/src/semantics.rs +++ b/fine/src/semantics.rs @@ -433,6 +433,34 @@ fn set_logical_parents( set_logical_parents(parents, syntax_tree, rhs, Some(t)); } } + TreeKind::ConditionalExpression => { + // Special case! If the condition expression is a `is` expression + // then it is the parent for the body of the `then` clause so + // that any variable bindings it makes remain in scope. The + // `else` clause and the condition itself do not have the + // bindings in scope, obviously. + let body_parent = if let Some(is_condition) = + tree.child_of_kind(syntax_tree, TreeKind::IsExpression) + { + Some(is_condition) + } else { + Some(t) + }; + + let then_body = tree.nth_tree(2); + for child in &tree.children { + match child { + Child::Token(_) => (), + Child::Tree(ct) => { + if Some(*ct) == then_body { + set_logical_parents(parents, syntax_tree, *ct, body_parent); + } else { + set_logical_parents(parents, syntax_tree, *ct, Some(t)); + } + } + } + } + } _ => { // By default, the parent for each child is current tree. for child in &tree.children { diff --git a/fine/tests/expression/is.fine b/fine/tests/expression/is.fine index 7003ab47..ade0ecd6 100644 --- a/fine/tests/expression/is.fine +++ b/fine/tests/expression/is.fine @@ -3,17 +3,20 @@ class Foo { } fun test() -> f64 { - let b = new Foo { a : 23 }; + let b = new Foo { a : 1000 }; let result = 0; - if b is c:Foo and c.a == 23 { + if b is c:Foo and c.a == 1000 { result = result + 1; } if b is c:Foo and c.a == 24 { result = result + 10; } + if b is c:Foo { + result = result + c.a; // c should still be in scope! + } result } // @no-errors -// @eval: Float(1.0) \ No newline at end of file +// @eval: Float(1001.0) \ No newline at end of file