diff options
author | Julian Schurhammer <julian.schurhammer@gmail.com> | 2022-07-23 09:33:25 +1200 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2023-03-13 10:48:26 +0000 |
commit | 1b305abbecbcd9004439ed9418077b367ff6b0b0 (patch) | |
tree | ba61bae239de89ca54e4e5af4f889c5ec43aa18d /src/gleam_stdlib.mjs | |
parent | 589a74661749626a4a7b8a5e27b536430ed680af (diff) | |
download | gleam_stdlib-1b305abbecbcd9004439ed9418077b367ff6b0b0.tar.gz gleam_stdlib-1b305abbecbcd9004439ed9418077b367ff6b0b0.zip |
initial implementation of 'hash array mapped trie' structure for persistent maps
Diffstat (limited to 'src/gleam_stdlib.mjs')
-rw-r--r-- | src/gleam_stdlib.mjs | 97 |
1 files changed, 16 insertions, 81 deletions
diff --git a/src/gleam_stdlib.mjs b/src/gleam_stdlib.mjs index 60ab625..9dca761 100644 --- a/src/gleam_stdlib.mjs +++ b/src/gleam_stdlib.mjs @@ -15,10 +15,10 @@ import { } from "./gleam/regex.mjs"; import { DecodeError } from "./gleam/dynamic.mjs"; import { Some, None } from "./gleam/option.mjs"; - -const HASHCODE_CACHE = new WeakMap(); +import * as pmap from "./persistent-hash-map.mjs"; const Nil = undefined; +const NOT_FOUND = {}; export function identity(x) { return x; @@ -395,71 +395,8 @@ export function regex_scan(regex, string) { return List.fromArray(matches); } -class Map { - static #hashcode_cache = new WeakMap(); - - static hash(value) { - let existing = this.#hashcode_cache.get(value); - if (existing) { - return existing; - } else if (value instanceof Object) { - let hashcode = inspect(value); - HASHCODE_CACHE.set(value, hashcode); - return hashcode; - } else { - return value.toString(); - } - } - - constructor() { - this.entries = new globalThis.Map(); - } - - get size() { - return this.entries.size; - } - - inspect() { - let entries = [...this.entries.values()] - .map((pair) => inspect(pair)) - .join(", "); - return `map.from_list([${entries}])`; - } - - copy() { - let map = new Map(); - map.entries = new globalThis.Map(this.entries); - return map; - } - - toList() { - return List.fromArray([...this.entries.values()]); - } - - insert(k, v) { - let map = this.copy(); - map.entries.set(Map.hash(k), [k, v]); - return map; - } - - delete(k) { - let map = this.copy(); - map.entries.delete(Map.hash(k)); - return map; - } - - get(key) { - let code = Map.hash(key); - if (this.entries.has(code)) { - return new Ok(this.entries.get(code)[1]); - } else { - return new Error(Nil); - } - } -} - export function new_map() { - return new Map(); + return pmap.create(); } export function map_size(map) { @@ -467,19 +404,23 @@ export function map_size(map) { } export function map_to_list(map) { - return map.toList(); + return List.fromArray(pmap.entries(map)); } -export function map_remove(k, map) { - return map.delete(k); +export function map_remove(key, map) { + return pmap.remove(map, key); } export function map_get(map, key) { - return map.get(key); + const value = pmap.getWithDefault(map, key, NOT_FOUND); + if (value === NOT_FOUND) { + return new Error(Nil); + } + return new Ok(value); } export function map_insert(key, value, map) { - return map.insert(key, value); + return pmap.set(map, key, value); } function unsafe_percent_decode(string) { @@ -610,7 +551,7 @@ export function classify_dynamic(data) { return `Tuple of ${data.length} elements`; } else if (BitString.isBitString(data)) { return "BitString"; - } else if (data instanceof Map) { + } else if (data instanceof pmap.Map) { return "Map"; } else if (typeof data === "number") { return "Float"; @@ -680,13 +621,7 @@ export function decode_result(data) { } export function decode_map(data) { - if (data instanceof Map) { - return new Ok(data) - } - if (typeof data === 'object' && data !== null && Object.getPrototypeOf(data) == Object.getPrototypeOf({})) { - return new Ok(new Map(Object.entries(data))) - } - return decoder_error("Map", data); + return data instanceof pmap.Map ? new Ok(data) : decoder_error("Map", data); } export function decode_option(data, decoder) { @@ -703,8 +638,8 @@ export function decode_option(data, decoder) { export function decode_field(value, name) { let error = () => decoder_error_no_classify("field", "nothing"); - if (value instanceof Map) { - let entry = value.get(name); + if (value instanceof pmap.Map) { + let entry = map_get(value, name); return entry.isOk() ? entry : error(); } try { |