aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Schurhammer <julian.schurhammer@gmail.com>2022-08-13 23:46:10 +1200
committerLouis Pilfold <louis@lpil.uk>2023-03-13 10:48:58 +0000
commitaae3caf4257adb202d6a6dbabc01dae9dad002c3 (patch)
tree904e10945c492e8d560cc18cbfe5f676bc2ada4b
parent507b28c8557af2f74d6504cd75eb687b1fc96a05 (diff)
downloadgleam_stdlib-aae3caf4257adb202d6a6dbabc01dae9dad002c3.tar.gz
gleam_stdlib-aae3caf4257adb202d6a6dbabc01dae9dad002c3.zip
js map: refactor into class
-rw-r--r--src/gleam_stdlib.mjs18
-rw-r--r--src/persistent-hash-map.mjs129
2 files changed, 85 insertions, 62 deletions
diff --git a/src/gleam_stdlib.mjs b/src/gleam_stdlib.mjs
index 81304fe..64dc1d0 100644
--- a/src/gleam_stdlib.mjs
+++ b/src/gleam_stdlib.mjs
@@ -15,7 +15,7 @@ import {
} from "./gleam/regex.mjs";
import { DecodeError } from "./gleam/dynamic.mjs";
import { Some, None } from "./gleam/option.mjs";
-import * as pmap from "./persistent-hash-map.mjs";
+import PMap from "./persistent-hash-map.mjs";
const Nil = undefined;
const NOT_FOUND = {};
@@ -396,7 +396,7 @@ export function regex_scan(regex, string) {
}
export function new_map() {
- return pmap.create();
+ return PMap.new();
}
export function map_size(map) {
@@ -404,15 +404,15 @@ export function map_size(map) {
}
export function map_to_list(map) {
- return List.fromArray(pmap.entries(map));
+ return List.fromArray(map.entries());
}
export function map_remove(key, map) {
- return pmap.remove(map, key);
+ return map.delete(key);
}
export function map_get(map, key) {
- const value = pmap.getWithDefault(map, key, NOT_FOUND);
+ const value = map.get(key, NOT_FOUND);
if (value === NOT_FOUND) {
return new Error(Nil);
}
@@ -420,7 +420,7 @@ export function map_get(map, key) {
}
export function map_insert(key, value, map) {
- return pmap.set(map, key, value);
+ return map.set(key, value);
}
function unsafe_percent_decode(string) {
@@ -551,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 pmap.PMap) {
+ } else if (data instanceof PMap) {
return "Map";
} else if (typeof data === "number") {
return "Float";
@@ -621,7 +621,7 @@ export function decode_result(data) {
}
export function decode_map(data) {
- return data instanceof pmap.PMap ? new Ok(data) : decoder_error("Map", data);
+ return data instanceof PMap ? new Ok(data) : decoder_error("Map", data);
}
export function decode_option(data, decoder) {
@@ -638,7 +638,7 @@ export function decode_option(data, decoder) {
export function decode_field(value, name) {
let error = () => decoder_error_no_classify("field", "nothing");
- if (value instanceof pmap.PMap) {
+ if (value instanceof PMap) {
let entry = map_get(value, name);
return entry.isOk() ? entry : error();
}
diff --git a/src/persistent-hash-map.mjs b/src/persistent-hash-map.mjs
index dc3db31..c3b2d17 100644
--- a/src/persistent-hash-map.mjs
+++ b/src/persistent-hash-map.mjs
@@ -577,73 +577,96 @@ function forEach(root, fn) {
}
}
/** Extra wrapper to keep track of map size */
-export class PMap {
+export default class PMap {
+ static fromObject(o) {
+ const keys = Object.keys(o);
+ let m = PMap.new()
+ for (let i = 0; i < keys.length; i++) {
+ const k = keys[i];
+ m = m.set(k, o[k])
+ }
+ return m
+ }
+ static fromMap(o) {
+ let m = PMap.new()
+ o.forEach((v, k) => {
+ m = m.set(k, v)
+ });
+ return m
+ }
+ static new() {
+ return new PMap(undefined, 0);
+ }
constructor(root, size) {
this.root = root;
this.size = size;
}
+ get(key, notFound) {
+ if (this.root === undefined) {
+ return notFound;
+ }
+ const found = find(this.root, 0, getHash(key), key);
+ if (found === undefined) {
+ return notFound;
+ }
+ return found.v;
+ }
+ set(key, val) {
+ const addedLeaf = { val: false };
+ const root = this.root === undefined ? EMPTY : this.root;
+ const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf);
+ if (newRoot === this.root) {
+ return this;
+ }
+ return new PMap(newRoot, addedLeaf.val ? this.size + 1 : this.size);
+ }
+ delete(key) {
+ if (this.root === undefined) {
+ return this;
+ }
+ const newRoot = without(this.root, 0, getHash(key), key);
+ if (newRoot === this.root) {
+ return this;
+ }
+ if (newRoot === undefined) {
+ return PMap.new();
+ }
+ return new PMap(newRoot, this.size - 1);
+ }
+ has(key) {
+ if (this.root === undefined) {
+ return false;
+ }
+ return find(this.root, 0, getHash(key), key) !== undefined;
+ }
+ entries() {
+ if (this.root === undefined) {
+ return [];
+ }
+ const result = [];
+ this.forEach((v, k) => result.push([k, v]));
+ return result;
+ }
+ forEach(fn) {
+ forEach(this.root, fn)
+ }
hashCode() {
let h = 0;
- forEach(this.root, (v, k) => {
+ this.forEach((v, k) => {
h = (h + hashMerge(getHash(v), getHash(k))) | 0;
});
return h;
}
equals(o) {
+ if(!(o instanceof PMap)) {
+ return
+ }
let equal = true;
- forEach(this.root, (v, k) => {
- equal = equal && isEqual(getWithDefault(o, k, !v), v);
+ this.forEach((v, k) => {
+ equal = equal && isEqual(o.get(k, !v), v);
});
return equal;
}
}
-export function create() {
- return new PMap(undefined, 0);
-}
-export function getWithDefault(map, key, notFound) {
- if (map.root === undefined) {
- return notFound;
- }
- const found = find(map.root, 0, getHash(key), key);
- if (found === undefined) {
- return notFound;
- }
- return found.v;
-}
-export function set(map, key, val) {
- const addedLeaf = { val: false };
- const root = map.root === undefined ? EMPTY : map.root;
- const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf);
- if (newRoot === map.root) {
- return map;
- }
- return new PMap(newRoot, addedLeaf.val ? map.size + 1 : map.size);
-}
-export function remove(map, key) {
- if (map.root === undefined) {
- return map;
- }
- const newRoot = without(map.root, 0, getHash(key), key);
- if (newRoot === map.root) {
- return map;
- }
- if (newRoot === undefined) {
- return create();
- }
- return new PMap(newRoot, map.size - 1);
-}
-export function has(map, key) {
- if (map.root === undefined) {
- return false;
- }
- return find(map.root, 0, getHash(key), key) !== undefined;
-}
-export function entries(map) {
- if (map.root === undefined) {
- return [];
- }
- const result = [];
- forEach(map.root, (v, k) => result.push([k, v]));
- return result;
-}
+
export function __include_me() {}