boot2

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

commit 63959a59c2526161431457084565f13ffa939916
parent b00065b8511ec5507c85584bdeddc5a02e1bb059
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sat, 25 Apr 2026 14:35:55 -0700

scheme1: string<->sym, bytevector-append, type preds, number<->str, quot/rem, bit-xor/not, set-car/cdr!

Diffstat:
Mdocs/scheme-shell-todo.md | 167++++++++++++++++++++++++++++++++++++-------------------------------------------
Mscheme1/scheme1.P1pp | 388++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 413 insertions(+), 142 deletions(-)

diff --git a/docs/scheme-shell-todo.md b/docs/scheme-shell-todo.md @@ -5,8 +5,12 @@ Checklist for getting `lisp/shell.scm` running under scheme1. **Workflow:** every item is red-green TDD. Add a failing `tests/scheme1/NN-*.scm` (with `.expected-exit` and/or `.expected`) first, run the suite to confirm it fails for the expected reason, then -implement until green. Multi-arch suite (`make test SUITE=scheme1`) -must stay clean before moving on. +implement until green. Multi-arch suite must stay clean before moving on. + +``` +# Run 1+ specific tests +scripts/run-tests.sh --suite scheme1 --arch aarch64 70-type-predicates +``` # Audit: deviations and known issues @@ -31,55 +35,60 @@ Per LISP.md and LISP-C.md, but not implemented: - [ ] **Special forms missing**: `set!`, `pmatch`, `cond`'s `=>` arrow form. -- [ ] **Primitives missing** (LISP.md lists them as required): - - Predicates: `boolean?`, `integer?`, `string?`, `procedure?`, - `record?`, `record-type?` - - Numeric: `quotient`, `remainder`, `modulo`, - `abs`, `min`, `max`, `bit-xor`, - `bit-not`, `number->string`, `string->number` - - Pair / list: `set-car!`, `set-cdr!`, `length`, - - Bytevector: `bytevector-append`, `bytevector=?`, `string->symbol`, - `symbol->string` -- [ ] **`+ - * = < >` are 2-arg only.** R7RS allows any arity. -- [ ] **Type names are not bound by `define-record-type`.** The TD is - reachable only via the parameterized prims that close over it; no - `record-type-of`, no way to inspect a TD from user code. Spec is - ambiguous on this; LISP-C.md's example uses a generated `<point-td>` - binding. -- [ ] **`scheme1/prelude.scm` carries both the language prelude and - the shell.scm library.** - Missing: `vector->list` / `list->vector` (need `make-vector` / - `vector-ref` / `vector-set!` / `vector-length`), - Each re-enables when its underlying primitives land. - -## Prelude scope (deliberately wider than `lisp/prelude.scm`) - -scheme1 keeps the shell.scm library inside `prelude.scm` rather than -mirroring the `lisp/` two-file split. The boot script catm's a single -file in front of the user script, so process / file-I/O / port -wrappers are always in scope. - -What lives in `prelude.scm` today, grouped: - -- **Language helpers** (subset of `lisp/prelude.scm`): see the bullet - in "Spec features still missing" above for the active set and what - remains commented out pending primitives. -- **Process management**: `sys-wait` (Scheme adapter over `sys-waitid` - returning a wait4-style raw wstatus), `decode-wait-status`, `wait`, - `exit`, `argv`, `spawn`, `run`. -- **File-I/O constants**: `BUFSIZE`, `AT_FDCWD`, `O_RDONLY`, `O_WRONLY`, - `O_CREAT`, `O_TRUNC`, `O_APPEND`, `MODE_644`, `NL-BYTE`, `NL-BV`. -- **Port record + handles**: `port` (via `define-record-type`) plus - `stdin` / `stdout` / `stderr`. -- **Buffered I/O**: `open-input` / `open-output` / `open-append` / - `close`, `refill!`, `read-bytes`, `read-line`, `read-all`, - `bv-concat-reverse`, `write-bytes`, `write-string`, `write-line`. - -Items to add as the underlying primitives land: - -- [ ] Re-enable `vector->list` / `list->vector` once - `make-vector` / `vector-ref` / `vector-set!` / `vector-length` - are primitives. + +### Records: target R7RS-small semantics + +Decision: track R7RS-small `define-record-type` exactly. The form +introduces a disjoint type and binds **only** these identifiers at +runtime: + +1. The constructor name (e.g. `make-point`) — a procedure. +2. The predicate name (e.g. `point?`) — a procedure. +3. One accessor per field (e.g. `point-x`) — a procedure. +4. One mutator per `(field acc mut)` clause (e.g. `set-point-y!`) — a + procedure. + +Explicitly **not** bound: the type name itself (`point` after +`(define-record-type point …)`). It is purely syntactic; the type +descriptor is not a user-visible value. There is no `record-type-of`, +no way to grab the TD from Scheme code, no `<point-td>`-style +generated binding. R7RS does not provide reflective access; we don't +add one. + +Also **not** in the user-facing API: + +- `record?`, `record-is-a?`, `record-type?` (LISP-C.md currently lists + these — drop from the spec). +- The six `%record-*` primitives (`%make-record-td`, `%make-record`, + `%record-ref`, `%record-set!`, `%record-is-a?`, `%record-td`). + Internal only; they must not appear in `prim_table`. + +Concrete cleanup tasks: + +- [ ] Remove `%make-record-td` / `%make-record` / `%record-ref` / + `%record-set!` / `%record-is-a?` / `%record-td` rows from + `prim_table` in `scheme1/scheme1.P1pp`. The parameterized record + PRIMs (`prim_ctor_entry`, `prim_pred_entry`, `prim_field_ref_entry`, + `prim_field_set_entry`) reach the entry labels directly via the + closure data slot, so removing the public bindings is local. + Tests `38-record-internal-prims.scm` (rewritten to assert unbound) + and `39-record-typename-unbound.scm` are the red-green guards. +- [ ] Update `docs/LISP-C.md`: + - In the `define-record-type` desugaring example (currently lines + 643+), drop the generated `(define <point-td> …)` line. Replace + the `%record-is-a?` / `%record-ref` / `%make-record` references + in the desugaring body with the parameterized-PRIM mechanism, or + flag them as illustrative pseudocode. The user-visible result is + just the four kinds of bindings listed above. + - Drop `record?`, `record-is-a?`, `record-type?` from the + Predicates / equality public-primitive list (line 660–662). Adjust + the "13" predicate count to 10. + - Move the `%record-*` count from "55 user-facing primitives plus 6 + internal record ops" to keep the 6 internal but ensure no + duplication or claim of public exposure. + +Note: `equal?` on records (test 59) keeps working — it walks the +internal layout via the runtime, not via user-callable primitives. ## Hacks and fragile invariants @@ -95,29 +104,10 @@ These work today but are easy to break. Capacity is never reset by `bytevector-copy!` or any other op, so the invariant only protects fresh / never-overwritten bytevectors. -- [ ] **`bytevector-grow!`** is a public primitive (`bv_grow`) that's - effectively only there to make the doubling path testable - (test 34). Not in R7RS, not in LISP.md. Either expose it as part of - a documented mutable-bytevector API or delete and demote `bv_grow` - to internal. - -- [ ] **`%record-*` primitives are exposed publicly** in `prim_table` - alongside the parameterized record entries. LISP-C.md says "internal, - not part of the user-facing primitive list". - -- [ ] **PRIM size grew from 16 to 24 bytes uniformly** to fit the - parameterized data slot used by record ctors / preds / accessors / - mutators. Plain primitives (sys-exit, cons, +, …) waste those 8 - bytes per instance. - -- [ ] **`apply` modification: prim ptr is now passed in `a1`** alongside - args in `a0`. All existing primitives ignore `a1`, but any future - primitive that uses `a1` for anything else will silently break. - -- [ ] **Symbol-table linear scan.** `intern` walks the table from idx 0 - on every call. LISP-C.md describes a 16384-slot open-addressing - hash; we have a 1024-slot linear scan that exits with code 5 on - overflow. +- [ ] **`%record-*` primitives are exposed publicly** — see the + Records: target R7RS-small semantics section above for the full + fix. Tracked there to keep desugaring + spec + tests + table + changes together. ## Test suite caveats @@ -187,10 +177,17 @@ before the suite can be considered authoritative. spawn bug by redefining `spawn` at user level. The prelude's `spawn` / `run` are therefore covered by zero passing tests. -- [ ] **`tests/scheme1/38-record-internal-prims.scm`** — the - `%record-*` primitives are tested via the Scheme surface; the only - way to invoke them is through the public binding, which conflicts - with LISP-C.md's "internal" classification. +- [ ] **`tests/scheme1/38-record-internal-prims.scm`** — rewritten to + assert that `%make-record-td` is **unbound** at user level, matching + the R7RS target (see the records spec section above). Currently red: + the prim is still in `prim_table`. Goes green once the table cleanup + lands. + +- [ ] **`tests/scheme1/39-record-typename-unbound.scm`** — asserts + `(define-record-type point …)` does not bind `point` to anything at + runtime; bare reference is unbound. Currently green (matches + existing impl) and protects against regressions that would add a + hidden TD binding. - [ ] **No test verifies `(set-car! …)` / `(set-cdr! …)`** — the primitives don't exist; spec requires them. @@ -215,17 +212,3 @@ before the suite can be considered authoritative. verify that a `(cond)` with no matching clause and no `else` returns UNSPEC (or whatever the policy is — currently it does, but unspecified by spec). - -## Suggested next steps before shipping - -In rough priority order: - -1. Track down and fix the prelude `spawn`-via-`run` bug; remove the - workaround in test 45. -2. Fill in the spec-required primitives (`eqv?`, `set-car!`, - `set-cdr!`, the comparison family, the bytevector family, the - number/string converters) — many of these unblock the - commented-out helpers in `prelude.scm` (`vector->list` / `list->vector`). -3. `set!`, `pmatch`. -4. Replace the 1024-slot linear-scan symtab with an open-addressing - hash per LISP-C.md. diff --git a/scheme1/scheme1.P1pp b/scheme1/scheme1.P1pp @@ -882,9 +882,13 @@ %tail(&intern) ::is_int - %ld(a0, sp, 0) - %ld(a1, sp, 8) - %tail(&parse_int) + %ld(t0, sp, 0) ; start_off + %ld(t1, sp, 8) ; end_off + %la(a0, &readbuf_buf_ptr) + %ld(a0, a0, 0) + %add(a0, a0, t0) ; ptr = base + start_off + %sub(a1, t1, t0) ; len = end_off - start_off + %tail(&parse_dec) }) # parse_string() -> tagged bytevector in a0. Cursor sits past the @@ -1126,39 +1130,58 @@ %die(msg_bad_char) }) -# parse_int(start_off=a0, end_off=a1) -> tagged fixnum in a0. Leaf. -:parse_int -%scope parse_int - %la(t0, &readbuf_buf_ptr) - %ld(t0, t0, 0) - %add(t1, t0, a1) ; t1 = end pointer = base + end_off - %add(t0, t0, a0) ; t0 = start pointer = base + start_off +# parse_dec(data_ptr=a0, len=a1) -> (tagged fixnum=a0, ok=a1). Leaf. +# Accepts an optional leading '-' followed by one or more decimal digits. +# ok=1 on a fully-consumed valid input; ok=0 on empty input, lone "-", +# or any non-digit byte. On failure a0 still holds the best-effort +# accumulator (sign-applied, retagged) so reader-style callers that +# don't check ok get the same garbage they got before this routine +# validated. UB on integer overflow. +:parse_dec +%scope parse_dec + %li(t4, 0) ; sign flag (0 = positive) + %li(t0, 0) ; accumulator (raw) + %beqz(a1, &::fail) - %li(a2, 0) ; a2 = "is negative" flag (0 = positive) - %lb(a3, t0, 0) - %addi(a3, a3, -45) - %bnez(a3, &::loop) - %li(a2, 1) - %addi(t0, t0, 1) + %lb(t2, a0, 0) + %li(t3, 45) ; '-' + %bne(t2, t3, &::loop) + %li(t4, 1) + %addi(a0, a0, 1) + %addi(a1, a1, -1) + %beqz(a1, &::fail) ::loop - %li(a0, 0) - %li(t2, 10) - ::step - %beq(t0, t1, &::done) - %lb(a3, t0, 0) - %addi(a3, a3, -48) - %mul(a0, a0, t2) - %add(a0, a0, a3) - %addi(t0, t0, 1) - %b(&::step) + %beqz(a1, &::done) + %lb(t2, a0, 0) + %addi(t2, t2, -48) + %bltz(t2, &::fail) + %li(t3, 10) + %bltu(t2, t3, &::digit_ok) + %b(&::fail) + ::digit_ok + %mul(t0, t0, t3) + %add(t0, t0, t2) + %addi(a0, a0, 1) + %addi(a1, a1, -1) + %b(&::loop) ::done - %beqz(a2, &::tag) - %li(t2, 0) - %sub(a0, t2, a0) + %beqz(t4, &::tag) + %li(t1, 0) + %sub(t0, t1, t0) ::tag - %mkfix(a0, a0) + %mkfix(a0, t0) + %li(a1, 1) + %ret + + ::fail + %beqz(t4, &::fail_tag) + %li(t1, 0) + %sub(t0, t1, t0) + ::fail_tag + %mkfix(a0, t0) + %li(a1, 0) %ret %endscope @@ -1356,9 +1379,16 @@ %die(msg_not_proc) ::prim - # Primitives are called with args list in a0 and the prim ptr itself - # in a1, so parameterized prims (eg record accessors) can read their - # data slot via a1+13. Plain primitives ignore a1. + # Primitive calling convention (interface, not coincidence): + # a0 = args list (proper list of evaluated args) + # a1 = the PRIM object itself (HEAP-tagged) + # Parameterized PRIMs (e.g. the per-field record accessors built + # by define-record-type) read their closed-over datum from + # a1+13. Plain PRIMs ignore a1. A primitive that needs a1 as a + # working register must save it first; this convention is shared + # across every entry in prim_table and is not negotiable per + # primitive. prim_apply_entry maintains the same contract when it + # tail-calls back into apply. %mov(a1, a0) %ld(t0, a0, 5) %ld(a0, sp, 0) @@ -2249,6 +2279,213 @@ %ret %endscope +# (bytevector-append bv ...) -- variadic concatenation. Two passes: +# the first sums the bv lengths so we can size the result up front; the +# second walks the args again and memcpy's each src into the result. +# The args list head is saved at +0 because pass 1 walks a separate +# cursor (t1) and pass 2 needs to re-read the head. memcpy clobbers +# t-regs, so the running write offset and remaining-args cursor live +# in the frame across each call. +# +# Frame: 32 bytes +# +0 args list head (re-read for pass 2; cursor during pass 2) +# +8 total length (raw) +# +16 result bv +# +24 write offset (raw, into result.data) +%fn(prim_bv_append_entry, 32, { + %st(a0, sp, 0) + + %li(t0, 0) + %mov(t1, a0) + ::sum_loop + %if_nil(t2, t1, &::sum_done) + %car(t2, t1) + %ld(a0, t2, -3) + %shri(a0, a0, 8) + %add(t0, t0, a0) + %cdr(t1, t1) + %b(&::sum_loop) + ::sum_done + %st(t0, sp, 8) + + %mov(a0, t0) + %call(&bv_alloc) + %st(a0, sp, 16) + + %li(t0, 0) + %st(t0, sp, 24) + + ::copy_loop + %ld(t0, sp, 0) + %if_nil(t1, t0, &::copy_done) + %car(t1, t0) ; src bv + %ld(t2, t1, -3) + %shri(t2, t2, 8) ; src length + + %ld(a0, sp, 16) + %ld(a0, a0, 5) ; result.data + %ld(a3, sp, 24) + %add(a0, a0, a3) ; dst = result.data + offset + %ld(a1, t1, 5) ; src.data + %mov(a2, t2) ; count + + %add(a3, a3, t2) + %st(a3, sp, 24) + %cdr(t0, t0) + %st(t0, sp, 0) + + %call(&memcpy) + %b(&::copy_loop) + + ::copy_done + %ld(a0, sp, 16) +}) + +# (string->symbol bv) -- intern the bytes and return the SYM-tagged +# value. intern copies the name into stable heap storage if it has to +# append, so the bv's data buffer is safe to relocate afterwards. +:prim_string_to_symbol_entry + %car(t0, a0) + %ld(a0, t0, 5) ; data ptr + %ld(a1, t0, -3) + %shri(a1, a1, 8) ; length + %b(&intern) + +# (symbol->string sym) -- fresh bv copy of the symtab name. sym_name +# returns (ptr, len); bv_alloc gives us a clean wrapper; memcpy fills +# the data. Frame holds the (ptr, len) pair across bv_alloc and the +# resulting bv across memcpy. +%fn(prim_symbol_to_string_entry, 24, { + %car(a0, a0) + %sari(a0, a0, 3) ; raw sym idx + %call(&sym_name) ; -> ptr (a0), len (a1) + %st(a0, sp, 0) + %st(a1, sp, 8) + %mov(a0, a1) + %call(&bv_alloc) ; tagged bv in a0 + %st(a0, sp, 16) + %ld(a1, sp, 0) ; src ptr + %ld(a2, sp, 8) ; len + %ld(t0, a0, 5) ; dst = bv.data + %mov(a0, t0) + %call(&memcpy) + %ld(a0, sp, 16) +}) + +# (number->string n) -- decimal repr in a fresh bv. bv_putint takes the +# raw value, so untag first; bv_alloc(0) gives an empty wrapper that +# bv_putint grows in place. +0 holds the raw value across bv_alloc. +%fn(prim_number_to_string_entry, 16, { + %car(t0, a0) + %sari(t0, t0, 3) ; raw value + %st(t0, sp, 0) + %li(a0, 0) + %call(&bv_alloc) + %ld(a1, sp, 0) + %tail(&bv_putint) +}) + +# (string->number bv) -- delegate parsing to parse_dec. Returns #f on +# non-bytevector input, empty string, lone "-", or any non-digit byte. +%fn(prim_string_to_number_entry, 0, { + %car(a0, a0) + %tagof(t0, a0) + %li(t1, %TAG.HEAP) + %bne(t0, t1, &::fail) + %hdr_type(t0, a0) + %li(t1, %HDR.BV) + %bne(t0, t1, &::fail) + + %ld(t0, a0, 5) ; data ptr + %ld(t1, a0, -3) + %shri(t1, t1, 8) ; length + %mov(a0, t0) + %mov(a1, t1) + %call(&parse_dec) ; -> (a0=value, a1=ok) + %bnez(a1, &::end) + ::fail + %li(a0, %imm_val(%IMM.FALSE)) + ::end +}) + +# (boolean? x) -- #t iff x is the IMM.FALSE or IMM.TRUE singleton. +:prim_booleanq_entry +%scope prim_booleanq + %car(t0, a0) + %li(a0, %imm_val(%IMM.TRUE)) + %li(t1, %imm_val(%IMM.FALSE)) + %beq(t0, t1, &::end) + %li(t1, %imm_val(%IMM.TRUE)) + %beq(t0, t1, &::end) + %li(a0, %imm_val(%IMM.FALSE)) + ::end + %ret +%endscope + +# (integer? x) -- #t iff x is a fixnum (low 3 tag bits == TAG.FIXNUM == 0). +:prim_integerq_entry +%scope prim_integerq + %car(t0, a0) + %tagof(t1, t0) + %li(a0, %imm_val(%IMM.FALSE)) + %bnez(t1, &::end) + %li(a0, %imm_val(%IMM.TRUE)) + ::end + %ret +%endscope + +# (procedure? x) -- #t iff x is HEAP-tagged with header HDR.CLOSURE or HDR.PRIM. +:prim_procedureq_entry +%scope prim_procedureq + %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.CLOSURE) + %beq(t1, t2, &::yes) + %li(t2, %HDR.PRIM) + %beq(t1, t2, &::yes) + %b(&::end) + ::yes + %li(a0, %imm_val(%IMM.TRUE)) + ::end + %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) @@ -2342,6 +2579,22 @@ %ret %endscope +# (quotient x y) -- truncating integer division. Both fixnums are tagged +# (real << 3); div(tagged, tagged) yields the raw quotient (the shifts +# cancel), which mkfix retags. UB on y == 0. +:prim_quotient_entry + %args2(t0, t1, a0) + %div(a0, t0, t1) + %mkfix(a0, a0) + %ret + +# (remainder x y) -- truncating remainder, sign of dividend. rem(tagged, +# tagged) = 8 * (real_x rem real_y), already in tagged form. +:prim_remainder_entry + %args2(t0, t1, a0) + %rem(a0, t0, t1) + %ret + :prim_bit_and_entry %car(t0, a0) %cdr(t1, a0) @@ -2356,6 +2609,23 @@ %or(a0, t0, t1) %ret +# (bit-xor x y) -- both operands have low 3 tag bits == 0 (fixnums), so +# bitwise XOR preserves zero tag bits in the result. +:prim_bit_xor_entry + %args2(t0, t1, a0) + %xor(a0, t0, t1) + %ret + +# (bit-not n) -- bitwise complement. Untag, XOR with -1 (= ~n), retag. +# Can't XOR the tagged value directly: that would flip the low 3 tag bits. +:prim_bit_not_entry + %car(t0, a0) + %untag_fix(t0, t0) + %li(t1, -1) + %xor(t0, t0, t1) + %mkfix(a0, t0) + %ret + # (arithmetic-shift n k): k > 0 means left shift; k < 0 means arith right. # Untag both, branch on sign of k, retag. :prim_arith_shift_entry @@ -2645,21 +2915,6 @@ %die(msg_bv_oob) }) -# (bytevector-grow! bv min-cap) -> bv. Forwards to bv_grow; min-cap is -# untagged at the boundary. Useful when a builder pattern wants to -# pre-extend capacity, but also makes the doubling path testable. -:prim_bv_grow_entry -%scope prim_bv_grow - %args2(t0, t1, a0) - %sari(t1, t1, 3) - %bltz(t1, &::bad) - %mov(a0, t0) - %mov(a1, t1) - %b(&bv_grow) - ::bad - %die(msg_bv_oob) -%endscope - # (bytevector-copy! dst dst-start src src-start src-end). Bounds: # 0 <= src-start <= src-end <= src.length and # 0 <= dst-start && dst-start + (src-end-src-start) <= dst.length. @@ -2937,6 +3192,13 @@ # (apply fn rest...) -- the trailing element of `rest` is a list; any # leading elements get prepended to it. apply_build_args walks `rest` and # returns the assembled args list; prim_apply_entry then tail-calls apply. +# +# `apply` is itself a primitive, so on entry here a0 holds (fn . rest) +# and a1 holds the apply PRIM ptr (per the convention documented at +# `apply::prim`). a1 is dead from this primitive's point of view; we +# clobber it freely while assembling args, then tail-call apply, which +# re-derives a1 from the callee fn it dispatches on. Outer convention +# stays intact end-to-end. %fn(prim_apply_entry, 16, { %st(a0, sp, 0) %cdr(a0, a0) @@ -4209,6 +4471,16 @@ :name_set_cdr "set-cdr!" :name_length "length" :name_list_ref "list-ref" +:name_str_to_sym "string->symbol" +:name_sym_to_str "symbol->string" +:name_num_to_str "number->string" +:name_str_to_num "string->number" +:name_bv_append "bytevector-append" +: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?" @@ -4219,8 +4491,12 @@ :name_eq "=" :name_lt "<" :name_gt ">" +:name_quotient "quotient" +:name_remainder "remainder" :name_bit_and "bit-and" :name_bit_or "bit-or" +:name_bit_xor "bit-xor" +:name_bit_not "bit-not" :name_arith_shift "arithmetic-shift" :name_apply "apply" :name_make_bv "make-bytevector" @@ -4229,7 +4505,6 @@ :name_bv_u8_set "bytevector-u8-set!" :name_bv_copy "bytevector-copy" :name_bv_copy_b "bytevector-copy!" -:name_bv_grow "bytevector-grow!" :name_bv_eq "bytevector=?" :name_make_rt "%make-record-td" :name_make_rec "%make-record" @@ -4283,6 +4558,16 @@ &name_set_cdr %(0) $(8) &prim_set_cdr_entry %(0) &name_length %(0) $(6) &prim_length_entry %(0) &name_list_ref %(0) $(8) &prim_list_ref_entry %(0) +&name_str_to_sym %(0) $(14) &prim_string_to_symbol_entry %(0) +&name_sym_to_str %(0) $(14) &prim_symbol_to_string_entry %(0) +&name_num_to_str %(0) $(14) &prim_number_to_string_entry %(0) +&name_str_to_num %(0) $(14) &prim_string_to_number_entry %(0) +&name_bv_append %(0) $(17) &prim_bv_append_entry %(0) +&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) @@ -4293,8 +4578,12 @@ &name_eq %(0) $(1) &prim_eq_entry %(0) &name_lt %(0) $(1) &prim_lt_entry %(0) &name_gt %(0) $(1) &prim_gt_entry %(0) +&name_quotient %(0) $(8) &prim_quotient_entry %(0) +&name_remainder %(0) $(9) &prim_remainder_entry %(0) &name_bit_and %(0) $(7) &prim_bit_and_entry %(0) &name_bit_or %(0) $(6) &prim_bit_or_entry %(0) +&name_bit_xor %(0) $(7) &prim_bit_xor_entry %(0) +&name_bit_not %(0) $(7) &prim_bit_not_entry %(0) &name_arith_shift %(0) $(16) &prim_arith_shift_entry %(0) &name_apply %(0) $(5) &prim_apply_entry %(0) &name_make_bv %(0) $(15) &prim_make_bytevector_entry %(0) @@ -4303,7 +4592,6 @@ &name_bv_u8_set %(0) $(18) &prim_bv_u8_set_entry %(0) &name_bv_copy %(0) $(15) &prim_bv_copy_entry %(0) &name_bv_copy_b %(0) $(16) &prim_bv_copy_bang_entry %(0) -&name_bv_grow %(0) $(16) &prim_bv_grow_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)