From df41da84b48977c392133fff56f18e8b24e3edd1 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Mon, 25 Oct 2021 01:02:19 -0700 Subject: [PATCH] Fix scope test bug This involved fixing how the ScopeResolver handles local bindings. I probably want to rewrite much of that code. --- schala-lang/language/src/ast/visitor.rs | 8 ++--- schala-lang/language/src/reduced_ir/mod.rs | 5 +++ schala-lang/language/src/symbol_table/mod.rs | 3 +- .../language/src/symbol_table/resolver.rs | 31 +++++++++++++------ .../language/src/tree_walk_eval/test.rs | 3 +- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/schala-lang/language/src/ast/visitor.rs b/schala-lang/language/src/ast/visitor.rs index b570cc1..c633ec7 100644 --- a/schala-lang/language/src/ast/visitor.rs +++ b/schala-lang/language/src/ast/visitor.rs @@ -8,7 +8,7 @@ pub enum Recursion { pub trait ASTVisitor: Sized { fn expression(&mut self, _expression: &Expression) -> Recursion { Recursion::Continue } - fn declaration(&mut self, _declaration: &Declaration) -> Recursion { Recursion::Continue } + fn declaration(&mut self, _declaration: &Declaration, _id: &ItemId) -> Recursion { Recursion::Continue } fn import(&mut self, _import: &ImportSpecifier) -> Recursion { Recursion::Continue } fn module(&mut self, _module: &ModuleSpecifier) -> Recursion { Recursion::Continue } @@ -28,7 +28,7 @@ pub fn walk_block(v: &mut V, block: &Block) { walk_expression(v, expr); } Declaration(ref decl) => { - walk_declaration(v, decl); + walk_declaration(v, decl, &statement.id); } Import(ref import_spec) => { v.import(import_spec); @@ -42,10 +42,10 @@ pub fn walk_block(v: &mut V, block: &Block) { } } -fn walk_declaration(v: &mut V, decl: &Declaration) { +fn walk_declaration(v: &mut V, decl: &Declaration, id: &ItemId) { use Declaration::*; - if let Recursion::Continue = v.declaration(decl) { + if let Recursion::Continue = v.declaration(decl, id) { match decl { FuncDecl(_sig, block) => { walk_block(v, block); diff --git a/schala-lang/language/src/reduced_ir/mod.rs b/schala-lang/language/src/reduced_ir/mod.rs index 1f845f8..a5454b3 100644 --- a/schala-lang/language/src/reduced_ir/mod.rs +++ b/schala-lang/language/src/reduced_ir/mod.rs @@ -91,6 +91,11 @@ impl<'a> Reducer<'a> { self.insert_function_definition(item_id, statements); None }, + ast::Declaration::Binding { constant, expr, ..} => { + let symbol = self.symbol_table.lookup_symbol(item_id).unwrap(); + Some(Statement::Binding { id: symbol.def_id.clone(), constant: *constant, expr: self.expression(&expr) }) + }, + _ => None }, _ => None diff --git a/schala-lang/language/src/symbol_table/mod.rs b/schala-lang/language/src/symbol_table/mod.rs index d77639f..7da29cb 100644 --- a/schala-lang/language/src/symbol_table/mod.rs +++ b/schala-lang/language/src/symbol_table/mod.rs @@ -283,11 +283,12 @@ impl SymbolTable { /// Register a new mapping of a fully-qualified symbol name (e.g. `Option::Some`) /// to a Symbol, a descriptor of what that name refers to. fn add_symbol(&mut self, id: &ItemId, fqsn: Fqsn, spec: SymbolSpec) { + let def_id = self.def_id_store.fresh(); let symbol = Rc::new(Symbol { local_name: fqsn.local_name(), fully_qualified_name: fqsn.clone(), spec, - def_id: self.def_id_store.fresh(), + def_id, }); self.symbol_trie.insert(&fqsn); self.fqsn_to_symbol.insert(fqsn, symbol.clone()); diff --git a/schala-lang/language/src/symbol_table/resolver.rs b/schala-lang/language/src/symbol_table/resolver.rs index d733f92..35673a5 100644 --- a/schala-lang/language/src/symbol_table/resolver.rs +++ b/schala-lang/language/src/symbol_table/resolver.rs @@ -8,14 +8,13 @@ use crate::util::ScopeStack; enum NameType { //TODO eventually this needs to support closures Param(u8), //TODO handle implications of functions being limited to 255 params - LocalVariable, + LocalVariable(ItemId), Import(Fqsn), } #[derive(Debug)] enum ScopeType { Function { - #[allow(dead_code)] name: Rc }, Lambda, @@ -71,6 +70,8 @@ impl<'a> ScopeResolver<'a> { fn lookup_name_in_scope(&mut self, name: &QualifiedName) { let QualifiedName { id, components } = name; //TODO handle a "partial" qualified name + //TODO some of these if lets that look into the fqsn_to_symbol table should probaby fail + //with an error if components.len() == 1 { let local_name: Rc = components[0].clone(); let name_type = self.lexical_scopes.lookup(&local_name); @@ -86,10 +87,11 @@ impl<'a> ScopeResolver<'a> { let fqsn = Fqsn { scopes: vec![Scope::Name(local_name.clone())] }; self.symbol_table.add_symbol(id, fqsn, spec); } - Some(NameType::LocalVariable) => { - let spec = SymbolSpec::LocalVariable; - let fqsn = Fqsn { scopes: vec![Scope::Name(local_name.clone())] }; - self.symbol_table.add_symbol(id, fqsn, spec); + Some(NameType::LocalVariable(item_id)) => { + let symbol = self.symbol_table.id_to_symbol.get(&item_id).cloned(); + if let Some(symbol) = symbol { + self.symbol_table.id_to_symbol.insert(id.clone(), symbol); + } }, None => { //TODO see if I can reduce this duplicate code @@ -158,8 +160,12 @@ impl<'a> ASTVisitor for ScopeResolver<'a> { Recursion::Continue } - fn declaration(&mut self, declaration: &Declaration) -> Recursion { - let is_function_scope = matches!(self.lexical_scopes.get_name(), Some(ScopeType::Function { .. })); + fn declaration(&mut self, declaration: &Declaration, id: &ItemId) -> Recursion { + let cur_function_name = match self.lexical_scopes.get_name() { + //TODO this needs to be a fqsn + Some(ScopeType::Function { name }) => Some(name.clone()), + _ => None + }; match declaration { Declaration::FuncDecl(signature, block) => { let param_names = signature.params.iter().map(|param| param.name.clone()); @@ -178,8 +184,13 @@ impl<'a> ASTVisitor for ScopeResolver<'a> { walk_block(&mut new_resolver, block); Recursion::Stop } - Declaration::Binding { name, .. } if is_function_scope => { - self.lexical_scopes.insert(name.clone(), NameType::LocalVariable); + Declaration::Binding { name, .. } => { + if let Some(fn_name) = cur_function_name { + // We are within a function scope + let fqsn = Fqsn { scopes: vec![Scope::Name(fn_name.clone()), Scope::Name(name.clone())] }; + self.symbol_table.add_symbol(id, fqsn, SymbolSpec::LocalVariable); + self.lexical_scopes.insert(name.clone(), NameType::LocalVariable(id.clone())); + } Recursion::Continue } _ => Recursion::Continue diff --git a/schala-lang/language/src/tree_walk_eval/test.rs b/schala-lang/language/src/tree_walk_eval/test.rs index 05ee593..a92962d 100644 --- a/schala-lang/language/src/tree_walk_eval/test.rs +++ b/schala-lang/language/src/tree_walk_eval/test.rs @@ -39,10 +39,10 @@ fn function_eval() { #[test] fn scopes() { - /* let scope_ok = r#" let a = 20 fn haha() { + let something = 38 let a = 10 a } @@ -60,6 +60,5 @@ fn scopes() { a "#; eval_assert(scope_ok, "20"); - */ }