diff --git a/schala-lang/language/src/source_map.rs b/schala-lang/language/src/source_map.rs index 43e8319..cfa2ce7 100644 --- a/schala-lang/language/src/source_map.rs +++ b/schala-lang/language/src/source_map.rs @@ -3,10 +3,12 @@ use std::fmt; use crate::ast::ItemId; +pub type LineNumber = usize; + #[derive(Debug, Clone, Copy, PartialEq)] pub struct Location { - pub line_num: usize, - pub char_num: usize + pub line_num: LineNumber, + pub char_num: usize, } impl fmt::Display for Location { @@ -27,4 +29,11 @@ impl SourceMap { pub fn add_location(&mut self, id: &ItemId, loc: Location) { self.map.insert(id.clone(), loc); } + + pub fn lookup(&self, id: &ItemId) -> Option { + match self.map.get(id) { + Some(loc) => Some(loc.clone()), + None => None + } + } } diff --git a/schala-lang/language/src/symbol_table.rs b/schala-lang/language/src/symbol_table.rs index 6a159c4..58d9227 100644 --- a/schala-lang/language/src/symbol_table.rs +++ b/schala-lang/language/src/symbol_table.rs @@ -5,6 +5,7 @@ use std::fmt; use std::fmt::Write; use crate::schala::SourceMapHandle; +use crate::source_map::{SourceMap, LineNumber}; use crate::ast; use crate::ast::{ItemId, TypeBody, TypeSingletonName, Signature, Statement, StatementKind}; use crate::typechecking::TypeName; @@ -27,7 +28,6 @@ mod symbol_trie; use symbol_trie::SymbolTrie; mod test; -type LineNumber = u32; type SymbolTrackTable = HashMap, LineNumber>; #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] @@ -163,14 +163,18 @@ impl SymbolTable { fn add_symbols_from_scope<'a>(&'a mut self, statements: &Vec, scope_name_stack: &mut Vec) -> Result<(), String> { use self::ast::Declaration::*; - fn insert_and_check_duplicate_symbol(table: &mut SymbolTrackTable, name: &Rc) -> Result<(), String> { + fn insert_and_check_duplicate_symbol(table: &mut SymbolTrackTable, name: &Rc, id: &ItemId, source_map: &SourceMap) -> Result<(), String> { match table.entry(name.clone()) { Entry::Occupied(o) => { - let line_number = o.get(); //TODO make this actually work + let line_number = o.get(); Err(format!("Duplicate definition: {}. It's already defined at {}", name, line_number)) }, Entry::Vacant(v) => { - let line_number = 0; //TODO should work + let line_number = if let Some(loc) = source_map.lookup(id) { + loc.line_num + } else { + 0 + }; v.insert(line_number); Ok(()) } @@ -180,14 +184,14 @@ impl SymbolTable { let mut seen_identifiers: SymbolTrackTable = HashMap::new(); for statement in statements.iter() { - if let Statement { kind: StatementKind::Declaration(decl), .. } = statement { + if let Statement { kind: StatementKind::Declaration(decl), id } = statement { match decl { FuncSig(ref signature) => { - insert_and_check_duplicate_symbol(&mut seen_identifiers, &signature.name)?; + insert_and_check_duplicate_symbol(&mut seen_identifiers, &signature.name, &id, &self.source_map_handle.borrow())?; self.add_function_signature(signature, scope_name_stack)? } FuncDecl(ref signature, ref body) => { - insert_and_check_duplicate_symbol(&mut seen_identifiers, &signature.name)?; + insert_and_check_duplicate_symbol(&mut seen_identifiers, &signature.name, &id, &self.source_map_handle.borrow())?; self.add_function_signature(signature, scope_name_stack)?; scope_name_stack.push(ScopeSegment{ name: signature.name.clone(), @@ -197,11 +201,11 @@ impl SymbolTable { output? }, TypeDecl { name, body, mutable } => { - insert_and_check_duplicate_symbol(&mut seen_identifiers, &name.name)?; + insert_and_check_duplicate_symbol(&mut seen_identifiers, &name.name, &id, &self.source_map_handle.borrow())?; self.add_type_decl(name, body, mutable, scope_name_stack)? }, Binding { name, .. } => { - insert_and_check_duplicate_symbol(&mut seen_identifiers, name)?; + insert_and_check_duplicate_symbol(&mut seen_identifiers, name, &id, &self.source_map_handle.borrow())?; self.add_new_symbol(name, scope_name_stack, SymbolSpec::Binding); } _ => () diff --git a/schala-lang/language/src/symbol_table/test.rs b/schala-lang/language/src/symbol_table/test.rs index 588554c..bd32904 100644 --- a/schala-lang/language/src/symbol_table/test.rs +++ b/schala-lang/language/src/symbol_table/test.rs @@ -46,7 +46,6 @@ fn no_duplicates() { let mut symbol_table = SymbolTable::new(source_map); let ast = quick_ast(source); let output = symbol_table.add_top_level_symbols(&ast).unwrap_err(); - println!("OUTPUT: {}", output); assert!(output.contains("Duplicate")) } @@ -61,6 +60,7 @@ fn no_duplicates_2() { let mut symbol_table = SymbolTable::new(source_map); let ast = quick_ast(source); let output = symbol_table.add_top_level_symbols(&ast).unwrap_err(); + println!("OUTPUT: {}", output); assert!(output.contains("Duplicate")); assert!(output.contains("Line 3")); }