A lot more type work
This commit is contained in:
parent
30a54d997c
commit
996f75e15c
@ -406,9 +406,9 @@ pub enum Declaration {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Signature {
|
pub struct Signature {
|
||||||
name: Rc<String>,
|
pub name: Rc<String>,
|
||||||
params: Vec<FormalParam>,
|
pub params: Vec<FormalParam>,
|
||||||
type_anno: Option<TypeName>,
|
pub type_anno: Option<TypeName>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use schala_lang::parsing::{AST, Statement, Declaration, Expression, ExpressionType, Operation, TypeName};
|
use schala_lang::parsing::{AST, Statement, Declaration, Signature, Expression, ExpressionType, Operation, TypeName};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
struct PathSpecifier {
|
struct PathSpecifier {
|
||||||
@ -11,12 +11,16 @@ struct PathSpecifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeContext {
|
pub struct TypeContext {
|
||||||
symbol_table: HashMap<PathSpecifier, Expression>,
|
symbol_table: HashMap<PathSpecifier, TypeVariable>,
|
||||||
|
existential_type_label_count: u64
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeContext {
|
impl TypeContext {
|
||||||
pub fn new() -> TypeContext {
|
pub fn new() -> TypeContext {
|
||||||
TypeContext { symbol_table: HashMap::new() }
|
TypeContext {
|
||||||
|
symbol_table: HashMap::new(),
|
||||||
|
existential_type_label_count: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn add_symbols(&mut self, ast: &AST) {
|
pub fn add_symbols(&mut self, ast: &AST) {
|
||||||
use self::Declaration::*;
|
use self::Declaration::*;
|
||||||
@ -36,11 +40,20 @@ impl TypeContext {
|
|||||||
kind: "binding",
|
kind: "binding",
|
||||||
constant: *constant
|
constant: *constant
|
||||||
};
|
};
|
||||||
let binding_contents = (*expr).clone();
|
let binding_contents = expr.1.as_ref()
|
||||||
|
.map(|ty| self.from_anno(ty))
|
||||||
|
.unwrap_or_else(|| { self.get_existential_type() });
|
||||||
self.symbol_table.insert(spec, binding_contents);
|
self.symbol_table.insert(spec, binding_contents);
|
||||||
},
|
},
|
||||||
FuncDecl(ref signature, ref type_anno) => {
|
FuncDecl(ref signature, _) => {
|
||||||
|
let spec = PathSpecifier {
|
||||||
|
name: signature.name.clone(),
|
||||||
|
kind: "binding",
|
||||||
|
constant: true
|
||||||
|
};
|
||||||
|
|
||||||
|
let func_type = self.from_signature(signature);
|
||||||
|
self.symbol_table.insert(spec, func_type);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,11 +63,55 @@ impl TypeContext {
|
|||||||
fn lookup(&mut self, binding: &Rc<String>) -> Option<TypeVariable> {
|
fn lookup(&mut self, binding: &Rc<String>) -> Option<TypeVariable> {
|
||||||
use self::TypeVariable::*;
|
use self::TypeVariable::*;
|
||||||
use self::UVar::*;
|
use self::UVar::*;
|
||||||
Some(Univ(Function(Box::new(Univ(Integer)), Box::new(Univ(Boolean)))))
|
|
||||||
|
let key = PathSpecifier {
|
||||||
|
name: binding.clone(),
|
||||||
|
kind: "binding",
|
||||||
|
constant: true
|
||||||
|
};
|
||||||
|
|
||||||
|
self.symbol_table.get(&key).map(|x| x.clone())
|
||||||
}
|
}
|
||||||
pub fn debug_symbol_table(&self) -> String {
|
pub fn debug_symbol_table(&self) -> String {
|
||||||
format!("Symbol table:\n {:?}", self.symbol_table)
|
format!("Symbol table:\n {:?}", self.symbol_table)
|
||||||
}
|
}
|
||||||
|
fn get_existential_type(&mut self) -> TypeVariable {
|
||||||
|
let ret = TypeVariable::Exist(self.existential_type_label_count);
|
||||||
|
self.existential_type_label_count += 1;
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_anno(&mut self, anno: &TypeName) -> TypeVariable {
|
||||||
|
use self::TypeVariable::*;
|
||||||
|
use self::UVar::*;
|
||||||
|
|
||||||
|
match anno {
|
||||||
|
&TypeName::Singleton { ref name, .. } => {
|
||||||
|
match name.as_ref().as_ref() {
|
||||||
|
"Int" => Univ(Integer),
|
||||||
|
"Bool" => Univ(Boolean),
|
||||||
|
_ => self.get_existential_type()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Univ(Bottom),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_signature(&mut self, sig: &Signature) -> TypeVariable {
|
||||||
|
use self::TypeVariable::Univ;
|
||||||
|
use self::UVar::{Unit, Function};
|
||||||
|
let return_type = sig.type_anno.as_ref().map(|anno| self.from_anno(&anno)).unwrap_or_else(|| { self.get_existential_type() });
|
||||||
|
if sig.params.len() == 0 {
|
||||||
|
Univ(Function(Box::new(Univ(Unit)), Box::new(return_type)))
|
||||||
|
} else {
|
||||||
|
let mut output_type = return_type;
|
||||||
|
for p in sig.params.iter() {
|
||||||
|
let p_type = p.1.as_ref().map(|anno| self.from_anno(anno)).unwrap_or_else(|| { self.get_existential_type() });
|
||||||
|
output_type = Univ(Function(Box::new(p_type), Box::new(output_type)));
|
||||||
|
}
|
||||||
|
output_type
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -72,24 +129,6 @@ pub enum UVar {
|
|||||||
Bottom,
|
Bottom,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeVariable {
|
|
||||||
fn from_anno(anno: &TypeName) -> TypeVariable {
|
|
||||||
use self::TypeVariable::*;
|
|
||||||
use self::UVar::*;
|
|
||||||
|
|
||||||
match anno {
|
|
||||||
&TypeName::Singleton { ref name, .. } => {
|
|
||||||
match name.as_ref().as_ref() {
|
|
||||||
"Int" => Univ(Integer),
|
|
||||||
"Bool" => Univ(Boolean),
|
|
||||||
_ => Univ(Bottom),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => Univ(Bottom),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type TypeCheckResult = Result<TypeVariable, String>;
|
type TypeCheckResult = Result<TypeVariable, String>;
|
||||||
|
|
||||||
// from Niko's talk
|
// from Niko's talk
|
||||||
@ -132,7 +171,7 @@ impl TypeContext {
|
|||||||
Ok(match (&expr.0, &expr.1) {
|
Ok(match (&expr.0, &expr.1) {
|
||||||
(ref _t, &Some(ref anno)) => {
|
(ref _t, &Some(ref anno)) => {
|
||||||
//TODO make this better,
|
//TODO make this better,
|
||||||
TypeVariable::from_anno(anno)
|
self.from_anno(anno)
|
||||||
},
|
},
|
||||||
(&IntLiteral(_), _) => Univ(UVar::Integer),
|
(&IntLiteral(_), _) => Univ(UVar::Integer),
|
||||||
(&BoolLiteral(_), _) => Univ(UVar::Boolean),
|
(&BoolLiteral(_), _) => Univ(UVar::Boolean),
|
||||||
|
Loading…
Reference in New Issue
Block a user