Bunch of rewrites to scope resolver
This commit is contained in:
parent
d8f6c41f04
commit
ba09919aa1
@ -8,7 +8,7 @@ mod visitor;
|
|||||||
mod operators;
|
mod operators;
|
||||||
|
|
||||||
pub use operators::{PrefixOp, BinOp};
|
pub use operators::{PrefixOp, BinOp};
|
||||||
pub use visitor::{walk_ast, walk_block, ASTVisitor};
|
pub use visitor::{walk_ast, walk_block, ASTVisitor, Recursion};
|
||||||
|
|
||||||
use crate::derivative::Derivative;
|
use crate::derivative::Derivative;
|
||||||
use crate::tokenizing::Location;
|
use crate::tokenizing::Location;
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Recursion {
|
||||||
|
Continue,
|
||||||
|
Stop
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ASTVisitor: Sized {
|
pub trait ASTVisitor: Sized {
|
||||||
fn expression(&mut self, _expression: &Expression) {}
|
fn expression(&mut self, _expression: &Expression) -> Recursion { Recursion::Continue }
|
||||||
fn expression_post(&mut self, _expression: &Expression) {}
|
fn declaration(&mut self, _declaration: &Declaration) -> Recursion { Recursion::Continue }
|
||||||
|
|
||||||
fn declaration(&mut self, _declaration: &Declaration) {}
|
fn import(&mut self, _import: &ImportSpecifier) -> Recursion { Recursion::Continue }
|
||||||
fn declaration_post(&mut self, _declaration: &Declaration) {}
|
fn module(&mut self, _module: &ModuleSpecifier) -> Recursion { Recursion::Continue }
|
||||||
|
|
||||||
fn import(&mut self, _import: &ImportSpecifier) {}
|
fn pattern(&mut self, _pat: &Pattern) -> Recursion { Recursion::Continue }
|
||||||
fn module(&mut self, _module: &ModuleSpecifier) {}
|
|
||||||
fn module_post(&mut self, _module: &ModuleSpecifier) {}
|
|
||||||
|
|
||||||
fn pattern(&mut self, _pat: &Pattern) {}
|
|
||||||
fn pattern_post(&mut self, _pat: &Pattern) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
|
pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
|
||||||
@ -29,11 +30,13 @@ pub fn walk_block<V: ASTVisitor>(v: &mut V, block: &Block) {
|
|||||||
Declaration(ref decl) => {
|
Declaration(ref decl) => {
|
||||||
walk_declaration(v, decl);
|
walk_declaration(v, decl);
|
||||||
}
|
}
|
||||||
Import(ref import_spec) => v.import(import_spec),
|
Import(ref import_spec) => {
|
||||||
|
v.import(import_spec);
|
||||||
|
},
|
||||||
Module(ref module_spec) => {
|
Module(ref module_spec) => {
|
||||||
v.module(module_spec);
|
if let Recursion::Continue = v.module(module_spec) {
|
||||||
walk_block(v, &module_spec.contents);
|
walk_block(v, &module_spec.contents);
|
||||||
v.module_post(module_spec);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,103 +45,101 @@ 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) {
|
||||||
use Declaration::*;
|
use Declaration::*;
|
||||||
|
|
||||||
v.declaration(decl);
|
if let Recursion::Continue = v.declaration(decl) {
|
||||||
|
match decl {
|
||||||
match decl {
|
FuncDecl(_sig, block) => {
|
||||||
FuncDecl(_sig, block) => {
|
walk_block(v, block);
|
||||||
walk_block(v, block);
|
}
|
||||||
}
|
Binding {
|
||||||
Binding {
|
name: _,
|
||||||
name: _,
|
constant: _,
|
||||||
constant: _,
|
type_anno: _,
|
||||||
type_anno: _,
|
expr,
|
||||||
expr,
|
} => {
|
||||||
} => {
|
walk_expression(v, expr);
|
||||||
walk_expression(v, expr);
|
}
|
||||||
}
|
_ => (),
|
||||||
_ => (),
|
};
|
||||||
};
|
}
|
||||||
v.declaration_post(decl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_expression<V: ASTVisitor>(v: &mut V, expr: &Expression) {
|
fn walk_expression<V: ASTVisitor>(v: &mut V, expr: &Expression) {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
v.expression(expr);
|
if let Recursion::Continue = v.expression(expr) {
|
||||||
|
match &expr.kind {
|
||||||
match &expr.kind {
|
NatLiteral(_) | FloatLiteral(_) | StringLiteral(_) | BoolLiteral(_) | Value(_) => (),
|
||||||
NatLiteral(_) | FloatLiteral(_) | StringLiteral(_) | BoolLiteral(_) | Value(_) => (),
|
BinExp(_, lhs, rhs) => {
|
||||||
BinExp(_, lhs, rhs) => {
|
walk_expression(v, &lhs);
|
||||||
walk_expression(v, &lhs);
|
walk_expression(v, &rhs);
|
||||||
walk_expression(v, &rhs);
|
|
||||||
}
|
|
||||||
PrefixExp(_, arg) => {
|
|
||||||
walk_expression(v, &arg);
|
|
||||||
}
|
|
||||||
TupleLiteral(exprs) => {
|
|
||||||
for expr in exprs {
|
|
||||||
walk_expression(v, &expr);
|
|
||||||
}
|
}
|
||||||
}
|
PrefixExp(_, arg) => {
|
||||||
NamedStruct { name: _, fields } => {
|
walk_expression(v, &arg);
|
||||||
for (_, expr) in fields.iter() {
|
|
||||||
walk_expression(v, expr);
|
|
||||||
}
|
}
|
||||||
}
|
TupleLiteral(exprs) => {
|
||||||
Call { f, arguments } => {
|
for expr in exprs {
|
||||||
walk_expression(v, &f);
|
walk_expression(v, &expr);
|
||||||
for arg in arguments.iter() {
|
|
||||||
match arg {
|
|
||||||
InvocationArgument::Positional(expr) => walk_expression(v, expr),
|
|
||||||
InvocationArgument::Keyword { expr, .. } => walk_expression(v, expr), //TODO maybe I can combine this pattern
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
NamedStruct { name: _, fields } => {
|
||||||
Index { indexee, indexers } => {
|
for (_, expr) in fields.iter() {
|
||||||
walk_expression(v, &indexee);
|
walk_expression(v, expr);
|
||||||
for indexer in indexers.iter() {
|
}
|
||||||
walk_expression(v, indexer);
|
|
||||||
}
|
}
|
||||||
}
|
Call { f, arguments } => {
|
||||||
IfExpression {
|
walk_expression(v, &f);
|
||||||
discriminator,
|
for arg in arguments.iter() {
|
||||||
body,
|
match arg {
|
||||||
} => {
|
InvocationArgument::Positional(expr) => walk_expression(v, expr),
|
||||||
if let Some(d) = discriminator.as_ref() {
|
InvocationArgument::Keyword { expr, .. } => walk_expression(v, expr), //TODO maybe I can combine this pattern
|
||||||
walk_expression(v, &d);
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
walk_if_expr_body(v, &body.as_ref());
|
Index { indexee, indexers } => {
|
||||||
}
|
walk_expression(v, &indexee);
|
||||||
WhileExpression { condition, body } => {
|
for indexer in indexers.iter() {
|
||||||
if let Some(d) = condition.as_ref() {
|
walk_expression(v, indexer);
|
||||||
walk_expression(v, d);
|
}
|
||||||
}
|
}
|
||||||
walk_block(v, &body);
|
IfExpression {
|
||||||
}
|
discriminator,
|
||||||
ForExpression { enumerators, body } => {
|
body,
|
||||||
for enumerator in enumerators {
|
} => {
|
||||||
walk_expression(v, &enumerator.generator);
|
if let Some(d) = discriminator.as_ref() {
|
||||||
|
walk_expression(v, &d);
|
||||||
|
}
|
||||||
|
walk_if_expr_body(v, &body.as_ref());
|
||||||
}
|
}
|
||||||
match body.as_ref() {
|
WhileExpression { condition, body } => {
|
||||||
ForBody::MonadicReturn(expr) => walk_expression(v, expr),
|
if let Some(d) = condition.as_ref() {
|
||||||
ForBody::StatementBlock(block) => walk_block(v, block),
|
walk_expression(v, d);
|
||||||
};
|
}
|
||||||
}
|
walk_block(v, &body);
|
||||||
Lambda {
|
|
||||||
params: _,
|
|
||||||
type_anno: _,
|
|
||||||
body,
|
|
||||||
} => {
|
|
||||||
walk_block(v, &body);
|
|
||||||
}
|
|
||||||
ListLiteral(exprs) => {
|
|
||||||
for expr in exprs {
|
|
||||||
walk_expression(v, &expr);
|
|
||||||
}
|
}
|
||||||
}
|
ForExpression { enumerators, body } => {
|
||||||
};
|
for enumerator in enumerators {
|
||||||
v.expression_post(expr);
|
walk_expression(v, &enumerator.generator);
|
||||||
|
}
|
||||||
|
match body.as_ref() {
|
||||||
|
ForBody::MonadicReturn(expr) => walk_expression(v, expr),
|
||||||
|
ForBody::StatementBlock(block) => walk_block(v, block),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Lambda {
|
||||||
|
params: _,
|
||||||
|
type_anno: _,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
walk_block(v, &body);
|
||||||
|
}
|
||||||
|
ListLiteral(exprs) => {
|
||||||
|
for expr in exprs {
|
||||||
|
walk_expression(v, &expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_if_expr_body<V: ASTVisitor>(v: &mut V, body: &IfExpressionBody) {
|
fn walk_if_expr_body<V: ASTVisitor>(v: &mut V, body: &IfExpressionBody) {
|
||||||
@ -187,26 +188,24 @@ fn walk_if_expr_body<V: ASTVisitor>(v: &mut V, body: &IfExpressionBody) {
|
|||||||
fn walk_pattern<V: ASTVisitor>(v: &mut V, pat: &Pattern) {
|
fn walk_pattern<V: ASTVisitor>(v: &mut V, pat: &Pattern) {
|
||||||
use Pattern::*;
|
use Pattern::*;
|
||||||
|
|
||||||
v.pattern(pat);
|
if let Recursion::Continue = v.pattern(pat) {
|
||||||
|
match pat {
|
||||||
match pat {
|
TuplePattern(patterns) => {
|
||||||
TuplePattern(patterns) => {
|
for pat in patterns {
|
||||||
for pat in patterns {
|
walk_pattern(v, pat);
|
||||||
walk_pattern(v, pat);
|
}
|
||||||
}
|
}
|
||||||
}
|
TupleStruct(_, patterns) => {
|
||||||
TupleStruct(_, patterns) => {
|
for pat in patterns {
|
||||||
for pat in patterns {
|
walk_pattern(v, pat);
|
||||||
walk_pattern(v, pat);
|
}
|
||||||
}
|
}
|
||||||
}
|
Record(_, name_and_patterns) => {
|
||||||
Record(_, name_and_patterns) => {
|
for (_, pat) in name_and_patterns {
|
||||||
for (_, pat) in name_and_patterns {
|
walk_pattern(v, pat);
|
||||||
walk_pattern(v, pat);
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => (),
|
||||||
_ => (),
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
v.pattern_post(pat);
|
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ impl<'a> Reducer<'a> {
|
|||||||
arity: *arity,
|
arity: *arity,
|
||||||
},
|
},
|
||||||
SymbolSpec::Func(_) => Expr::Sym(local_name.clone()),
|
SymbolSpec::Func(_) => Expr::Sym(local_name.clone()),
|
||||||
SymbolSpec::Binding => Expr::Sym(local_name.clone()), //TODO not sure if this is right, probably needs to eventually be fqsn
|
SymbolSpec::GlobalBinding => Expr::Sym(local_name.clone()), //TODO not sure if this is right, probably needs to eventually be fqsn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +189,7 @@ impl SymbolTable {
|
|||||||
self.id_to_symbol.get(id).map(|s| s.as_ref())
|
self.id_to_symbol.get(id).map(|s| s.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO optimize this
|
||||||
pub fn lookup_symbol_by_def(&self, def: &DefId) -> Option<&Symbol> {
|
pub fn lookup_symbol_by_def(&self, def: &DefId) -> Option<&Symbol> {
|
||||||
self.id_to_symbol.iter().find(|(_, sym)| sym.def_id == *def)
|
self.id_to_symbol.iter().find(|(_, sym)| sym.def_id == *def)
|
||||||
.map(|(_, sym)| sym.as_ref())
|
.map(|(_, sym)| sym.as_ref())
|
||||||
@ -223,7 +224,7 @@ pub enum SymbolSpec {
|
|||||||
members: HashMap<Rc<String>, TypeName>,
|
members: HashMap<Rc<String>, TypeName>,
|
||||||
type_name: TypeName,
|
type_name: TypeName,
|
||||||
},
|
},
|
||||||
Binding,
|
GlobalBinding, //Only for global variables, not for function-local ones or ones within a `let` scope context
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SymbolSpec {
|
impl fmt::Display for SymbolSpec {
|
||||||
@ -283,13 +284,14 @@ impl SymbolTable {
|
|||||||
/// up name tables that will be used by further parts of the compiler
|
/// up name tables that will be used by further parts of the compiler
|
||||||
fn populate_name_tables(&mut self, ast: &ast::AST) -> Vec<SymbolError> {
|
fn populate_name_tables(&mut self, ast: &ast::AST) -> Vec<SymbolError> {
|
||||||
let mut scope_stack = vec![];
|
let mut scope_stack = vec![];
|
||||||
self.add_from_scope(ast.statements.as_ref(), &mut scope_stack)
|
self.add_from_scope(ast.statements.as_ref(), &mut scope_stack, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_from_scope<'a>(
|
fn add_from_scope<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
statements: &[Statement],
|
statements: &[Statement],
|
||||||
scope_stack: &mut Vec<Scope>,
|
scope_stack: &mut Vec<Scope>,
|
||||||
|
function_scope: bool,
|
||||||
) -> Vec<SymbolError> {
|
) -> Vec<SymbolError> {
|
||||||
let mut errors = vec![];
|
let mut errors = vec![];
|
||||||
|
|
||||||
@ -300,7 +302,7 @@ impl SymbolTable {
|
|||||||
location,
|
location,
|
||||||
} = statement; //TODO I'm not sure if I need to do anything with this ID
|
} = statement; //TODO I'm not sure if I need to do anything with this ID
|
||||||
let location = *location;
|
let location = *location;
|
||||||
if let Err(err) = self.add_single_statement(id, kind, location, scope_stack) {
|
if let Err(err) = self.add_single_statement(id, kind, location, scope_stack, function_scope) {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
} else {
|
} else {
|
||||||
// If there's an error with a name, don't recurse into subscopes of that name
|
// If there's an error with a name, don't recurse into subscopes of that name
|
||||||
@ -308,14 +310,14 @@ impl SymbolTable {
|
|||||||
StatementKind::Declaration(Declaration::FuncDecl(signature, body)) => {
|
StatementKind::Declaration(Declaration::FuncDecl(signature, body)) => {
|
||||||
let new_scope = Scope::Name(signature.name.clone());
|
let new_scope = Scope::Name(signature.name.clone());
|
||||||
scope_stack.push(new_scope);
|
scope_stack.push(new_scope);
|
||||||
let output = self.add_from_scope(body.as_ref(), scope_stack);
|
let output = self.add_from_scope(body.as_ref(), scope_stack, true);
|
||||||
scope_stack.pop();
|
scope_stack.pop();
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
StatementKind::Module(ModuleSpecifier { name, contents }) => {
|
StatementKind::Module(ModuleSpecifier { name, contents }) => {
|
||||||
let new_scope = Scope::Name(name.clone());
|
let new_scope = Scope::Name(name.clone());
|
||||||
scope_stack.push(new_scope);
|
scope_stack.push(new_scope);
|
||||||
let output = self.add_from_scope(contents.as_ref(), scope_stack);
|
let output = self.add_from_scope(contents.as_ref(), scope_stack, false);
|
||||||
scope_stack.pop();
|
scope_stack.pop();
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
@ -339,6 +341,7 @@ impl SymbolTable {
|
|||||||
kind: &StatementKind,
|
kind: &StatementKind,
|
||||||
location: Location,
|
location: Location,
|
||||||
scope_stack: &[Scope],
|
scope_stack: &[Scope],
|
||||||
|
function_scope: bool,
|
||||||
) -> Result<(), SymbolError> {
|
) -> Result<(), SymbolError> {
|
||||||
match kind {
|
match kind {
|
||||||
StatementKind::Declaration(Declaration::FuncSig(signature)) => {
|
StatementKind::Declaration(Declaration::FuncSig(signature)) => {
|
||||||
@ -407,12 +410,13 @@ impl SymbolTable {
|
|||||||
kind: NameKind::Binding,
|
kind: NameKind::Binding,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
println!("Adding Binding symbol: {:?}", fq_binding);
|
if !function_scope {
|
||||||
self.add_symbol(
|
self.add_symbol(
|
||||||
id,
|
id,
|
||||||
fq_binding,
|
fq_binding,
|
||||||
SymbolSpec::Binding,
|
SymbolSpec::GlobalBinding,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
StatementKind::Module(ModuleSpecifier { name, .. }) => {
|
StatementKind::Module(ModuleSpecifier { name, .. }) => {
|
||||||
let fq_module = Fqsn::from_scope_stack(scope_stack, name.clone());
|
let fq_module = Fqsn::from_scope_stack(scope_stack, name.clone());
|
||||||
|
@ -1,24 +1,45 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::symbol_table::{Fqsn, Scope, SymbolTable};
|
use crate::symbol_table::{Fqsn, Scope, SymbolTable, DefId};
|
||||||
use crate::util::ScopeStack;
|
use crate::util::ScopeStack;
|
||||||
|
|
||||||
type FqsnPrefix = Vec<Scope>;
|
type FqsnPrefix = Vec<Scope>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum NameType {
|
||||||
|
//TODO eventually this needs to support closures
|
||||||
|
Param(u8), //TODO functions limited to 255 params
|
||||||
|
LocalVariable,
|
||||||
|
ImportedDefinition(DefId),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum ScopeType {
|
||||||
|
Function {
|
||||||
|
name: Rc<String>
|
||||||
|
},
|
||||||
|
//TODO add some notion of a let-like scope?
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ScopeResolver<'a> {
|
pub struct ScopeResolver<'a> {
|
||||||
symbol_table: &'a mut super::SymbolTable,
|
symbol_table: &'a mut super::SymbolTable,
|
||||||
|
/// Used for import resolution. TODO maybe this can also use the lexical scope table.
|
||||||
name_scope_stack: ScopeStack<'a, Rc<String>, FqsnPrefix>,
|
name_scope_stack: ScopeStack<'a, Rc<String>, FqsnPrefix>,
|
||||||
|
lexical_scopes: ScopeStack<'a, Rc<String>, NameType, ScopeType>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ScopeResolver<'a> {
|
impl<'a> ScopeResolver<'a> {
|
||||||
pub fn new(symbol_table: &'a mut SymbolTable) -> Self {
|
pub fn new(symbol_table: &'a mut SymbolTable) -> Self {
|
||||||
let name_scope_stack: ScopeStack<'a, Rc<String>, FqsnPrefix> = ScopeStack::new(None);
|
let name_scope_stack = ScopeStack::new(None);
|
||||||
|
let lexical_scopes = ScopeStack::new(None);
|
||||||
Self {
|
Self {
|
||||||
symbol_table,
|
symbol_table,
|
||||||
name_scope_stack,
|
name_scope_stack,
|
||||||
|
lexical_scopes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve(&mut self, ast: &AST) {
|
pub fn resolve(&mut self, ast: &AST) {
|
||||||
walk_ast(self, ast);
|
walk_ast(self, ast);
|
||||||
}
|
}
|
||||||
@ -46,10 +67,11 @@ impl<'a> ScopeResolver<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn qualified_name(&mut self, name: &QualifiedName) {
|
/// This method correctly modifies the id_to_symbol table (ItemId) to have the appropriate
|
||||||
|
/// mappings.
|
||||||
|
fn handle_qualified_name(&mut self, name: &QualifiedName) {
|
||||||
println!("Handling qualified_name in resolver.rs: {:?}", name);
|
println!("Handling qualified_name in resolver.rs: {:?}", name);
|
||||||
let fqsn = self.lookup_name_in_scope(name);
|
let fqsn = self.lookup_name_in_scope(name);
|
||||||
println!("Computed FQSN: {:?}", fqsn);
|
|
||||||
let symbol = self.symbol_table.fqsn_to_symbol.get(&fqsn);
|
let symbol = self.symbol_table.fqsn_to_symbol.get(&fqsn);
|
||||||
if let Some(symbol) = symbol {
|
if let Some(symbol) = symbol {
|
||||||
self.symbol_table.id_to_symbol.insert(name.id.clone(), symbol.clone());
|
self.symbol_table.id_to_symbol.insert(name.id.clone(), symbol.clone());
|
||||||
@ -58,8 +80,10 @@ impl<'a> ScopeResolver<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ASTVisitor for ScopeResolver<'a> {
|
impl<'a> ASTVisitor for ScopeResolver<'a> {
|
||||||
//TODO need to un-insert these - maybe need to rethink visitor
|
// Import statements bring in a bunch of local names that all map to a specific FQSN.
|
||||||
fn import(&mut self, import_spec: &ImportSpecifier) {
|
// FQSNs map to a Symbol (or this is an error), Symbols have a DefId. So for every
|
||||||
|
// name we import, we map a local name (a string) to a NameType::ImportedDefinition(DefId).
|
||||||
|
fn import(&mut self, import_spec: &ImportSpecifier) -> Recursion {
|
||||||
let ImportSpecifier {
|
let ImportSpecifier {
|
||||||
ref path_components,
|
ref path_components,
|
||||||
ref imported_names,
|
ref imported_names,
|
||||||
@ -99,22 +123,45 @@ impl<'a> ASTVisitor for ScopeResolver<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Recursion::Continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression(&mut self, expression: &Expression) {
|
fn declaration(&mut self, declaration: &Declaration) -> Recursion {
|
||||||
use ExpressionKind::*;
|
if let Declaration::FuncDecl(signature, block) = declaration {
|
||||||
match &expression.kind {
|
let param_names = signature.params.iter().map(|param| param.name.clone());
|
||||||
Value(name) => {
|
let mut new_scope = self.lexical_scopes.new_scope(Some(ScopeType::Function { name: signature.name.clone() }));
|
||||||
self.qualified_name(name);
|
|
||||||
},
|
for (n, param) in param_names.enumerate().into_iter() {
|
||||||
NamedStruct { name, fields: _ } => {
|
new_scope.insert(param, NameType::Param(n as u8));
|
||||||
self.qualified_name(name);
|
}
|
||||||
},
|
|
||||||
_ => (),
|
let mut new_resolver = ScopeResolver {
|
||||||
|
symbol_table: self.symbol_table,
|
||||||
|
name_scope_stack: self.name_scope_stack.new_scope(None),
|
||||||
|
lexical_scopes: new_scope,
|
||||||
|
};
|
||||||
|
walk_block(&mut new_resolver, block);
|
||||||
|
Recursion::Stop
|
||||||
|
} else {
|
||||||
|
Recursion::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pattern(&mut self, pat: &Pattern) {
|
fn expression(&mut self, expression: &Expression) -> Recursion {
|
||||||
|
use ExpressionKind::*;
|
||||||
|
match &expression.kind {
|
||||||
|
Value(name) => {
|
||||||
|
self.handle_qualified_name(name);
|
||||||
|
},
|
||||||
|
NamedStruct { name, fields: _ } => {
|
||||||
|
self.handle_qualified_name(name);
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
Recursion::Continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pattern(&mut self, pat: &Pattern) -> Recursion {
|
||||||
use Pattern::*;
|
use Pattern::*;
|
||||||
|
|
||||||
match pat {
|
match pat {
|
||||||
@ -122,8 +169,9 @@ impl<'a> ASTVisitor for ScopeResolver<'a> {
|
|||||||
TuplePattern(_) => (),
|
TuplePattern(_) => (),
|
||||||
Literal(_) | Ignored => (),
|
Literal(_) | Ignored => (),
|
||||||
TupleStruct(name, _) | Record(name, _) | VarOrName(name) => {
|
TupleStruct(name, _) | Record(name, _) | VarOrName(name) => {
|
||||||
self.qualified_name(name);
|
self.handle_qualified_name(name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Recursion::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user