From e21285ac82dec295449edfb602c902ec25121184 Mon Sep 17 00:00:00 2001 From: Fogus Date: Mon, 2 Dec 2024 17:02:35 -0500 Subject: [PATCH 1/8] CLJ-2888: WiP --- src/clj/clojure/genclass.clj | 22 +++++++++++++++++++++- src/jvm/clojure/lang/Util.java | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index 710e58a1a3..df0b6befcd 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -101,7 +101,27 @@ 'char Character/TYPE 'chars (Class/forName "[C")}) -(defn- ^Class the-class [x] +(defn- maybe-array-descriptor [x] + (if-let [dim (and (symbol? x) + (namespace x) + (clojure.lang.Util/isPosDigit (name x)) + (-> x name (.charAt 0) int (- (int \0))))] + (let [cn (namespace x) + classname (if (some #{\.} cn) cn (str "java.lang." cn))] + (str (String/join "" ^Iterable (repeat dim "[")) "L" classname ";")) + (str x))) + +(defn- ^Class the-class [x] + (cond + (class? x) x + (contains? prim->class x) (prim->class x) + :else (let [strx (maybe-array-descriptor x)] + (clojure.lang.RT/classForName + (if (some #{\. \[} strx) + strx + (str "java.lang." strx)))))) + +#_(defn- ^Class the-class [x] (cond (class? x) x (contains? prim->class x) (prim->class x) diff --git a/src/jvm/clojure/lang/Util.java b/src/jvm/clojure/lang/Util.java index 11647f800c..a5ca27ec46 100644 --- a/src/jvm/clojure/lang/Util.java +++ b/src/jvm/clojure/lang/Util.java @@ -256,7 +256,7 @@ static public Object loadWithClass(String scriptbase, Class loadFrom) throws } } -static boolean isPosDigit(String s) { +public static boolean isPosDigit(String s) { if(s.length() != 1) return false; char ch = s.charAt(0); From 7bfb0bc7a78fad533763b8f18bd6f4c4fc091624 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 10 Dec 2024 09:04:35 -0500 Subject: [PATCH 2/8] properly handling prims --- src/clj/clojure/genclass.clj | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index df0b6befcd..03b67f95c4 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -107,8 +107,14 @@ (clojure.lang.Util/isPosDigit (name x)) (-> x name (.charAt 0) int (- (int \0))))] (let [cn (namespace x) - classname (if (some #{\.} cn) cn (str "java.lang." cn))] - (str (String/join "" ^Iterable (repeat dim "[")) "L" classname ";")) + ^Class pc (prim->class (symbol cn)) + classname (cond (some #{\.} cn) cn + pc (-> pc Type/getType Type/.getDescriptor) + :default (str "java.lang." cn)) + ^Iterable dim-descr (repeat dim "[")] + (if pc + (str (String/join "" dim-descr) classname) + (str (String/join "" dim-descr) "L" classname ";"))) (str x))) (defn- ^Class the-class [x] From 9d55d9f1a960de2d5b0c2f3c6695c930df34b3de Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 10 Dec 2024 09:37:19 -0500 Subject: [PATCH 3/8] Tightening code --- src/clj/clojure/genclass.clj | 12 +++++------- src/jvm/clojure/lang/Compiler.java | 2 +- test/clojure/test_clojure/genclass.clj | 10 ++++++++++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index 03b67f95c4..ab9685e884 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -107,14 +107,12 @@ (clojure.lang.Util/isPosDigit (name x)) (-> x name (.charAt 0) int (- (int \0))))] (let [cn (namespace x) - ^Class pc (prim->class (symbol cn)) - classname (cond (some #{\.} cn) cn - pc (-> pc Type/getType Type/.getDescriptor) - :default (str "java.lang." cn)) ^Iterable dim-descr (repeat dim "[")] - (if pc - (str (String/join "" dim-descr) classname) - (str (String/join "" dim-descr) "L" classname ";"))) + (if-let [^Class pc (clojure.lang.Compiler/primClass (symbol cn))] + (str (String/join "" dim-descr) (-> pc Type/getType Type/.getDescriptor)) + (str (String/join "" dim-descr) "L" + (if (some #{\.} cn) cn (str "java.lang." cn)) + ";"))) (str x))) (defn- ^Class the-class [x] diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 6324456fa1..2b957fc20b 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -9184,7 +9184,7 @@ static Class retType(Class tc, Class ret){ return tc; } - static Class primClass(Symbol sym){ + public static Class primClass(Symbol sym){ if(sym == null) return null; Class c = null; diff --git a/test/clojure/test_clojure/genclass.clj b/test/clojure/test_clojure/genclass.clj index 18e808dc11..48ad866365 100644 --- a/test/clojure/test_clojure/genclass.clj +++ b/test/clojure/test_clojure/genclass.clj @@ -149,3 +149,13 @@ (visitSource [source debug] (.append sourceFile source)))] (.accept classReader sourceVisitor 0) (is (= "examples.clj" (str sourceFile))))) + +(deftest array-descriptors->class + (are [descr c] (= (#'clojure.core/the-class descr) c) + "[Ljava.util.UUID;" java.util.UUID/1 + 'String java.lang.String + 'String/1 java.lang.String/1 + 'java.util.UUID java.util.UUID + 'java.util.UUID/2 java.util.UUID/2 + 'int/1 int/1 + 'boolean/9 boolean/9)) From 8f6ebbf66d8d3b1569be586a68ed714e289517f0 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 10 Dec 2024 09:42:22 -0500 Subject: [PATCH 4/8] remove old the-class impl --- src/clj/clojure/genclass.clj | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index ab9685e884..6ca9fe77b2 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -125,16 +125,6 @@ strx (str "java.lang." strx)))))) -#_(defn- ^Class the-class [x] - (cond - (class? x) x - (contains? prim->class x) (prim->class x) - :else (let [strx (str x)] - (clojure.lang.RT/classForName - (if (some #{\. \[} strx) - strx - (str "java.lang." strx)))))) - ;; someday this can be made codepoint aware (defn- valid-java-method-name [^String s] From e01b2a7aabfdc926ef90dd4d59190194a7fc53d6 Mon Sep 17 00:00:00 2001 From: Fogus Date: Thu, 12 Dec 2024 07:58:53 -0500 Subject: [PATCH 5/8] rearranging to highlight user intent --- src/clj/clojure/genclass.clj | 44 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index 6ca9fe77b2..ba621778bc 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -101,29 +101,33 @@ 'char Character/TYPE 'chars (Class/forName "[C")}) -(defn- maybe-array-descriptor [x] - (if-let [dim (and (symbol? x) - (namespace x) - (clojure.lang.Util/isPosDigit (name x)) - (-> x name (.charAt 0) int (- (int \0))))] - (let [cn (namespace x) - ^Iterable dim-descr (repeat dim "[")] - (if-let [^Class pc (clojure.lang.Compiler/primClass (symbol cn))] - (str (String/join "" dim-descr) (-> pc Type/getType Type/.getDescriptor)) - (str (String/join "" dim-descr) "L" - (if (some #{\.} cn) cn (str "java.lang." cn)) - ";"))) - (str x))) +(defn- array-class? [x] + (and (symbol? x) + (namespace x) + (clojure.lang.Util/isPosDigit (name x)))) + +(defn- resolve-array-class [x] + (clojure.lang.RT/classForName + (let [dim (-> x name (.charAt 0) int (- (int \0))) + cn (namespace x) + ^Iterable dim-descr (repeat dim "[")] + (if-let [^Class pc (clojure.lang.Compiler/primClass (symbol cn))] + (str (String/join "" dim-descr) (-> pc Type/getType Type/.getDescriptor)) + (str (String/join "" dim-descr) "L" + (if (some #{\.} cn) cn (str "java.lang." cn)) + ";"))))) (defn- ^Class the-class [x] (cond - (class? x) x - (contains? prim->class x) (prim->class x) - :else (let [strx (maybe-array-descriptor x)] - (clojure.lang.RT/classForName - (if (some #{\. \[} strx) - strx - (str "java.lang." strx)))))) + (class? x) x + (symbol? x) (cond (contains? prim->class x) (prim->class x) + (array-class? x) (resolve-array-class x) + :else (let [strx (str x)] + (clojure.lang.RT/classForName + (if (some #{\. \[} strx) + strx + (str "java.lang." strx))))) + :else (clojure.lang.RT/classForName x))) ;; someday this can be made codepoint aware (defn- valid-java-method-name From 9acdde0ac7e5bb1c3d97ed5edaf061a9ee7f2468 Mon Sep 17 00:00:00 2001 From: Fogus Date: Thu, 19 Dec 2024 15:41:46 -0500 Subject: [PATCH 6/8] opening Compiler helpers --- src/clj/clojure/genclass.clj | 23 ++++++++--------------- src/jvm/clojure/lang/Compiler.java | 18 +++++++++++++----- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index ba621778bc..f42d507950 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -101,27 +101,20 @@ 'char Character/TYPE 'chars (Class/forName "[C")}) -(defn- array-class? [x] - (and (symbol? x) - (namespace x) - (clojure.lang.Util/isPosDigit (name x)))) - -(defn- resolve-array-class [x] +(defn- resolve-array-class [sym] (clojure.lang.RT/classForName - (let [dim (-> x name (.charAt 0) int (- (int \0))) - cn (namespace x) - ^Iterable dim-descr (repeat dim "[")] - (if-let [^Class pc (clojure.lang.Compiler/primClass (symbol cn))] - (str (String/join "" dim-descr) (-> pc Type/getType Type/.getDescriptor)) - (str (String/join "" dim-descr) "L" - (if (some #{\.} cn) cn (str "java.lang." cn)) - ";"))))) + (let [cn (namespace sym)] + (clojure.lang.Compiler$HostExpr/buildArrayClassDescriptor + (if (or (clojure.lang.Compiler/primClass (symbol cn)) (some #{\.} cn)) + sym + (symbol (str "java.lang." cn) (name sym))))))) (defn- ^Class the-class [x] (cond (class? x) x (symbol? x) (cond (contains? prim->class x) (prim->class x) - (array-class? x) (resolve-array-class x) + (clojure.lang.Compiler$HostExpr/looksLikeArrayClass x) + (resolve-array-class x) :else (let [strx (str x)] (clojure.lang.RT/classForName (if (some #{\. \[} strx) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 2b957fc20b..80c25e79e6 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -1124,10 +1124,11 @@ static Class tagToClass(Object tag) { throw new IllegalArgumentException("Unable to resolve classname: " + tag); } - public static Class maybeArrayClass(Symbol sym) { - if(sym.ns == null || !Util.isPosDigit(sym.name)) - return null; + public static boolean looksLikeArrayClass(Symbol sym) { + return sym.ns != null && Util.isPosDigit(sym.name); + } + public static String buildArrayClassDescriptor(Symbol sym) { int dim = sym.name.charAt(0) - '0'; Symbol componentClassName = Symbol.intern(null, sym.ns); Class componentClass = primClass(componentClassName); @@ -1137,7 +1138,7 @@ public static Class maybeArrayClass(Symbol sym) { if(componentClass == null) throw Util.sneakyThrow(new ClassNotFoundException("Unable to resolve component classname: " - + componentClassName)); + + componentClassName)); StringBuilder arrayDescriptor = new StringBuilder(); @@ -1149,7 +1150,14 @@ public static Class maybeArrayClass(Symbol sym) { : "L" + componentClass.getName() + ";"; arrayDescriptor.append(ccDescr); - return maybeClass(arrayDescriptor.toString(), true); + return arrayDescriptor.toString(); + } + + public static Class maybeArrayClass(Symbol sym) { + if(!looksLikeArrayClass(sym)) + return null; + + return maybeClass(buildArrayClassDescriptor(sym), true); } } From a69236355b9d1547a607a5327ea30f2d4843541b Mon Sep 17 00:00:00 2001 From: Fogus Date: Wed, 25 Dec 2024 11:37:13 -0500 Subject: [PATCH 7/8] the-array-class --- src/clj/clojure/genclass.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index f42d507950..afef85c8ef 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -101,7 +101,7 @@ 'char Character/TYPE 'chars (Class/forName "[C")}) -(defn- resolve-array-class [sym] +(defn- the-array-class [sym] (clojure.lang.RT/classForName (let [cn (namespace sym)] (clojure.lang.Compiler$HostExpr/buildArrayClassDescriptor @@ -114,7 +114,7 @@ (class? x) x (symbol? x) (cond (contains? prim->class x) (prim->class x) (clojure.lang.Compiler$HostExpr/looksLikeArrayClass x) - (resolve-array-class x) + (the-array-class x) :else (let [strx (str x)] (clojure.lang.RT/classForName (if (some #{\. \[} strx) From f405793db436bf0ea0fb2ed573c284c7e997608a Mon Sep 17 00:00:00 2001 From: Fogus Date: Mon, 13 Jan 2025 08:04:27 -0500 Subject: [PATCH 8/8] isPosDigit doesn't need to be public --- src/jvm/clojure/lang/Util.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jvm/clojure/lang/Util.java b/src/jvm/clojure/lang/Util.java index a5ca27ec46..11647f800c 100644 --- a/src/jvm/clojure/lang/Util.java +++ b/src/jvm/clojure/lang/Util.java @@ -256,7 +256,7 @@ static public Object loadWithClass(String scriptbase, Class loadFrom) throws } } -public static boolean isPosDigit(String s) { +static boolean isPosDigit(String s) { if(s.length() != 1) return false; char ch = s.charAt(0);