Various cleanup of comments, stringifying types
This commit is contained in:
parent
5bac01cf20
commit
e501f4bd10
@ -1,8 +1,5 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
//THINGS TODO
|
use std::fmt::Write;
|
||||||
// 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 ena::unify::{UnifyKey, InPlaceUnificationTable, UnificationTable, EqUnifyValue};
|
use ena::unify::{UnifyKey, InPlaceUnificationTable, UnificationTable, EqUnifyValue};
|
||||||
|
|
||||||
@ -10,9 +7,6 @@ use crate::ast::*;
|
|||||||
use crate::util::ScopeStack;
|
use crate::util::ScopeStack;
|
||||||
use crate::builtin::{PrefixOp, BinOp};
|
use crate::builtin::{PrefixOp, BinOp};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::hash::Hash;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct TypeData {
|
pub struct TypeData {
|
||||||
@ -40,7 +34,7 @@ type InferResult<T> = Result<T, TypeError>;
|
|||||||
pub struct TypeError { pub msg: String }
|
pub struct TypeError { pub msg: String }
|
||||||
|
|
||||||
impl TypeError {
|
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() })
|
Err(TypeError { msg: msg.into() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,28 +75,56 @@ pub enum TypeConst {
|
|||||||
UserDefined
|
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 { }
|
impl EqUnifyValue for TypeConst { }
|
||||||
|
|
||||||
macro_rules! ty {
|
macro_rules! ty {
|
||||||
($type_name:ident) => { Type::Const(TypeConst::$type_name) };
|
($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) => { 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) } };
|
($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
|
//TODO find a better way to capture the to/from string logic
|
||||||
impl Type {
|
impl Type {
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
use self::Type::*;
|
use self::Type::*;
|
||||||
use self::TypeConst::*;
|
|
||||||
match self {
|
match self {
|
||||||
Const(Unit) => format!("()"),
|
Const(c) => c.to_string(),
|
||||||
Const(Nat) => format!("Nat"),
|
Var(v) => format!("t_{}", v.0),
|
||||||
Const(Int) => format!("Int"),
|
Arrow { params, box ref ret } => {
|
||||||
Const(Float) => format!("Float"),
|
if params.len() == 0 {
|
||||||
Const(StringT) => format!("String"),
|
format!("-> {}", ret.to_string())
|
||||||
Const(Bool) => format!("Bool"),
|
} else {
|
||||||
Const(Ordering) => format!("Ordering"),
|
let mut buf = String::new();
|
||||||
_ => format!("UNKNOWN TYPE"),
|
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> {
|
pub fn typecheck(&mut self, ast: &AST) -> Result<Type, TypeError> {
|
||||||
let mut returned_type = Type::Const(TypeConst::Unit);
|
let mut returned_type = Type::Const(TypeConst::Unit);
|
||||||
for statement in ast.0.iter() {
|
for statement in ast.0.iter() {
|
||||||
@ -334,11 +359,12 @@ impl<'a> TypeContext<'a> {
|
|||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
let argument_types = argument_types?;
|
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);
|
Ok(ty!(argument_types, ret_type))
|
||||||
|
|
||||||
//TODO finish this
|
|
||||||
Ok(ty!(UserDefined))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, f: &Expression, args: &Vec<Meta<Expression>>) -> InferResult<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> {
|
fn unify(&mut self, t1: Type, t2: Type) -> InferResult<Type> {
|
||||||
use self::Type::*;
|
use self::Type::*;
|
||||||
use std::collections::hash_map::Entry;
|
|
||||||
|
|
||||||
match (t1, t2) {
|
match (t1, t2) {
|
||||||
(Const(ref c1), Const(ref c2)) if c1 == c2 => Ok(Const(c1.clone())), //choice of c1 is arbitrary I *think*
|
(Const(ref c1), Const(ref c2)) if c1 == c2 => Ok(Const(c1.clone())), //choice of c1 is arbitrary I *think*
|
||||||
|
Loading…
Reference in New Issue
Block a user