More cleaning up of how scopes are stored
on Symbol
This commit is contained in:
parent
dbcd2278a6
commit
bdcae36b60
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user