Merge pull request #114 from jolt-lang/refactor-phase3c-dedups
Refactor phase 3c: dedup collection readers + phm bucket scans (jolt-26dm)
This commit is contained in:
commit
7632be811b
2 changed files with 38 additions and 58 deletions
|
|
@ -39,25 +39,26 @@
|
|||
(defn- hash-idx [m k]
|
||||
(if (nil? k) 0 (mod (hash (ck k)) (length (m :buckets)))))
|
||||
|
||||
(defn- phm-bucket-find [bucket k]
|
||||
(var i 0) (var n (length bucket)) (var found nil)
|
||||
# Index of key k in a bucket (entries are stored stride-2: k v k v ...), or nil.
|
||||
# The single scan all the bucket ops share — keeping it one place stops the
|
||||
# stride logic drifting between them.
|
||||
(defn- bucket-index-of [bucket k]
|
||||
(var i 0) (def n (length bucket)) (var found nil)
|
||||
(while (< i n)
|
||||
(if (key= k (in bucket i)) (do (set found (in bucket (+ i 1))) (break)))
|
||||
(if (key= k (in bucket i)) (do (set found i) (break)))
|
||||
(+= i 2))
|
||||
found)
|
||||
|
||||
(defn- phm-bucket-find [bucket k]
|
||||
(let [i (bucket-index-of bucket k)]
|
||||
(if i (in bucket (+ i 1)) nil)))
|
||||
|
||||
(defn phm-bucket-contains? [bucket k]
|
||||
(var i 0) (var n (length bucket)) (var found false)
|
||||
(while (< i n)
|
||||
(if (key= k (in bucket i)) (do (set found true) (break)))
|
||||
(+= i 2))
|
||||
found)
|
||||
(not (nil? (bucket-index-of bucket k))))
|
||||
|
||||
(defn- phm-bucket-assoc [bucket k v]
|
||||
(var i 0) (var n (length bucket)) (var found-i nil)
|
||||
(while (< i n)
|
||||
(if (key= k (in bucket i)) (do (set found-i i) (break)))
|
||||
(+= i 2))
|
||||
(def n (length bucket))
|
||||
(def found-i (bucket-index-of bucket k))
|
||||
(if (not (nil? found-i))
|
||||
(let [nb @[]] (var j 0)
|
||||
(while (< j n) (array/push nb (if (= j (+ found-i 1)) v (in bucket j))) (++ j)) nb)
|
||||
|
|
@ -66,10 +67,8 @@
|
|||
(array/push nb k) (array/push nb v) nb)))
|
||||
|
||||
(defn- phm-bucket-dissoc [bucket k]
|
||||
(var i 0) (var n (length bucket)) (var found-i nil)
|
||||
(while (< i n)
|
||||
(if (key= k (in bucket i)) (do (set found-i i) (break)))
|
||||
(+= i 2))
|
||||
(def n (length bucket))
|
||||
(def found-i (bucket-index-of bucket k))
|
||||
(if (nil? found-i) bucket
|
||||
(if (= n 2) nil
|
||||
(let [nb @[]] (var j 0)
|
||||
|
|
@ -82,12 +81,8 @@
|
|||
# Single pass with a presence flag (not nil-of-value): a key mapped to nil
|
||||
# is still present, so return nil (not the default) when it exists.
|
||||
(if bucket
|
||||
(do
|
||||
(var i 0) (var n (length bucket)) (var result default)
|
||||
(while (< i n)
|
||||
(if (key= k (in bucket i)) (do (set result (in bucket (+ i 1))) (break)))
|
||||
(+= i 2))
|
||||
result)
|
||||
(let [i (bucket-index-of bucket k)]
|
||||
(if i (in bucket (+ i 1)) default))
|
||||
default)))
|
||||
|
||||
# Rehash every entry of `buckets` into a fresh array of `nb` buckets.
|
||||
|
|
|
|||
|
|
@ -298,39 +298,35 @@
|
|||
(+ exp-end 1) exp-end)]
|
||||
[(if neg (- val) val) fin]))))))
|
||||
|
||||
(defn read-list [s pos]
|
||||
# pos is at opening paren
|
||||
(defn read-list-items [s pos items]
|
||||
# Read forms until `close` (a byte), returning [items end-pos]. Shared by the
|
||||
# list/vector/set readers: skip #_ discards and splice #?@ items uniformly, so the
|
||||
# skip/splice handling can't drift between them (it did once). The map reader
|
||||
# keeps its own loop — its key/value pairing needs a different value-slot scan.
|
||||
(defn read-delimited [s start-pos close err]
|
||||
(defn read-items [s pos items]
|
||||
(let [pos (skip-whitespace s pos)]
|
||||
(if (>= pos (length s))
|
||||
(reader-error "Unterminated list" pos))
|
||||
(if (= (s pos) 41) # )
|
||||
(reader-error err pos))
|
||||
(if (= (s pos) close)
|
||||
[items (+ pos 1)]
|
||||
(let [[form new-pos] (read-form s pos)]
|
||||
# skip #_ discarded forms
|
||||
(if (and (struct? form) (= :jolt/skip (form :jolt/type)))
|
||||
(read-list-items s new-pos items)
|
||||
# splice #?@ items into the list
|
||||
(read-items s new-pos items)
|
||||
# splice #?@ items into the collection
|
||||
(if (and (struct? form) (= :jolt/splice (form :jolt/type)))
|
||||
(read-list-items s new-pos (array/concat items (form :items)))
|
||||
(read-list-items s new-pos (array/push items form))))))))
|
||||
(read-list-items s (+ pos 1) @[]))
|
||||
(read-items s new-pos (array/concat items (form :items)))
|
||||
(read-items s new-pos (array/push items form))))))))
|
||||
(read-items s start-pos @[]))
|
||||
|
||||
(defn read-list [s pos]
|
||||
# pos is at opening paren
|
||||
(read-delimited s (+ pos 1) 41 "Unterminated list")) # )
|
||||
|
||||
(defn read-vector [s pos]
|
||||
# pos is at opening bracket
|
||||
(defn read-vec-items [s pos items]
|
||||
(let [pos (skip-whitespace s pos)]
|
||||
(if (>= pos (length s))
|
||||
(reader-error "Unterminated vector" pos))
|
||||
(if (= (s pos) 93) # ]
|
||||
[(tuple/slice (tuple ;items)) (+ pos 1)]
|
||||
(let [[form new-pos] (read-form s pos)]
|
||||
(if (and (struct? form) (= :jolt/skip (form :jolt/type)))
|
||||
(read-vec-items s new-pos items)
|
||||
(if (and (struct? form) (= :jolt/splice (form :jolt/type)))
|
||||
(read-vec-items s new-pos (array/concat items (form :items)))
|
||||
(read-vec-items s new-pos (array/push items form))))))))
|
||||
(read-vec-items s (+ pos 1) @[]))
|
||||
(let [[items end] (read-delimited s (+ pos 1) 93 "Unterminated vector")] # ]
|
||||
[(tuple/slice (tuple ;items)) end]))
|
||||
|
||||
# A map-literal form. Janet structs drop nil keys/values, so when a key or value
|
||||
# is nil (e.g. {:a nil}) build a phm — it preserves nil, matching Clojure. The
|
||||
|
|
@ -400,19 +396,8 @@
|
|||
|
||||
(defn read-set [s pos]
|
||||
# pos is at #, next char is {
|
||||
(defn read-set-items [s pos items]
|
||||
(let [pos (skip-whitespace s pos)]
|
||||
(if (>= pos (length s))
|
||||
(reader-error "Unterminated set" pos))
|
||||
(if (= (s pos) 125) # }
|
||||
[{:jolt/type :jolt/set :value (tuple/slice (tuple ;items))} (+ pos 1)]
|
||||
(let [[form new-pos] (read-form s pos)]
|
||||
(if (and (struct? form) (= :jolt/skip (form :jolt/type)))
|
||||
(read-set-items s new-pos items)
|
||||
(if (and (struct? form) (= :jolt/splice (form :jolt/type)))
|
||||
(read-set-items s new-pos (array/concat items (form :items)))
|
||||
(read-set-items s new-pos (array/push items form))))))))
|
||||
(read-set-items s (+ pos 2) @[]))
|
||||
(let [[items end] (read-delimited s (+ pos 2) 125 "Unterminated set")] # }
|
||||
[{:jolt/type :jolt/set :value (tuple/slice (tuple ;items))} end]))
|
||||
|
||||
(defn read-char-name-end [s pos]
|
||||
(if (and (< pos (length s)) (symbol-char? (s pos)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue