aboutsummaryrefslogtreecommitdiff
path: root/src/sexp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sexp')
-rw-r--r--src/sexp/display.rs2
-rw-r--r--src/sexp/mod.rs19
-rw-r--r--src/sexp/step.rs24
3 files changed, 44 insertions, 1 deletions
diff --git a/src/sexp/display.rs b/src/sexp/display.rs
index a978f61..5d78e93 100644
--- a/src/sexp/display.rs
+++ b/src/sexp/display.rs
@@ -29,6 +29,8 @@ impl fmt::Display for SLeaf {
Vector => "vector".to_string(),
Print => "print".to_string(),
Let => "let".to_string(),
+ Ty(t) => t.to_string(),
+ Arr => "->".to_string(),
Nil => "()".to_string(),
})
}
diff --git a/src/sexp/mod.rs b/src/sexp/mod.rs
index 296553f..11c185f 100644
--- a/src/sexp/mod.rs
+++ b/src/sexp/mod.rs
@@ -4,6 +4,8 @@ pub mod util;
pub mod subst;
pub mod display;
+use crate::r#type::Type;
+
/// A leaf node for S-Expressions.
///
/// May represent built-in operators,
@@ -33,6 +35,9 @@ pub enum SLeaf {
Let,
+ Ty(Type),
+ Arr,
+
Print,
Int(i32),
@@ -58,6 +63,7 @@ pub enum SExp {
use SExp::*;
use SLeaf::*;
+use crate::sexp::util::*;
impl SExp {
@@ -71,7 +77,7 @@ impl SExp {
SCons(a, b) =>
SCons(a.clone(), b.clone()).check_let().is_some() ||
(
- (**a == Atom(Quote) || **a == Atom(Vector))
+ (**a == Atom(Quote) || **a == Atom(Vector) || (**a).is_type_lit())
&& b.consists_of_values()
),
Atom(Var(_)) => false,
@@ -85,4 +91,15 @@ impl SExp {
_ => false
}
}
+
+ pub fn is_type_lit(&self) -> bool {
+ match self {
+ Atom(Ty(_)) => true,
+ SCons(a, b) => scons(a.clone(), b.clone())
+ .parts()
+ .into_iter()
+ .all(|x| x.is_type_lit()),
+ _ => false
+ }
+ }
}
diff --git a/src/sexp/step.rs b/src/sexp/step.rs
index 11df257..c26dce9 100644
--- a/src/sexp/step.rs
+++ b/src/sexp/step.rs
@@ -1,5 +1,6 @@
use crate::sexp::{SExp, SExp::*, SLeaf::*, util::*};
+use crate::r#type::{Type::*, util::*};
impl SExp {
@@ -521,6 +522,29 @@ impl SExp {
}
},
+ // Type arrow
+ SCons(op, l) if *op == Atom(Arr) => {
+ let ls = l.parts();
+ 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.clone().multistep()?, t2.clone().multistep()?) {
+ (Atom(Ty(a)), Atom(Ty(b))) => Ok(Atom(Ty(arr(a.clone(), b.clone())))),
+ _ => Err("invalid args".to_string()),
+ }
+ },
+
+ // Type list
+ SCons(op, l) if (*op).is_type_lit() => {
+ let mut res = vec![];
+ for exp in std::iter::once(*op).chain(l.parts()) {
+ res.push(match exp.multistep()? {
+ Atom(Ty(t)) => Ok(t),
+ e => Err(format!("not a type: {e}")),
+ }?);
+ }
+ Ok(Atom(Ty(List(res))))
+ },
+
// Print
SCons(op, l) if *op == Atom(Print) => {
println!("{}", *l);