From 75130876c785897fd9ee81b1241faf3678caa1f5 Mon Sep 17 00:00:00 2001 From: giles Date: Mon, 6 Apr 2026 14:34:16 +0000 Subject: [PATCH] =?UTF-8?q?Fix=20compiler:=20handle=20clause-syntax=20cond?= =?UTF-8?q?=20=E2=80=94=20(cond=20(test=20body)=20...)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit compile-cond expected flat syntax (cond test body test body ...) but hs-parse uses clause syntax (cond (test body) (test body) ...). The compiler treated the whole clause as the test expression, compiling ((and ...) (do ...)) as a function call — which tried to call the and-result as a function, producing "not callable: false" JIT errors. Now detects clause syntax (first arg is a list whose first element is also a list) and flattens to the expected format before compilation. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/compiler.sx | 63 ++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/lib/compiler.sx b/lib/compiler.sx index 5f2e328a..1f0e963f 100644 --- a/lib/compiler.sx +++ b/lib/compiler.sx @@ -724,38 +724,41 @@ compile-cond (fn (em args scope tail?) - "Compile (cond test1 body1 test2 body2 ... :else fallback)." - (if - (< (len args) 2) - (emit-op em 2) - (let - ((test (first args)) - (body (nth args 1)) - (rest-clauses (if (> (len args) 2) (slice args 2) (list)))) - (if - (or - (and - (= (type-of test) "keyword") - (= (keyword-name test) "else")) - (= test true)) - (compile-expr em body scope tail?) - (do - (compile-expr em test scope false) - (emit-op em 33) - (let - ((skip (current-offset em))) - (emit-i16 em 0) - (compile-expr em body scope tail?) - (emit-op em 32) + "Compile (cond test1 body1 test2 body2 ... :else fallback).\n Also handles clause syntax: (cond (test1 body1) (test2 body2) ...)." + (let + ((flat-args (if (and (not (empty? args)) (list? (first args)) (> (len (first args)) 1) (list? (first (first args)))) (reduce (fn (acc clause) (if (list? clause) (append acc clause) (append acc (list clause)))) (list) args) args))) + (if + (< (len flat-args) 2) + (emit-op em 2) + (let + ((test (nth flat-args 0)) + (body (nth flat-args 1)) + (rest-clauses + (if (> (len flat-args) 2) (slice flat-args 2) (list)))) + (if + (or + (and + (= (type-of test) "keyword") + (= (keyword-name test) "else")) + (= test true)) + (compile-expr em body scope tail?) + (do + (compile-expr em test scope false) + (emit-op em 33) (let - ((end-jump (current-offset em))) + ((skip (current-offset em))) (emit-i16 em 0) - (patch-i16 em skip (- (current-offset em) (+ skip 2))) - (compile-cond em rest-clauses scope tail?) - (patch-i16 - em - end-jump - (- (current-offset em) (+ end-jump 2))))))))))) + (compile-expr em body scope tail?) + (emit-op em 32) + (let + ((end-jump (current-offset em))) + (emit-i16 em 0) + (patch-i16 em skip (- (current-offset em) (+ skip 2))) + (compile-cond em rest-clauses scope tail?) + (patch-i16 + em + end-jump + (- (current-offset em) (+ end-jump 2)))))))))))) (define compile-case (fn