diff --git a/deps.edn b/deps.edn index 3e88a5ba..3bfbf3b4 100644 --- a/deps.edn +++ b/deps.edn @@ -25,7 +25,8 @@ org.hsqldb/hsqldb {:mvn/version "2.4.0"} datascript/datascript {:mvn/version "0.18.11"} http-kit/http-kit {:mvn/version "2.5.0"} - babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"}} + babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"} + org.clojure/math.combinatorics {:mvn/version "0.1.6"}} :aliases {:main {:main-opts ["-m" "babashka.main"]} :profile diff --git a/project.clj b/project.clj index 4538aaa3..a14c16e2 100644 --- a/project.clj +++ b/project.clj @@ -20,7 +20,8 @@ [org.clojure/tools.cli "1.0.194"] [cheshire "5.10.0"] [nrepl/bencode "1.1.0"] - [borkdude/sci.impl.reflector "0.0.1-java11"]] + [borkdude/sci.impl.reflector "0.0.1-java11"] + [org.clojure/math.combinatorics "0.1.6"]] :profiles {:feature/xml {:source-paths ["feature-xml"] :dependencies [[org.clojure/data.xml "0.2.0-alpha6"]]} :feature/yaml {:source-paths ["feature-yaml"] diff --git a/sci b/sci index ea5a87b3..323a2574 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit ea5a87b34570b7baab358368b192e7ecb764a242 +Subproject commit 323a2574ec4d59a0544a829c1fa529fcbc110140 diff --git a/src/babashka/impl/reify.clj b/src/babashka/impl/reify.clj index cc98666b..11b9cb1f 100644 --- a/src/babashka/impl/reify.clj +++ b/src/babashka/impl/reify.clj @@ -1,23 +1,40 @@ (ns babashka.impl.reify - {:no-doc true}) + {:no-doc true} + (:require [clojure.math.combinatorics :as combo])) +(set! *warn-on-reflection* false) + +(defmacro gen-reify-combos + "Generates pre-compiled reify combinations" + [methods] + (let [subsets (rest (combo/subsets (seq methods)))] + (reduce (fn [opts classes] + (assoc opts + (set (map (fn [[class _]] + (list 'quote class)) + classes)) + (list 'fn ['methods] + (list* 'reify + (mapcat + (fn [[clazz methods]] + (cons clazz + (map + (fn [[meth args]] + (list meth args + (list* + (list 'get-in 'methods + [(list 'quote clazz) (list 'quote meth)]) + args))) + methods))) + classes))))) + {} + subsets))) + +#_:clj-kondo/ignore (def reify-opts - {'java.nio.file.FileVisitor - (fn [{:keys [:methods]}] - {:obj (reify java.nio.file.FileVisitor - (preVisitDirectory [this p attrs] - ((get methods 'preVisitDirectory) this p attrs)) - (postVisitDirectory [this p attrs] - ((get methods 'postVisitDirectory) this p attrs)) - (visitFile [this p attrs] - ((get methods 'visitFile) this p attrs)))}) - 'java.io.FileFilter - (fn [{:keys [:methods]}] - {:obj (reify java.io.FileFilter - (accept [this f] - ((get methods 'accept) this f)))}) - 'java.io.FilenameFilter - (fn [{:keys [:methods]}] - {:obj (reify java.io.FilenameFilter - (accept [this f s] - ((get methods 'accept) this f s)))})}) + (gen-reify-combos + {java.nio.file.FileVisitor {preVisitDirectory [this p attrs] + postVisitDirectory [this p attrs] + visitFile [this p attrs]} + java.io.FileFilter {accept [this f]} + java.io.FilenameFilter {accept [this f s]}})) diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index e8ff53ff..067b216e 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -363,7 +363,16 @@ (is (.exists f2)) (let [v (bb nil "-f" (.getPath (io/file "test-resources" "babashka" "glob.clj")))] (is (vector? v)) - (is (.exists (io/file (first v))))))) + (is (.exists (io/file (first v)))))) + (testing "reify can handle multiple classes at once" + (is (true? (bb nil " +(def filter-obj (reify java.io.FileFilter + (accept [this f] (prn (.getPath f)) true) + java.io.FilenameFilter + (accept [this f name] (prn name) true))) +(def s1 (with-out-str (.listFiles (clojure.java.io/file \".\") filter-obj))) +(def s2 (with-out-str (.list (clojure.java.io/file \".\") filter-obj))) +(and (pos? (count s1)) (pos? (count s2)))"))))) (deftest future-print-test (testing "the root binding of sci/*out*"