Derive class identity from one hierarchy graph
instance?, extend-protocol dispatch, isa?/supers/ancestors, and the exception hierarchy each read their own hand-kept table, and those tables had drifted: (instance? clojure.lang.Associative [1 2]) was true but a protocol extended to Associative wouldn't dispatch to a vector; keyword/IFn and seq/Seqable had the same split; (isa? ExceptionInfo RuntimeException) was false and (supers NumberFormatException) was empty. Add one FQN -> direct-supers graph (class-hierarchy.ss) and derive the views from it. value-host-tags builds on the graph closure so a vector reports Associative/Indexed/ILookup/Counted/Seqable, a keyword reports IFn, a seq reports Seqable/List/Counted, etc. instance? now tests membership in that same list, so it can't disagree with dispatch. canonical-host-tag recognizes any modeled class (was a separate literal set missing Seqable/ILookup/...). class-direct-supers unions the graph edges and class-supers returns the transitive closure, so the exception hierarchy answers isa?/supers/ancestors. The graph is open: jolt.host/register-class-supers! lets a library graft its own classes on and get every view for free. Runtime only, no re-mint. make test green (0 new/stale divergences), +3 JVM-certified corpus rows.
This commit is contained in:
parent
d7dad2b450
commit
d4acd69a73
5 changed files with 251 additions and 18 deletions
|
|
@ -3505,4 +3505,7 @@
|
|||
{:suite "number / toString radix" :label ".toString(radix) renders in base, lowercase" :expected "[\"ff\" \"377\" \"1001\"]" :actual "[(.toString (biginteger 255) 16) (.toString (biginteger 255) 8) (.toString (biginteger 9) 2)]"}
|
||||
{:suite "quote / metadata" :label "a quoted form keeps user metadata, drops reader location" :expected "[{:x true} nil]" :actual "[(meta (quote ^:x (1 2))) (meta (quote (1 2)))]"}
|
||||
{:suite "enumeration-seq" :label "enumeration-seq drives a java.util.Enumeration (StringTokenizer)" :expected "[\"1\" \"2\" \"3\"]" :actual "(vec (enumeration-seq (java.util.StringTokenizer. \"1 2 3\")))"}
|
||||
{:suite "protocols / interface dispatch" :label "extend-protocol to an interface a builtin implements dispatches (instance? and protocol dispatch agree)" :expected "[:assoc :ifn :seqable]" :actual "(do (defprotocol PA (ma [_])) (extend-protocol PA clojure.lang.Associative (ma [_] :assoc)) (defprotocol PF (mf [_])) (extend-protocol PF clojure.lang.IFn (mf [_] :ifn)) (defprotocol PS (ms [_])) (extend-protocol PS clojure.lang.Seqable (ms [_] :seqable)) [(ma [1 2]) (mf :k) (ms (map inc [1 2]))])"}
|
||||
{:suite "protocols / instance? matches dispatch" :label "instance? agrees with what a value's class implements" :expected "[true true false true true]" :actual "[(instance? clojure.lang.Associative [1 2]) (instance? clojure.lang.IFn :k) (instance? java.util.Map [1 2]) (instance? clojure.lang.Seqable (map inc [1 2])) (instance? clojure.lang.IPersistentVector [1 2])]"}
|
||||
{:suite "class / hierarchy views agree" :label "isa?/supers see the modeled exception + collection hierarchy" :expected "[true true true true]" :actual "[(isa? clojure.lang.ExceptionInfo java.lang.RuntimeException) (contains? (supers java.lang.NumberFormatException) java.lang.RuntimeException) (isa? clojure.lang.Keyword clojure.lang.IFn) (contains? (ancestors clojure.lang.PersistentVector) java.util.List)]"}
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue