boot2

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

commit 0b8e9e9a5fea1e7a28489feccb4f6b827be64292
parent c576c830a889502cf3a6ee0dfb510cbb21a02a26
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sat, 25 Apr 2026 15:06:14 -0700

scheme1: match record api to r7rs

Diffstat:
Mscheme1/scheme1.P1pp | 159++++---------------------------------------------------------------------------
Mtests/scheme1/70-type-predicates.scm | 22+++++-----------------
2 files changed, 13 insertions(+), 168 deletions(-)

diff --git a/scheme1/scheme1.P1pp b/scheme1/scheme1.P1pp @@ -2464,38 +2464,6 @@ %ret %endscope -# (record? x) -- #t iff x is HEAP-tagged with HDR.REC. -:prim_recordq_entry -%scope prim_recordq - %car(t0, a0) - %tagof(t1, t0) - %li(t2, %TAG.HEAP) - %li(a0, %imm_val(%IMM.FALSE)) - %bne(t1, t2, &::end) - %hdr_type(t1, t0) - %li(t2, %HDR.REC) - %bne(t1, t2, &::end) - %li(a0, %imm_val(%IMM.TRUE)) - ::end - %ret -%endscope - -# (record-type? x) -- #t iff x is HEAP-tagged with HDR.TD. -:prim_record_typeq_entry -%scope prim_record_typeq - %car(t0, a0) - %tagof(t1, t0) - %li(t2, %TAG.HEAP) - %li(a0, %imm_val(%IMM.FALSE)) - %bne(t1, t2, &::end) - %hdr_type(t1, t0) - %li(t2, %HDR.TD) - %bne(t1, t2, &::end) - %li(a0, %imm_val(%IMM.TRUE)) - ::end - %ret -%endscope - :prim_zeroq_entry %scope prim_zeroq %car(t0, a0) @@ -3299,111 +3267,14 @@ %st(t1, a0, 13) }) -# (%make-record-td name nfields) -- args = (name nfields). -%fn(prim_make_record_td_entry, 16, { - %st(a0, sp, 0) - %li(a0, 24) - %li(a1, %HDR.TD) - %call(&alloc_hdr) - - %ld(t0, sp, 0) - %car(t1, t0) ; name sym - %st(t1, a0, 5) - %cdr(t0, t0) - %car(t0, t0) - %sari(t0, t0, 3) ; raw nfields - %st(t0, a0, 13) -}) - -# (%make-record td f0 f1 ...) -- args = (td . fields). -%fn(prim_make_record_entry, 24, { - %st(a0, sp, 0) - - # Count fields = length(args) - 1. - %cdr(a0, a0) - %call(&list_length) - %shli(a0, a0, 3) - %addi(a0, a0, 16) - %li(a1, %HDR.REC) - %call(&alloc_hdr) - %st(a0, sp, 8) - - # td (offset +5) = car(args) - %ld(t0, sp, 0) - %car(t0, t0) - %st(t0, a0, 5) - - # Walk fields, filling +13, +21, ... - %ld(t0, sp, 0) - %cdr(t0, t0) - %addi(t1, a0, 13) - - ::fill_loop - %if_nil(t2, t0, &::fill_done) - %car(t2, t0) - %st(t2, t1, 0) - %addi(t1, t1, 8) - %cdr(t0, t0) - %b(&::fill_loop) - - ::fill_done - %ld(a0, sp, 8) -}) - -# (%record-ref rec idx) -:prim_record_ref_entry - %car(t0, a0) ; rec - %cdr(t1, a0) - %car(t1, t1) ; tagged idx (= idx << 3) - %addi(t1, t1, 13) - %add(t1, t1, t0) - %ld(a0, t1, 0) - %ret - -# (%record-set! rec idx val) -:prim_record_set_entry -%scope prim_record_set - %car(t0, a0) - %cdr(t1, a0) - %car(t2, t1) ; tagged idx - %cdr(t1, t1) - %car(t1, t1) ; val - %addi(t2, t2, 13) - %add(t2, t2, t0) - %st(t1, t2, 0) - %li(a0, %imm_val(%IMM.UNSPEC)) - %ret -%endscope - -# (%record-is-a? rec td) -:prim_record_is_a_entry -%scope prim_record_is_a - %car(t0, a0) - %cdr(t1, a0) - %car(t1, t1) - %tagof(t2, t0) - %li(a0, %imm_val(%IMM.FALSE)) - %li(a2, %TAG.HEAP) - %bne(t2, a2, &::end) - %hdr_type(t2, t0) - %li(a2, %HDR.REC) - %bne(t2, a2, &::end) - %ld(t2, t0, 5) - %bne(t2, t1, &::end) - %li(a0, %imm_val(%IMM.TRUE)) - ::end - %ret -%endscope - -# (%record-td rec) -- returns rec's TD pointer. -:prim_record_td_entry - %car(t0, a0) - %ld(a0, t0, 5) - %ret - # Parameterized PRIM entries used by define-record-type. Each receives # args in a0 and the prim itself in a1; the prim's data slot (offset 13 -# from tagged) holds either the TD or a tagged field index. +# from tagged) holds either the TD or a tagged field index. The +# constructor inlines record allocation; predicate / accessor / mutator +# inline what would otherwise be %record-is-a? / %record-ref / +# %record-set! bodies. None of these primitives are exposed at the +# user level — R7RS define-record-type binds only ctor / pred / +# accessor / mutator names. # ctor: prim.data = TD (HEAP); args = (f0 f1 ...). Inlines the # %make-record body so we don't have to cons (TD . args) first. @@ -4489,8 +4360,6 @@ :name_booleanq "boolean?" :name_integerq "integer?" :name_procedureq "procedure?" -:name_recordq "record?" -:name_record_typeq "record-type?" :name_zeroq "zero?" :name_not "not" :name_eqq "eq?" @@ -4516,12 +4385,6 @@ :name_bv_copy "bytevector-copy" :name_bv_copy_b "bytevector-copy!" :name_bv_eq "bytevector=?" -:name_make_rt "%make-record-td" -:name_make_rec "%make-record" -:name_record_ref "%record-ref" -:name_record_set "%record-set!" -:name_record_isa "%record-is-a?" -:name_record_td "%record-td" :name_sys_read "sys-read" :name_sys_write "sys-write" @@ -4576,8 +4439,6 @@ &name_booleanq %(0) $(8) &prim_booleanq_entry %(0) &name_integerq %(0) $(8) &prim_integerq_entry %(0) &name_procedureq %(0) $(10) &prim_procedureq_entry %(0) -&name_recordq %(0) $(7) &prim_recordq_entry %(0) -&name_record_typeq %(0) $(12) &prim_record_typeq_entry %(0) &name_zeroq %(0) $(5) &prim_zeroq_entry %(0) &name_not %(0) $(3) &prim_not_entry %(0) &name_eqq %(0) $(3) &prim_eqq_entry %(0) @@ -4603,12 +4464,6 @@ &name_bv_copy %(0) $(15) &prim_bv_copy_entry %(0) &name_bv_copy_b %(0) $(16) &prim_bv_copy_bang_entry %(0) &name_bv_eq %(0) $(12) &prim_bytevector_eq_entry %(0) -&name_make_rt %(0) $(15) &prim_make_record_td_entry %(0) -&name_make_rec %(0) $(12) &prim_make_record_entry %(0) -&name_record_ref %(0) $(11) &prim_record_ref_entry %(0) -&name_record_set %(0) $(12) &prim_record_set_entry %(0) -&name_record_isa %(0) $(13) &prim_record_is_a_entry %(0) -&name_record_td %(0) $(10) &prim_record_td_entry %(0) &name_sys_read %(0) $(8) &prim_sys_read_entry %(0) &name_sys_write %(0) $(9) &prim_sys_write_entry %(0) &name_sys_close %(0) $(9) &prim_sys_close_entry %(0) @@ -4640,6 +4495,8 @@ :msg_unterm_string "scheme1: unterminated string literal" '0a' '00' :msg_bad_escape "scheme1: bad string escape" '0a' '00' :msg_bad_char "scheme1: bad #\\ character literal" '0a' '00' +:msg_bad_number "scheme1: bad number literal" '0a' '00' +:msg_bad_ident "scheme1: bad identifier" '0a' '00' :name_ch_tab "tab" :name_ch_null "null" diff --git a/tests/scheme1/70-type-predicates.scm b/tests/scheme1/70-type-predicates.scm @@ -1,9 +1,8 @@ -; boolean?, integer?, procedure?, record?, record-type? — tag-checking -; predicates. TDs are reached via %record-td (no surface name binding). - -(define-record-type point (make-point x y) point? (x point-x) (y point-y)) -(define p (make-point 1 2)) -(define td (%record-td p)) +; boolean?, integer?, procedure? — tag-checking predicates. +; +; Per R7RS-small, define-record-type does not expose the type +; descriptor or any cross-type record predicate. record? / +; record-type? are not part of the user-facing API. ; boolean? — only #t and #f (if (boolean? #t) 0 (sys-exit 1)) @@ -28,15 +27,4 @@ (if (not (procedure? 'car)) 0 (sys-exit 16)) (if (not (procedure? '())) 0 (sys-exit 17)) -; record? — only HDR.REC heap objects -(if (record? p) 0 (sys-exit 18)) -(if (not (record? td)) 0 (sys-exit 19)) -(if (not (record? 1)) 0 (sys-exit 20)) -(if (not (record? "abc")) 0 (sys-exit 21)) - -; record-type? — only HDR.TD heap objects -(if (record-type? td) 0 (sys-exit 22)) -(if (not (record-type? p)) 0 (sys-exit 23)) -(if (not (record-type? 0)) 0 (sys-exit 24)) - (sys-exit 0)