From 63ef1451d9082b11e871ba56dd186389f02b31a5 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Tue, 2 Nov 2021 18:07:08 -0700 Subject: [PATCH] Fix bug with nested function scopes --- .../language/src/symbol_table/resolver.rs | 10 +++++ .../language/src/tree_walk_eval/test.rs | 38 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/schala-lang/language/src/symbol_table/resolver.rs b/schala-lang/language/src/symbol_table/resolver.rs index 89aece4..ec2d851 100644 --- a/schala-lang/language/src/symbol_table/resolver.rs +++ b/schala-lang/language/src/symbol_table/resolver.rs @@ -11,6 +11,7 @@ enum NameType { //TODO eventually this needs to support closures Param(u8), //TODO handle implications of functions being limited to 255 params LocalVariable(ItemId), + LocalFunction(ItemId), Import(Fqsn), } @@ -67,6 +68,13 @@ impl<'a> ScopeResolver<'a> { let fqsn = Fqsn { scopes: vec![lscope, ScopeSegment::Name(local_name.clone())] }; self.symbol_table.add_symbol(id, fqsn, spec); } + Some(NameType::LocalFunction(item_id)) => { + let def_id = self.symbol_table.id_to_def.get(item_id); + if let Some(def_id) = def_id { + let def_id = def_id.clone(); + self.symbol_table.id_to_def.insert(*id, def_id); + } + } Some(NameType::LocalVariable(item_id)) => { let def_id = self.symbol_table.id_to_def.get(item_id); if let Some(def_id) = def_id { @@ -139,6 +147,8 @@ impl<'a> ASTVisitor for ScopeResolver<'a> { new_scope.insert(param, NameType::Param(n as u8)); } + self.lexical_scopes.insert(signature.name.clone(), NameType::LocalFunction(*id)); + let mut new_resolver = ScopeResolver { symbol_table: self.symbol_table, lexical_scopes: new_scope }; walk_block(&mut new_resolver, block); diff --git a/schala-lang/language/src/tree_walk_eval/test.rs b/schala-lang/language/src/tree_walk_eval/test.rs index ab2f3ed..2184776 100644 --- a/schala-lang/language/src/tree_walk_eval/test.rs +++ b/schala-lang/language/src/tree_walk_eval/test.rs @@ -78,6 +78,44 @@ fn scopes() { eval_assert(scope_ok, "20"); } +#[test] +fn eval_scopes_2() { + eval_assert( + r#" +fn trad() { + let a = 10 + fn jinner() { + let b = 20 + b + } + + a + jinner() +} +trad()"#, + "30", + ); + + let err = + "No symbol found for name: QualifiedName { id: Id { idx: 4, t: PhantomData }, components: [\"a\"] }"; + + eval_assert_failure( + r#" +fn trad() { + let a = 10 + fn inner() { + let b = 20 + a + b + } + + inner() +} + +trad() +"#, + err, + ); +} + #[test] fn adt_output_1() { let source = r#"