Symbol table detects some duplicate symbols

This commit is contained in:
greg 2019-03-08 03:57:32 -08:00
parent 956353cd80
commit 9716b5e55b
3 changed files with 59 additions and 5 deletions

View File

@ -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)

View File

@ -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"))
}
}

View File

@ -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()) }
}