Handle local variables and function params in symbol table

This commit is contained in:
Greg Shuflin 2021-10-24 02:02:04 -07:00
parent 9540dc70f2
commit 82de5c6e27
3 changed files with 28 additions and 5 deletions

View File

@ -126,6 +126,7 @@ impl<'a> Reducer<'a> {
}, },
SymbolSpec::Func(_) => Expr::Sym(local_name.clone()), SymbolSpec::Func(_) => Expr::Sym(local_name.clone()),
SymbolSpec::GlobalBinding => 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
_ => Expr::UnimplementedSigilValue,
} }
} }

View File

@ -16,6 +16,7 @@ use symbol_trie::SymbolTrie;
mod test; mod test;
//TODO parameterize different types of ID
/// ID used for definitions /// ID used for definitions
#[derive(Debug, PartialEq, Eq, Hash, Clone, Default)] #[derive(Debug, PartialEq, Eq, Hash, Clone, Default)]
pub struct DefId { pub struct DefId {
@ -199,7 +200,7 @@ impl SymbolTable {
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Symbol { pub struct Symbol {
pub local_name: Rc<String>, pub local_name: Rc<String>, //TODO get rid of this, it can be computed from fqsn
fully_qualified_name: Fqsn, fully_qualified_name: Fqsn,
pub spec: SymbolSpec, pub spec: SymbolSpec,
pub def_id: DefId, pub def_id: DefId,
@ -211,6 +212,15 @@ impl fmt::Display for Symbol {
} }
} }
//TODO - I think I eventually want to draw a distinction between true global items
//i.e. global vars, and items whose definitions are scoped. Right now there's a sense
//in which Func, DataConstructor, RecordConstructor, and GlobalBinding are "globals",
//whereas LocalVarible and FunctionParam have local scope. But right now, they all
//get put into a common table, and all get DefId's from a common source.
//
//It would be good if individual functions could in parallel look up their own
//local vars without interfering with other lookups. Also some type definitions
//should be scoped in a similar way.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum SymbolSpec { pub enum SymbolSpec {
Func(Vec<TypeName>), Func(Vec<TypeName>),
@ -225,6 +235,8 @@ pub enum SymbolSpec {
type_name: TypeName, type_name: TypeName,
}, },
GlobalBinding, //Only for global variables, not for function-local ones or ones within a `let` scope context GlobalBinding, //Only for global variables, not for function-local ones or ones within a `let` scope context
LocalVariable,
FunctionParam(u8),
} }
impl fmt::Display for SymbolSpec { impl fmt::Display for SymbolSpec {
@ -249,6 +261,8 @@ impl fmt::Display for SymbolSpec {
index, type_name index, type_name
), ),
GlobalBinding => write!(f, "GlobalBinding"), GlobalBinding => write!(f, "GlobalBinding"),
LocalVariable => write!(f, "Local variable"),
FunctionParam(n) => write!(f, "Function param: {}", n),
} }
} }
} }

View File

@ -1,7 +1,7 @@
use std::rc::Rc; use std::rc::Rc;
use crate::ast::*; use crate::ast::*;
use crate::symbol_table::{Fqsn, Scope, SymbolTable, DefId}; use crate::symbol_table::{Fqsn, Scope, SymbolTable, Symbol, SymbolSpec, DefId};
use crate::util::ScopeStack; use crate::util::ScopeStack;
type FqsnPrefix = Vec<Scope>; type FqsnPrefix = Vec<Scope>;
@ -82,8 +82,16 @@ impl<'a> ScopeResolver<'a> {
self.symbol_table.id_to_symbol.insert(id.clone(), symbol.clone()); self.symbol_table.id_to_symbol.insert(id.clone(), symbol.clone());
} }
}, },
Some(NameType::Param(n)) => (), Some(NameType::Param(n)) => {
Some(NameType::LocalVariable) => (), let spec = SymbolSpec::FunctionParam(*n);
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);
},
None => (), None => (),
} }
} else { } else {
@ -151,7 +159,7 @@ impl<'a> ASTVisitor for ScopeResolver<'a> {
let param_names = signature.params.iter().map(|param| param.name.clone()); let param_names = signature.params.iter().map(|param| param.name.clone());
//TODO I'm 90% sure this is right, until I get to closures //TODO I'm 90% sure this is right, until I get to closures
//let mut new_scope = self.lexical_scopes.new_scope(Some(ScopeType::Function { name: signature.name.clone() })); //let mut new_scope = self.lexical_scopes.new_scope(Some(ScopeType::Function { name: signature.name.clone() }));
let mut new_scope = ScopeStack::new(None); let mut new_scope = ScopeStack::new(Some(ScopeType::Function { name: signature.name.clone() }));
for (n, param) in param_names.enumerate().into_iter() { for (n, param) in param_names.enumerate().into_iter() {
new_scope.insert(param, NameType::Param(n as u8)); new_scope.insert(param, NameType::Param(n as u8));