Compare commits

..

1 Commits

Author SHA1 Message Date
Greg Shuflin
cbdd247c5c Add note about typestates 2021-12-03 14:23:05 -08:00
6 changed files with 46 additions and 81 deletions

View File

@ -616,8 +616,8 @@ fn primary_expr_no_struct(input: Span) -> ParseResult<ExpressionKind> {
bool_literal, bool_literal,
float_literal, float_literal,
number_literal, number_literal,
self_expr,
string_literal, string_literal,
self_expr,
)), )),
)(input) )(input)
} }

View File

@ -339,7 +339,7 @@ impl<'a, 'b> Reducer<'a, 'b> {
match symbol.spec() { match symbol.spec() {
Builtin(b) => Expression::Callable(Callable::Builtin(b)), Builtin(b) => Expression::Callable(Callable::Builtin(b)),
Func { .. } => Expression::Lookup(Lookup::Function(def_id.unwrap())), Func => Expression::Lookup(Lookup::Function(def_id.unwrap())),
GlobalBinding => Expression::Lookup(Lookup::GlobalVar(def_id.unwrap())), GlobalBinding => Expression::Lookup(Lookup::GlobalVar(def_id.unwrap())),
LocalVariable => Expression::Lookup(Lookup::LocalVar(def_id.unwrap())), LocalVariable => Expression::Lookup(Lookup::LocalVar(def_id.unwrap())),
FunctionParam(n) => Expression::Lookup(Lookup::Param(n)), FunctionParam(n) => Expression::Lookup(Lookup::Param(n)),

View File

@ -17,12 +17,6 @@ impl Fqsn {
Fqsn { scopes: v } Fqsn { scopes: v }
} }
pub fn extend(&self, new_item: &str) -> Self {
let mut new = self.clone();
new.scopes.push(ScopeSegment::Name(Rc::new(new_item.to_string())));
new
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn from_strs(strs: &[&str]) -> Fqsn { pub fn from_strs(strs: &[&str]) -> Fqsn {
let mut scopes = vec![]; let mut scopes = vec![];

View File

@ -32,7 +32,7 @@ pub type DefId = Id<DefItem>;
pub enum SymbolError { pub enum SymbolError {
DuplicateName { prev_name: Fqsn, location: Location }, DuplicateName { prev_name: Fqsn, location: Location },
DuplicateVariant { type_fqsn: Fqsn, name: String }, DuplicateVariant { type_fqsn: Fqsn, name: String },
DuplicateRecord { type_fqsn: Fqsn, location: Location, record: String, member: String }, DuplicateRecord { type_name: Fqsn, location: Location, member: String },
UnknownAnnotation { name: String }, UnknownAnnotation { name: String },
BadAnnotation { name: String, msg: String }, BadAnnotation { name: String, msg: String },
} }
@ -52,10 +52,7 @@ enum NameKind {
} }
#[derive(Debug)] #[derive(Debug)]
enum TypeKind { struct TypeKind;
Function,
Constructor,
}
/// Keeps track of what names were used in a given namespace. /// Keeps track of what names were used in a given namespace.
struct NameTable<K> { struct NameTable<K> {
@ -117,7 +114,7 @@ impl SymbolTable {
) -> Result<(), Vec<SymbolError>> { ) -> Result<(), Vec<SymbolError>> {
let mut populator = SymbolTablePopulator { type_context, table: self }; let mut populator = SymbolTablePopulator { type_context, table: self };
let errs = populator.populate_definition_tables(ast); let errs = populator.populate_name_tables(ast);
if !errs.is_empty() { if !errs.is_empty() {
return Err(errs); return Err(errs);
} }
@ -156,8 +153,7 @@ impl SymbolTable {
/// to a Symbol, a descriptor of what that name refers to. /// to a Symbol, a descriptor of what that name refers to.
fn add_symbol(&mut self, id: &ItemId, fqsn: Fqsn, spec: SymbolSpec) { fn add_symbol(&mut self, id: &ItemId, fqsn: Fqsn, spec: SymbolSpec) {
let def_id = self.def_id_store.fresh(); let def_id = self.def_id_store.fresh();
let local_name = fqsn.last_elem(); let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), spec, def_id });
let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), local_name, spec, def_id });
self.symbol_trie.insert(&fqsn, def_id); self.symbol_trie.insert(&fqsn, def_id);
self.id_to_def.insert(*id, def_id); self.id_to_def.insert(*id, def_id);
self.def_to_symbol.insert(def_id, symbol); self.def_to_symbol.insert(def_id, symbol);
@ -166,8 +162,7 @@ impl SymbolTable {
fn populate_single_builtin(&mut self, fqsn: Fqsn, builtin: Builtin) { fn populate_single_builtin(&mut self, fqsn: Fqsn, builtin: Builtin) {
let def_id = self.def_id_store.fresh(); let def_id = self.def_id_store.fresh();
let spec = SymbolSpec::Builtin(builtin); let spec = SymbolSpec::Builtin(builtin);
let local_name = fqsn.last_elem(); let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), spec, def_id });
let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), local_name, spec, def_id });
self.symbol_trie.insert(&fqsn, def_id); self.symbol_trie.insert(&fqsn, def_id);
self.def_to_symbol.insert(def_id, symbol); self.def_to_symbol.insert(def_id, symbol);
@ -178,14 +173,13 @@ impl SymbolTable {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Symbol { pub struct Symbol {
fully_qualified_name: Fqsn, fully_qualified_name: Fqsn,
local_name: Rc<String>,
spec: SymbolSpec, spec: SymbolSpec,
def_id: DefId, def_id: DefId,
} }
impl Symbol { impl Symbol {
pub fn local_name(&self) -> &str { pub fn local_name(&self) -> Rc<String> {
self.local_name.as_ref() self.fully_qualified_name.last_elem()
} }
pub fn def_id(&self) -> Option<DefId> { pub fn def_id(&self) -> Option<DefId> {
@ -218,7 +212,7 @@ impl fmt::Display for Symbol {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum SymbolSpec { pub enum SymbolSpec {
Builtin(Builtin), Builtin(Builtin),
Func { method: Option<crate::ast::TypeSingletonName> }, Func,
DataConstructor { tag: u32, type_id: TypeId }, DataConstructor { tag: u32, type_id: TypeId },
RecordConstructor { tag: u32, type_id: TypeId }, RecordConstructor { tag: u32, type_id: TypeId },
GlobalBinding, //Only for global variables, not for function-local ones or ones within a `let` scope context GlobalBinding, //Only for global variables, not for function-local ones or ones within a `let` scope context
@ -231,7 +225,7 @@ impl fmt::Display for SymbolSpec {
use self::SymbolSpec::*; use self::SymbolSpec::*;
match self { match self {
Builtin(b) => write!(f, "Builtin: {:?}", b), Builtin(b) => write!(f, "Builtin: {:?}", b),
Func { .. } => write!(f, "Func"), Func => write!(f, "Func"),
DataConstructor { tag, type_id } => write!(f, "DataConstructor(tag: {}, type: {})", tag, type_id), DataConstructor { tag, type_id } => write!(f, "DataConstructor(tag: {}, type: {})", tag, type_id),
RecordConstructor { type_id, tag, .. } => RecordConstructor { type_id, tag, .. } =>
write!(f, "RecordConstructor(tag: {})(<members> -> {})", tag, type_id), write!(f, "RecordConstructor(tag: {})(<members> -> {})", tag, type_id),

View File

@ -1,5 +1,6 @@
use std::{ use std::{
collections::{hash_map::Entry, HashMap, HashSet}, collections::{hash_map::Entry, HashMap, HashSet},
rc::Rc,
str::FromStr, str::FromStr,
}; };
@ -31,7 +32,7 @@ impl<'a> SymbolTablePopulator<'a> {
/// constants, functions, types, and modules defined within. This simultaneously /// constants, functions, types, and modules defined within. This simultaneously
/// checks for dupicate definitions (and returns errors if discovered), and sets /// checks for dupicate definitions (and returns errors if discovered), and sets
/// up name tables that will be used by further parts of the compiler /// up name tables that will be used by further parts of the compiler
pub fn populate_definition_tables(&mut self, ast: &AST) -> Vec<SymbolError> { pub fn populate_name_tables(&mut self, ast: &AST) -> Vec<SymbolError> {
let mut scope_stack = vec![]; let mut scope_stack = vec![];
self.add_from_scope(ast.statements.as_ref(), &mut scope_stack, false) self.add_from_scope(ast.statements.as_ref(), &mut scope_stack, false)
} }
@ -50,36 +51,24 @@ impl<'a> SymbolTablePopulator<'a> {
if let Err(err) = self.add_single_statement(id, kind, location, scope_stack, function_scope) { if let Err(err) = self.add_single_statement(id, kind, location, scope_stack, function_scope) {
errors.push(err); errors.push(err);
} else { } else {
let decl = match kind {
StatementKind::Declaration(decl) => decl,
_ => continue,
};
// If there's an error with a name, don't recurse into subscopes of that name // If there's an error with a name, don't recurse into subscopes of that name
let recursive_errs = match decl { let recursive_errs = match kind {
Declaration::FuncDecl(signature, body) => { StatementKind::Declaration(Declaration::FuncDecl(signature, body)) => {
let new_scope = ScopeSegment::Name(signature.name.clone()); let new_scope = ScopeSegment::Name(signature.name.clone());
scope_stack.push(new_scope); scope_stack.push(new_scope);
let output = self.add_from_scope(body.as_ref(), scope_stack, true); let output = self.add_from_scope(body.as_ref(), scope_stack, true);
scope_stack.pop(); scope_stack.pop();
output output
} }
Declaration::Module { name, items } => { StatementKind::Declaration(Declaration::Module { name, items }) => {
let new_scope = ScopeSegment::Name(name.clone()); let new_scope = ScopeSegment::Name(name.clone());
scope_stack.push(new_scope); scope_stack.push(new_scope);
let output = self.add_from_scope(items.as_ref(), scope_stack, false); let output = self.add_from_scope(items.as_ref(), scope_stack, false);
scope_stack.pop(); scope_stack.pop();
output output
} }
Declaration::TypeDecl { name, body, mutable } => { StatementKind::Declaration(Declaration::TypeDecl { name, body, mutable }) =>
let type_fqsn = Fqsn::from_scope_stack(scope_stack, name.name.clone()); self.add_type_members(name, body, mutable, location, scope_stack),
self.add_type_members(name, body, mutable, location, type_fqsn)
}
/*
Declaration::Impl { type_name, body, .. } => {
},
*/
_ => vec![], _ => vec![],
}; };
errors.extend(recursive_errs.into_iter()); errors.extend(recursive_errs.into_iter());
@ -103,11 +92,9 @@ impl<'a> SymbolTablePopulator<'a> {
self.table self.table
.fq_names .fq_names
.register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?; .register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?;
self.table self.table.types.register(fq_function.clone(), NameSpec { location, kind: TypeKind })?;
.types
.register(fq_function.clone(), NameSpec { location, kind: TypeKind::Function })?;
self.add_symbol(id, fq_function, SymbolSpec::Func { method: None }); self.add_symbol(id, fq_function, SymbolSpec::Func);
} }
StatementKind::Declaration(Declaration::FuncDecl(signature, ..)) => { StatementKind::Declaration(Declaration::FuncDecl(signature, ..)) => {
let fn_name = &signature.name; let fn_name = &signature.name;
@ -115,15 +102,13 @@ impl<'a> SymbolTablePopulator<'a> {
self.table self.table
.fq_names .fq_names
.register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?; .register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?;
self.table self.table.types.register(fq_function.clone(), NameSpec { location, kind: TypeKind })?;
.types
.register(fq_function.clone(), NameSpec { location, kind: TypeKind::Function })?;
self.add_symbol(id, fq_function, SymbolSpec::Func { method: None }); self.add_symbol(id, fq_function, SymbolSpec::Func);
} }
StatementKind::Declaration(Declaration::TypeDecl { name, .. }) => { StatementKind::Declaration(Declaration::TypeDecl { name, .. }) => {
let fq_type = Fqsn::from_scope_stack(scope_stack, name.name.clone()); let fq_type = Fqsn::from_scope_stack(scope_stack, name.name.clone());
self.table.types.register(fq_type, NameSpec { location, kind: TypeKind::Constructor })?; self.table.types.register(fq_type, NameSpec { location, kind: TypeKind })?;
} }
StatementKind::Declaration(Declaration::Binding { name, .. }) => { StatementKind::Declaration(Declaration::Binding { name, .. }) => {
let fq_binding = Fqsn::from_scope_stack(scope_stack, name.clone()); let fq_binding = Fqsn::from_scope_stack(scope_stack, name.clone());
@ -205,7 +190,7 @@ impl<'a> SymbolTablePopulator<'a> {
type_body: &TypeBody, type_body: &TypeBody,
_mutable: &bool, _mutable: &bool,
location: Location, location: Location,
type_fqsn: Fqsn, scope_stack: &mut Vec<ScopeSegment>,
) -> Vec<SymbolError> { ) -> Vec<SymbolError> {
let (variants, immediate_variant) = match type_body { let (variants, immediate_variant) = match type_body {
TypeBody::Variants(variants) => (variants.clone(), false), TypeBody::Variants(variants) => (variants.clone(), false),
@ -218,6 +203,10 @@ impl<'a> SymbolTablePopulator<'a> {
true, true,
), ),
}; };
let type_fqsn = Fqsn::from_scope_stack(scope_stack, type_name.name.clone());
let new_scope = ScopeSegment::Name(type_name.name.clone());
scope_stack.push(new_scope);
// Check for duplicates before registering any types with the TypeContext // Check for duplicates before registering any types with the TypeContext
let mut seen_variants = HashSet::new(); let mut seen_variants = HashSet::new();
@ -233,15 +222,15 @@ impl<'a> SymbolTablePopulator<'a> {
seen_variants.insert(variant.name.clone()); seen_variants.insert(variant.name.clone());
if let VariantKind::Record(ref members) = variant.kind { if let VariantKind::Record(ref members) = variant.kind {
let variant_name = Fqsn::from_scope_stack(scope_stack.as_ref(), variant.name.clone());
let mut seen_members = HashMap::new(); let mut seen_members = HashMap::new();
for (member_name, _) in members.iter() { for (member_name, _) in members.iter() {
match seen_members.entry(member_name.as_ref()) { match seen_members.entry(member_name.as_ref()) {
Entry::Occupied(o) => { Entry::Occupied(o) => {
let location = *o.get(); let location = *o.get();
errors.push(SymbolError::DuplicateRecord { errors.push(SymbolError::DuplicateRecord {
type_fqsn: type_fqsn.clone(), type_name: variant_name.clone(),
location, location,
record: variant.name.as_ref().to_string(),
member: member_name.as_ref().to_string(), member: member_name.as_ref().to_string(),
}); });
} }
@ -260,11 +249,11 @@ impl<'a> SymbolTablePopulator<'a> {
let mut type_builder = TypeBuilder::new(type_name.name.as_ref()); let mut type_builder = TypeBuilder::new(type_name.name.as_ref());
let mut variant_name_map = HashMap::new(); let mut fqsn_id_map = HashMap::new();
for variant in variants.iter() { for variant in variants.iter() {
let Variant { name, kind, id } = variant; let Variant { name, kind, id } = variant;
variant_name_map.insert(name.clone(), id); fqsn_id_map.insert(Fqsn::from_scope_stack(scope_stack.as_ref(), name.clone()), id);
let mut variant_builder = VariantBuilder::new(name.as_ref()); let mut variant_builder = VariantBuilder::new(name.as_ref());
match kind { match kind {
@ -288,23 +277,30 @@ impl<'a> SymbolTablePopulator<'a> {
// This index is guaranteed to be the correct tag // This index is guaranteed to be the correct tag
for (index, variant) in type_definition.variants.iter().enumerate() { for (index, variant) in type_definition.variants.iter().enumerate() {
let id = variant_name_map.get(&variant.name).unwrap(); let fqsn = Fqsn::from_scope_stack(scope_stack.as_ref(), Rc::new(variant.name.to_string()));
let id = fqsn_id_map.get(&fqsn).unwrap();
let tag = index as u32; let tag = index as u32;
let spec = match &variant.members { let spec = match &variant.members {
type_inference::VariantMembers::Unit => SymbolSpec::DataConstructor { tag, type_id }, type_inference::VariantMembers::Unit => SymbolSpec::DataConstructor { tag, type_id },
type_inference::VariantMembers::Tuple(..) => SymbolSpec::DataConstructor { tag, type_id }, type_inference::VariantMembers::Tuple(..) => SymbolSpec::DataConstructor { tag, type_id },
type_inference::VariantMembers::Record(..) => SymbolSpec::RecordConstructor { tag, type_id }, type_inference::VariantMembers::Record(..) => SymbolSpec::RecordConstructor { tag, type_id },
}; };
self.table.add_symbol(id, type_fqsn.extend(&variant.name), spec); self.table.add_symbol(id, fqsn, spec);
} }
if immediate_variant { if immediate_variant {
let variant = &type_definition.variants[0]; let variant = &type_definition.variants[0];
let id = variant_name_map.get(&variant.name).unwrap(); let fqsn = Fqsn::from_scope_stack(scope_stack.as_ref(), Rc::new(variant.name.to_string()));
let id = fqsn_id_map.get(&fqsn).unwrap();
let abbrev_fqsn = Fqsn::from_scope_stack(
scope_stack[0..scope_stack.len() - 1].as_ref(),
Rc::new(variant.name.to_string()),
);
let spec = SymbolSpec::RecordConstructor { tag: 0, type_id }; let spec = SymbolSpec::RecordConstructor { tag: 0, type_id };
self.table.add_symbol(id, type_fqsn, spec); self.table.add_symbol(id, abbrev_fqsn, spec);
} }
scope_stack.pop();
vec![] vec![]
} }
} }

View File

@ -263,29 +263,10 @@ fn duplicate_struct_members() {
"#; "#;
let (_, output) = add_symbols(source); let (_, output) = add_symbols(source);
let errs = dbg!(output.unwrap_err()); let errs = output.unwrap_err();
assert_matches!(&errs[..], [ assert_matches!(&errs[..], [
SymbolError::DuplicateRecord { SymbolError::DuplicateRecord {
type_fqsn, member, record, ..}, type_name, member, ..},
] if type_fqsn == &Fqsn::from_strs(&["Tarak"]) && member == "mets" && record == "Tarak" ] if type_name == &Fqsn::from_strs(&["Tarak", "Tarak"]) && member == "mets"
); );
} }
/*
#[test]
fn methods() {
let source = r#"
type Foo = { x: Int, y: Int }
impl Foo {
fn hella() {
self.x + 50
}
}
"#;
let (symbols, _) = add_symbols(source);
symbols.debug();
assert!(symbols.fq_names.table.get(&make_fqsn(&["hella"])).is_some());
}
*/