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:
parent
9ec1e00afa
commit
df41da84b4
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
*/
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user