Partway there in terms of implementing source map lookup

This commit is contained in:
greg 2019-10-23 03:08:36 -07:00
parent 7495f30e16
commit 1ffe61cf5f
3 changed files with 25 additions and 12 deletions

View File

@ -3,10 +3,12 @@ use std::fmt;
use crate::ast::ItemId; use crate::ast::ItemId;
pub type LineNumber = usize;
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct Location { pub struct Location {
pub line_num: usize, pub line_num: LineNumber,
pub char_num: usize pub char_num: usize,
} }
impl fmt::Display for Location { impl fmt::Display for Location {
@ -27,4 +29,11 @@ impl SourceMap {
pub fn add_location(&mut self, id: &ItemId, loc: Location) { pub fn add_location(&mut self, id: &ItemId, loc: Location) {
self.map.insert(id.clone(), loc); self.map.insert(id.clone(), loc);
} }
pub fn lookup(&self, id: &ItemId) -> Option<Location> {
match self.map.get(id) {
Some(loc) => Some(loc.clone()),
None => None
}
}
} }

View File

@ -5,6 +5,7 @@ use std::fmt;
use std::fmt::Write; use std::fmt::Write;
use crate::schala::SourceMapHandle; use crate::schala::SourceMapHandle;
use crate::source_map::{SourceMap, LineNumber};
use crate::ast; use crate::ast;
use crate::ast::{ItemId, TypeBody, TypeSingletonName, Signature, Statement, StatementKind}; use crate::ast::{ItemId, TypeBody, TypeSingletonName, Signature, Statement, StatementKind};
use crate::typechecking::TypeName; use crate::typechecking::TypeName;
@ -27,7 +28,6 @@ mod symbol_trie;
use symbol_trie::SymbolTrie; use symbol_trie::SymbolTrie;
mod test; mod test;
type LineNumber = u32;
type SymbolTrackTable = HashMap<Rc<String>, LineNumber>; type SymbolTrackTable = HashMap<Rc<String>, LineNumber>;
#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] #[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<Statement>, scope_name_stack: &mut Vec<ScopeSegment>) -> Result<(), String> { fn add_symbols_from_scope<'a>(&'a mut self, statements: &Vec<Statement>, scope_name_stack: &mut Vec<ScopeSegment>) -> Result<(), String> {
use self::ast::Declaration::*; use self::ast::Declaration::*;
fn insert_and_check_duplicate_symbol(table: &mut SymbolTrackTable, name: &Rc<String>) -> Result<(), String> { fn insert_and_check_duplicate_symbol(table: &mut SymbolTrackTable, name: &Rc<String>, id: &ItemId, source_map: &SourceMap) -> Result<(), String> {
match table.entry(name.clone()) { match table.entry(name.clone()) {
Entry::Occupied(o) => { 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)) Err(format!("Duplicate definition: {}. It's already defined at {}", name, line_number))
}, },
Entry::Vacant(v) => { 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); v.insert(line_number);
Ok(()) Ok(())
} }
@ -180,14 +184,14 @@ impl SymbolTable {
let mut seen_identifiers: SymbolTrackTable = HashMap::new(); let mut seen_identifiers: SymbolTrackTable = HashMap::new();
for statement in statements.iter() { for statement in statements.iter() {
if let Statement { kind: StatementKind::Declaration(decl), .. } = statement { if let Statement { kind: StatementKind::Declaration(decl), id } = statement {
match decl { match decl {
FuncSig(ref signature) => { 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)? self.add_function_signature(signature, scope_name_stack)?
} }
FuncDecl(ref signature, ref body) => { 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)?; self.add_function_signature(signature, scope_name_stack)?;
scope_name_stack.push(ScopeSegment{ scope_name_stack.push(ScopeSegment{
name: signature.name.clone(), name: signature.name.clone(),
@ -197,11 +201,11 @@ impl SymbolTable {
output? output?
}, },
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, &id, &self.source_map_handle.borrow())?;
self.add_type_decl(name, body, mutable, scope_name_stack)? self.add_type_decl(name, body, mutable, scope_name_stack)?
}, },
Binding { name, .. } => { 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); self.add_new_symbol(name, scope_name_stack, SymbolSpec::Binding);
} }
_ => () _ => ()

View File

@ -46,7 +46,6 @@ fn no_duplicates() {
let mut symbol_table = SymbolTable::new(source_map); let mut symbol_table = SymbolTable::new(source_map);
let ast = quick_ast(source); let ast = quick_ast(source);
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err(); let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
println!("OUTPUT: {}", output);
assert!(output.contains("Duplicate")) assert!(output.contains("Duplicate"))
} }
@ -61,6 +60,7 @@ fn no_duplicates_2() {
let mut symbol_table = SymbolTable::new(source_map); let mut symbol_table = SymbolTable::new(source_map);
let ast = quick_ast(source); let ast = quick_ast(source);
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err(); let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
println!("OUTPUT: {}", output);
assert!(output.contains("Duplicate")); assert!(output.contains("Duplicate"));
assert!(output.contains("Line 3")); assert!(output.contains("Line 3"));
} }