data.priority-map: deftype interop fixes (rseq, arity-overload, empty, Sorted)
data.priority-map's whole suite passes (4/4). It leans on deftype/collection
interop jolt got wrong; four general fixes:
- rseq dispatches to a deftype's clojure.lang.Reversible.rseq method instead of
always demanding a vector/sorted-coll (natives-seq.ss).
- a deftype method declared at two arities from two interfaces now dispatches by
arity: the priority-map has seq[this] (Seqable) and seq[this ascending]
(Sorted), so (.seq pm false) must reach the 2-arg one. find-method-any-protocol
now matches the call's arg count via procedure-arity-mask, and a deftype's own
declared method wins over the generic collection interop in dot-forms.
- (empty x) on a deftype/record with its own empty method uses it rather than
returning {} (jolt.host/jrec-method? gate in clojure.core/empty).
- clojure.lang.Sorted (comparator / entryKey / seqFrom) works on jolt's
sorted-map/set, so subseq/rsubseq run — including the priority-map delegating
.comparator to its backing sorted-map (dot-forms.ss + host-static.ss).
Listed in docs/libraries.md + the site. One re-mint (clojure.core/empty);
everything else runtime. make test green (0 new divergences), shakesmoke
byte-identical.
This commit is contained in:
parent
8a4df7b204
commit
75f6bc79d1
7 changed files with 80 additions and 5 deletions
|
|
@ -56,6 +56,40 @@
|
|||
|
||||
;; record-method-dispatch (records.ss) gets a jhost arm: dispatch (.method obj a*)
|
||||
;; through the tag's method table.
|
||||
;; clojure.lang.Sorted on jolt's sorted-map / sorted-set: comparator / entryKey /
|
||||
;; seqFrom / seq. data.priority-map's subseq/rsubseq reach for these (its
|
||||
;; PersistentPriorityMap delegates .comparator to the backing sorted-map). The
|
||||
;; comparator is returned as a small Comparator object whose .compare runs the
|
||||
;; map's 3-way fn, since (.. sc comparator (compare a b)) is the calling form.
|
||||
(define sorted-cmp-kw (keyword #f "cmp"))
|
||||
(register-host-methods! "jolt-comparator"
|
||||
(list (cons "compare" (lambda (self a b) (jolt-invoke (jhost-state self) a b)))))
|
||||
(define (sorted-comparator-of sc)
|
||||
(let ((c (jolt-ref-get sc sorted-cmp-kw)))
|
||||
(make-jhost "jolt-comparator" (if (jolt-nil? c) jolt-compare c))))
|
||||
(define (sorted-iface-method? m)
|
||||
(or (string=? m "comparator") (string=? m "entryKey")
|
||||
(string=? m "seqFrom") (string=? m "seq")))
|
||||
(define (sorted-iface-dispatch obj method rest)
|
||||
(cond
|
||||
((string=? method "comparator") (sorted-comparator-of obj))
|
||||
((string=? method "entryKey") (jolt-first (car rest))) ; map entry -> its key
|
||||
((string=? method "seq") ; (.seq sc) or (.seq sc ascending?)
|
||||
(if (or (null? rest) (jolt-truthy? (car rest))) (jolt-seq obj) (jolt-rseq obj)))
|
||||
;; (.seqFrom sc k ascending?) — the entries from k onward, in order. Done with a
|
||||
;; comparator filter over the seq (jolt has no tree cursor), like subseq.
|
||||
((string=? method "seqFrom")
|
||||
(let* ((k (car rest)) (asc (jolt-truthy? (cadr rest)))
|
||||
(cmp (jolt-ref-get obj sorted-cmp-kw))
|
||||
(cmpf (if (jolt-nil? cmp) jolt-compare cmp))
|
||||
(es (seq->list (jolt-seq obj)))
|
||||
(keep (filter (lambda (e)
|
||||
(let ((c (jnum->exact (jolt-invoke cmpf (jolt-first e) k))))
|
||||
(if asc (>= c 0) (<= c 0))))
|
||||
es)))
|
||||
(list->cseq (if asc keep (reverse keep)))))
|
||||
(else (error #f (string-append "No method " method " on sorted collection")))))
|
||||
|
||||
(define %hs-record-method-dispatch record-method-dispatch)
|
||||
(set! record-method-dispatch
|
||||
(lambda (obj method-name rest-args)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue