spec: mutable hash tables (make-hash-table/ref/set!/delete!/etc)
Phase 10 — 11 primitives: make-hash-table, hash-table?, hash-table-set!, hash-table-ref, hash-table-delete!, hash-table-size, hash-table-keys, hash-table-values, hash-table->alist, hash-table-for-each, hash-table-merge!. OCaml HashTable variant; JS Map-based. 28 tests, both hosts green. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1030,7 +1030,7 @@ PRIMITIVES_JS_MODULES: dict[str, str] = {
|
||||
PRIMITIVES["inexact?"] = function(x) { return typeof x === "number" && !Number.isInteger(x); };
|
||||
PRIMITIVES["string?"] = function(x) { return typeof x === "string"; };
|
||||
PRIMITIVES["list?"] = Array.isArray;
|
||||
PRIMITIVES["dict?"] = function(x) { return x !== null && typeof x === "object" && !Array.isArray(x) && !x._sym && !x._kw && !x._string_buffer && !x._vector; };
|
||||
PRIMITIVES["dict?"] = function(x) { return x !== null && typeof x === "object" && !Array.isArray(x) && !x._sym && !x._kw && !x._string_buffer && !x._vector && !x._hash_table; };
|
||||
PRIMITIVES["empty?"] = function(c) { return isNil(c) || (Array.isArray(c) ? c.length === 0 : typeof c === "string" ? c.length === 0 : Object.keys(c).length === 0); };
|
||||
PRIMITIVES["contains?"] = function(c, k) {
|
||||
if (typeof c === "string") return c.indexOf(String(k)) !== -1;
|
||||
@@ -1329,6 +1329,35 @@ PRIMITIVES_JS_MODULES: dict[str, str] = {
|
||||
if (a === 0) return 0;
|
||||
return 32 - Math.clz32(Math.abs(a));
|
||||
};
|
||||
''',
|
||||
"stdlib.hash-table": '''
|
||||
// stdlib.hash-table
|
||||
function SxHashTable() { this.data = new Map(); this._hash_table = true; }
|
||||
PRIMITIVES["make-hash-table"] = function() { return new SxHashTable(); };
|
||||
PRIMITIVES["hash-table?"] = function(x) { return x instanceof SxHashTable; };
|
||||
PRIMITIVES["hash-table-set!"] = function(ht, k, v) { ht.data.set(k, v); return null; };
|
||||
PRIMITIVES["hash-table-ref"] = function(ht, k, dflt) {
|
||||
if (ht.data.has(k)) return ht.data.get(k);
|
||||
if (arguments.length > 2) return dflt;
|
||||
throw new Error("hash-table-ref: key not found");
|
||||
};
|
||||
PRIMITIVES["hash-table-delete!"] = function(ht, k) { ht.data.delete(k); return null; };
|
||||
PRIMITIVES["hash-table-size"] = function(ht) { return ht.data.size; };
|
||||
PRIMITIVES["hash-table-keys"] = function(ht) { return Array.from(ht.data.keys()); };
|
||||
PRIMITIVES["hash-table-values"] = function(ht) { return Array.from(ht.data.values()); };
|
||||
PRIMITIVES["hash-table->alist"] = function(ht) {
|
||||
var result = [];
|
||||
ht.data.forEach(function(v, k) { result.push([k, v]); });
|
||||
return result;
|
||||
};
|
||||
PRIMITIVES["hash-table-for-each"] = function(ht, fn) {
|
||||
ht.data.forEach(function(v, k) { apply(fn, [k, v]); });
|
||||
return null;
|
||||
};
|
||||
PRIMITIVES["hash-table-merge!"] = function(dst, src) {
|
||||
src.data.forEach(function(v, k) { dst.data.set(k, v); });
|
||||
return null;
|
||||
};
|
||||
''',
|
||||
}
|
||||
# Modules to include by default (all)
|
||||
@@ -1370,6 +1399,7 @@ PLATFORM_JS_PRE = '''
|
||||
if (x._sx_expr) return "sx-expr";
|
||||
if (x._vector) return "vector";
|
||||
if (x._string_buffer) return "string-buffer";
|
||||
if (x._hash_table) return "hash-table";
|
||||
if (typeof Node !== "undefined" && x instanceof Node) return "dom-node";
|
||||
if (Array.isArray(x)) return "list";
|
||||
if (typeof x === "object") return "dict";
|
||||
@@ -1633,6 +1663,7 @@ PLATFORM_JS_POST = '''
|
||||
if (isLambda(f)) return trampoline(callLambda(f, args, lambdaClosure(f)));
|
||||
return f.apply(null, args);
|
||||
};
|
||||
PRIMITIVES["apply"] = apply;
|
||||
|
||||
// Additional primitive aliases used by adapter/engine transpiled code
|
||||
var split = PRIMITIVES["split"];
|
||||
|
||||
Reference in New Issue
Block a user