[#89] #t self-evaluates: the truth constant no longer dies as a value #93

Merged
robertismo merged 1 commit from 89-t into master 2026-09-30 01:33:55 +00:00
Owner

#89 — "Can't put #t in certain positions": root-caused and fixed.

The trap: #t reads as the symbol t and truthy() accepts any symbol, so #t worked as a test ((if #t ...), a cond clause). As a value — a hook body returning #t, a let binding, a cond result — eval ran the symbol lookup and died with "unbound symbol: t". In headless benches that error was swallowed and the hook silently went inert. #f never had the problem: it reads as nil, and nil self-evaluates.

The fix: t is now a self-evaluating constant exactly like nil — eval returns trueVal for the symbol t before any environment lookup (lisp.go, 7 lines). t is also added to the reserved names so a brain can't redefine it, matching the constant semantics.

Regression tests (t_truth_test.go): (if #t 1 2) → 1; (cond (#t 7)) → 7; a let binding carrying #t; a defun returning #t; #f still falsy; a (define-hook revoke? () #t) file that loads and returns truthy through callHook; (defvar t 5) rejected at load.

Verified: go build, go test -count=1 (full suite), go vet, spectate smoke seed 33 → 0 ai errors / 0 divergence.

Found while Lane B hit it on #80 (their workaround was numeric 1/0); this makes the Lisp behave the way a Lisp should and removes the whole class of silent failures.

#89 — "Can't put #t in certain positions": root-caused and fixed. **The trap**: `#t` reads as the symbol `t` and `truthy()` accepts any symbol, so `#t` worked as a *test* (`(if #t ...)`, a cond clause). As a *value* — a hook body returning `#t`, a let binding, a cond result — eval ran the symbol lookup and died with "unbound symbol: t". In headless benches that error was swallowed and the hook silently went inert. `#f` never had the problem: it reads as nil, and nil self-evaluates. **The fix**: `t` is now a self-evaluating constant exactly like nil — eval returns `trueVal` for the symbol `t` before any environment lookup (lisp.go, 7 lines). `t` is also added to the reserved names so a brain can't redefine it, matching the constant semantics. **Regression tests** (t_truth_test.go): `(if #t 1 2)` → 1; `(cond (#t 7))` → 7; a let binding carrying #t; a defun returning #t; `#f` still falsy; a `(define-hook revoke? () #t)` file that loads and returns truthy through callHook; `(defvar t 5)` rejected at load. **Verified**: go build, go test -count=1 (full suite), go vet, spectate smoke seed 33 → 0 ai errors / 0 divergence. Found while Lane B hit it on #80 (their workaround was numeric 1/0); this makes the Lisp behave the way a Lisp should and removes the whole class of silent failures.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Winnie/bankwars!93
No description provided.