Some more type work
This commit is contained in:
parent
5e1799268d
commit
35da1748f0
@ -80,12 +80,10 @@ impl PrefixOp {
|
|||||||
pub fn is_prefix(op: &str) -> bool {
|
pub fn is_prefix(op: &str) -> bool {
|
||||||
PREFIX_OPS.get(op).is_some()
|
PREFIX_OPS.get(op).is_some()
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
pub fn get_type(&self) -> Result<Type, String> {
|
pub fn get_type(&self) -> Result<Type, String> {
|
||||||
let s = self.sigil.as_str();
|
let s = self.sigil.as_str();
|
||||||
PREFIX_OPS.get(s).map(|x| x.0.clone()).ok_or(format!("Prefix op {} not found", s))
|
PREFIX_OPS.get(s).map(|x| x.0.clone()).ok_or(format!("Prefix op {} not found", s))
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO make this macro exportable?
|
//TODO make this macro exportable?
|
||||||
@ -98,8 +96,8 @@ macro_rules! mk_type {
|
|||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref PREFIX_OPS: HashMap<&'static str, (Type, ())> =
|
static ref PREFIX_OPS: HashMap<&'static str, (Type, ())> =
|
||||||
hashmap! {
|
hashmap! {
|
||||||
"+" => (mk_type!(Int -> Int), ()),
|
"+" => (mk_type!(Nat -> Int), ()),
|
||||||
"-" => (mk_type!(Int -> Int), ()),
|
"-" => (mk_type!(Nat -> Int), ()),
|
||||||
"!" => (mk_type!(Bool -> Bool), ()),
|
"!" => (mk_type!(Bool -> Bool), ()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
use std::rc::Rc;
|
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 crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::util::ScopeStack;
|
use crate::util::ScopeStack;
|
||||||
|
use crate::builtin::PrefixOp;
|
||||||
|
|
||||||
pub type TypeName = Rc<String>;
|
pub type TypeName = Rc<String>;
|
||||||
|
|
||||||
@ -218,10 +223,32 @@ impl<'a> TypeContext<'a> {
|
|||||||
BoolLiteral(_) => Type::Const(TypeConst::Bool),
|
BoolLiteral(_) => Type::Const(TypeConst::Bool),
|
||||||
FloatLiteral(_) => Type::Const(TypeConst::Float),
|
FloatLiteral(_) => Type::Const(TypeConst::Float),
|
||||||
StringLiteral(_) => Type::Const(TypeConst::StringT),
|
StringLiteral(_) => Type::Const(TypeConst::StringT),
|
||||||
|
PrefixExp(op, expr) => self.typecheck_prefix(op, expr.node())?,
|
||||||
|
IfExpression { discriminator, body } => self.typecheck_if_expr(discriminator, body)?,
|
||||||
_ => Type::Const(TypeConst::Unit)
|
_ => Type::Const(TypeConst::Unit)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO get rid of 'typecheck_' on all these methods - too wordy, already in typecontext
|
||||||
|
fn typecheck_prefix(&mut self, op: &PrefixOp, expr: &Expression) -> InferResult<Type> {
|
||||||
|
let f = match op.get_type() {
|
||||||
|
Ok(ty) => ty,
|
||||||
|
Err(e) => return TypeError::new("Couldn't find a type for this prefix op")
|
||||||
|
};
|
||||||
|
|
||||||
|
let x = self.typecheck_expr(expr)?;
|
||||||
|
self.handle_apply(f, x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_apply(&mut self, f: Type, x: Type) -> InferResult<Type> {
|
||||||
|
Ok(Type::Const(TypeConst::Unit))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn typecheck_if_expr(&mut self, discriminator: &Discriminator, body: &IfExpressionBody) -> InferResult<Type> {
|
||||||
|
//only handle simple case for now
|
||||||
|
|
||||||
|
Ok(Type::Const(TypeConst::Unit))
|
||||||
|
}
|
||||||
|
|
||||||
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::TypeConst::*;
|
use self::Type::*; use self::TypeConst::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user