aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/sexp/step.rs141
-rw-r--r--src/sexp/util.rs6
-rw-r--r--src/type/check.rs17
-rw-r--r--src/type/display.rs2
-rw-r--r--src/type/mod.rs2
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(());