diff options
-rw-r--r-- | src/sexp/step.rs | 141 | ||||
-rw-r--r-- | src/sexp/util.rs | 6 | ||||
-rw-r--r-- | src/type/check.rs | 17 | ||||
-rw-r--r-- | src/type/display.rs | 2 | ||||
-rw-r--r-- | src/type/mod.rs | 2 |
5 files changed, 146 insertions, 22 deletions
diff --git a/src/sexp/step.rs b/src/sexp/step.rs index bb3ada5..f09c014 100644 --- a/src/sexp/step.rs +++ b/src/sexp/step.rs @@ -110,28 +110,28 @@ impl SExp { /// /// assert_eq!( /// scons(Le, scons(1, scons(2, Nil))).step(), - /// Ok(Atom(True)) + /// Ok(Atom(True)), "le 1" /// ); /// assert_eq!( /// scons(Le, scons(2, scons(2, Nil))).step(), - /// Ok(Atom(True)) + /// Ok(Atom(True)), "le 2" /// ); /// assert_eq!( - /// scons(Lt, scons(2, scons(1, Nil))).step(), - /// Ok(Atom(False)) + /// scons(Le, scons(2, scons(1, Nil))).step(), + /// Ok(Atom(False)), "le 3" /// ); /// /// assert_eq!( /// scons(Ge, scons(2, scons(1, Nil))).step(), - /// Ok(Atom(True)) + /// Ok(Atom(True)), "ge 1" /// ); /// assert_eq!( /// scons(Ge, scons(1, scons(1, Nil))).step(), - /// Ok(Atom(True)) + /// Ok(Atom(True)), "ge 2" /// ); /// assert_eq!( - /// scons(Lt, scons(1, scons(2, Nil))).step(), - /// Ok(Atom(False)) + /// scons(Ge, scons(1, scons(2, Nil))).step(), + /// Ok(Atom(False)), "ge 3" /// ); /// /// assert_eq!( @@ -315,6 +315,131 @@ impl SExp { } }, + + // t1,t2 booleans + // ----------------------- + // (and t1 t2) -> t1 && t2 + SCons(op, l) if *op == Atom(And) => { + let ls = l.into_vec()?; + if ls.len() == 2 { + match (ls[0].clone(), ls[1].clone()) { + (True, True) => Ok(Atom(True)), + (True | False, True | False) => Ok(Atom(False)), + _ => Err("'and' should be only given booleans".to_string()) + } + } else { + Err(format!("'and' should be given 2 arguments, found {}", ls.len())) + } + }, + + // t1,t2 booleans + // ----------------------- + // (or t1 t2) -> t1 || t2 + SCons(op, l) if *op == Atom(Or) => { + let ls = l.into_vec()?; + if ls.len() == 2 { + match (ls[0].clone(), ls[1].clone()) { + (False, False) => Ok(Atom(False)), + (True | False, True | False) => Ok(Atom(True)), + _ => Err("'or' should be only given booleans".to_string()) + } + } else { + Err(format!("'or' should be given 2 arguments, found {}", ls.len())) + } + }, + + // t1,t2 booleans + // -------------- + // (xor t1 t2) -> t1 ^ t2 + SCons(op, l) if *op == Atom(Xor) => { + let ls = l.into_vec()?; + let t1 = ls.get(0).ok_or("wrong list length".to_string())?; + let t2 = ls.get(1).ok_or("wrong list length".to_string())?; + match (t1, t2) { + (True, False) => Ok(Atom(True)), + (False, True) => Ok(Atom(True)), + (True | False, True | False) => Ok(Atom(False)), + _ => Err("invalid args".to_string()), + } + }, + + // Not + SCons(op, l) if *op == Atom(Not) => { + let ls = l.into_vec()?; + let t1 = ls.get(0).ok_or("wrong list length".to_string())?; + match t1 { + True => Ok(Atom(False)), + False => Ok(Atom(True)), + _ => Err("invalid args".to_string()), + } + }, + + // Lt + SCons(op, l) if *op == Atom(Lt) => { + let ls = l.into_vec()?; + let t1 = ls.get(0).ok_or("wrong list length".to_string())?; + let t2 = ls.get(1).ok_or("wrong list length".to_string())?; + match (t1, t2) { + (Int(a), Int(b)) => Ok((a < b).into()), + _ => Err("invalid args".to_string()), + } + }, + + // Gt + SCons(op, l) if *op == Atom(Gt) => { + let ls = l.into_vec()?; + let t1 = ls.get(0).ok_or("wrong list length".to_string())?; + let t2 = ls.get(1).ok_or("wrong list length".to_string())?; + match (t1, t2) { + (Int(a), Int(b)) => Ok((a > b).into()), + _ => Err("invalid args".to_string()), + } + }, + + // Le + SCons(op, l) if *op == Atom(Le) => { + let ls = l.into_vec()?; + let t1 = ls.get(0).ok_or("wrong list length".to_string())?; + let t2 = ls.get(1).ok_or("wrong list length".to_string())?; + match (t1, t2) { + (Int(a), Int(b)) => Ok((a <= b).into()), + _ => Err("invalid args".to_string()), + } + }, + + // Ge + SCons(op, l) if *op == Atom(Ge) => { + let ls = l.into_vec()?; + let t1 = ls.get(0).ok_or("wrong list length".to_string())?; + let t2 = ls.get(1).ok_or("wrong list length".to_string())?; + match (t1, t2) { + (Int(a), Int(b)) => Ok((a >= b).into()), + _ => Err("invalid args".to_string()), + } + }, + + // Eq + SCons(op, l) if *op == Atom(Eq) => { + let ls = l.into_vec()?; + let t1 = ls.get(0).ok_or("wrong list length".to_string())?; + let t2 = ls.get(1).ok_or("wrong list length".to_string())?; + match (t1, t2) { + (Int(a), Int(b)) => Ok((a == b).into()), + _ => Err("invalid args".to_string()), + } + }, + + // Neq + SCons(op, l) if *op == Atom(Neq) => { + let ls = l.into_vec()?; + let t1 = ls.get(0).ok_or("wrong list length".to_string())?; + let t2 = ls.get(1).ok_or("wrong list length".to_string())?; + match (t1, t2) { + (Int(a), Int(b)) => Ok((a != b).into()), + _ => Err("invalid args".to_string()), + } + }, + // t is value // ---------- // t -> t diff --git a/src/sexp/util.rs b/src/sexp/util.rs index f01dab9..b3edf19 100644 --- a/src/sexp/util.rs +++ b/src/sexp/util.rs @@ -12,6 +12,12 @@ impl From<i32> for Box<SExp> { } } +impl From<bool> for SExp { + fn from(bl: bool) -> Self { + Atom( if bl { True } else { False } ) + } +} + impl From<SLeaf> for Box<SExp> { fn from(leaf: SLeaf) -> Self { Box::new(Atom(leaf)) diff --git a/src/type/check.rs b/src/type/check.rs index e9917c7..d678411 100644 --- a/src/type/check.rs +++ b/src/type/check.rs @@ -136,8 +136,7 @@ impl SExp { match self { Atom(Int(_)) => Ok(Integer), - Atom(True) => todo!(), - Atom(False) => todo!(), + Atom(True | False) => Ok(Boolean), Atom(Var(name)) => ctx.get(name) .ok_or(UndefinedVariable(name.to_string())) .cloned(), @@ -145,16 +144,10 @@ impl SExp { Atom(Mul) => Ok(arr(List(vec![Integer, Integer]), Integer)), // TODO varlen Atom(Sub) => Ok(arr(List(vec![Integer, Integer]), Integer)), Atom(Div) => Ok(arr(List(vec![Integer, Integer]), Integer)), - Atom(Eq) => todo!(), - Atom(Neq) => todo!(), - Atom(Lt) => todo!(), - Atom(Gt) => todo!(), - Atom(Le) => todo!(), - Atom(Ge) => todo!(), - Atom(Or) => todo!(), - Atom(And) => todo!(), - Atom(Xor) => todo!(), - Atom(Not) => todo!(), + Atom(Eq | Neq | Lt | Gt | Le | Ge) => + Ok(arr(List(vec![Integer, Integer]), Boolean)), + Atom(Or | And | Xor) => Ok(arr(List(vec![Boolean, Boolean]), Boolean)), + Atom(Not) => Ok(arr(Boolean, Boolean)), Atom(Nil) => Ok(List(vec![])), Atom(Quote) => Ok(arr( VarType("T".to_string()), diff --git a/src/type/display.rs b/src/type/display.rs index 832b289..3e4f49c 100644 --- a/src/type/display.rs +++ b/src/type/display.rs @@ -18,6 +18,7 @@ impl fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Integer => write!(f, "{}", "Int"), + Boolean => write!(f, "{}", "Bool"), Arrow(a, b) => write!(f, "({} -> {})", a, b), List(types) => write!( f, @@ -28,7 +29,6 @@ impl fmt::Display for Type { .join(" ") ), VarType(name) => write!(f, "{}", name), - Boolean => todo!(), } } } diff --git a/src/type/mod.rs b/src/type/mod.rs index 8977d85..e4c0841 100644 --- a/src/type/mod.rs +++ b/src/type/mod.rs @@ -91,7 +91,7 @@ impl Type { pub fn is_concrete(&self) -> Result<(), String> { match self { Integer => Ok(()), - Boolean => todo!(), + Boolean => Ok(()), Arrow(a, b) => b.is_concrete().and_then(|_ok| a.is_concrete()), List(v) => { let mut res = Ok(()); |