commit 8e4ccaa7eeaadf4c3d5a43c289021ff306bdbd11
parent 8a0f5873757ecdbf47038906555141d5351145e4
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sat, 25 Apr 2026 15:58:49 -0700
scheme1: tests for set! and number/string radix-arg surface
81 covers (set! name value) at global, lexical (let / lambda param),
and closure-captured-cell scope, plus that an inner set! on a shadow
binding does not escape its let. 74 grows two cases pinning the
radix-10 arg shape per LISP.md (number->string, string->number both
accept an optional radix); other radices are not yet pinned since
the prim is decimal-only for now.
Diffstat:
3 files changed, 62 insertions(+), 0 deletions(-)
diff --git a/tests/scheme1/74-num-str-conv.scm b/tests/scheme1/74-num-str-conv.scm
@@ -23,4 +23,10 @@
(if (= 99 (string->number (number->string 99))) 0 (sys-exit 16))
(if (= -99 (string->number (number->string -99))) 0 (sys-exit 17))
+; Radix arg is part of the surface (LISP.md). Impl is decimal-only for
+; now; passing radix=10 must match the no-radix call. Other radices are
+; not yet pinned by tests since the impl ignores them.
+(if (bytevector=? "42" (number->string 42 10)) 0 (sys-exit 18))
+(if (= 42 (string->number "42" 10)) 0 (sys-exit 19))
+
(sys-exit 0)
diff --git a/tests/scheme1/81-set-bang.expected-exit b/tests/scheme1/81-set-bang.expected-exit
@@ -0,0 +1 @@
+0
diff --git a/tests/scheme1/81-set-bang.scm b/tests/scheme1/81-set-bang.scm
@@ -0,0 +1,55 @@
+; (set! name value) -- mutate an existing binding in place. Returns
+; unspecified. Must work on globals, lexicals (let-bound, lambda-bound),
+; and lexicals captured by a closure (mutation visible to all closures
+; that captured the same binding).
+
+;; --- Global rebind ----------------------------------------------------
+(define g 1)
+(set! g 2)
+(if (= g 2) 0 (sys-exit 1))
+
+;; --- Lexical (let-bound) ---------------------------------------------
+(if (= 9
+ (let ((x 1))
+ (set! x 9)
+ x))
+ 0 (sys-exit 2))
+
+;; --- Lexical, set! does NOT escape the let -------------------------
+;; Outer g is unaffected by the inner set! on a shadowing binding.
+(define outer-touched 0)
+(let ((g 100))
+ (set! g 200)
+ (set! outer-touched g))
+(if (= g 2) 0 (sys-exit 3)) ; outer g unchanged
+(if (= outer-touched 200) 0 (sys-exit 4)) ; inner saw 200
+
+;; --- Lambda parameter --------------------------------------------------
+(define (bump x) (set! x (+ x 1)) x)
+(if (= (bump 4) 5) 0 (sys-exit 5))
+
+;; --- Closure-captured cell: counter pattern --------------------------
+(define counter
+ (let ((n 0))
+ (lambda ()
+ (set! n (+ n 1))
+ n)))
+
+(if (= (counter) 1) 0 (sys-exit 6))
+(if (= (counter) 2) 0 (sys-exit 7))
+(if (= (counter) 3) 0 (sys-exit 8))
+
+;; --- Two closures sharing the same captured cell ---------------------
+;; Both closures close over the same `s`; mutations through one are
+;; visible through the other.
+(define get #f)
+(define put #f)
+(let ((s 10))
+ (set! get (lambda () s))
+ (set! put (lambda (v) (set! s v))))
+
+(if (= (get) 10) 0 (sys-exit 9))
+(put 42)
+(if (= (get) 42) 0 (sys-exit 10))
+
+(sys-exit 0)