Various cleanup of comments, stringifying types

This commit is contained in:
greg 2019-02-23 09:58:44 -08:00
parent 5bac01cf20
commit e501f4bd10
1 changed files with 47 additions and 22 deletions

View File

@ -1,8 +1,5 @@
use std::rc::Rc;
//THINGS TODO
// look at the haskell compiler, see where in its flow the typechecking happens
// -nope, ghc deliberately does typechecking before desugaring to core
// cf. a history of haskell, peyton-jones
use std::fmt::Write;
use ena::unify::{UnifyKey, InPlaceUnificationTable, UnificationTable, EqUnifyValue};
@ -10,9 +7,6 @@ use crate::ast::*;
use crate::util::ScopeStack;
use crate::builtin::{PrefixOp, BinOp};
use std::collections::HashMap;
use std::hash::Hash;
#[derive(Debug, Clone, PartialEq)]
pub struct TypeData {
@ -40,7 +34,7 @@ type InferResult<T> = Result<T, TypeError>;
pub struct TypeError { pub msg: String }
impl TypeError {
fn new<A, T>(msg: T) -> InferResult<A> where T: Into<String> { //TODO make these kinds of error-producing functions CoW-ready
fn new<A, T>(msg: T) -> InferResult<A> where T: Into<String> {
Err(TypeError { msg: msg.into() })
}
}
@ -81,28 +75,56 @@ pub enum TypeConst {
UserDefined
}
impl TypeConst {
pub fn to_string(&self) -> String {
use self::TypeConst::*;
match self {
Unit => format!("()"),
Nat => format!("Nat"),
Int => format!("Int"),
Float => format!("Float"),
StringT => format!("String"),
Bool => format!("Bool"),
Ordering => format!("Ordering"),
_ => format!("UNKNOWN TYPE"),
}
}
}
impl EqUnifyValue for TypeConst { }
macro_rules! ty {
($type_name:ident) => { Type::Const(TypeConst::$type_name) };
($t1:ident -> $t2:ident) => { Type::Arrow { params: vec![ty!($t1)], ret: box ty!($t2) } };
($t1:ident -> $t2:ident -> $t3:ident) => { Type::Arrow { params: vec![ty!($t1), ty!($t2)], ret: box ty!($t3) } };
($type_list:ident, $ret_type:ident) => {
Type::Arrow {
params: $type_list,
ret: box $ret_type,
}
}
}
//TODO find a better way to capture the to/from string logic
impl Type {
pub fn to_string(&self) -> String {
use self::Type::*;
use self::TypeConst::*;
match self {
Const(Unit) => format!("()"),
Const(Nat) => format!("Nat"),
Const(Int) => format!("Int"),
Const(Float) => format!("Float"),
Const(StringT) => format!("String"),
Const(Bool) => format!("Bool"),
Const(Ordering) => format!("Ordering"),
_ => format!("UNKNOWN TYPE"),
Const(c) => c.to_string(),
Var(v) => format!("t_{}", v.0),
Arrow { params, box ref ret } => {
if params.len() == 0 {
format!("-> {}", ret.to_string())
} else {
let mut buf = String::new();
for p in params.iter() {
write!(buf, "{} -> ", p.to_string());
}
write!(buf, "{}", ret.to_string());
buf
}
},
Compound { .. } => format!("<some compound type>")
}
}
@ -228,6 +250,9 @@ impl<'a> TypeContext<'a> {
}
/// `typecheck` is the entry into the type-inference system, accepting an AST as an argument
/// Following the example of GHC, the compiler deliberately does typechecking before de-sugaring
/// the AST to ReducedAST
pub fn typecheck(&mut self, ast: &AST) -> Result<Type, TypeError> {
let mut returned_type = Type::Const(TypeConst::Unit);
for statement in ast.0.iter() {
@ -334,11 +359,12 @@ impl<'a> TypeContext<'a> {
}
}).collect();
let argument_types = argument_types?;
let ret_type = match type_anno.as_ref() {
Some(anno) => self.get_type_from_name(anno)?,
None => Type::Var(self.fresh_type_variable())
};
println!("ARGUMENT TYPES: {:?}", argument_types);
//TODO finish this
Ok(ty!(UserDefined))
Ok(ty!(argument_types, ret_type))
}
fn call(&mut self, f: &Expression, args: &Vec<Meta<Expression>>) -> InferResult<Type> {
@ -379,7 +405,6 @@ impl<'a> TypeContext<'a> {
fn unify(&mut self, t1: Type, t2: Type) -> InferResult<Type> {
use self::Type::*;
use std::collections::hash_map::Entry;
match (t1, t2) {
(Const(ref c1), Const(ref c2)) if c1 == c2 => Ok(Const(c1.clone())), //choice of c1 is arbitrary I *think*