commit 96a683eb9e0aea5e8d4d98763f66b069cfd5fff9
parent 0b51b30098797ce891ca56c01d9d829c29530a3c
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sat, 25 Apr 2026 16:26:08 -0700
scheme1: tighten cond no-else, let* shadow, letrec recursion tests
- 16-cond: pin the (cond) no-match-no-else policy via UNSPEC eq? checks
(UNSPEC singleton eq? to itself, distinct from #t/#f/0/'()).
- 19-letstar: also assert outer x is unchanged after the let* body
returns, not just that the inner shadow wins inside the body.
- 20-letrec: replace the one-step (if n n (f #t)) workaround with
factorial(5) = 120 -- exercises real stack-walking recursion.
Diffstat:
5 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/tests/scheme1/16-cond.scm b/tests/scheme1/16-cond.scm
@@ -1,2 +1,13 @@
; First-truthy clause wins; subsequent clauses are not evaluated.
+
+; No-match-no-else: scheme1 returns UNSPEC. LISP.md does not pin this,
+; so the checks below guard the current behavior -- a change should be
+; deliberate. UNSPEC is a singleton, so two such results are eq?, and
+; it is distinguishable from any other value via eq?.
+(if (eq? (cond (#f 1)) (cond (#f 2))) 0 (sys-exit 1))
+(if (not (eq? (cond (#f 1)) #t)) 0 (sys-exit 2))
+(if (not (eq? (cond (#f 1)) #f)) 0 (sys-exit 3))
+(if (not (eq? (cond (#f 1)) 0)) 0 (sys-exit 4))
+(if (not (eq? (cond (#f 1)) '())) 0 (sys-exit 5))
+
(sys-exit (cond (#f 1) (#t 33) (#f 2)))
diff --git a/tests/scheme1/19-letstar.expected-exit b/tests/scheme1/19-letstar.expected-exit
@@ -1 +1 @@
-5
+0
diff --git a/tests/scheme1/19-letstar.scm b/tests/scheme1/19-letstar.scm
@@ -1,3 +1,9 @@
-; let* binds sequentially: y's init may reference the new x.
-(define x 1) ; outer x; let*'s x must shadow inside the body.
-(sys-exit (let* ((x 5) (y x)) y))
+; let* binds sequentially: y's init may reference the new x. The let*'s
+; x shadows the outer x inside the body, and the shadow does not escape
+; the body -- after the form returns, the outer x is unchanged.
+(define x 1)
+
+(if (= 5 (let* ((x 5) (y x)) y)) 0 (sys-exit 1))
+(if (= 1 x) 0 (sys-exit 2))
+
+(sys-exit 0)
diff --git a/tests/scheme1/20-letrec.expected-exit b/tests/scheme1/20-letrec.expected-exit
@@ -1 +1 @@
-44
+120
diff --git a/tests/scheme1/20-letrec.scm b/tests/scheme1/20-letrec.scm
@@ -1,4 +1,7 @@
; letrec: a local helper that calls itself. The closure must see its own
-; binding via the same env it captured. Without numeric primitives we
-; terminate by passing #t at the recursive call.
-(sys-exit (letrec ((f (lambda (n) (if n n (f #t))))) (f 44)))
+; binding via the captured env. Real recursion -- factorial walks the
+; stack down to the base case and back, so a one-step bug would not
+; produce 120.
+(sys-exit (letrec ((fact (lambda (n)
+ (if (= n 0) 1 (* n (fact (- n 1)))))))
+ (fact 5))) ; 5! = 120