Fix scope test bug

This involved fixing how the ScopeResolver handles local bindings. I
probably want to rewrite much of that code.
This commit is contained in:
Greg Shuflin 2021-10-25 01:02:19 -07:00
parent 9ec1e00afa
commit df41da84b4
5 changed files with 33 additions and 17 deletions

View File

@ -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: ASTVisitor>(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: ASTVisitor>(v: &mut V, block: &Block) {
}
}
fn walk_declaration<V: ASTVisitor>(v: &mut V, decl: &Declaration) {
fn walk_declaration<V: ASTVisitor>(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);

View File

@ -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

View File

@ -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());

View File

@ -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<String>
},
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<String> = 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

View File

@ -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");
*/
}