Skip to content

Commit 40f2439

Browse files
committed
fix: into-array in native-image
1 parent 1dbae69 commit 40f2439

File tree

2 files changed

+31
-19
lines changed

2 files changed

+31
-19
lines changed

src/uclj/core.clj

+27-19
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,29 @@
218218
(concat (repeatedly (- (count args) 2) gensym) '[& variadic])
219219
(repeatedly (count args) gensym))))))
220220

221+
(def custom-var-impls (atom {}))
222+
(defmacro custom-var! [v val] `(swap! custom-var-impls assoc ~v ~val))
223+
224+
(declare evaluator)
225+
(custom-var! #'clojure.core/load-file
226+
(fn [fname]
227+
(binding [*file* (io/file fname)]
228+
(with-open [in (new java.io.PushbackReader (io/reader *file*))]
229+
(doseq [read (repeatedly #(read {:eof ::eof} in))
230+
:while (not= ::eof read)]
231+
(evaluator read))))))
232+
233+
;; Due to the closed-world assumption, we cannot instantiate array of any types.
234+
(custom-var! #'clojure.core/into-array
235+
(fn ([xs] (dorun xs) (try (into-array xs) (catch IllegalArgumentException _ (into-array Object xs))))
236+
([x xs] (dorun xs) (try (into-array x xs) (catch IllegalArgumentException _ (into-array Object xs))))))
237+
238+
(declare var-set-reset!)
239+
(custom-var! #'clojure.core/in-ns
240+
(fn [new-ns]
241+
(alter-meta! (var *ns*) assoc :dynamic true)
242+
(var-set-reset! (var *ns*) (create-ns new-ns))))
243+
221244
(def clojure-core-inlined-fns
222245
(template
223246
(hash-map
@@ -227,6 +250,7 @@
227250
v (vals (ns-publics ns))
228251
:when (not (#{#'clojure.core/aget #'clojure.core/aclone ;; suppress reflection warning
229252
#'clojure.core/alength #'clojure.core/aset} v))
253+
:when (not (@custom-var-impls v))
230254
:when (not (:macro (meta v)))
231255
:let [arglists (var->arglists v)]
232256
:when arglists]
@@ -553,25 +577,6 @@
553577
;; runs in GraalVM but does nothing in REPL:
554578
(.doReset v new-val))))
555579

556-
(doseq [lf '[in-ns clojure.core/in-ns]]
557-
(defmethod seq->eval-node lf [&a _ [_ nssym]]
558-
(let [sym-node (->eval-node &a nil nssym)]
559-
(gen-eval-node
560-
(let [new-ns (create-ns (evalme sym-node &b))]
561-
(alter-meta! (var *ns*) assoc :dynamic true)
562-
(var-set-reset! (var *ns*) new-ns))))))
563-
564-
(declare evaluator)
565-
(doseq [lf '[clojure.core/load-file load-file]]
566-
(defmethod seq->eval-node lf [&a _ [_ fname]]
567-
(let [arg (->eval-node &a nil fname)]
568-
(gen-eval-node
569-
(binding [*file* (io/file (evalme arg &b))]
570-
(with-open [in (new java.io.PushbackReader (io/reader *file*))]
571-
(doseq [read (repeatedly #(read {:eof ::eof} in))
572-
:while (not= ::eof read)]
573-
(evaluator read))))))))
574-
575580
;; Needed by (ns) forms.
576581
(defmethod seq->eval-node 'clojure.core/with-loading-context [&a _ [_ & bodies]]
577582
(seq->eval-node &a nil (list* 'do bodies)))
@@ -603,6 +608,9 @@
603608
(let [^clojure.lang.Var resolved-expr (resolve expr)]
604609
(cond (.isMacro resolved-expr)
605610
(throw (new RuntimeException (str "Can't take value of a macro: " resolved-expr)))
611+
(contains? @custom-var-impls resolved-expr)
612+
(let [custom-val (get @custom-var-impls resolved-expr)]
613+
(gen-eval-node custom-val))
606614
(and (bound? resolved-expr) (not (.isDynamic resolved-expr)))
607615
(let [expr-val @resolved-expr] (gen-eval-node {::var resolved-expr} expr-val))
608616
:else

test/clojure_core_test.clj

+4
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,9 @@
4646
(is (= "123" (with-out-str ^{(print 2) (print 3)} #{:b (print 1)}))))
4747
(is (= "123" (with-out-str [^{:b ^{:b (print 3)} {:c (print 2)}} [(print 1) 5]]))))
4848

49+
(deftest test-arrays
50+
;; Long[][][][]... is not supported by the closed-world assumption
51+
(is (every? some? (take 10 (iterate (fn [x] (into-array [x])) 3)))))
52+
4953
(deftest test-xml-lib
5054
(is (map? (clojure.data.xml/parse-str "<a>1</a>"))))

0 commit comments

Comments
 (0)