# HG changeset patch # User Michael Pavone # Date 1428653950 25200 # Node ID 60292f131de91bb544f76447cf3761603f7906d1 # Parent a840e9a068a29256ecc490ebdfdd47072069d045 Make map actually work right on hashmaps diff -r a840e9a068a2 -r 60292f131de9 modules/dict.tp --- a/modules/dict.tp Fri Apr 10 00:48:42 2015 -0700 +++ b/modules/dict.tp Fri Apr 10 01:19:10 2015 -0700 @@ -102,6 +102,120 @@ = <- :other { k = other } } } + _hashWithBuckets:size:hashdiffs <- :_buckets :_size :_hashdiffs { + #{ + size <- { size } + ifget:else <- :key ifpres :ifnot { + basehash <- key hash + notdone <- true + i <- 0 + ret <- _empty + + while: { if: notdone { i < (_hashdiffs length)}} do: { + hv <- basehash + (_hashdiffs get: i) + trunc <- hv % (_buckets length) + if: trunc < 0 { trunc <- 0 - trunc } + bucket <- _buckets get: trunc + if: (bucket empty?) { + notdone <- false + } else: { + if: bucket = key { + ret <- bucket + notdone <- false + } + } + i <- i + 1 + } + if: (ret empty?) ifnot else: { + ifpres: (ret v) + } + } + + get:else <- :key :else { + ifget: key :val { + val + } else: else + } + + contains? <- :key { + ifget: key :_ { + true + } else: { + false + } + } + + set <- :key val { + notdone <- true + basehash <- key hash + i <- 0 + while: { if: notdone { i < (_hashdiffs length) } } do: { + hv <- basehash + (_hashdiffs get: i) + trunc <- hv % (_buckets length) + if: trunc < 0 { trunc <- 0 - trunc } + bucket <- (_buckets get: trunc) + if: (bucket empty?) { + _size <- _size + 1 + _buckets set: trunc (_makeBucket: key val) + notdone <- false + } else: { + if: bucket = key { + bucket v!: val + notdone <- false + } + } + i <- i + 1 + } + if: notdone { + newsize <- (_buckets length) * 3 + 1 + lastdiff <- _hashdiffs get: ((_hashdiffs length) - 1) + if: lastdiff <= 0 { + _hashdiffs append: 0 - lastdiff + 1 + } else: { + _hashdiffs append: 0 - lastdiff + } + newbucks <- #[] + newbucks resize: newsize + while: { (newbucks length) < newsize } do: { + newbucks append: _empty + } + oldbucks <- _buckets + _buckets <- newbucks + _size <- 0 + foreach: oldbucks :idx el { + if: (not: (el empty?)) { + set: (el k) (el v) + } + } + set: key val + } + self + } + + foreach <- :fun { + foreach: _buckets :idx el { + if: (not: (el empty?)) { + fun: (el k) (el v) + } + } + } + + map <- :fun { + newbucks <- _buckets map: :bucket { + if: (bucket empty?) { + bucket + } else: { + _makeBucket: (bucket k) (fun: (bucket v)) + } + } + _hashWithBuckets: newbucks size: _size hashdiffs: (_hashdiffs map: :e { e }) + } + + jsonEncode <- { + _jsonEncode: self + } + } + } #{ //requires only that keys support equality linear <- { @@ -110,123 +224,13 @@ //requires that keys support equality and hash hash <- { - - _buckets <- #[ + _hashWithBuckets: #[ _empty _empty _empty - _empty] - _size <- 0 - _hashdiffs <- #[0] - #{ - size <- { size } - ifget:else <- :key ifpres :ifnot { - basehash <- key hash - notdone <- true - i <- 0 - ret <- _empty - - while: { if: notdone { i < (_hashdiffs length)}} do: { - hv <- basehash + (_hashdiffs get: i) - trunc <- hv % (_buckets length) - if: trunc < 0 { trunc <- 0 - trunc } - bucket <- _buckets get: trunc - if: (bucket empty?) { - notdone <- false - } else: { - if: bucket = key { - ret <- bucket - notdone <- false - } - } - i <- i + 1 - } - if: (ret empty?) ifnot else: { - ifpres: (ret v) - } - } - - get:else <- :key :else { - ifget: key :val { - val - } else: else - } - - contains? <- :key { - ifget: key :_ { - true - } else: { - false - } - } - - set <- :key val { - notdone <- true - basehash <- key hash - i <- 0 - while: { if: notdone { i < (_hashdiffs length) } } do: { - hv <- basehash + (_hashdiffs get: i) - trunc <- hv % (_buckets length) - if: trunc < 0 { trunc <- 0 - trunc } - bucket <- (_buckets get: trunc) - if: (bucket empty?) { - _size <- _size + 1 - _buckets set: trunc (_makeBucket: key val) - notdone <- false - } else: { - if: bucket = key { - bucket v!: val - notdone <- false - } - } - i <- i + 1 - } - if: notdone { - newsize <- (_buckets length) * 3 + 1 - lastdiff <- _hashdiffs get: ((_hashdiffs length) - 1) - if: lastdiff <= 0 { - _hashdiffs append: 0 - lastdiff + 1 - } else: { - _hashdiffs append: 0 - lastdiff - } - newbucks <- #[] - newbucks resize: newsize - while: { (newbucks length) < newsize } do: { - newbucks append: _empty - } - oldbucks <- _buckets - _buckets <- newbucks - _size <- 0 - foreach: oldbucks :idx el { - if: (not: (el empty?)) { - set: (el k) (el v) - } - } - set: key val - } - self - } - - foreach <- :fun { - foreach: _buckets :idx el { - if: (not: (el empty?)) { - fun: (el k) (el v) - } - } - } - - map <- :fun { - foreach: _buckets :idx el { - if: (not: (el empty?)) { - el v!: (fun: (el v)) - } - } - } - - jsonEncode <- { - _jsonEncode: self - } - } + _empty + ] size: 0 hashdiffs: #[0] + } main <- {