diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-07-26 17:50:09 +0300 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-07-26 17:50:09 +0300 |
commit | 6dbcbc54352dc81b6ef2f2ecd9719eac40d8f1e6 (patch) | |
tree | 03a14eac21c058ddf5af52e67227553c465900e2 /src/sexp/step.rs | |
parent | bf4632c461508de5202db98d25cd7ec06787c8dd (diff) | |
download | myslip-6dbcbc54352dc81b6ef2f2ecd9719eac40d8f1e6.tar.gz myslip-6dbcbc54352dc81b6ef2f2ecd9719eac40d8f1e6.zip |
Implemented integer operator dynamics, fixed some tests and added a combination test.
Diffstat (limited to 'src/sexp/step.rs')
-rw-r--r-- | src/sexp/step.rs | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/src/sexp/step.rs b/src/sexp/step.rs index 86ad9ea..a6ce664 100644 --- a/src/sexp/step.rs +++ b/src/sexp/step.rs @@ -1,5 +1,5 @@ -use crate::sexp::SExp; +use crate::sexp::{SExp, SExp::*, SLeaf::*, util::*}; impl SExp { @@ -13,22 +13,22 @@ impl SExp { /// use melisp::sexp::{SExp::*, SLeaf::*, util::*}; /// /// assert_eq!( - /// sexp(Add, sexp(1, 1)).step().unwrap(), + /// scons(Add, scons(1, 1)).step().unwrap(), /// Atom(Int(2)) /// ); /// /// assert_eq!( - /// sexp(Sub, sexp(1, 2).step().unwrap()), + /// scons(Sub, scons(1, 2)).step().unwrap(), /// Atom(Int(-1)) /// ); /// /// assert_eq!( - /// sexp(Mul, sexp(2, 3).step().unwrap()), + /// scons(Mul, scons(2, 3)).step().unwrap(), /// Atom(Int(6)) /// ); /// /// assert_eq!( - /// sexp(Div, sexp(6, 2).step().unwrap()), + /// scons(Div, scons(6, 2)).step().unwrap(), /// Atom(Int(3)) /// ); /// ``` @@ -38,12 +38,58 @@ impl SExp { /// use melisp::sexp::{SExp::*, SLeaf::*, util::*}; /// /// assert_eq!( - /// sexp(Div, sexp(5, 2).step().unwrap()), + /// scons(Div, scons(5, 2)).step().unwrap(), /// Atom(Int(2)) /// ); /// /// ``` + /// + /// Here's an example of a bit more complicated expression: + /// ```rust + /// use melisp::sexp::{SExp::*, SLeaf::*, util::*}; + /// + /// fn main() { + /// let exp = scons(Mul, scons( + /// 2, + /// scons(Add, scons( + /// scons(Div, scons(5, 2)), + /// 4 + /// )) + /// )); + /// + /// let exp = exp.step().unwrap(); + /// assert_eq!(exp, scons(Mul, scons(2, scons(Add, scons(2, 4))))); + /// + /// let exp = exp.step().unwrap(); + /// assert_eq!(exp, scons(Mul, scons(2, 6))); + /// + /// let exp = exp.step().unwrap(); + /// assert_eq!(exp, Atom(Int(12))); + /// } + /// + /// ``` pub fn step(self) -> Result<Self, String> { - todo!(); + match self { + + SCons(op, e1) if *op == Atom(Add) + || *op == Atom(Sub) + || *op == Atom(Mul) + || *op == Atom(Div) => match *e1 { + SCons(e1, e2) => match (*e1, *e2) { + (Atom(Int(a)), Atom(Int(b))) => match *op { + Atom(Add) => Ok(Atom(Int(a + b))), + Atom(Sub) => Ok(Atom(Int(a - b))), + Atom(Mul) => Ok(Atom(Int(a * b))), + Atom(Div) => Ok(Atom(Int(a / b))), + _ => panic!("unreachable as per match arm"), + } + (Atom(Int(a)), e2) => Ok(scons(op, scons(a, e2.step()?))), + (e1, e2) => Ok(scons(op, scons(e1.step()?, e2))), + }, + _ => Err(format!("{:?} should be given two arguments, only one was given: {:?}", op, e1)), + }, + + t => Err(format!("unimplemented: {:?}.step()", t)), + } } } |