Symbol table detects some duplicate symbols
This commit is contained in:
parent
956353cd80
commit
9716b5e55b
5
TODO.md
5
TODO.md
@ -1,5 +1,10 @@
|
||||
#Typechecking Notes
|
||||
|
||||
|
||||
IDEA: - if you have a pattern-match where one variant has a variable and the other lacks it
|
||||
instead of treating this as a type error, promote the bound variable to an option type
|
||||
|
||||
|
||||
IS BOX SYNTAX READY????
|
||||
|
||||
(cf. cardelli paper)
|
||||
|
@ -1,12 +1,17 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::rc::Rc;
|
||||
use std::fmt;
|
||||
use std::fmt::Write;
|
||||
use std::iter::IntoIterator;
|
||||
|
||||
use crate::ast;
|
||||
use crate::ast::{TypeBody, TypeSingletonName, Signature};
|
||||
use crate::ast::{Meta, TypeBody, TypeSingletonName, Signature, Statement};
|
||||
use crate::typechecking::TypeName;
|
||||
|
||||
type LineNumber = u32;
|
||||
type SymbolTrackTable = HashMap<Rc<String>, LineNumber>;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
struct SymbolPath {
|
||||
name: Rc<String>,
|
||||
@ -85,14 +90,43 @@ impl fmt::Display for SymbolSpec {
|
||||
impl SymbolTable {
|
||||
/* note: this adds names for *forward reference* but doesn't actually create any types. solve that problem
|
||||
* later */
|
||||
|
||||
pub fn add_top_level_symbols(&mut self, ast: &ast::AST) -> Result<(), String> {
|
||||
use self::ast::Statement;
|
||||
let mut seen_identifiers = HashMap::new();
|
||||
self.add_symbols_from_scope(&ast.0, &mut seen_identifiers)
|
||||
}
|
||||
|
||||
fn add_symbols_from_scope<'a>(&'a mut self, statements: &Vec<Meta<Statement>>, seen_identifiers: &mut SymbolTrackTable) -> Result<(), String> {
|
||||
use self::ast::Declaration::*;
|
||||
for statement in ast.0.iter() {
|
||||
let statement = statement.node();
|
||||
|
||||
fn check_symbol(table: &mut SymbolTrackTable, name: &Rc<String>) -> Result<(), String> {
|
||||
match table.entry(name.clone()) {
|
||||
Entry::Occupied(o) => {
|
||||
let line_number = o.get(); //TODO make this actually work
|
||||
Err(format!("Duplicate definition: {}. It's already defined at {}", name, line_number))
|
||||
},
|
||||
Entry::Vacant(v) => {
|
||||
let line_number = 0; //TODO should work
|
||||
v.insert(line_number);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for meta in statements.iter() {
|
||||
let statement = meta.node();
|
||||
if let Statement::Declaration(decl) = statement {
|
||||
match decl {
|
||||
FuncSig(signature) | FuncDecl(signature, _) => self.add_function_signature(signature)?,
|
||||
FuncSig(ref signature) => {
|
||||
check_symbol(seen_identifiers, &signature.name)?;
|
||||
self.add_function_signature(signature)?
|
||||
}
|
||||
FuncDecl(ref signature, ref body) => {
|
||||
check_symbol(seen_identifiers, &signature.name)?;
|
||||
self.add_function_signature(signature)?;
|
||||
let mut subscope_seen_identifiers = HashMap::new();
|
||||
self.add_symbols_from_scope(body, &mut subscope_seen_identifiers)?
|
||||
},
|
||||
TypeDecl { name, body, mutable } => self.add_type_decl(name, body, mutable)?,
|
||||
_ => ()
|
||||
}
|
||||
@ -204,5 +238,18 @@ mod symbol_table_tests {
|
||||
fn basic_symbol_table() {
|
||||
values_in_table! { "let a = 10; fn b() { 20 }", &rc!(b) };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_duplicates() {
|
||||
let source = r#"
|
||||
fn a() { 1 }
|
||||
fn b() { 2 }
|
||||
fn a() { 3 }
|
||||
"#;
|
||||
let mut symbol_table = SymbolTable::new();
|
||||
let ast = crate::util::quick_ast(source);
|
||||
let output = symbol_table.add_top_level_symbols(&ast).unwrap_err();
|
||||
assert!(output.contains("Duplicate"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,12 +42,14 @@ impl<'a, T, V> ScopeStack<'a, T, V> where T: Hash + Eq {
|
||||
}
|
||||
|
||||
/// this is intended for use in tests, and does no error-handling whatsoever
|
||||
#[allow(dead_code)]
|
||||
pub fn quick_ast(input: &str) -> crate::ast::AST {
|
||||
let tokens = crate::tokenizing::tokenize(input);
|
||||
let mut parser = crate::parsing::Parser::new(tokens);
|
||||
parser.parse().unwrap()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
macro_rules! rc {
|
||||
($string:tt) => { Rc::new(stringify!($string).to_string()) }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user