diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-10 22:33:48 +0300 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-10 22:33:48 +0300 |
commit | 2f101372e3311f1ccf7f8ec093c7fde9f4373439 (patch) | |
tree | 209cac3d19bc9ee714eedd17766bdc939a1feefa /src/sexp | |
parent | d6d1ec80ffcc0b13234b170a91b920371078a027 (diff) | |
download | myslip-2f101372e3311f1ccf7f8ec093c7fde9f4373439.tar.gz myslip-2f101372e3311f1ccf7f8ec093c7fde9f4373439.zip |
Implemented functions
Diffstat (limited to 'src/sexp')
-rw-r--r-- | src/sexp/step.rs | 70 |
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)), } } |