The trio the author decided on 2026-09-20 is now all built: def is CL's defparameter — its initialiser runs on every daemon re-run, unguarded, so an edited initialiser repaints the same storage on C-c C-c plus re-run — defonce (Clojure's name for CL's defvar, per the author) initialises once behind the .init~once. flag, and defconst stays the image. One parse arm reads both forms; the difference is Ast.reinit, carried to Tast.global's grerun. Emit.startup_plan gives a def no guard flag, and Check.check_global lifts every def initialiser — zero and literal included — into global/<n>, so the host's startup reaches it through the function cell and a re-evaluated def swaps it (Session's def_inits; Emit.redefinition declares the cell for a non-sibling target). The old defvar spelling is refused with the rename and both compiling spellings, and every program, test, doc and editor list is swept — except sand.flan, the author's live WIP, whose seven defvar lines are flagged in FIX.org and keep its three dependent tests red on this branch.
86 lines
3.2 KiB
Plaintext
86 lines
3.2 KiB
Plaintext
;;;; A shift whose count reaches the operand's own width, at every width.
|
||
;;;;
|
||
;;;; This backend computes every integer in a full 64-bit register and narrows
|
||
;;;; only on the way to memory, so the shift instruction it emits is the 64-bit
|
||
;;;; one whatever the type says. The hardware masks a 64-bit shift's count to
|
||
;;;; 63 — not to 31, 15 or 7 — so for every width below 64 the mask the
|
||
;;;; language promises (count masked to width−1, which is what emit writes into
|
||
;;;; the IR) has to be emitted by hand. Without it a count of 32 on an i32
|
||
;;;; shifts the value clean out of the low half and stores zero, where the rule
|
||
;;;; says the count is 0 and the value comes back unchanged.
|
||
;;;;
|
||
;;;; Every count is a global and never a literal: the checker rejects a literal
|
||
;;;; count that is out of range — that is a typo, not a program — so the only
|
||
;;;; shift that can reach either backend out of range is a computed one, and a
|
||
;;;; literal would be folded away before the code under test ran anyway.
|
||
|
||
(defonce i8min i8 -128)
|
||
(defonce i16min i16 -32768)
|
||
(defonce i32min i32 -2147483648)
|
||
(defonce i64min i64 -9223372036854775808)
|
||
(defonce u8hi u8 255)
|
||
(defonce u16hi u16 65535)
|
||
(defonce u32hi u32 4294967295)
|
||
(defonce one8 i8 1)
|
||
(defonce one16 i16 1)
|
||
(defonce one32 i32 1)
|
||
(defonce oneu8 u8 1)
|
||
(defonce oneu16 u16 1)
|
||
(defonce oneu32 u32 1)
|
||
(defonce one64 i64 1)
|
||
|
||
(defonce c8 i8 8)
|
||
(defonce c9 i8 9)
|
||
(defonce cu8 u8 8)
|
||
(defonce c16 i16 16)
|
||
(defonce cu16 u16 17)
|
||
(defonce c32 i32 32)
|
||
(defonce c33 i32 33)
|
||
(defonce cu32 u32 32)
|
||
(defonce cu33 u32 33)
|
||
(defonce c64 i64 64)
|
||
(defonce c65 i64 65)
|
||
|
||
(defn main [] i32
|
||
;; ── The count exactly at the width: masks to 0, so nothing moves ──
|
||
(println (<< one8 c8))
|
||
(println (<< one16 c16))
|
||
(println (<< one32 c32))
|
||
(println (<< oneu8 cu8))
|
||
(println (<< oneu32 cu32))
|
||
(println (<< one64 c64))
|
||
|
||
;; ── The sign bit, shifted by the width ────────────────────────────
|
||
;; An arithmetic shift of a negative number by a count the hardware would
|
||
;; read as the full width answers all-ones; masked, it answers the value.
|
||
(println (<< i8min c8))
|
||
(println (>> i8min c8))
|
||
(println (<< i16min c16))
|
||
(println (>> i16min c16))
|
||
(println (<< i32min c32))
|
||
(println (>> i32min c32))
|
||
(println (<< i64min c64))
|
||
(println (>> i64min c64))
|
||
|
||
;; ── The same edge unsigned, where the shift is logical ────────────
|
||
(println (>> u8hi cu8))
|
||
(println (>> u16hi cu16)) ; 17, one past the width: masks to 1
|
||
(println (>> u32hi cu32))
|
||
(println (<< u32hi cu33)) ; 33 masks to 1: the top of u32 doubled, wrapped
|
||
|
||
;; ── One past the width, where the masked count is 1 ───────────────
|
||
(println (<< one8 c9))
|
||
(println (<< one32 c33))
|
||
(println (<< one64 c65))
|
||
|
||
;; ── And the ordinary counts, which never needed a mask ────────────
|
||
(println (<< one32 one32))
|
||
(println (>> i32min one32))
|
||
(println (>> u32hi oneu32))
|
||
(println (>> i8min one8))
|
||
(println (>> u8hi oneu8))
|
||
(println (<< one16 one16))
|
||
(println (>> i16min one16))
|
||
(println (>> u16hi oneu16))
|
||
0)
|