2018-05-20 20:36:57 -07:00
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::rc::Rc;
|
|
|
|
use std::fmt;
|
|
|
|
use std::fmt::Write;
|
|
|
|
|
2019-01-07 13:00:37 -08:00
|
|
|
use crate::ast;
|
2019-01-20 00:22:35 -08:00
|
|
|
use crate::ast::Signature;
|
2019-01-07 13:00:37 -08:00
|
|
|
use crate::typechecking::TypeName;
|
2018-05-20 20:36:57 -07:00
|
|
|
|
|
|
|
//cf. p. 150 or so of Language Implementation Patterns
|
|
|
|
pub struct SymbolTable {
|
|
|
|
pub values: HashMap<Rc<String>, Symbol> //TODO this will eventually have real type information
|
|
|
|
}
|
|
|
|
|
2018-08-05 18:01:42 -07:00
|
|
|
//TODO add various types of lookups here, maybe multiple hash tables internally? also make values
|
|
|
|
//non-public
|
2018-05-20 20:36:57 -07:00
|
|
|
impl SymbolTable {
|
|
|
|
pub fn new() -> SymbolTable {
|
|
|
|
SymbolTable { values: HashMap::new() }
|
|
|
|
}
|
2018-08-05 18:19:48 -07:00
|
|
|
|
|
|
|
pub fn lookup_by_name(&self, name: &Rc<String>) -> Option<&Symbol> {
|
|
|
|
self.values.get(name)
|
|
|
|
}
|
2018-05-20 20:36:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Symbol {
|
|
|
|
pub name: Rc<String>,
|
|
|
|
pub spec: SymbolSpec,
|
|
|
|
}
|
|
|
|
|
2018-06-03 23:04:07 -07:00
|
|
|
impl fmt::Display for Symbol {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "<Name: {}, Spec: {}>", self.name, self.spec)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-20 20:36:57 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum SymbolSpec {
|
2018-06-03 02:39:49 -07:00
|
|
|
Func(Vec<TypeName>),
|
2018-05-30 23:54:24 -07:00
|
|
|
DataConstructor {
|
2018-08-05 13:59:13 -07:00
|
|
|
index: usize,
|
2018-05-30 23:54:24 -07:00
|
|
|
type_name: Rc<String>,
|
|
|
|
type_args: Vec<Rc<String>>,
|
|
|
|
},
|
2018-05-20 20:36:57 -07:00
|
|
|
}
|
|
|
|
|
2018-06-03 23:04:07 -07:00
|
|
|
impl fmt::Display for SymbolSpec {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
use self::SymbolSpec::*;
|
|
|
|
match self {
|
|
|
|
Func(type_names) => write!(f, "Func({:?})", type_names),
|
2018-10-15 19:37:02 -07:00
|
|
|
DataConstructor { index, type_name, type_args } => write!(f, "DataConstructor(idx: {})({:?} -> {})", index, type_args, type_name),
|
2018-06-03 23:04:07 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-20 20:36:57 -07:00
|
|
|
impl SymbolTable {
|
|
|
|
/* note: this adds names for *forward reference* but doesn't actually create any types. solve that problem
|
|
|
|
* later */
|
2018-06-04 19:25:40 -07:00
|
|
|
pub fn add_top_level_symbols(&mut self, ast: &ast::AST) -> Result<(), String> {
|
2018-10-18 13:27:09 -07:00
|
|
|
use self::ast::{Statement, TypeIdentifier, Variant, TypeSingletonName, TypeBody};
|
2018-06-04 19:25:40 -07:00
|
|
|
use self::ast::Declaration::*;
|
2018-05-20 20:36:57 -07:00
|
|
|
for statement in ast.0.iter() {
|
2019-01-04 22:58:25 -08:00
|
|
|
let statement = statement.node();
|
2018-05-20 20:36:57 -07:00
|
|
|
if let Statement::Declaration(decl) = statement {
|
|
|
|
match decl {
|
2019-01-20 00:22:35 -08:00
|
|
|
FuncSig(signature) | FuncDecl(signature, _) => self.add_function_signature(signature),
|
2018-08-14 23:07:00 -07:00
|
|
|
//TODO figure out why _params isn't being used here
|
|
|
|
TypeDecl { name: TypeSingletonName { name, params: _params}, body: TypeBody(variants), mutable: _mutable, } => {
|
2018-08-05 13:59:13 -07:00
|
|
|
for (index, var) in variants.iter().enumerate() {
|
2018-05-20 20:36:57 -07:00
|
|
|
match var {
|
|
|
|
Variant::UnitStruct(variant_name) => {
|
2018-05-30 23:54:24 -07:00
|
|
|
let spec = SymbolSpec::DataConstructor {
|
2018-08-05 13:59:13 -07:00
|
|
|
index,
|
2018-05-30 23:54:24 -07:00
|
|
|
type_name: name.clone(),
|
|
|
|
type_args: vec![],
|
|
|
|
};
|
2018-05-20 20:36:57 -07:00
|
|
|
self.values.insert(variant_name.clone(), Symbol { name: variant_name.clone(), spec });
|
|
|
|
},
|
2018-05-30 23:54:24 -07:00
|
|
|
Variant::TupleStruct(variant_name, tuple_members) => {
|
2018-06-04 19:04:51 -07:00
|
|
|
let type_args = tuple_members.iter().map(|type_name| match type_name {
|
2018-10-18 13:27:09 -07:00
|
|
|
TypeIdentifier::Singleton(TypeSingletonName { name, ..}) => name.clone(),
|
|
|
|
TypeIdentifier::Tuple(_) => unimplemented!(),
|
2018-06-04 19:04:51 -07:00
|
|
|
}).collect();
|
2018-08-05 13:59:13 -07:00
|
|
|
let spec = SymbolSpec::DataConstructor {
|
|
|
|
index,
|
2018-05-30 23:54:24 -07:00
|
|
|
type_name: name.clone(),
|
|
|
|
type_args
|
|
|
|
};
|
|
|
|
let symbol = Symbol { name: variant_name.clone(), spec };
|
|
|
|
self.values.insert(variant_name.clone(), symbol);
|
|
|
|
},
|
2018-05-20 20:36:57 -07:00
|
|
|
e => return Err(format!("{:?} not supported in typing yet", e)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
pub fn debug_symbol_table(&self) -> String {
|
|
|
|
let mut output = format!("Symbol table\n");
|
2018-06-03 23:04:07 -07:00
|
|
|
for (name, sym) in &self.values {
|
|
|
|
write!(output, "{} -> {}\n", name, sym).unwrap();
|
2018-05-20 20:36:57 -07:00
|
|
|
}
|
|
|
|
output
|
|
|
|
}
|
2019-01-20 00:22:35 -08:00
|
|
|
|
|
|
|
fn add_function_signature(&mut self, signature: &Signature) {
|
|
|
|
let mut local_type_context = LocalTypeContext::new();
|
|
|
|
let types = signature.params.iter().map(|param| match param {
|
|
|
|
(_, Some(type_identifier)) => Rc::new(format!("{:?}", type_identifier)),
|
|
|
|
(_, None) => local_type_context.new_universal_type()
|
|
|
|
}).collect();
|
|
|
|
let spec = SymbolSpec::Func(types);
|
|
|
|
self.values.insert(
|
|
|
|
signature.name.clone(),
|
|
|
|
Symbol { name: signature.name.clone(), spec }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct LocalTypeContext {
|
|
|
|
state: u8
|
|
|
|
}
|
|
|
|
impl LocalTypeContext {
|
|
|
|
fn new() -> LocalTypeContext {
|
|
|
|
LocalTypeContext { state: 0 }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn new_universal_type(&mut self) -> TypeName {
|
|
|
|
let n = self.state;
|
|
|
|
self.state += 1;
|
|
|
|
Rc::new(format!("{}", (('a' as u8) + n) as char))
|
|
|
|
}
|
2018-05-20 20:36:57 -07:00
|
|
|
}
|