Class/forName honesty + class/isa? conformance for builtins (#243)
Class/forName claimed every java.*/clojure.* name found (and any "x.y.Class" matched the registered Class via a short-name fallback), so a library's (class-found? "optional.Dep") feature-probe always said yes — tools.logging then tried to build the java.util.logging / log4j backends jolt lacks and crashed. Resolve forName by exact registry lookup + an honest prefix that excludes the unbacked optional packages (java.util.logging, javax.management), so the probe sees them absent and skips the backend. class of a persistent collection / namespace now reports its JVM class name (clojure.lang.PersistentHashSet, …Namespace, …) instead of jolt's internal :set/ :object tag, and isa? consults JVM class assignability — Object as every class's root plus a modeled clojure.lang/java.util hierarchy — so (isa? (class x) C) and a class-keyed multimethod dispatch like the JVM (e.g. (isa? Keyword Object) was false). Adds the bare class tokens (Fn/Namespace/Set/…) these dispatch on. (type x) is unchanged — it keeps jolt's documented internal-keyword form. Six JVM-certified corpus rows. make test green, 0 new divergences. Co-authored-by: Yogthos <yogthos@gmail.com>
This commit is contained in:
parent
283a0f0eec
commit
6c03dffd00
6 changed files with 80 additions and 5 deletions
|
|
@ -848,6 +848,21 @@
|
|||
(reg-class-supers! "java.net.UnknownHostException" '("java.io.IOException" "java.lang.Exception" "java.lang.Throwable" "java.lang.Object"))
|
||||
(reg-class-supers! "java.net.ConnectException" '("java.net.SocketException" "java.io.IOException" "java.lang.Exception" "java.lang.Throwable" "java.lang.Object"))
|
||||
(reg-class-supers! "java.net.SocketTimeoutException" '("java.io.InterruptedIOException" "java.io.IOException" "java.lang.Exception" "java.lang.Throwable" "java.lang.Object"))
|
||||
;; clojure.lang / java.util ancestry for the builtins (class) reports, so a
|
||||
;; class-keyed multimethod / (isa? (class x) SomeClass) dispatches like the JVM.
|
||||
;; (Object is supplied universally by class-isa?, so it need not be listed.)
|
||||
(reg-class-supers! "clojure.lang.IFn" '("clojure.lang.Fn" "java.lang.Runnable" "java.util.concurrent.Callable"))
|
||||
(reg-class-supers! "clojure.lang.Keyword" '("clojure.lang.Named" "java.lang.Comparable"))
|
||||
(reg-class-supers! "clojure.lang.Symbol" '("clojure.lang.Named" "java.lang.Comparable"))
|
||||
(reg-class-supers! "java.lang.String" '("java.lang.CharSequence" "java.lang.Comparable"))
|
||||
(reg-class-supers! "clojure.lang.PersistentHashSet" '("clojure.lang.APersistentSet" "clojure.lang.IPersistentSet" "clojure.lang.IPersistentCollection" "java.util.Set" "java.util.Collection" "java.lang.Iterable"))
|
||||
(reg-class-supers! "clojure.lang.PersistentTreeSet" '("clojure.lang.APersistentSet" "clojure.lang.IPersistentSet" "clojure.lang.IPersistentCollection" "java.util.Set" "java.util.Collection" "java.lang.Iterable"))
|
||||
(reg-class-supers! "clojure.lang.PersistentVector" '("clojure.lang.APersistentVector" "clojure.lang.IPersistentVector" "clojure.lang.IPersistentCollection" "clojure.lang.Sequential" "clojure.lang.Associative" "java.util.List" "java.util.Collection" "java.lang.Iterable"))
|
||||
(reg-class-supers! "clojure.lang.PersistentArrayMap" '("clojure.lang.APersistentMap" "clojure.lang.IPersistentMap" "clojure.lang.IPersistentCollection" "clojure.lang.Associative" "java.util.Map" "java.lang.Iterable"))
|
||||
(reg-class-supers! "clojure.lang.PersistentHashMap" '("clojure.lang.APersistentMap" "clojure.lang.IPersistentMap" "clojure.lang.IPersistentCollection" "clojure.lang.Associative" "java.util.Map" "java.lang.Iterable"))
|
||||
(reg-class-supers! "clojure.lang.PersistentList" '("clojure.lang.ASeq" "clojure.lang.ISeq" "clojure.lang.IPersistentCollection" "clojure.lang.Sequential" "clojure.lang.Seqable" "java.util.List" "java.util.Collection" "java.lang.Iterable"))
|
||||
(reg-class-supers! "clojure.lang.LazySeq" '("clojure.lang.ISeq" "clojure.lang.IPersistentCollection" "clojure.lang.Sequential" "clojure.lang.Seqable" "java.lang.Iterable"))
|
||||
(reg-class-supers! "clojure.lang.Cons" '("clojure.lang.ASeq" "clojure.lang.ISeq" "clojure.lang.Sequential" "clojure.lang.Seqable" "java.lang.Iterable"))
|
||||
|
||||
;; transitive closure of direct supers (set semantics via an accumulator list)
|
||||
(define (class-ancestors-list name)
|
||||
|
|
@ -875,6 +890,24 @@
|
|||
(else (loop (cdr names))))))
|
||||
'pass)))
|
||||
|
||||
;; JVM class assignability for isa? (20-coll): true when child and parent are both
|
||||
;; class values and parent is child, java.lang.Object (every class's root), or a
|
||||
;; modeled ancestor of child (full name or last segment). nil for non-class args, so
|
||||
;; isa? falls through to its hierarchy/vector logic.
|
||||
(def-var! "jolt.host" "class-isa?"
|
||||
(lambda (child parent)
|
||||
(let ((cc (class-key child)) (pp (class-key parent)))
|
||||
(if (and cc pp)
|
||||
(let ((pseg (hsc-last-segment pp)))
|
||||
(if (let loop ((names (cons cc (class-ancestors-list cc))))
|
||||
(cond ((string=? pp "java.lang.Object") #t)
|
||||
((null? names) #f)
|
||||
((or (string=? pp (car names))
|
||||
(string=? pseg (hsc-last-segment (car names)))) #t)
|
||||
(else (loop (cdr names)))))
|
||||
#t jolt-nil))
|
||||
jolt-nil))))
|
||||
|
||||
;; (jolt.host/class-supers name) / (jolt.host/class-ancestors name) — a jolt seq of
|
||||
;; super / ancestor class-name strings, or nil when jolt models no hierarchy for it.
|
||||
(def-var! "jolt.host" "class-supers"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue