Source src/silo:std.collections.btreemap
1##! BTreeMap — ordered key-value collection. 2##! 3##! `BTreeMap k v` is a newtype over `(HashMap k v)` so it has a 4##! dispatch identity distinct from `HashMap` while borrowing the hash 5##! runtime. `(Ord k k)` constraints are elided from the current 6##! signatures; they return once the real B-tree representation lands. 7##! 8##! Methods currently panic at runtime; real bodies require either 9##! host B-tree intrinsics or a working BTreeMap↔HashMap coercion 10##! surface. Range and drain operations surface as eager `(Vec (Pair k 11##! v))` today and narrow to lazy sequences once the Seq hierarchy is 12##! wired. `Cursor` / `CursorMut` are deferred. 13##! 14##! Not re-exported by the prelude — use 15##! `:use :open silo:std.collections.btreemap ...`. 16 17:use 18 :open core AnyInt Bool Option Pair Range Vec 19 :open collections.hashmap HashMap 20 :open effects.panic panic 21:end 22 23# si[impl coll.btreemap.entry] 24## Result of an entry lookup on a `BTreeMap`. `Occupied` carries both 25## the key and the current value; `Vacant` carries only the key. Real 26## implementation requires `(Ord k k)`; the stub union omits the bound 27## for the same reason the method stubs do (see file-header note 2). 28:union(pub) BTreeEntry k v 29 | Occupied k v 30 | Vacant k 31:end 32 33# si[impl coll.btreemap.len] 34# si[impl coll.btreemap.is-empty] 35# si[impl coll.btreemap.first] 36# si[impl coll.btreemap.last] 37# si[impl coll.btreemap.insert] 38# si[impl coll.btreemap.remove] 39# si[impl coll.btreemap.get] 40# si[impl coll.btreemap.contains-key] 41# si[impl coll.btreemap.drain] 42# si[impl coll.btreemap.extend] 43# si[impl coll.btreemap.filter-keys] 44# si[impl coll.btreemap.range+1] 45# si[impl coll.btreemap.range-from] 46# si[impl coll.btreemap.range-to] 47# si[impl coll.btreemap.merge] 48# si[impl coll.btreemap.retain] 49# si[impl coll.btreemap.map-values] 50# si[impl coll.btreemap.entry.lookup] 51# si[impl coll.btreemap.entry.or-insert] 52# si[impl coll.btreemap.from-hashmap] 53# si[impl coll.btreemap.to-hashmap] 54## Ordered key-value collection. Runtime layout shares `(HashMap k v)` 55## but `BTreeMap` is a distinct type for dispatch — HashMap methods 56## like `.insert` do NOT resolve through `BTreeMap`. 57:type(pub) BTreeMap k v (HashMap k v) 58 59:impl (BTreeMap k v) 60 # si[impl coll.btreemap.len+1] 61 ## Number of entries in O(1). 62 .len ( (BTreeMap k v) -> AnyInt ) 63 btreemap-len-intrinsic ; 64 65 # si[impl coll.btreemap.is-empty+1] 66 ## True iff the map contains zero entries. Equivalent to `.len 0 eq`. 67 .is-empty ( (BTreeMap k v) -> Bool ) 68 btreemap-is-empty-intrinsic ; 69 70 # si[impl coll.btreemap.first] 71 ## `.first` returns `Some` with the (key, value) pair having the 72 ## smallest key, or `None` if the map is empty. O(log n). 73 .first ( (BTreeMap k v) -> (Option (Pair k v)) ) 74 :todo "awaits host B-tree intrinsics" ; 75 76 # si[impl coll.btreemap.last] 77 ## `.last` returns `Some` with the (key, value) pair having the 78 ## largest key, or `None` if the map is empty. O(log n). 79 .last ( (BTreeMap k v) -> (Option (Pair k v)) ) 80 :todo "awaits host B-tree intrinsics" ; 81 82 # si[impl coll.btreemap.insert] 83 ## `.insert` inserts a key-value pair; returns the updated map and 84 ## `(Option v)` carrying the displaced prior value (`None` if the 85 ## key was absent). O(log n). 86 .insert ( k v (BTreeMap k v) -> (BTreeMap k v) (Option v) ) 87 :todo "awaits host B-tree intrinsics" ; 88 89 # si[impl coll.btreemap.remove] 90 ## `.remove` removes an entry by key; returns the updated map and 91 ## `(Option v)` carrying the removed value (`None` if the key was 92 ## absent). O(log n). 93 .remove ( k (BTreeMap k v) -> (BTreeMap k v) (Option v) ) 94 :todo "awaits host B-tree intrinsics" ; 95 96 # si[impl coll.btreemap.get] 97 ## `.get` returns `(Option v)` for a given key: `Some v` when 98 ## present, `None` otherwise. Conforms to `(Keyed .lookup)` once 99 ## `BTreeMap` joins the `Keyed` impl surface. Real body uses linear 100 ## scan with structural equality over the backing HashMap cell; real 101 ## O(log n) balanced-tree lookup arrives with the tree runtime. 102 .get ( k (BTreeMap k v) -> (Option v) ) 103 btreemap-get-intrinsic ; 104 105 # si[impl coll.btreemap.contains-key] 106 ## `.contains-key` — true iff the given key is present. Conforms to 107 ## `(Keyed .contains-key)` once `BTreeMap` joins that impl surface. 108 ## Real body uses linear scan over the backing HashMap cell. 109 .contains-key ( k (BTreeMap k v) -> Bool ) 110 btreemap-contains-key-intrinsic ; 111 112 # si[impl coll.btreemap.drain] 113 ## `.drain` consumes the map and returns a `(Vec (Pair k v))` of 114 ## every entry in ascending key order, plus a fresh empty 115 ## `(BTreeMap k v)`. Spec says `unique` input mode and `(Seq ...)` 116 ## output — see file-header notes 3 and 5 for the stub's 117 ## simplifications. 118 .drain ( (BTreeMap k v) -> (Vec (Pair k v)) (BTreeMap k v) ) 119 :todo "awaits host B-tree intrinsics" ; 120 121 # si[impl coll.btreemap.extend] 122 ## `.extend` inserts every `(Pair k v)` from a `(Vec (Pair k v))` 123 ## source into the map. Incoming values overwrite existing ones. 124 ## Spec says `(Foldable (Pair k v))` source; the stub pins to 125 ## `Vec` to avoid the trait-constraint-on-quotation surface while 126 ## the impl is stubbed. 127 .extend ( (BTreeMap k v) (Vec (Pair k v)) -> (BTreeMap k v) ) 128 :todo "awaits host B-tree intrinsics" ; 129 130 # si[impl coll.btreemap.filter-keys] 131 ## `.filter-keys` keeps only entries whose key satisfies the 132 ## predicate. Key order is preserved. 133 .filter-keys ( (BTreeMap k v) [ k -> Bool ] -> (BTreeMap k v) ) 134 :todo "awaits host B-tree intrinsics" ; 135 136 # si[impl coll.btreemap.range+1] 137 ## `.range` returns a `(Vec (Pair k v))` of entries whose key falls 138 ## within `[start, end)` — half-open — in ascending key order. 139 ## Spec surface is `(Seq (Pair k v))`; see file-header note 3. 140 ## O(log n + k). 141 .range ( (RangeBoth k k) (BTreeMap k v) -> (Vec (Pair k v)) ) 142 :todo "awaits host B-tree intrinsics" ; 143 144 # si[impl coll.btreemap.range-from] 145 ## `.range-from` returns a `(Vec (Pair k v))` of entries whose key 146 ## is >= `start`, in ascending key order. O(log n + k). 147 .range-from ( (RangeFrom k) (BTreeMap k v) -> (Vec (Pair k v)) ) 148 :todo "awaits host B-tree intrinsics" ; 149 150 # si[impl coll.btreemap.range-to] 151 ## `.range-to` returns a `(Vec (Pair k v))` of entries whose key 152 ## is < `end`, in ascending key order. O(log n + k). 153 .range-to ( (RangeTo k) (BTreeMap k v) -> (Vec (Pair k v)) ) 154 :todo "awaits host B-tree intrinsics" ; 155 156 # si[impl coll.btreemap.merge] 157 ## `.merge` combines two maps. On duplicate keys, the second (top of 158 ## stack) map's value wins. 159 .merge ( (BTreeMap k v) (BTreeMap k v) -> (BTreeMap k v) ) 160 :todo "awaits host B-tree intrinsics" ; 161 162 # si[impl coll.btreemap.retain] 163 ## `.retain` keeps only entries for which the `[k v -> Bool]` 164 ## predicate returns `true`. 165 .retain ( [ k v -> Bool ] (BTreeMap k v) -> (BTreeMap k v) ) 166 :todo "awaits host B-tree intrinsics" ; 167 168 # si[impl coll.btreemap.map-values] 169 ## `.map-values` transforms every value via the quotation; keys and 170 ## key order are preserved. Note the resulting `v` type may differ. 171 .map-values ( [ v -> w ] (BTreeMap k v) -> (BTreeMap k w) ) 172 :todo "awaits host B-tree intrinsics" ; 173 174 # si[impl coll.btreemap.entry.lookup] 175 ## `.entry` returns `(BTreeEntry k v)`: `Occupied` when the key is 176 ## present, `Vacant` otherwise. 177 .entry ( k (BTreeMap k v) -> (BTreeEntry k v) ) 178 :todo "awaits host B-tree intrinsics" ; 179 180 # si[impl coll.btreemap.to-hashmap] 181 ## `.to-hashmap` — runtime identity cast. The backing cell is already a 182 ## HashMap; the ordering discipline is dropped. Spec mandates element 183 ## contents are identical. 184 .to-hashmap ( (BTreeMap k v) -> (HashMap k v) ) 185 btreemap-to-hashmap-intrinsic ; 186:end 187 188# si[impl coll.btreemap.entry.or-insert] 189## `.or-insert` — free fn rather than method because dispatch would 190## need to pick between `BTreeEntry` and `BTreeMap` as Self. If the 191## entry is `Occupied`, the existing value surfaces; if `Vacant`, 192## the default inserts. Stack effect matches the spec: default and 193## entry pop, updated value and map push. 194:fn(pub) btreemap-or-insert ( v (BTreeEntry k v) (BTreeMap k v) -> v (BTreeMap k v) ) 195 :todo "awaits host B-tree intrinsics" :ret 196:end 197 198# si[impl coll.btreemap.from-hashmap] 199## `.from-hashmap` converts a `(HashMap k v)` into a `(BTreeMap k v)`. 200## Contents are identical; only the ordering discipline changes. The 201## WP-F3 partial body is an identity cast at the runtime layer (the 202## cell layout is already a HashMap). Ordered-iteration semantics 203## arrive when the real B-tree intrinsics land — callers that rely on 204## ordered traversal MUST NOT depend on this behaviour yet. Free fn 205## rather than method because method dispatch on `(HashMap k v)` would 206## collide with other HashMap-wrapping newtypes in the future. 207:fn(pub) btreemap-from-hashmap ( (HashMap k v) -> (BTreeMap k v) ) 208 btreemap-from-hashmap-intrinsic 209:end