;; ========================================================================== ;; test-gate-pins.sx — W14 regression pins for the review's landed fixes ;; ;; The quick-wins batch (commit dc7aa709 + siblings) landed real semantics ;; fixes but shipped WITHOUT pinning tests, so a regression would pass ;; silently. This file pins each confirmed-and-fixed finding with a minimal ;; repro lifted from the review lane files (plans/sx-review/*.md). One suite ;; per finding. ;; ;; TEST-ONLY: no semantics edits. If a pin fails, the fix regressed — do NOT ;; relax the assertion; investigate the evaluator/primitive change. ;; NB: assert= uses `=` (not `equal?`); compare lists with `=`. ;; ========================================================================== ;; -------------------------------------------------------------------------- ;; K18 [W7, high] expt silently wrapped at 63-bit int — now promotes to float ;; like +/*. Repro (core.md): (expt 2 62) -> -4611686018427387904 (wrapped); ;; (expt 2 100) -> 0. Fixed: both are positive floats. ;; -------------------------------------------------------------------------- (defsuite "gate-K18-expt-overflow" (deftest "small integer exponents stay exact" (do (assert= (expt 2 0) 1) (assert= (expt 2 10) 1024))) (deftest "expt 2^62 does not wrap to a negative int" (assert (> (expt 2 62) 0))) (deftest "expt 2^100 does not wrap to zero" (assert (> (expt 2 100) 0))) (deftest "expt 2^100 promotes to float" (assert (number? (expt 2 100))))) ;; -------------------------------------------------------------------------- ;; K20 [W7, high] contains? did not support dicts in the real runtime — ;; (contains? {:a 1} :a) threw "contains?: 2 args", contradicting its :doc ;; ("Dicts: key check"). Fixed: dict key membership works; lists/strings ;; unchanged. Repro (core.md). ;; -------------------------------------------------------------------------- (defsuite "gate-K20-contains-dict" (deftest "contains? finds a present dict key" (assert (contains? {:a 1 :b 2} :a))) (deftest "contains? reports a missing dict key as false" (assert (not (contains? {:a 1 :b 2} :zz)))) (deftest "contains? still works on list membership" (do (assert (contains? (list 10 20 30) 20)) (assert (not (contains? (list 10 20 30) 99))))) (deftest "contains? still works on string substrings" (assert (contains? "hello" "ell")))) ;; -------------------------------------------------------------------------- ;; K09 [W5, high] R7RS longhand (unquote-splicing X) silently no-spliced — ;; only shorthand ,@/`splice-unquote` was recognized, so the longhand ;; serialized literally (zero-splice). Fixed: aliased to splice-unquote. ;; Repro (core.md). ;; -------------------------------------------------------------------------- (defsuite "gate-K09-longhand-unquote-splicing" (deftest "longhand unquote-splicing splices a list" (assert= (quasiquote (1 (unquote-splicing (list 2 3)) 4)) (list 1 2 3 4))) (deftest "longhand unquote-splicing of an empty list contributes nothing" (assert= (quasiquote (0 (unquote-splicing (list)) 9)) (list 0 9))) (deftest "shorthand splice-unquote still works" (assert= (quasiquote (a (splice-unquote (list 2 3)) z)) (list (quote a) 2 3 (quote z))))) ;; -------------------------------------------------------------------------- ;; K11 [W5, high] guard re-raise sentinel was a plain forgeable symbol — a ;; body/clause legitimately returning (list '__guard-reraise__ X) was ;; misread as a re-raise of X. Fixed: sentinel gensym'd per execution, so a ;; user value with that head is returned as data. Repro (core.md). ;; -------------------------------------------------------------------------- (defsuite "gate-K11-guard-reraise-forgeable" (deftest "body value shaped like the sentinel is returned as data" (assert= (guard (e (true "caught")) (list (quote __guard-reraise__) "hi")) (list (quote __guard-reraise__) "hi"))) (deftest "clause returning the forged sentinel is not re-raised" (assert= (guard (e (true (list (quote __guard-reraise__) "forged"))) (error "boom")) (list (quote __guard-reraise__) "forged")))) ;; -------------------------------------------------------------------------- ;; K39 [W5, med] `do` misparsed a first form whose head is a list (an IIFE) ;; as a Scheme do-loop binding spec. Repro (core.md): (do ((fn (x) x) 5) 99) ;; threw "first: expected list, got 5"; expected 99. Fixed: `do` is begin. ;; -------------------------------------------------------------------------- (defsuite "gate-K39-do-iife-head" (deftest "do with an IIFE first form returns the last form (not a do-loop)" (assert= (do ((fn (x) x) 5) 99) 99)) (deftest "do with a single IIFE form returns its value" (assert= (do ((fn () 42))) 42)))