Some more primitive types + binop-checking
This commit is contained in:
parent
22b4738726
commit
bb880d44fa
@ -85,7 +85,7 @@ impl ReplState {
|
|||||||
let opstr: &str = &op.0;
|
let opstr: &str = &op.0;
|
||||||
Ok(match (opstr, evaled_lhs, evaled_rhs) {
|
Ok(match (opstr, evaled_lhs, evaled_rhs) {
|
||||||
("+", UnsignedInt(l), UnsignedInt(r)) => UnsignedInt(l + r),
|
("+", UnsignedInt(l), UnsignedInt(r)) => UnsignedInt(l + r),
|
||||||
("+", Str(s1), Str(s2)) => Str(format!("{}{}", s1, s2)),
|
("++", Str(s1), Str(s2)) => Str(format!("{}{}", s1, s2)),
|
||||||
("-", UnsignedInt(l), UnsignedInt(r)) => UnsignedInt(l - r),
|
("-", UnsignedInt(l), UnsignedInt(r)) => UnsignedInt(l - r),
|
||||||
("*", UnsignedInt(l), UnsignedInt(r)) => UnsignedInt(l * r),
|
("*", UnsignedInt(l), UnsignedInt(r)) => UnsignedInt(l * r),
|
||||||
("/", UnsignedInt(l), UnsignedInt(r)) => UnsignedInt(l / r),
|
("/", UnsignedInt(l), UnsignedInt(r)) => UnsignedInt(l / r),
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
|
||||||
//SKOLEMIZATION - how you prevent an unassigned existential type variable from leaking!
|
//SKOLEMIZATION - how you prevent an unassigned existential type variable from leaking!
|
||||||
|
|
||||||
use schala_lang::parsing::{AST, Statement, Declaration, Signature, Expression, ExpressionType, Operation, Variant, TypeName};
|
use schala_lang::parsing::{AST, Statement, Declaration, Signature, Expression, ExpressionType, Operation, Variant, TypeName};
|
||||||
@ -329,18 +328,38 @@ impl TypeContext {
|
|||||||
|
|
||||||
Ok(match ex {
|
Ok(match ex {
|
||||||
&IntLiteral(_) => TConst(Integer),
|
&IntLiteral(_) => TConst(Integer),
|
||||||
|
&FloatLiteral(_) => TConst(Float),
|
||||||
|
&StringLiteral(_) => TConst(StringT),
|
||||||
&BoolLiteral(_) => TConst(Boolean),
|
&BoolLiteral(_) => TConst(Boolean),
|
||||||
&Value(ref name) => {
|
&Value(ref name) => {
|
||||||
self.lookup(name)
|
self.lookup(name)
|
||||||
.map(|entry| entry.ty)
|
.map(|entry| entry.ty)
|
||||||
.ok_or(format!("Couldn't find {}", name))?
|
.ok_or(format!("Couldn't find {}", name))?
|
||||||
},
|
},
|
||||||
|
&BinExp(ref op, ref lhs, ref rhs) => {
|
||||||
|
let t_lhs = self.infer(lhs)?;
|
||||||
|
match self.infer_op(op)? {
|
||||||
|
TFunc(t1, t2) => {
|
||||||
|
let _ = self.unify(t_lhs, *t1)?;
|
||||||
|
let t_rhs = self.infer(rhs)?;
|
||||||
|
let x = *t2;
|
||||||
|
match x {
|
||||||
|
TFunc(t3, t4) => {
|
||||||
|
let _ = self.unify(t_rhs, *t3)?;
|
||||||
|
*t4
|
||||||
|
},
|
||||||
|
_ => return Err(format!("Not a function type either")),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => return Err(format!("Op {:?} is not a function type", op)),
|
||||||
|
}
|
||||||
|
},
|
||||||
&Call { ref f, ref arguments } => {
|
&Call { ref f, ref arguments } => {
|
||||||
let tf = self.infer(f)?;
|
let tf = self.infer(f)?;
|
||||||
let targ = self.infer(arguments.get(0).unwrap())?;
|
let targ = self.infer(arguments.get(0).unwrap())?;
|
||||||
match tf {
|
match tf {
|
||||||
TFunc(box t1, box t2) => {
|
TFunc(box t1, box t2) => {
|
||||||
let _ = self.unify(t1, targ);
|
let _ = self.unify(t1, targ)?;
|
||||||
t2
|
t2
|
||||||
},
|
},
|
||||||
_ => return Err(format!("Not a function!")),
|
_ => return Err(format!("Not a function!")),
|
||||||
@ -350,11 +369,30 @@ impl TypeContext {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unify(&mut self, t1: Type, t2: Type) -> TypeCheckResult {
|
fn infer_op(&mut self, op: &Operation) -> TypeCheckResult {
|
||||||
use self::Type::*;
|
use self::Type::*;
|
||||||
use self::TypeConst::*;
|
use self::TypeConst::*;
|
||||||
|
macro_rules! binoptype {
|
||||||
|
($lhs:expr, $rhs:expr, $out:expr) => { TFunc(Box::new($lhs), Box::new(TFunc(Box::new($rhs), Box::new($out)))) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(match (*op.0).as_ref() {
|
||||||
|
"+" => binoptype!(TConst(Integer), TConst(Integer), TConst(Integer)),
|
||||||
|
"++" => binoptype!(TConst(StringT), TConst(StringT), TConst(StringT)),
|
||||||
|
"-" => binoptype!(TConst(Integer), TConst(Integer), TConst(Integer)),
|
||||||
|
"*" => binoptype!(TConst(Integer), TConst(Integer), TConst(Integer)),
|
||||||
|
"/" => binoptype!(TConst(Integer), TConst(Integer), TConst(Integer)),
|
||||||
|
"%" => binoptype!(TConst(Integer), TConst(Integer), TConst(Integer)),
|
||||||
|
_ => TConst(Bottom)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unify(&mut self, t1: Type, t2: Type) -> TypeCheckResult {
|
||||||
|
use self::Type::*;
|
||||||
use self::TypeVar::*;
|
use self::TypeVar::*;
|
||||||
|
|
||||||
|
println!("Calling unify with `{:?}` and `{:?}`", t1, t2);
|
||||||
|
|
||||||
match (&t1, &t2) {
|
match (&t1, &t2) {
|
||||||
(&TConst(ref c1), &TConst(ref c2)) if c1 == c2 => Ok(TConst(c1.clone())),
|
(&TConst(ref c1), &TConst(ref c2)) if c1 == c2 => Ok(TConst(c1.clone())),
|
||||||
(&TFunc(ref t1, ref t2), &TFunc(ref t3, ref t4)) => {
|
(&TFunc(ref t1, ref t2), &TFunc(ref t3, ref t4)) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user