boot2

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

commit 602a59d9deda0b87d23dac8403305bc861227249
parent 20b90492c047e3b99f894691d4e596dfa74c5713
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sat, 25 Apr 2026 14:32:55 -0700

scheme1: red-green tests for R7RS record API surface

Targeting R7RS-small define-record-type: only the constructor,
predicate, accessors, and mutators are user-bound; type name and
%record-* primitives are not.

- 38 rewritten to assert %make-record-td is unbound at user level
  (red until the %record-* rows are removed from prim_table).
- 39 added to lock in that the type name itself stays unbound
  after define-record-type runs (green; regression guard).

Diffstat:
Atests/scheme1/38-record-internal-prims.expected | 1+
Mtests/scheme1/38-record-internal-prims.expected-exit | 2+-
Mtests/scheme1/38-record-internal-prims.scm | 17++++++++++-------
Atests/scheme1/39-record-typename-unbound.expected | 1+
Atests/scheme1/39-record-typename-unbound.expected-exit | 1+
Atests/scheme1/39-record-typename-unbound.scm | 22++++++++++++++++++++++
6 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/tests/scheme1/38-record-internal-prims.expected b/tests/scheme1/38-record-internal-prims.expected @@ -0,0 +1 @@ +scheme1: unbound variable diff --git a/tests/scheme1/38-record-internal-prims.expected-exit b/tests/scheme1/38-record-internal-prims.expected-exit @@ -1 +1 @@ -33 +1 diff --git a/tests/scheme1/38-record-internal-prims.scm b/tests/scheme1/38-record-internal-prims.scm @@ -1,7 +1,10 @@ -; Internal record primitives are accessible directly: build a TD, build -; a record, ref/set/predicate via %record-*. -(define td (%make-record-td 'foo 2)) -(define r (%make-record td 11 22)) -(sys-exit (if (%record-is-a? r td) - (+ (%record-ref r 0) (%record-ref r 1)) - 999)) +; Internal record primitives are not part of the user-facing API +; (R7RS records bind only the constructor / predicate / accessors / +; mutators introduced by define-record-type). Calling %make-record-td +; from user code must abort with "scheme1: unbound variable". +; +; This test is RED until the %record-* rows are removed from +; prim_table; today it would otherwise return 33 from the old +; through-public-binding path. +(%make-record-td 'foo 2) +(sys-exit 0) diff --git a/tests/scheme1/39-record-typename-unbound.expected b/tests/scheme1/39-record-typename-unbound.expected @@ -0,0 +1 @@ +scheme1: unbound variable diff --git a/tests/scheme1/39-record-typename-unbound.expected-exit b/tests/scheme1/39-record-typename-unbound.expected-exit @@ -0,0 +1 @@ +1 diff --git a/tests/scheme1/39-record-typename-unbound.scm b/tests/scheme1/39-record-typename-unbound.scm @@ -0,0 +1,22 @@ +; In R7RS-small, the type name introduced by define-record-type is +; purely syntactic. After the form runs, only the constructor / +; predicate / accessors / mutators have runtime bindings; the type +; name itself (`point`) does not. A bare reference must abort with +; "scheme1: unbound variable". +; +; Today this test is green — the impl never bound the name. It exists +; to lock in that R7RS behavior against any future change that would +; expose the TD as a value (e.g. a generated <point-td> binding). +(define-record-type point + (make-point x y) + point? + (x point-x) + (y point-y)) + +; Touch a generated binding to prove the form ran. +(define p (make-point 1 2)) +(if (point? p) 0 (sys-exit 99)) + +; Bare reference to the type name -> unbound -> abort. +point +(sys-exit 0)