Compare commits
2 Commits
803a836887
...
d084deac80
Author | SHA1 | Date | |
---|---|---|---|
|
d084deac80 | ||
|
87024b79ba |
6
TODO.md
6
TODO.md
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
## Testing
|
## 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
|
* Make an automatic (macro-based?) system for numbering compiler errors, this should be every type of error
|
||||||
|
|
||||||
## Symbols
|
## Symbols
|
||||||
@ -24,6 +22,10 @@
|
|||||||
|
|
||||||
2. Once FQSNs are aware of function parameters, most of the Rc<String> things in eval.rs can go away
|
2. Once FQSNs are aware of function parameters, most of the Rc<String> things in eval.rs can go away
|
||||||
|
|
||||||
|
## Semantics
|
||||||
|
|
||||||
|
* Use annotations to indicate builtin functions
|
||||||
|
|
||||||
## Parser
|
## Parser
|
||||||
* I think I can restructure the parser to get rid of most instances of expect!, at least at the beginning of a rule
|
* I think I can restructure the parser to get rid of most instances of expect!, at least at the beginning of a rule
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ pub enum Builtin {
|
|||||||
GreaterThan,
|
GreaterThan,
|
||||||
GreaterThanOrEqual,
|
GreaterThanOrEqual,
|
||||||
Comparison,
|
Comparison,
|
||||||
FieldAccess,
|
|
||||||
IOPrint,
|
IOPrint,
|
||||||
IOPrintLn,
|
IOPrintLn,
|
||||||
IOGetLine,
|
IOGetLine,
|
||||||
@ -59,7 +58,6 @@ impl Builtin {
|
|||||||
GreaterThan => ty!(Nat -> Nat -> Bool),
|
GreaterThan => ty!(Nat -> Nat -> Bool),
|
||||||
GreaterThanOrEqual => ty!(Nat -> Nat -> Bool),
|
GreaterThanOrEqual => ty!(Nat -> Nat -> Bool),
|
||||||
Comparison => ty!(Nat -> Nat -> Ordering),
|
Comparison => ty!(Nat -> Nat -> Ordering),
|
||||||
FieldAccess => ty!(Unit),
|
|
||||||
IOPrint => ty!(Unit),
|
IOPrint => ty!(Unit),
|
||||||
IOPrintLn => ty!(Unit),
|
IOPrintLn => ty!(Unit),
|
||||||
IOGetLine => ty!(StringT),
|
IOGetLine => ty!(StringT),
|
||||||
@ -120,7 +118,6 @@ impl FromStr for Builtin {
|
|||||||
"==" => Equality,
|
"==" => Equality,
|
||||||
"=" => Assignment,
|
"=" => Assignment,
|
||||||
"<=>" => Comparison,
|
"<=>" => Comparison,
|
||||||
"." => FieldAccess,
|
|
||||||
"print" => IOPrint,
|
"print" => IOPrint,
|
||||||
"println" => IOPrintLn,
|
"println" => IOPrintLn,
|
||||||
"getline" => IOGetLine,
|
"getline" => IOGetLine,
|
||||||
|
@ -394,14 +394,14 @@ impl Parser {
|
|||||||
let tok = self.token_handler.peek();
|
let tok = self.token_handler.peek();
|
||||||
let kind = match tok.get_kind() {
|
let kind = match tok.get_kind() {
|
||||||
AtSign => self.annotation().map(StatementKind::Declaration),
|
AtSign => self.annotation().map(StatementKind::Declaration),
|
||||||
Keyword(Type) => self.type_declaration().map(|decl| StatementKind::Declaration(decl)),
|
Keyword(Type) => self.type_declaration().map(StatementKind::Declaration),
|
||||||
Keyword(Func) => self.func_declaration().map(|func| StatementKind::Declaration(func)),
|
Keyword(Func) => self.func_declaration().map(StatementKind::Declaration),
|
||||||
Keyword(Let) => self.binding_declaration().map(StatementKind::Declaration),
|
Keyword(Let) => self.binding_declaration().map(StatementKind::Declaration),
|
||||||
Keyword(Interface) => self.interface_declaration().map(StatementKind::Declaration),
|
Keyword(Interface) => self.interface_declaration().map(StatementKind::Declaration),
|
||||||
Keyword(Impl) => self.impl_declaration().map(StatementKind::Declaration),
|
Keyword(Impl) => self.impl_declaration().map(StatementKind::Declaration),
|
||||||
Keyword(Import) => self.import_declaration().map(StatementKind::Import),
|
Keyword(Import) => self.import_declaration().map(StatementKind::Import),
|
||||||
Keyword(Module) => self.module_declaration().map(StatementKind::Module),
|
Keyword(Module) => self.module_declaration().map(StatementKind::Module),
|
||||||
_ => self.expression().map(|expr| StatementKind::Expression(expr)),
|
_ => self.expression().map(StatementKind::Expression),
|
||||||
}?;
|
}?;
|
||||||
let id = self.id_store.fresh();
|
let id = self.id_store.fresh();
|
||||||
Ok(Statement { kind, id, location: tok.location })
|
Ok(Statement { kind, id, location: tok.location })
|
||||||
@ -693,13 +693,8 @@ impl Parser {
|
|||||||
|
|
||||||
#[recursive_descent_method]
|
#[recursive_descent_method]
|
||||||
fn prefix_expr(&mut self) -> ParseResult<Expression> {
|
fn prefix_expr(&mut self) -> ParseResult<Expression> {
|
||||||
loop {
|
while let Semicolon | Newline = self.token_handler.peek_kind() {
|
||||||
match self.token_handler.peek_kind() {
|
self.token_handler.next();
|
||||||
Semicolon | Newline => {
|
|
||||||
self.token_handler.next();
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.token_handler.peek_kind() {
|
match self.token_handler.peek_kind() {
|
||||||
|
@ -142,7 +142,7 @@ impl<'a, 'b> Reducer<'a, 'b> {
|
|||||||
e => return Expression::ReductionError(format!("Bad symbol for NamedStruct: {:?}", e)),
|
e => return Expression::ReductionError(format!("Bad symbol for NamedStruct: {:?}", e)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let field_order = compute_field_orderings(&self.type_context, &type_id, tag).unwrap();
|
let field_order = compute_field_orderings(self.type_context, &type_id, tag).unwrap();
|
||||||
|
|
||||||
let mut field_map = HashMap::new();
|
let mut field_map = HashMap::new();
|
||||||
for (name, expr) in fields.iter() {
|
for (name, expr) in fields.iter() {
|
||||||
@ -310,6 +310,7 @@ impl<'a, 'b> Reducer<'a, 'b> {
|
|||||||
let def_id = symbol.def_id();
|
let def_id = symbol.def_id();
|
||||||
|
|
||||||
match symbol.spec() {
|
match symbol.spec() {
|
||||||
|
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())),
|
||||||
|
@ -12,6 +12,7 @@ use crate::{
|
|||||||
Declaration, ItemId, ModuleSpecifier, Statement, StatementKind, TypeBody, TypeSingletonName, Variant,
|
Declaration, ItemId, ModuleSpecifier, Statement, StatementKind, TypeBody, TypeSingletonName, Variant,
|
||||||
VariantKind,
|
VariantKind,
|
||||||
},
|
},
|
||||||
|
builtin::Builtin,
|
||||||
tokenizing::Location,
|
tokenizing::Location,
|
||||||
type_inference::{self, PendingType, TypeBuilder, TypeContext, TypeId, VariantBuilder},
|
type_inference::{self, PendingType, TypeBuilder, TypeContext, TypeId, VariantBuilder},
|
||||||
};
|
};
|
||||||
@ -42,7 +43,6 @@ impl Fqsn {
|
|||||||
Fqsn { scopes: v }
|
Fqsn { scopes: v }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
fn from_strs(strs: &[&str]) -> Fqsn {
|
fn from_strs(strs: &[&str]) -> Fqsn {
|
||||||
let mut scopes = vec![];
|
let mut scopes = vec![];
|
||||||
for s in strs {
|
for s in strs {
|
||||||
@ -152,7 +152,7 @@ pub struct SymbolTable {
|
|||||||
|
|
||||||
impl SymbolTable {
|
impl SymbolTable {
|
||||||
pub fn new() -> SymbolTable {
|
pub fn new() -> SymbolTable {
|
||||||
SymbolTable {
|
let mut table = SymbolTable {
|
||||||
def_id_store: IdStore::new(),
|
def_id_store: IdStore::new(),
|
||||||
symbol_trie: SymbolTrie::new(),
|
symbol_trie: SymbolTrie::new(),
|
||||||
fq_names: NameTable::new(),
|
fq_names: NameTable::new(),
|
||||||
@ -161,7 +161,10 @@ impl SymbolTable {
|
|||||||
fqsn_to_symbol: HashMap::new(),
|
fqsn_to_symbol: HashMap::new(),
|
||||||
id_to_symbol: HashMap::new(),
|
id_to_symbol: HashMap::new(),
|
||||||
def_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
|
/// 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.id_to_symbol.insert(*id, symbol.clone());
|
||||||
self.def_to_symbol.insert(def_id, symbol);
|
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> {
|
struct SymbolTableRunner<'a> {
|
||||||
@ -258,6 +279,7 @@ impl fmt::Display for Symbol {
|
|||||||
//function parameters (even though they are currently assigned).
|
//function parameters (even though they are currently assigned).
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum SymbolSpec {
|
pub enum SymbolSpec {
|
||||||
|
Builtin(Builtin),
|
||||||
Func,
|
Func,
|
||||||
DataConstructor { tag: u32, type_id: TypeId },
|
DataConstructor { tag: u32, type_id: TypeId },
|
||||||
RecordConstructor { tag: u32, members: HashMap<Rc<String>, TypeId>, type_id: TypeId },
|
RecordConstructor { tag: u32, members: HashMap<Rc<String>, TypeId>, type_id: TypeId },
|
||||||
@ -270,6 +292,7 @@ impl fmt::Display for SymbolSpec {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use self::SymbolSpec::*;
|
use self::SymbolSpec::*;
|
||||||
match self {
|
match self {
|
||||||
|
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, .. } =>
|
||||||
|
@ -276,16 +276,13 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
let evaled_args = evaled_args?;
|
let evaled_args = evaled_args?;
|
||||||
|
|
||||||
Ok(match (builtin, evaled_args.as_slice()) {
|
Ok(match (builtin, evaled_args.as_slice()) {
|
||||||
(FieldAccess, /*&[Node::PrimObject { .. }]*/ _) => {
|
|
||||||
return Err("Field access unimplemented".into());
|
|
||||||
}
|
|
||||||
/* builtin functions */
|
/* builtin functions */
|
||||||
(IOPrint, &[ref anything]) => {
|
(IOPrint, &[ref anything]) => {
|
||||||
print!("{}", anything.to_repl(self.type_context));
|
print!("{}", anything.to_repl(self.type_context));
|
||||||
Primitive::Tuple(vec![])
|
Primitive::Tuple(vec![])
|
||||||
}
|
}
|
||||||
(IOPrintLn, &[ref anything]) => {
|
(IOPrintLn, &[ref anything]) => {
|
||||||
print!("{}", anything.to_repl(self.type_context));
|
println!("{}", anything.to_repl(self.type_context));
|
||||||
Primitive::Tuple(vec![])
|
Primitive::Tuple(vec![])
|
||||||
}
|
}
|
||||||
(IOGetLine, &[]) => {
|
(IOGetLine, &[]) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user