Make symbol names better
Refactor of symbol table to make name lookups more precise, necessary for struct member lookups
This commit is contained in:
parent
3d6447abb4
commit
611e46938d
@ -11,25 +11,46 @@ use crate::typechecking::TypeName;
|
|||||||
type LineNumber = u32;
|
type LineNumber = u32;
|
||||||
type SymbolTrackTable = HashMap<Rc<String>, LineNumber>;
|
type SymbolTrackTable = HashMap<Rc<String>, LineNumber>;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
|
||||||
struct PathToSymbol(Vec<Rc<String>>);
|
pub struct FullyQualifiedSymbolName(Vec<ScopeSegment>);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
struct ScopeSegment {
|
pub struct ScopeSegment {
|
||||||
scope_name: Rc<String>,
|
name: Rc<String>, //TODO maybe this could be a &str, for efficiency?
|
||||||
scope_type: ScopeSegmentKind,
|
kind: ScopeSegmentKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
enum ScopeSegmentKind {
|
pub enum ScopeSegmentKind {
|
||||||
Function,
|
Function,
|
||||||
//Type,
|
Type,
|
||||||
|
Terminal,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! fqsn {
|
||||||
|
( $( $name:expr ; $kind:tt),* ) => {
|
||||||
|
{
|
||||||
|
let mut vec = vec![];
|
||||||
|
$(
|
||||||
|
vec.push(ScopeSegment {
|
||||||
|
name: Rc::new($name.to_string()),
|
||||||
|
kind: sym_path_kind!($kind),
|
||||||
|
});
|
||||||
|
)*
|
||||||
|
FullyQualifiedSymbolName(vec)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! sym_path_kind {
|
||||||
|
(fn) => { ScopeSegmentKind::Function };
|
||||||
|
(ty) => { ScopeSegmentKind::Type };
|
||||||
|
(tr) => { ScopeSegmentKind::Terminal };
|
||||||
}
|
}
|
||||||
|
|
||||||
//cf. p. 150 or so of Language Implementation Patterns
|
//cf. p. 150 or so of Language Implementation Patterns
|
||||||
pub struct SymbolTable {
|
pub struct SymbolTable {
|
||||||
symbol_path_to_symbol: HashMap<PathToSymbol, Symbol>,
|
symbol_path_to_symbol: HashMap<FullyQualifiedSymbolName, Symbol>,
|
||||||
type_name_to_symbol: HashMap<Rc<String>, PathToSymbol>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO add various types of lookups here, maybe multiple hash tables internally?
|
//TODO add various types of lookups here, maybe multiple hash tables internally?
|
||||||
@ -37,38 +58,37 @@ impl SymbolTable {
|
|||||||
pub fn new() -> SymbolTable {
|
pub fn new() -> SymbolTable {
|
||||||
SymbolTable {
|
SymbolTable {
|
||||||
symbol_path_to_symbol: HashMap::new(),
|
symbol_path_to_symbol: HashMap::new(),
|
||||||
type_name_to_symbol: HashMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_new_symbol(&mut self, name: &Rc<String>, scope_path: &Vec<ScopeSegment>, spec: SymbolSpec) {
|
fn add_new_symbol(&mut self, name: &Rc<String>, scope_path: &Vec<ScopeSegment>, spec: SymbolSpec) {
|
||||||
let mut vec: Vec<Rc<String>> = scope_path.iter().map(|segment| segment.scope_name.clone()).collect();
|
let mut vec: Vec<ScopeSegment> = scope_path.clone();
|
||||||
vec.push(name.clone());
|
vec.push(ScopeSegment { name: name.clone(), kind: ScopeSegmentKind::Terminal });
|
||||||
let symbol_path = PathToSymbol(vec);
|
let fully_qualified_name = FullyQualifiedSymbolName(vec);
|
||||||
let symbol = Symbol { name: name.clone(), scopes: scope_path.to_vec(), spec };
|
let symbol = Symbol { name: name.clone(), fully_qualified_name: fully_qualified_name.clone(), spec };
|
||||||
self.symbol_path_to_symbol.insert(symbol_path, symbol);
|
self.symbol_path_to_symbol.insert(fully_qualified_name, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_by_name(&self, name: &Rc<String>) -> Option<&Symbol> {
|
pub fn lookup_by_name(&self, name: &Rc<String>) -> Option<&Symbol> {
|
||||||
self.lookup_by_path(name, &vec![])
|
let vec = vec![
|
||||||
|
ScopeSegment {
|
||||||
|
name: name.clone(),
|
||||||
|
kind: ScopeSegmentKind::Terminal,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
let symbol_path = FullyQualifiedSymbolName(vec);
|
||||||
|
self.lookup_by_path(&symbol_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_by_path(&self, name: &Rc<String>, path: &Vec<Rc<String>>) -> Option<&Symbol> {
|
pub fn lookup_by_path(&self, fully_qualified_path: &FullyQualifiedSymbolName) -> Option<&Symbol> {
|
||||||
let mut vec = path.clone();
|
self.symbol_path_to_symbol.get(fully_qualified_path)
|
||||||
vec.push(name.clone());
|
|
||||||
let symbol_path = PathToSymbol(vec);
|
|
||||||
self.symbol_path_to_symbol.get(&symbol_path)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lookup_by_type_and_tag(&self, type_name: &Rc<String>, tag: usize) -> Option<&Symbol> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Symbol {
|
pub struct Symbol {
|
||||||
pub name: Rc<String>, //TODO does this need to be pub?
|
pub name: Rc<String>, //TODO does this need to be pub?
|
||||||
scopes: Vec<ScopeSegment>,
|
fully_qualified_name: FullyQualifiedSymbolName,
|
||||||
pub spec: SymbolSpec,
|
pub spec: SymbolSpec,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,8 +166,8 @@ impl SymbolTable {
|
|||||||
insert_and_check_duplicate_symbol(&mut seen_identifiers, &signature.name)?;
|
insert_and_check_duplicate_symbol(&mut seen_identifiers, &signature.name)?;
|
||||||
self.add_function_signature(signature, scope_name_stack)?;
|
self.add_function_signature(signature, scope_name_stack)?;
|
||||||
scope_name_stack.push(ScopeSegment{
|
scope_name_stack.push(ScopeSegment{
|
||||||
scope_name: signature.name.clone(),
|
name: signature.name.clone(),
|
||||||
scope_type: ScopeSegmentKind::Function,
|
kind: ScopeSegmentKind::Function,
|
||||||
});
|
});
|
||||||
let output = self.add_symbols_from_scope(body, scope_name_stack);
|
let output = self.add_symbols_from_scope(body, scope_name_stack);
|
||||||
let _ = scope_name_stack.pop();
|
let _ = scope_name_stack.pop();
|
||||||
@ -155,6 +175,7 @@ impl SymbolTable {
|
|||||||
},
|
},
|
||||||
TypeDecl { name, body, mutable } => {
|
TypeDecl { name, body, mutable } => {
|
||||||
insert_and_check_duplicate_symbol(&mut seen_identifiers, &name.name)?;
|
insert_and_check_duplicate_symbol(&mut seen_identifiers, &name.name)?;
|
||||||
|
//TODO add ScopeSegmentKind::Type here
|
||||||
self.add_type_decl(name, body, mutable, scope_name_stack)?
|
self.add_type_decl(name, body, mutable, scope_name_stack)?
|
||||||
},
|
},
|
||||||
Binding { name, .. } => {
|
Binding { name, .. } => {
|
||||||
@ -343,8 +364,8 @@ mod symbol_table_tests {
|
|||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
let ast = quick_ast(source);
|
let ast = quick_ast(source);
|
||||||
symbol_table.add_top_level_symbols(&ast).unwrap();
|
symbol_table.add_top_level_symbols(&ast).unwrap();
|
||||||
assert!(symbol_table.lookup_by_path(&rc!(a), &vec![]).is_some());
|
assert!(symbol_table.lookup_by_path(&fqsn!["a"; tr]).is_some());
|
||||||
assert!(symbol_table.lookup_by_path(&rc!(a), &vec![rc!(some_func)]).is_some());
|
assert!(symbol_table.lookup_by_path(&fqsn!["some_func"; fn, "a";tr]).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -359,8 +380,8 @@ fn outer_func(x) {
|
|||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
let ast = quick_ast(source);
|
let ast = quick_ast(source);
|
||||||
symbol_table.add_top_level_symbols(&ast).unwrap();
|
symbol_table.add_top_level_symbols(&ast).unwrap();
|
||||||
assert!(symbol_table.lookup_by_path(&rc!(outer_func), &vec![]).is_some());
|
assert!(symbol_table.lookup_by_path(&fqsn!("outer_func"; tr)).is_some());
|
||||||
assert!(symbol_table.lookup_by_path(&rc!(inner_func), &vec![rc!(outer_func)]).is_some());
|
assert!(symbol_table.lookup_by_path(&fqsn!("outer_func"; fn, "inner_func"; tr)).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -382,10 +403,10 @@ fn outer_func(x) {
|
|||||||
let ast = quick_ast(source);
|
let ast = quick_ast(source);
|
||||||
symbol_table.add_top_level_symbols(&ast).unwrap();
|
symbol_table.add_top_level_symbols(&ast).unwrap();
|
||||||
println!("{}", symbol_table.debug_symbol_table());
|
println!("{}", symbol_table.debug_symbol_table());
|
||||||
assert!(symbol_table.lookup_by_path(&rc!(outer_func), &vec![]).is_some());
|
assert!(symbol_table.lookup_by_path(&fqsn!("outer_func"; tr)).is_some());
|
||||||
assert!(symbol_table.lookup_by_path(&rc!(inner_func), &vec![rc!(outer_func)]).is_some());
|
assert!(symbol_table.lookup_by_path(&fqsn!("outer_func"; fn, "inner_func"; tr)).is_some());
|
||||||
assert!(symbol_table.lookup_by_path(&rc!(second_inner_func), &vec![rc!(outer_func)]).is_some());
|
assert!(symbol_table.lookup_by_path(&fqsn!("outer_func"; fn, "second_inner_func"; tr)).is_some());
|
||||||
assert!(symbol_table.lookup_by_path(&rc!(another_inner_func), &vec![rc!(outer_func), rc!(second_inner_func)]).is_some());
|
assert!(symbol_table.lookup_by_path(&fqsn!("outer_func"; fn, "second_inner_func"; fn, "another_inner_func"; tr)).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user