More cleaning up of how scopes are stored

on Symbol
This commit is contained in:
greg 2019-03-11 02:47:47 -07:00
parent dbcd2278a6
commit bdcae36b60
2 changed files with 23 additions and 26 deletions

View File

@ -467,7 +467,7 @@ impl<'a> State<'a> {
let symbol_table = self.symbol_table_handle.borrow();
let value = symbol_table.lookup_by_name(&name);
Ok(match value {
Some(Symbol { name, spec }) => match spec {
Some(Symbol { name, spec, .. }) => match spec {
//TODO I'll need this type_name later to do a table lookup
SymbolSpec::DataConstructor { type_name: _type_name, type_args, .. } => {
if type_args.len() == 0 {

View File

@ -3,7 +3,6 @@ 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::{Meta, TypeBody, TypeSingletonName, Signature, Statement};
@ -15,14 +14,14 @@ type SymbolTrackTable = HashMap<Rc<String>, LineNumber>;
#[derive(PartialEq, Eq, Hash, Debug)]
struct PathToSymbol(Vec<Rc<String>>);
#[derive(Debug)]
#[derive(Debug, Clone)]
struct ScopeSegment {
scope_name: Rc<String>,
scope_type: ScopeType,
scope_type: ScopeSegmentKind,
}
#[derive(Debug)]
enum ScopeType {
#[derive(Debug, Clone)]
enum ScopeSegmentKind {
Function,
Type,
}
@ -40,10 +39,11 @@ impl SymbolTable {
}
}
fn add_new_symbol(&mut self, name: &Rc<String>, path: &Vec<Rc<String>>, symbol: Symbol) {
let mut vec = path.clone();
fn add_new_symbol(&mut self, name: &Rc<String>, scope_path: &Vec<ScopeSegment>, spec: SymbolSpec) {
let mut vec: Vec<Rc<String>> = scope_path.iter().map(|segment| segment.scope_name.clone()).collect();
vec.push(name.clone());
let symbol_path = PathToSymbol(vec);
let symbol = Symbol { name: name.clone(), scopes: scope_path.to_vec(), spec };
self.values.insert(symbol_path, symbol);
}
@ -61,7 +61,8 @@ impl SymbolTable {
#[derive(Debug)]
pub struct Symbol {
pub name: Rc<String>,
pub name: Rc<String>, //TODO does this need to be pub?
scopes: Vec<ScopeSegment>,
pub spec: SymbolSpec,
}
@ -106,7 +107,7 @@ impl SymbolTable {
self.add_symbols_from_scope(&ast.0, &mut scope_name_stack)
}
fn add_symbols_from_scope<'a>(&'a mut self, statements: &Vec<Meta<Statement>>, scope_name_stack: &mut Vec<Rc<String>>) -> Result<(), String> {
fn add_symbols_from_scope<'a>(&'a mut self, statements: &Vec<Meta<Statement>>, scope_name_stack: &mut Vec<ScopeSegment>) -> Result<(), String> {
use self::ast::Declaration::*;
fn insert_and_check_duplicate_symbol(table: &mut SymbolTrackTable, name: &Rc<String>) -> Result<(), String> {
@ -136,7 +137,10 @@ impl SymbolTable {
FuncDecl(ref signature, ref body) => {
insert_and_check_duplicate_symbol(&mut seen_identifiers, &signature.name)?;
self.add_function_signature(signature, scope_name_stack)?;
scope_name_stack.push(signature.name.clone());
scope_name_stack.push(ScopeSegment{
scope_name: signature.name.clone(),
scope_type: ScopeSegmentKind::Function,
});
let output = self.add_symbols_from_scope(body, scope_name_stack);
let _ = scope_name_stack.pop();
output?
@ -147,8 +151,7 @@ impl SymbolTable {
},
Binding { name, .. } => {
insert_and_check_duplicate_symbol(&mut seen_identifiers, name)?;
let symbol = Symbol { name: name.clone(), spec: SymbolSpec::Binding };
self.add_new_symbol(name, scope_name_stack, symbol);
self.add_new_symbol(name, scope_name_stack, SymbolSpec::Binding);
}
_ => ()
}
@ -164,22 +167,17 @@ impl SymbolTable {
output
}
fn add_function_signature(&mut self, signature: &Signature, scope_name_stack: &mut Vec<Rc<String>>) -> Result<(), String> {
fn add_function_signature(&mut self, signature: &Signature, scope_name_stack: &mut Vec<ScopeSegment>) -> Result<(), String> {
let mut local_type_context = LocalTypeContext::new();
let types = signature.params.iter().map(|param| match param {
(_, Some(type_identifier)) => Rc::new(format!("{:?}", type_identifier)),
(_, None) => local_type_context.new_universal_type()
}).collect();
let spec = SymbolSpec::Func(types);
self.add_new_symbol(
&signature.name,
scope_name_stack,
Symbol { name: signature.name.clone(), spec }
);
self.add_new_symbol(&signature.name, scope_name_stack, SymbolSpec::Func(types));
Ok(())
}
fn add_type_decl(&mut self, type_name: &TypeSingletonName, body: &TypeBody, _mutable: &bool, scope_name_stack: &mut Vec<Rc<String>>) -> Result<(), String> {
fn add_type_decl(&mut self, type_name: &TypeSingletonName, body: &TypeBody, _mutable: &bool, scope_name_stack: &mut Vec<ScopeSegment>) -> Result<(), String> {
use crate::ast::{TypeIdentifier, Variant};
let TypeBody(variants) = body;
let TypeSingletonName { name, .. } = type_name;
@ -194,7 +192,7 @@ impl SymbolTable {
type_name: name.clone(),
type_args: vec![],
};
self.add_new_symbol(variant_name, scope_name_stack, Symbol { name: variant_name.clone(), spec });
self.add_new_symbol(variant_name, scope_name_stack, spec);
},
Variant::TupleStruct(variant_name, tuple_members) => {
let type_args = tuple_members.iter().map(|type_name| match type_name {
@ -206,16 +204,14 @@ impl SymbolTable {
type_name: name.clone(),
type_args
};
let symbol = Symbol { name: variant_name.clone(), spec };
self.add_new_symbol(variant_name, scope_name_stack, symbol);
self.add_new_symbol(variant_name, scope_name_stack, spec);
},
//TODO if there is only one variant, and it is a record, it doesn't need to have an
//explicit name
Variant::Record { name, members: _members } => {
let fields = HashMap::new();
let spec = SymbolSpec::RecordConstructor { fields };
let symbol = Symbol { name: name.clone(), spec };
self.add_new_symbol(name, scope_name_stack, symbol);
self.add_new_symbol(name, scope_name_stack, spec);
},
}
}
@ -311,6 +307,7 @@ mod symbol_table_tests {
assert!(output.contains("Duplicate"))
}
#[test]
fn dont_falsely_detect_duplicates() {
let source = r#"
let a = 20;