diff --git a/TODO.md b/TODO.md index c217638..ab03791 100644 --- a/TODO.md +++ b/TODO.md @@ -2,8 +2,6 @@ ## Testing -* Get a test library for running many unit tests working -* Write a human-readable display of the AST * Make an automatic (macro-based?) system for numbering compiler errors, this should be every type of error ## Symbols @@ -24,6 +22,10 @@ 2. Once FQSNs are aware of function parameters, most of the Rc things in eval.rs can go away +## Semantics + +* Use annotations to indicate builtin functions + ## Parser * I think I can restructure the parser to get rid of most instances of expect!, at least at the beginning of a rule diff --git a/schala-lang/language/src/builtin.rs b/schala-lang/language/src/builtin.rs index fec7a9f..7de1f16 100644 --- a/schala-lang/language/src/builtin.rs +++ b/schala-lang/language/src/builtin.rs @@ -28,7 +28,6 @@ pub enum Builtin { GreaterThan, GreaterThanOrEqual, Comparison, - FieldAccess, IOPrint, IOPrintLn, IOGetLine, @@ -59,7 +58,6 @@ impl Builtin { GreaterThan => ty!(Nat -> Nat -> Bool), GreaterThanOrEqual => ty!(Nat -> Nat -> Bool), Comparison => ty!(Nat -> Nat -> Ordering), - FieldAccess => ty!(Unit), IOPrint => ty!(Unit), IOPrintLn => ty!(Unit), IOGetLine => ty!(StringT), @@ -120,7 +118,6 @@ impl FromStr for Builtin { "==" => Equality, "=" => Assignment, "<=>" => Comparison, - "." => FieldAccess, "print" => IOPrint, "println" => IOPrintLn, "getline" => IOGetLine, diff --git a/schala-lang/language/src/reduced_ir/mod.rs b/schala-lang/language/src/reduced_ir/mod.rs index d5dad04..6c882c9 100644 --- a/schala-lang/language/src/reduced_ir/mod.rs +++ b/schala-lang/language/src/reduced_ir/mod.rs @@ -310,6 +310,7 @@ impl<'a, 'b> Reducer<'a, 'b> { let def_id = symbol.def_id(); match symbol.spec() { + Builtin(b) => Expression::Callable(Callable::Builtin(b)), Func => Expression::Lookup(Lookup::Function(def_id.unwrap())), GlobalBinding => Expression::Lookup(Lookup::GlobalVar(def_id.unwrap())), LocalVariable => Expression::Lookup(Lookup::LocalVar(def_id.unwrap())), diff --git a/schala-lang/language/src/symbol_table/mod.rs b/schala-lang/language/src/symbol_table/mod.rs index 4ed9a7a..eb406ce 100644 --- a/schala-lang/language/src/symbol_table/mod.rs +++ b/schala-lang/language/src/symbol_table/mod.rs @@ -12,6 +12,7 @@ use crate::{ Declaration, ItemId, ModuleSpecifier, Statement, StatementKind, TypeBody, TypeSingletonName, Variant, VariantKind, }, + builtin::Builtin, tokenizing::Location, type_inference::{self, PendingType, TypeBuilder, TypeContext, TypeId, VariantBuilder}, }; @@ -42,7 +43,6 @@ impl Fqsn { Fqsn { scopes: v } } - #[cfg(test)] fn from_strs(strs: &[&str]) -> Fqsn { let mut scopes = vec![]; for s in strs { @@ -152,7 +152,7 @@ pub struct SymbolTable { impl SymbolTable { pub fn new() -> SymbolTable { - SymbolTable { + let mut table = SymbolTable { def_id_store: IdStore::new(), symbol_trie: SymbolTrie::new(), fq_names: NameTable::new(), @@ -161,7 +161,10 @@ impl SymbolTable { fqsn_to_symbol: HashMap::new(), id_to_symbol: HashMap::new(), def_to_symbol: HashMap::new(), - } + }; + + table.populate_builtins(); + table } /// The main entry point into the symbol table. This will traverse the AST in several @@ -209,6 +212,24 @@ impl SymbolTable { self.id_to_symbol.insert(*id, symbol.clone()); self.def_to_symbol.insert(def_id, symbol); } + + fn populate_single_builtin(&mut self, fqsn: Fqsn, builtin: Builtin) { + let def_id = self.def_id_store.fresh(); + let spec = SymbolSpec::Builtin(builtin); + let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), spec, def_id }); + + self.symbol_trie.insert(&fqsn); + self.fqsn_to_symbol.insert(fqsn, symbol.clone()); + self.def_to_symbol.insert(def_id, symbol); + } + + fn populate_builtins(&mut self) { + let fqsn = Fqsn::from_strs(&["println"]); + self.populate_single_builtin(fqsn, Builtin::IOPrintLn); + + let fqsn = Fqsn::from_strs(&["print"]); + self.populate_single_builtin(fqsn, Builtin::IOPrint); + } } struct SymbolTableRunner<'a> { @@ -258,6 +279,7 @@ impl fmt::Display for Symbol { //function parameters (even though they are currently assigned). #[derive(Debug, Clone)] pub enum SymbolSpec { + Builtin(Builtin), Func, DataConstructor { tag: u32, type_id: TypeId }, RecordConstructor { tag: u32, members: HashMap, TypeId>, type_id: TypeId }, @@ -270,6 +292,7 @@ impl fmt::Display for SymbolSpec { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::SymbolSpec::*; match self { + Builtin(b) => write!(f, "Builtin: {:?}", b), Func => write!(f, "Func"), DataConstructor { tag, type_id } => write!(f, "DataConstructor(tag: {}, type: {})", tag, type_id), RecordConstructor { type_id, tag, .. } => diff --git a/schala-lang/language/src/tree_walk_eval/evaluator.rs b/schala-lang/language/src/tree_walk_eval/evaluator.rs index 67b9953..8760f79 100644 --- a/schala-lang/language/src/tree_walk_eval/evaluator.rs +++ b/schala-lang/language/src/tree_walk_eval/evaluator.rs @@ -276,16 +276,13 @@ impl<'a, 'b> Evaluator<'a, 'b> { let evaled_args = evaled_args?; Ok(match (builtin, evaled_args.as_slice()) { - (FieldAccess, /*&[Node::PrimObject { .. }]*/ _) => { - return Err("Field access unimplemented".into()); - } /* builtin functions */ (IOPrint, &[ref anything]) => { print!("{}", anything.to_repl(self.type_context)); Primitive::Tuple(vec![]) } (IOPrintLn, &[ref anything]) => { - print!("{}", anything.to_repl(self.type_context)); + println!("{}", anything.to_repl(self.type_context)); Primitive::Tuple(vec![]) } (IOGetLine, &[]) => {