aboutsummaryrefslogtreecommitdiff
path: root/src/sexp/step.rs
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-10 22:33:48 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-10 22:33:48 +0300
commit2f101372e3311f1ccf7f8ec093c7fde9f4373439 (patch)
tree209cac3d19bc9ee714eedd17766bdc939a1feefa /src/sexp/step.rs
parentd6d1ec80ffcc0b13234b170a91b920371078a027 (diff)
downloadmyslip-2f101372e3311f1ccf7f8ec093c7fde9f4373439.tar.gz
myslip-2f101372e3311f1ccf7f8ec093c7fde9f4373439.zip
Implemented functions
Diffstat (limited to 'src/sexp/step.rs')
-rw-r--r--src/sexp/step.rs70
1 files changed, 51 insertions, 19 deletions
diff --git a/src/sexp/step.rs b/src/sexp/step.rs
index 8cc1e64..fd6be9e 100644
--- a/src/sexp/step.rs
+++ b/src/sexp/step.rs
@@ -275,13 +275,13 @@ impl SExp {
/// use myslip::{sexp::{SExp::*, SLeaf::*, util::*}, r#type::{Type::*, util::*}};
///
/// let varlist = scons(var("a"), scons(var("b"), Nil));
- /// let typelist = scons(Ty(List(vec![Integer])), Nil);
+ /// let typelist = scons(Ty(List(vec![Integer, Integer])), Nil);
/// let ret = Atom(Ty(Boolean));
/// let body = scons(Gt, varlist.clone());
/// let fun = scons(Fun, scons(varlist, scons(typelist, scons(ret, scons(body, Nil)))));
/// let args = scons(2, scons(1, Nil));
/// assert_eq!(
- /// scons(fun, scons(args, Nil)).multistep(),
+ /// scons(fun, args).multistep(),
/// Ok(Atom(True))
/// );
/// ```
@@ -309,6 +309,29 @@ impl SExp {
pub fn step(self) -> Result<Self, String> {
match self {
+
+ // Type list (maybe these should just be parsed...)
+ SCons(op, l) if (*op).is_type_lit() => {
+ if *l == Atom(Nil) {
+ return Ok(*op);
+ }
+ 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))))
+ },
+
+ // t is value
+ // ----------
+ // t -> t
+ t if t.is_value() => Ok(t),
+
+
+
// List processing
// op not a value
@@ -342,6 +365,32 @@ impl SExp {
},
+ // Custom anonymous functions
+ SCons(op, l) if (*op).is_fun() => {
+
+ // Get function parts
+ let ls = op.parts();
+ let argnames = ls.get(1).unwrap()
+ .clone().parts();
+ let mut argnamevec = vec![];
+ for name in argnames.clone() {
+ argnamevec.push(match name {
+ Atom(Var(s)) => Ok(s),
+ _ => Err("invalid entry in argument list (should be unreachable after type checker)".to_string()),
+ }?);
+ }
+ let mut body = ls.get(4).unwrap().clone();
+
+ // Get argument parts
+ let suppliedargs = l.parts();
+ for (name, value) in argnamevec.into_iter().zip(suppliedargs) {
+ body = body.subst(&name, &value);
+ }
+
+ Ok(body)
+ },
+
+
// Arithmetic
@@ -549,29 +598,12 @@ impl SExp {
}
},
- // 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);
Ok(Atom(Nil))
},
- // t is value
- // ----------
- // t -> t
- t if t.is_value() => Ok(t),
-
t => Err(format!("unimplemented: {:?}.step()", t)),
}
}