From 0e9b3229e9bd7b477c9271267ed2917617838c54 Mon Sep 17 00:00:00 2001 From: greg Date: Sat, 23 Feb 2019 03:33:56 -0800 Subject: [PATCH] Refactor Arrow; add general handle_apply --- schala-lang/language/src/typechecking.rs | 42 ++++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index 2ce70f2..4394366 100644 --- a/schala-lang/language/src/typechecking.rs +++ b/schala-lang/language/src/typechecking.rs @@ -49,7 +49,10 @@ impl TypeError { pub enum Type { Const(TypeConst), Var(TypeVar), - Arrow(Box, Box), + Arrow { + params: Vec, + ret: Box + }, Compound { ty_name: String, args:Vec @@ -82,8 +85,8 @@ impl EqUnifyValue for TypeConst { } macro_rules! ty { ($type_name:ident) => { Type::Const(TypeConst::$type_name) }; - ($t1:ident -> $t2:ident) => { Type::Arrow(Box::new(ty!($t1)), Box::new(ty!($t2))) }; - ($t1:ident -> $t2:ident -> $t3:ident) => { Type::Arrow(Box::new(ty!($t1)), Box::new(ty!($t2 -> $t3))) }; + ($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) } }; } //TODO find a better way to capture the to/from string logic @@ -281,13 +284,13 @@ impl<'a> TypeContext<'a> { } fn prefix(&mut self, op: &PrefixOp, expr: &Expression) -> InferResult { - let f = match op.get_type() { + let tf = match op.get_type() { Ok(ty) => ty, Err(e) => return TypeError::new(e) }; - let x = self.expr(expr)?; - self.handle_apply(f, x) + let tx = self.expr(expr)?; + self.handle_apply(tf, vec![tx]) } fn binexp(&mut self, op: &BinOp, lhs: &Expression, rhs: &Expression) -> InferResult { @@ -297,19 +300,9 @@ impl<'a> TypeContext<'a> { }; let t_lhs = self.expr(lhs)?; - let t_curried = self.handle_apply(tf, t_lhs)?; - let t_rhs = self.expr(rhs)?; - self.handle_apply(t_curried, t_rhs) - } + let t_rhs = self.expr(rhs)?; //TODO is this order a problem? not sure - fn handle_apply(&mut self, tf: Type, tx: Type) -> InferResult { - Ok(match tf { - Type::Arrow(box ref t1, box ref t2) => { - let _ = self.unify(t1.clone(), tx)?; - t2.clone() - }, - _ => return TypeError::new(format!("Not a function")) - }) + self.handle_apply(tf, vec![t_lhs, t_rhs]) } fn if_expr(&mut self, discriminator: &Discriminator, body: &IfExpressionBody) -> InferResult { @@ -352,6 +345,19 @@ impl<'a> TypeContext<'a> { Ok(ty!(UserDefined)) } + fn handle_apply(&mut self, tf: Type, args: Vec) -> InferResult { + Ok(match tf { + Type::Arrow { ref params, ret: box ref t_ret } if params.len() == args.len() => { + for (t_param, t_arg) in params.iter().zip(args.iter()) { + let _ = self.unify(t_param.clone(), t_arg.clone())?; //TODO I think this needs to reference a sub-scope + } + t_ret.clone() + }, + Type::Arrow { .. } => return TypeError::new("Wrong length"), + _ => return TypeError::new(format!("Not a function")) + }) + } + fn block(&mut self, block: &Block) -> InferResult { let mut output = ty!(Unit); for s in block.iter() {