compiler: self-hosted analyzer compiles set literals (#{…})
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.
This commit is contained in:
parent
fdf2c742c4
commit
b6d9247b80
3 changed files with 16 additions and 3 deletions
|
|
@ -15,12 +15,12 @@
|
||||||
declared — the bootstrap compiles forward refs through var cells, but keeping
|
declared — the bootstrap compiles forward refs through var cells, but keeping
|
||||||
them to one keeps the compiled namespace simple."
|
them to one keeps the compiled namespace simple."
|
||||||
(:require [jolt.ir :refer [const local var-ref host-ref if-node do-node invoke
|
(: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]]
|
quote-node throw-node]]
|
||||||
[jolt.host :refer [form-sym? form-sym-name form-sym-ns form-list?
|
[jolt.host :refer [form-sym? form-sym-name form-sym-ns form-list?
|
||||||
form-vec? form-map? form-set? form-char?
|
form-vec? form-map? form-set? form-char?
|
||||||
form-literal? form-elements form-vec-items
|
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-macro? form-expand-1 resolve-global
|
||||||
form-sym-meta host-intern! form-syntax-quote-lower]]))
|
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)
|
(form-map? form) (map-node (mapv (fn [p] [(analyze ctx (first p) env)
|
||||||
(analyze ctx (second p) env)])
|
(analyze ctx (second p) env)])
|
||||||
(form-map-pairs form)))
|
(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)
|
(form-list? form) (analyze-list ctx form env)
|
||||||
:else (uncompilable "unsupported form"))))
|
:else (uncompilable "unsupported form"))))
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,12 @@
|
||||||
(array/push args (emit ctx (in p 1))))
|
(array/push args (emit ctx (in p 1))))
|
||||||
(tuple/slice args))
|
(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
|
(set emit
|
||||||
(fn emit [ctx raw]
|
(fn emit [ctx raw]
|
||||||
(def node (norm-node raw))
|
(def node (norm-node raw))
|
||||||
|
|
@ -259,6 +265,7 @@
|
||||||
:invoke (emit-invoke ctx node)
|
:invoke (emit-invoke ctx node)
|
||||||
:vector (emit-vector ctx node)
|
:vector (emit-vector ctx node)
|
||||||
:map (emit-map ctx node)
|
:map (emit-map ctx node)
|
||||||
|
:set (emit-set ctx node)
|
||||||
:quote ['quote (node :form)]
|
:quote ['quote (node :form)]
|
||||||
(error (string "backend: unhandled op " (node :op))))))
|
(error (string "backend: unhandled op " (node :op))))))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,12 @@
|
||||||
["map as fn default" "99" "({:a 1} :z 99)"]
|
["map as fn default" "99" "({:a 1} :z 99)"]
|
||||||
["set as fn" "2" "(#{1 2 3} 2)"]
|
["set as fn" "2" "(#{1 2 3} 2)"]
|
||||||
["set as fn miss" "nil" "(#{1 2 3} 9)"]
|
["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})"]
|
["keyword as fn" "1" "(:a {:a 1})"]
|
||||||
["map fn over coll" "(quote (1 3))" "(map {:a 1 :b 3} [:a :b])"]
|
["map fn over coll" "(quote (1 3))" "(map {:a 1 :b 3} [:a :b])"]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue