Compare commits

...

2 Commits

Author SHA1 Message Date
Greg Shuflin
3bb323667d Rename SourceMap -> DeclLocations 2021-10-14 06:55:57 -07:00
Greg Shuflin
69304de998 Various refactors around symbol table 2021-10-14 06:53:36 -07:00
3 changed files with 22 additions and 21 deletions

View File

@ -90,7 +90,7 @@ impl Schala {
// Typechecking // Typechecking
// TODO typechecking not working // TODO typechecking not working
let _overall_type = self.type_context.typecheck(&ast) let _overall_type = self.type_context.typecheck(&ast)
.map_err(|err| SchalaError::from_type_error(err)); .map_err(SchalaError::from_type_error);
// Reduce AST - TODO this doesn't produce an error yet, but probably should // Reduce AST - TODO this doesn't produce an error yet, but probably should
let symbol_table = self.symbol_table.borrow(); let symbol_table = self.symbol_table.borrow();

View File

@ -23,8 +23,8 @@ macro_rules! fqsn {
}; };
} }
mod source_map; mod tables;
use source_map::SourceMap; use tables::DeclLocations;
mod symbol_trie; mod symbol_trie;
use symbol_trie::SymbolTrie; use symbol_trie::SymbolTrie;
mod test; mod test;
@ -40,14 +40,14 @@ impl DuplicateNameTrackTable {
DuplicateNameTrackTable { table: HashMap::new() } DuplicateNameTrackTable { table: HashMap::new() }
} }
fn try_register(&mut self, name: &Rc<String>, id: &ItemId, source_map: &SourceMap) -> Result<(), LineNumber> { fn try_register(&mut self, name: &Rc<String>, id: &ItemId, decl_locations: &DeclLocations) -> Result<(), LineNumber> {
match self.table.entry(name.clone()) { match self.table.entry(name.clone()) {
Entry::Occupied(o) => { Entry::Occupied(o) => {
let line_number = o.get(); let line_number = o.get();
Err(*line_number) Err(*line_number)
}, },
Entry::Vacant(v) => { Entry::Vacant(v) => {
let line_number = if let Some(loc) = source_map.lookup(id) { let line_number = if let Some(loc) = decl_locations.lookup(id) {
loc.line_num loc.line_num
} else { } else {
0 0
@ -94,7 +94,7 @@ impl ScopeSegment {
//cf. p. 150 or so of Language Implementation Patterns //cf. p. 150 or so of Language Implementation Patterns
pub struct SymbolTable { pub struct SymbolTable {
source_map: SourceMap, decl_locations: DeclLocations,
symbol_path_to_symbol: HashMap<FullyQualifiedSymbolName, Symbol>, symbol_path_to_symbol: HashMap<FullyQualifiedSymbolName, Symbol>,
id_to_fqsn: HashMap<ItemId, FullyQualifiedSymbolName>, id_to_fqsn: HashMap<ItemId, FullyQualifiedSymbolName>,
symbol_trie: SymbolTrie, symbol_trie: SymbolTrie,
@ -103,7 +103,7 @@ pub struct SymbolTable {
impl SymbolTable { impl SymbolTable {
pub fn new() -> SymbolTable { pub fn new() -> SymbolTable {
SymbolTable { SymbolTable {
source_map: SourceMap::new(), decl_locations: DeclLocations::new(),
symbol_path_to_symbol: HashMap::new(), symbol_path_to_symbol: HashMap::new(),
id_to_fqsn: HashMap::new(), id_to_fqsn: HashMap::new(),
symbol_trie: SymbolTrie::new() symbol_trie: SymbolTrie::new()
@ -139,7 +139,7 @@ impl SymbolTable {
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
pub struct Symbol { pub struct Symbol {
pub local_name: Rc<String>, //TODO does this need to be pub? pub local_name: Rc<String>,
fully_qualified_name: FullyQualifiedSymbolName, fully_qualified_name: FullyQualifiedSymbolName,
pub spec: SymbolSpec, pub spec: SymbolSpec,
} }
@ -200,16 +200,16 @@ impl SymbolTable {
for statement in statements.iter() { for statement in statements.iter() {
match statement { match statement {
Statement { kind: StatementKind::Declaration(decl), id, location, } => { Statement { kind: StatementKind::Declaration(decl), id, location, } => {
self.source_map.add_location(id, *location); self.decl_locations.add_location(id, *location);
match decl { match decl {
FuncSig(ref signature) => { FuncSig(ref signature) => {
seen_identifiers.try_register(&signature.name, &id, &self.source_map) seen_identifiers.try_register(&signature.name, id, &self.decl_locations)
.map_err(|line| format!("Duplicate function definition: {}. It's already defined at {}", signature.name, line))?; .map_err(|line| format!("Duplicate function definition: {}. It's already defined at {}", signature.name, line))?;
self.add_function_signature(signature, scope_name_stack)? self.add_function_signature(signature, scope_name_stack)?
} }
FuncDecl(ref signature, ref body) => { FuncDecl(ref signature, ref body) => {
seen_identifiers.try_register(&signature.name, &id, &self.source_map) seen_identifiers.try_register(&signature.name, id, &self.decl_locations)
.map_err(|line| format!("Duplicate function definition: {}. It's already defined at {}", signature.name, line))?; .map_err(|line| format!("Duplicate function definition: {}. It's already defined at {}", signature.name, line))?;
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{
@ -220,12 +220,12 @@ impl SymbolTable {
output? output?
}, },
TypeDecl { name, body, mutable } => { TypeDecl { name, body, mutable } => {
seen_identifiers.try_register(&name.name, &id, &self.source_map) seen_identifiers.try_register(&name.name, &id, &self.decl_locations)
.map_err(|line| format!("Duplicate type definition: {}. It's already defined at {}", name.name, line))?; .map_err(|line| format!("Duplicate type definition: {}. It's already defined at {}", name.name, line))?;
self.add_type_decl(name, body, mutable, scope_name_stack)? self.add_type_decl(name, body, mutable, scope_name_stack)?
}, },
Binding { name, .. } => { Binding { name, .. } => {
seen_identifiers.try_register(&name, &id, &self.source_map) seen_identifiers.try_register(&name, &id, &self.decl_locations)
.map_err(|line| format!("Duplicate variable definition: {}. It's already defined at {}", name, line))?; .map_err(|line| format!("Duplicate variable definition: {}. It's already defined at {}", name, line))?;
self.add_new_symbol(name, scope_name_stack, SymbolSpec::Binding); self.add_new_symbol(name, scope_name_stack, SymbolSpec::Binding);
} }
@ -233,8 +233,8 @@ impl SymbolTable {
} }
}, },
Statement { kind: StatementKind::Module(ModuleSpecifier { name, contents}), id, location } => { Statement { kind: StatementKind::Module(ModuleSpecifier { name, contents}), id, location } => {
self.source_map.add_location(id, *location); self.decl_locations.add_location(id, *location);
seen_modules.try_register(&name, &id, &self.source_map) seen_modules.try_register(name, id, &self.decl_locations)
.map_err(|line| format!("Duplicate module definition: {}. It's already defined at {}", name, line))?; .map_err(|line| format!("Duplicate module definition: {}. It's already defined at {}", name, line))?;
scope_name_stack.push(ScopeSegment { name: name.clone() }); scope_name_stack.push(ScopeSegment { name: name.clone() });
let output = self.add_symbols_from_scope(contents, scope_name_stack); let output = self.add_symbols_from_scope(contents, scope_name_stack);
@ -248,7 +248,7 @@ impl SymbolTable {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn debug_symbol_table(&self) -> String { pub fn debug_symbol_table(&self) -> String {
let mut output = format!("Symbol table\n"); let mut output = "Symbol table\n".to_string();
let mut sorted_symbols: Vec<(&FullyQualifiedSymbolName, &Symbol)> = self.symbol_path_to_symbol.iter().collect(); let mut sorted_symbols: Vec<(&FullyQualifiedSymbolName, &Symbol)> = self.symbol_path_to_symbol.iter().collect();
sorted_symbols.sort_by(|(fqsn, _), (other_fqsn, _)| fqsn.cmp(other_fqsn)); sorted_symbols.sort_by(|(fqsn, _), (other_fqsn, _)| fqsn.cmp(other_fqsn));
for (name, sym) in sorted_symbols.iter() { for (name, sym) in sorted_symbols.iter() {

View File

@ -4,14 +4,15 @@ use crate::ast::ItemId;
use crate::tokenizing::Location; use crate::tokenizing::Location;
//TODO rename this type to make its purpose clearer /// Maps top-level declarations to Locations in source code, to detect
pub struct SourceMap { /// multiply-defined top level items.
pub struct DeclLocations {
map: HashMap<ItemId, Location> map: HashMap<ItemId, Location>
} }
impl SourceMap { impl DeclLocations {
pub fn new() -> SourceMap { pub fn new() -> Self {
SourceMap { map: HashMap::new() } Self { map: HashMap::new() }
} }
pub(crate) fn add_location(&mut self, id: &ItemId, loc: Location) { pub(crate) fn add_location(&mut self, id: &ItemId, loc: Location) {