aboutsummaryrefslogtreecommitdiff
path: root/src/sexp/step.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sexp/step.rs')
-rw-r--r--src/sexp/step.rs34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/sexp/step.rs b/src/sexp/step.rs
index e031fca..816582c 100644
--- a/src/sexp/step.rs
+++ b/src/sexp/step.rs
@@ -240,6 +240,8 @@ impl SExp {
/// ```
///
/// **Let-bindings**
+ ///
+ /// Basic operation:
/// ```rust
/// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
///
@@ -261,7 +263,27 @@ impl SExp {
/// ).step(),
/// Ok(scons(
/// scons(Let, scons(var("x"), scons(5, Nil))), scons(
- /// scons(Add, scons(var("x"), scons(1, Nil))), Nil
+ /// scons(Add, scons(var("x"), scons(4, Nil))), Nil
+ /// )
+ /// ))
+ /// );
+ /// ```
+ ///
+ /// Shadowing:
+ /// ```rust
+ /// use myslip::sexp::{SExp::*, SLeaf::*, util::*};
+ ///
+ /// assert_eq!(
+ /// scons(
+ /// scons(Let, scons(var("x"), scons(4, Nil))),
+ /// scons(
+ /// scons(Let, scons(var("x"), scons(5, Nil))),
+ /// scons(scons(Add, scons(var("x"), scons(4, Nil))), Nil)
+ /// )
+ /// ).step(),
+ /// Ok(scons(
+ /// scons(Let, scons(var("x"), scons(5, Nil))), scons(
+ /// scons(Add, scons(var("x"), scons(4, Nil))), Nil
/// )
/// ))
/// );
@@ -278,6 +300,16 @@ impl SExp {
SCons(op, l) if !(*op).is_value() => Ok(scons(op.step()?, l)),
+ // let binds
+ SCons(op, l) if op.clone().check_let().is_some() => match (*op).check_let() {
+ Some((varname, val)) => Ok(match *l {
+ SCons(a, b) if *b == Atom(Nil) => *a,
+ t => t,
+ }.subst(&varname, &val)),
+ None => panic!("unreachable as per match guard arm"),
+ },
+
+
// op value and a1 .. an values, and b0, b1 .. bn not values
// ---------------------------------------------------------
// (op a1 ... an b) -> (op a1 ... an b0.step() b1 .. bn)