;; persistent collections on the Chez RT. ;; ;; The vector / map / set the emitted programs construct from literals and ;; operate on via the lowered leaf ops (conj/get/nth/count/assoc/...). Loaded by ;; rt.ss after values.ss; jolt=2 / jolt-hash (values.ss) call into the ;; jolt-coll? / jolt-coll=? / jolt-coll-hash hooks defined here (forward refs, ;; resolved at run time — nothing is CALLED during load). ;; ;; The persistent vector is a copy-on-write Scheme vector and the map/set are a ;; bitmap HAMT. They live in Scheme; correctness, not perf, is the gate. ;; ============================================================================ ;; small immutable-vector helpers (manual; avoid stdlib arg-order ambiguity) ;; ============================================================================ (define (vec-copy-range v start end) (let ((out (make-vector (fx- end start)))) (let loop ((i start)) (when (fxvector xs))) (define (make-map-entry k v) (make-pvec (vector k v) #t)) (define (jolt-map-entry? x) (and (pvec? x) (pvec-ent x) #t)) (define (pvec-count p) (vector-length (pvec-v p))) ;; jolt models every number as a double, so vector indices arrive as flonums — ;; coerce an integer-valued index to a Scheme fixnum before bounds math. (define (->idx i) (if (fixnum? i) i (if (flonum? i) (exact (floor i)) i))) (define (pvec-nth-d p i d) (let ((v (pvec-v p)) (i (->idx i))) (if (and (fixnum? i) (fx>=? i 0) (fxidx i))) (cond ((and (fx>=? i 0) (fx? shift max-shift) (fx=? eh h)) (make-hcoll h (list (cons ek ev) (cons k v))) (let ((ei (chunk eh shift)) (ni (chunk h shift))) (if (fx=? ei ni) (make-hnode (fxsll 1 ei) (vector (split-leaf (fx+ shift 5) ek ev h k v))) (let ((eb (fxsll 1 ei)) (nb (fxsll 1 ni))) (if (fx []; (conj nil a b ...) builds a list (conj prepending -> (b a)). (define (jolt-conj . args) (if (null? args) (jolt-vector) (let ((coll (car args)) (xs (cdr args))) (if (jolt-nil? coll) (fold-left jolt-conj1 jolt-empty-list xs) (fold-left jolt-conj1 coll xs))))) (define jolt-get (case-lambda ((coll k) (jolt-get coll k jolt-nil)) ((coll k d) (cond ((pmap? coll) (pmap-get coll k d)) ((pset? coll) (if (pset-contains? coll k) k d)) ((pvec? coll) (pvec-nth-d coll k d)) ((string? coll) (let ((i (->idx k))) (if (and (fixnum? i) (fx>=? i 0) (fxidx i))) (cond ((pvec? coll) (let ((v (pvec-v coll))) (if (and (fx>=? i 0) (fx=? i 0) (fxidx i))) (cond ((pvec? coll) (pvec-nth-d coll i d)) ((string? coll) (if (and (fx>=? i 0) (fx 2 vs exact 2 -> true. (define (jolt-count coll) (begin (cond ((pvec? coll) (pvec-count coll)) ((pmap? coll) (pmap-cnt coll)) ((pset? coll) (pset-count coll)) ((string? coll) (string-length coll)) ((jolt-nil? coll) 0) ((empty-list-t? coll) 0) ((cseq? coll) (let loop ((s coll) (n 0)) ; walk (forces a finite seq) (if (jolt-nil? s) n (loop (jolt-seq (seq-more s)) (fx+ n 1))))) (else (error 'count "uncountable"))))) (define (jolt-assoc1 coll k v) (cond ((pmap? coll) (pmap-assoc coll k v)) ((pvec? coll) (pvec-assoc coll k v)) ((jolt-nil? coll) (pmap-assoc empty-pmap k v)) (else (error 'assoc "unsupported collection")))) (define (jolt-assoc coll . kvs) (let loop ((coll coll) (kvs kvs)) (cond ((null? kvs) coll) ((null? (cdr kvs)) (error 'assoc "assoc expects an even number of key/vals")) (else (loop (jolt-assoc1 coll (car kvs) (cadr kvs)) (cddr kvs)))))) (define (jolt-dissoc coll . ks) (cond ((jolt-nil? coll) jolt-nil) ((pmap? coll) (fold-left pmap-dissoc coll ks)) (else (error 'dissoc "unsupported collection")))) (define (jolt-contains? coll k) (cond ((pmap? coll) (pmap-contains? coll k)) ((pset? coll) (pset-contains? coll k)) ((pvec? coll) (let ((k (->idx k))) (and (fixnum? k) (fx>=? k 0) (fx