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 {
|
pub trait ASTVisitor: Sized {
|
||||||
fn expression(&mut self, _expression: &Expression) -> Recursion { Recursion::Continue }
|
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 import(&mut self, _import: &ImportSpecifier) -> Recursion { Recursion::Continue }
|
||||||
fn module(&mut self, _module: &ModuleSpecifier) -> 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);
|
walk_expression(v, expr);
|
||||||
}
|
}
|
||||||
Declaration(ref decl) => {
|
Declaration(ref decl) => {
|
||||||
walk_declaration(v, decl);
|
walk_declaration(v, decl, &statement.id);
|
||||||
}
|
}
|
||||||
Import(ref import_spec) => {
|
Import(ref import_spec) => {
|
||||||
v.import(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::*;
|
use Declaration::*;
|
||||||
|
|
||||||
if let Recursion::Continue = v.declaration(decl) {
|
if let Recursion::Continue = v.declaration(decl, id) {
|
||||||
match decl {
|
match decl {
|
||||||
FuncDecl(_sig, block) => {
|
FuncDecl(_sig, block) => {
|
||||||
walk_block(v, block);
|
walk_block(v, block);
|
||||||
|
@ -91,6 +91,11 @@ impl<'a> Reducer<'a> {
|
|||||||
self.insert_function_definition(item_id, statements);
|
self.insert_function_definition(item_id, statements);
|
||||||
None
|
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
|
||||||
},
|
},
|
||||||
_ => None
|
_ => None
|
||||||
|
@ -283,11 +283,12 @@ impl SymbolTable {
|
|||||||
/// Register a new mapping of a fully-qualified symbol name (e.g. `Option::Some`)
|
/// 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.
|
/// to a Symbol, a descriptor of what that name refers to.
|
||||||
fn add_symbol(&mut self, id: &ItemId, fqsn: Fqsn, spec: SymbolSpec) {
|
fn add_symbol(&mut self, id: &ItemId, fqsn: Fqsn, spec: SymbolSpec) {
|
||||||
|
let def_id = self.def_id_store.fresh();
|
||||||
let symbol = Rc::new(Symbol {
|
let symbol = Rc::new(Symbol {
|
||||||
local_name: fqsn.local_name(),
|
local_name: fqsn.local_name(),
|
||||||
fully_qualified_name: fqsn.clone(),
|
fully_qualified_name: fqsn.clone(),
|
||||||
spec,
|
spec,
|
||||||
def_id: self.def_id_store.fresh(),
|
def_id,
|
||||||
});
|
});
|
||||||
self.symbol_trie.insert(&fqsn);
|
self.symbol_trie.insert(&fqsn);
|
||||||
self.fqsn_to_symbol.insert(fqsn, symbol.clone());
|
self.fqsn_to_symbol.insert(fqsn, symbol.clone());
|
||||||
|
@ -8,14 +8,13 @@ use crate::util::ScopeStack;
|
|||||||
enum NameType {
|
enum NameType {
|
||||||
//TODO eventually this needs to support closures
|
//TODO eventually this needs to support closures
|
||||||
Param(u8), //TODO handle implications of functions being limited to 255 params
|
Param(u8), //TODO handle implications of functions being limited to 255 params
|
||||||
LocalVariable,
|
LocalVariable(ItemId),
|
||||||
Import(Fqsn),
|
Import(Fqsn),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum ScopeType {
|
enum ScopeType {
|
||||||
Function {
|
Function {
|
||||||
#[allow(dead_code)]
|
|
||||||
name: Rc<String>
|
name: Rc<String>
|
||||||
},
|
},
|
||||||
Lambda,
|
Lambda,
|
||||||
@ -71,6 +70,8 @@ impl<'a> ScopeResolver<'a> {
|
|||||||
fn lookup_name_in_scope(&mut self, name: &QualifiedName) {
|
fn lookup_name_in_scope(&mut self, name: &QualifiedName) {
|
||||||
let QualifiedName { id, components } = name;
|
let QualifiedName { id, components } = name;
|
||||||
//TODO handle a "partial" qualified 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 {
|
if components.len() == 1 {
|
||||||
let local_name: Rc<String> = components[0].clone();
|
let local_name: Rc<String> = components[0].clone();
|
||||||
let name_type = self.lexical_scopes.lookup(&local_name);
|
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())] };
|
let fqsn = Fqsn { scopes: vec![Scope::Name(local_name.clone())] };
|
||||||
self.symbol_table.add_symbol(id, fqsn, spec);
|
self.symbol_table.add_symbol(id, fqsn, spec);
|
||||||
}
|
}
|
||||||
Some(NameType::LocalVariable) => {
|
Some(NameType::LocalVariable(item_id)) => {
|
||||||
let spec = SymbolSpec::LocalVariable;
|
let symbol = self.symbol_table.id_to_symbol.get(&item_id).cloned();
|
||||||
let fqsn = Fqsn { scopes: vec![Scope::Name(local_name.clone())] };
|
if let Some(symbol) = symbol {
|
||||||
self.symbol_table.add_symbol(id, fqsn, spec);
|
self.symbol_table.id_to_symbol.insert(id.clone(), symbol);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
//TODO see if I can reduce this duplicate code
|
//TODO see if I can reduce this duplicate code
|
||||||
@ -158,8 +160,12 @@ impl<'a> ASTVisitor for ScopeResolver<'a> {
|
|||||||
Recursion::Continue
|
Recursion::Continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declaration(&mut self, declaration: &Declaration) -> Recursion {
|
fn declaration(&mut self, declaration: &Declaration, id: &ItemId) -> Recursion {
|
||||||
let is_function_scope = matches!(self.lexical_scopes.get_name(), Some(ScopeType::Function { .. }));
|
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 {
|
match declaration {
|
||||||
Declaration::FuncDecl(signature, block) => {
|
Declaration::FuncDecl(signature, block) => {
|
||||||
let param_names = signature.params.iter().map(|param| param.name.clone());
|
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);
|
walk_block(&mut new_resolver, block);
|
||||||
Recursion::Stop
|
Recursion::Stop
|
||||||
}
|
}
|
||||||
Declaration::Binding { name, .. } if is_function_scope => {
|
Declaration::Binding { name, .. } => {
|
||||||
self.lexical_scopes.insert(name.clone(), NameType::LocalVariable);
|
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
|
||||||
}
|
}
|
||||||
_ => Recursion::Continue
|
_ => Recursion::Continue
|
||||||
|
@ -39,10 +39,10 @@ fn function_eval() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn scopes() {
|
fn scopes() {
|
||||||
/*
|
|
||||||
let scope_ok = r#"
|
let scope_ok = r#"
|
||||||
let a = 20
|
let a = 20
|
||||||
fn haha() {
|
fn haha() {
|
||||||
|
let something = 38
|
||||||
let a = 10
|
let a = 10
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
@ -60,6 +60,5 @@ fn scopes() {
|
|||||||
a
|
a
|
||||||
"#;
|
"#;
|
||||||
eval_assert(scope_ok, "20");
|
eval_assert(scope_ok, "20");
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user