Variable binding insertion infrastructure

This commit is contained in:
greg 2018-05-21 01:19:50 -07:00
parent 4db3595d7c
commit bb29df4a73

View File

@ -130,9 +130,17 @@ impl TypeEnvironment {
self.map.get(name).map(|x| x.clone()) self.map.get(name).map(|x| x.clone())
} }
fn insert(&mut self, name: &TypeName, ty: PolyType) { fn extend(&mut self, name: &TypeName, ty: PolyType) {
self.map.insert(name.clone(), ty); self.map.insert(name.clone(), ty);
} }
fn free_vars(&self) -> HashSet<TypeName> {
let mut free = HashSet::new();
for (_, ptype) in self.map.iter() {
free = free.union(&ptype.free_vars()).cloned().collect()
}
free
}
} }
pub struct TypeContext { pub struct TypeContext {
@ -156,7 +164,7 @@ impl TypeContext {
} }
struct Infer<'a> { struct Infer<'a> {
env: &'a TypeEnvironment env: &'a mut TypeEnvironment
} }
#[derive(Debug)] #[derive(Debug)]
@ -170,13 +178,21 @@ enum InferError {
type InferResult<T> = Result<T, InferError>; type InferResult<T> = Result<T, InferError>;
impl<'a> Infer<'a> { impl<'a> Infer<'a> {
fn generalize(&mut self, ty: MonoType) -> PolyType {
let free_mtype = ty.free_vars();
let free_env = self.env.free_vars();
let diff: HashSet<TypeName> = free_mtype.difference(&free_env).cloned().collect();
PolyType(diff, ty)
}
fn block(&mut self, block: &Vec<parsing::Statement>) -> InferResult<MonoType> { fn block(&mut self, block: &Vec<parsing::Statement>) -> InferResult<MonoType> {
let mut ret = MonoType::Const(TypeConst::Unit); let mut ret = MonoType::Const(TypeConst::Unit);
for s in block { for s in block {
ret = match s { ret = match s {
parsing::Statement::ExpressionStatement(expr) => self.anno_expression(expr)?, parsing::Statement::ExpressionStatement(expr) => self.infer_expression(expr)?,
parsing::Statement::Declaration(decl) => { parsing::Statement::Declaration(decl) => {
self.declaration(decl)?; self.infer_declaration(decl)?;
MonoType::Const(TypeConst::Unit) MonoType::Const(TypeConst::Unit)
} }
} }
@ -184,19 +200,20 @@ impl<'a> Infer<'a> {
Ok(ret) Ok(ret)
} }
fn declaration(&mut self, decl: &parsing::Declaration) -> InferResult<MonoType> { fn infer_declaration(&mut self, decl: &parsing::Declaration) -> InferResult<MonoType> {
use parsing::Declaration::*; use parsing::Declaration::*;
match decl { match decl {
Binding { name, expr, .. } => { Binding { name, expr, .. } => {
let ty = self.anno_expression(&expr)?; let tau: MonoType = self.infer_expression(&expr)?;
return Err(InferError::Custom(format!("This decl not yet supported"))) let sigma = self.generalize(tau);
self.env.extend(name, sigma);
}, },
_ => return Err(InferError::Custom(format!("This decl not yet supported"))) _ => return Err(InferError::Custom(format!("This decl not yet supported")))
} }
Ok(MonoType::Const(TypeConst::Unit)) Ok(MonoType::Const(TypeConst::Unit))
} }
fn anno_expression(&mut self, expr: &parsing::Expression) -> InferResult<MonoType> { fn infer_expression(&mut self, expr: &parsing::Expression) -> InferResult<MonoType> {
match expr { match expr {
parsing::Expression(e, Some(anno)) => { parsing::Expression(e, Some(anno)) => {
return Err(InferError::Custom(format!("Annotations not done yet"))) return Err(InferError::Custom(format!("Annotations not done yet")))
@ -206,11 +223,11 @@ impl<'a> Infer<'a> {
self.unify(ty, anno_ty) self.unify(ty, anno_ty)
*/ */
}, },
parsing::Expression(e, None) => self.expression(e) parsing::Expression(e, None) => self.infer_expression_type(e)
} }
} }
fn expression(&mut self, expr: &parsing::ExpressionType) -> InferResult<MonoType> { fn infer_expression_type(&mut self, expr: &parsing::ExpressionType) -> InferResult<MonoType> {
use self::parsing::ExpressionType::*; use self::parsing::ExpressionType::*;
Ok(match expr { Ok(match expr {
NatLiteral(_) => MonoType::Const(TypeConst::Nat), NatLiteral(_) => MonoType::Const(TypeConst::Nat),