From b6d9247b80a03e30f1f93f3db7c73a41c3a16e84 Mon Sep 17 00:00:00 2001 From: Yogthos Date: Mon, 8 Jun 2026 22:38:35 -0400 Subject: [PATCH] =?UTF-8?q?compiler:=20self-hosted=20analyzer=20compiles?= =?UTF-8?q?=20set=20literals=20(#{=E2=80=A6})?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stage 1 Task 1. analyzer.clj punted set literals to the interpreter ((form-set? form) (uncompilable "set literal")); now it builds the set-node IR (already defined in ir.clj) from (form-set-items form), and backend.janet emits (make-phs e1 e2 …) — each element evaluated then the persistent set built, mirroring compiler.janet's emit-set-expr and the interpreter's :jolt/set path. Closes a self-hosted-analyzer vs bootstrap-compiler parity gap: #{…} no longer forces interpreter fallback on the compile path. Gate: conformance 262x3 (+4 set-literal cases incl computed elements / empty / in-let), fixpoint, self-host, sci, suite 3981/66, specs+unit green; core-bench neutral (A/B). set?/disj-as-fns remain deliberately interpreted (in-sync across all three lists) — adjudicated in Task 2. --- jolt-core/jolt/analyzer.clj | 6 +++--- src/jolt/backend.janet | 7 +++++++ test/integration/conformance-test.janet | 6 ++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/jolt-core/jolt/analyzer.clj b/jolt-core/jolt/analyzer.clj index d5d016d..d820318 100644 --- a/jolt-core/jolt/analyzer.clj +++ b/jolt-core/jolt/analyzer.clj @@ -15,12 +15,12 @@ declared — the bootstrap compiles forward refs through var cells, but keeping them to one keeps the compiled namespace simple." (:require [jolt.ir :refer [const local var-ref host-ref if-node do-node invoke - def-node let-node fn-node vector-node map-node + def-node let-node fn-node vector-node map-node set-node quote-node throw-node]] [jolt.host :refer [form-sym? form-sym-name form-sym-ns form-list? form-vec? form-map? form-set? form-char? form-literal? form-elements form-vec-items - form-map-pairs form-special? compile-ns + form-map-pairs form-set-items form-special? compile-ns form-macro? form-expand-1 resolve-global form-sym-meta host-intern! form-syntax-quote-lower]])) @@ -207,6 +207,6 @@ (form-map? form) (map-node (mapv (fn [p] [(analyze ctx (first p) env) (analyze ctx (second p) env)]) (form-map-pairs form))) - (form-set? form) (uncompilable "set literal") + (form-set? form) (set-node (mapv #(analyze ctx % env) (form-set-items form))) (form-list? form) (analyze-list ctx form env) :else (uncompilable "unsupported form")))) diff --git a/src/jolt/backend.janet b/src/jolt/backend.janet index d1d1961..fe797cb 100644 --- a/src/jolt/backend.janet +++ b/src/jolt/backend.janet @@ -230,6 +230,12 @@ (array/push args (emit ctx (in p 1)))) (tuple/slice args)) +# A set literal: build (make-phs e1 e2 …) so each element is evaluated at runtime +# then the persistent set is constructed — mirrors compiler.janet's emit-set-expr. +(defn- emit-set [ctx node] + (def items (map |(emit ctx $) (vview (node :items)))) + (tuple/slice (array/concat @[phm/make-phs] items))) + (set emit (fn emit [ctx raw] (def node (norm-node raw)) @@ -259,6 +265,7 @@ :invoke (emit-invoke ctx node) :vector (emit-vector ctx node) :map (emit-map ctx node) + :set (emit-set ctx node) :quote ['quote (node :form)] (error (string "backend: unhandled op " (node :op)))))) diff --git a/test/integration/conformance-test.janet b/test/integration/conformance-test.janet index 81fa206..368d387 100644 --- a/test/integration/conformance-test.janet +++ b/test/integration/conformance-test.janet @@ -50,6 +50,12 @@ ["map as fn default" "99" "({:a 1} :z 99)"] ["set as fn" "2" "(#{1 2 3} 2)"] ["set as fn miss" "nil" "(#{1 2 3} 9)"] + # set literals compile (Stage 1 Task 1): computed elements are each evaluated + # then the persistent set is built, matching the interpreter. + ["set literal computed" "true" "(= #{1 2} #{(inc 0) 2})"] + ["empty set literal" "true" "(empty? #{})"] + ["set literal count" "3" "(count #{1 2 3})"] + ["set literal in let" "true" "(let [x 5] (= #{5 6} #{x (inc x)}))"] ["keyword as fn" "1" "(:a {:a 1})"] ["map fn over coll" "(quote (1 3))" "(map {:a 1 :b 3} [:a :b])"]