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 symbol_table = self.symbol_table_handle.borrow();
let value = symbol_table.lookup_by_name(&name); let value = symbol_table.lookup_by_name(&name);
Ok(match value { 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 //TODO I'll need this type_name later to do a table lookup
SymbolSpec::DataConstructor { type_name: _type_name, type_args, .. } => { SymbolSpec::DataConstructor { type_name: _type_name, type_args, .. } => {
if type_args.len() == 0 { if type_args.len() == 0 {

View File

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