boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

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:
Mtests/scheme1/74-num-str-conv.scm | 6++++++
Atests/scheme1/81-set-bang.expected-exit | 1+
Atests/scheme1/81-set-bang.scm | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
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)