boot2

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

commit 80d020d670c6ae7d9443d603301d7a989b1a7c7a
parent 55aff4595c1c22c2a6a3bd402153a547a57ad516
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Sat, 25 Apr 2026 13:58:21 -0700

scheme1: > primitive, positive? prelude entry, comparison test coverage

Adds prim_gt (mirrors prim_lt with swapped operands to %blt), uncomments
positive? in the prelude now that > is available, and extends
25-comparisons.scm with both directions of >, positive?, and negative?.
TODO doc trimmed: remove completed bug entries, drop already-implemented
helpers from the missing-primitives list, and add > to the 2-arg-only set.

Diffstat:
Mdocs/scheme-shell-todo.md | 34++++------------------------------
Mscheme1/prelude.scm | 4+---
Mscheme1/scheme1.P1pp | 14++++++++++++++
Mtests/scheme1/25-comparisons.expected-exit | 2+-
Mtests/scheme1/25-comparisons.scm | 38++++++++++++++++++++++++++++++--------
5 files changed, 50 insertions(+), 42 deletions(-)

diff --git a/docs/scheme-shell-todo.md b/docs/scheme-shell-todo.md @@ -25,48 +25,22 @@ gap that must be addressed before calling scheme1 shippable. redefining `spawn` at user level. Until this is understood, the prelude's `spawn` and `run` are effectively unverified. -- [x] **No heap-exhaustion check.** `cons`, `alloc_hdr`, and - `alloc_bytes` now compare `heap_next + bytes` against `:heap_end` - (initialized to `heap_buf_ptr + HEAP_CAP_BYTES` at startup) and abort - via `runtime_error` on overflow. `load_source` and `eval_prelude` - reject sources that would overrun `READBUF_CAP_BYTES`. - -- [x] **No symtab-name copy bound.** Name copies still go through - `alloc_bytes`, but that path now errors cleanly when the heap arena - is exhausted instead of silently scribbling into the symtab. - `intern`'s 1024-slot count check remains and routes through the same - `runtime_error`. - -- [x] **Bytevector-u8-set! / -ref / -copy / -copy! have no bounds - check.** All four now check `0 <= idx < length` (or - `0 <= start <= end <= length`, plus the dst-side range for - `bytevector-copy!`) and abort via `runtime_error`. `make-bytevector` - and `bytevector-grow!` reject negative arguments through the same - path. - -- [ ] **`car` / `cdr` of non-pair, `quotient`/`remainder` of zero, etc., - are silent UB** — same policy as above, no abort path. - ## Spec features still missing Per LISP.md and LISP-C.md, but not implemented: - [ ] **Special forms missing**: `set!`, `pmatch`, `cond`'s - `=>` arrow form. `pmatch` is called out by LISP-C.md as a built-in - special form needed by the self-hosted compiler. + `=>` arrow form. - [ ] **Primitives missing** (LISP.md lists them as required): - Predicates: `boolean?`, `integer?`, `string?`, `procedure?`, `record?`, `record-type?` - Numeric: `quotient`, `remainder`, `modulo`, - `negative?`, `abs`, `min`, `max`, `bit-xor`, + `abs`, `min`, `max`, `bit-xor`, `bit-not`, `number->string`, `string->number` - - Pair / list: `set-car!`, `set-cdr!`, `length`, `list-ref`, `map`, - `for-each` as primitives (we provide them via the prelude only) + - Pair / list: `set-car!`, `set-cdr!`, `length`, - Bytevector: `bytevector-append`, `bytevector=?`, `string->symbol`, `symbol->string` -- [ ] **`+ - * = <` are 2-arg only.** R7RS allows any arity. -- [ ] **`apply` is variadic on the trailing list** but otherwise - unverified for arity edge cases. +- [ ] **`+ - * = < >` 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 diff --git a/scheme1/prelude.scm b/scheme1/prelude.scm @@ -12,9 +12,7 @@ (define (>= x y) (if (< x y) #f #t)) (define (negative? x) (< x 0)) - -; positive? needs `>`, which is not yet a primitive. -; (define (positive? x) (> x 0)) +(define (positive? x) (> x 0)) (define (abs x) (if (< x 0) (- 0 x) x)) diff --git a/scheme1/scheme1.P1pp b/scheme1/scheme1.P1pp @@ -2272,6 +2272,18 @@ %ret %endscope +:prim_gt_entry +%scope prim_gt + %car(t0, a0) + %cdr(t1, a0) + %car(t1, t1) + %li(a0, %imm_val(%IMM.TRUE)) + %blt(t1, t0, &::end) + %li(a0, %imm_val(%IMM.FALSE)) + ::end + %ret +%endscope + :prim_bit_and_entry %car(t0, a0) %cdr(t1, a0) @@ -4143,6 +4155,7 @@ :name_mult "*" :name_eq "=" :name_lt "<" +:name_gt ">" :name_bit_and "bit-and" :name_bit_or "bit-or" :name_arith_shift "arithmetic-shift" @@ -4211,6 +4224,7 @@ &name_mult %(0) $(1) &prim_mult_entry %(0) &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_bit_and %(0) $(7) &prim_bit_and_entry %(0) &name_bit_or %(0) $(6) &prim_bit_or_entry %(0) &name_arith_shift %(0) $(16) &prim_arith_shift_entry %(0) diff --git a/tests/scheme1/25-comparisons.expected-exit b/tests/scheme1/25-comparisons.expected-exit @@ -1 +1 @@ -26 +33 diff --git a/tests/scheme1/25-comparisons.scm b/tests/scheme1/25-comparisons.scm @@ -1,4 +1,6 @@ -; <, =, zero?, not, eq?, pair?, null? interact correctly with truthiness. +; <, =, zero?, not, eq?, pair?, null?, >, positive?, negative? interact +; correctly with truthiness. Failure at depth N exits N (1..16); full +; success exits 33. (sys-exit (if (< 3 5) (if (= 4 4) @@ -6,10 +8,30 @@ (if (not (pair? '())) (if (pair? (cons 1 2)) (if (null? '()) - (if (eq? 'a 'a) 26 1) - 2) - 3) - 4) - 5) - 6) - 7)) + (if (eq? 'a 'a) + (if (> 5 3) + (if (not (> 3 5)) + (if (not (> 4 4)) + (if (positive? 7) + (if (not (positive? -5)) + (if (not (positive? 0)) + (if (negative? -3) + (if (not (negative? 3)) + (if (not (negative? 0)) + 33 + 1) + 2) + 3) + 4) + 5) + 6) + 7) + 8) + 9) + 10) + 11) + 12) + 13) + 14) + 15) + 16))