spec: string-buffer primitive — make-string-buffer/append!/->string/length
OCaml: StringBuffer of Buffer.t in sx_types.ml; 5 primitives in sx_primitives.ml (make-string-buffer, string-buffer?, string-buffer-append!, string-buffer->string, string-buffer-length); inspect case added. JS: SxStringBuffer with array+join backend; _string_buffer marker for typeOf dispatch and dict? exclusion (also excludes _vector from dict?). spec/primitives.sx: 5 define-primitive entries. 17/17 tests pass on both OCaml and JS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
// =========================================================================
|
||||
|
||||
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
|
||||
var SX_VERSION = "2026-04-26T14:13:13Z";
|
||||
var SX_VERSION = "2026-04-26T17:04:43Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -169,6 +169,7 @@
|
||||
if (x._raw) return "raw-html";
|
||||
if (x._sx_expr) return "sx-expr";
|
||||
if (x._vector) return "vector";
|
||||
if (x._string_buffer) return "string-buffer";
|
||||
if (typeof Node !== "undefined" && x instanceof Node) return "dom-node";
|
||||
if (Array.isArray(x)) return "list";
|
||||
if (typeof x === "object") return "dict";
|
||||
@@ -424,7 +425,7 @@
|
||||
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; };
|
||||
PRIMITIVES["dict?"] = function(x) { return x !== null && typeof x === "object" && !Array.isArray(x) && !x._sym && !x._kw && !x._string_buffer && !x._vector; };
|
||||
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;
|
||||
@@ -578,6 +579,16 @@
|
||||
return new SxVector(v.arr.slice(s, e));
|
||||
};
|
||||
|
||||
// String buffers — O(1) amortised append via array+join
|
||||
function SxStringBuffer() { this.parts = []; this.len = 0; this._string_buffer = true; }
|
||||
PRIMITIVES["make-string-buffer"] = function() { return new SxStringBuffer(); };
|
||||
PRIMITIVES["string-buffer?"] = function(x) { return x instanceof SxStringBuffer; };
|
||||
PRIMITIVES["string-buffer-append!"] = function(buf, s) {
|
||||
buf.parts.push(String(s)); buf.len += String(s).length; return NIL;
|
||||
};
|
||||
PRIMITIVES["string-buffer->string"] = function(buf) { return buf.parts.join(""); };
|
||||
PRIMITIVES["string-buffer-length"] = function(buf) { return buf.len; };
|
||||
|
||||
|
||||
// stdlib.format
|
||||
PRIMITIVES["format-decimal"] = function(v, p) { return Number(v).toFixed(p || 2); };
|
||||
@@ -3311,6 +3322,10 @@ PRIMITIVES["eval-expr-cek"] = evalExprCek;
|
||||
var trampolineCek = function(val) { return (isSxTruthy(isThunk(val)) ? evalExprCek(thunkExpr(val), thunkEnv(val)) : val); };
|
||||
PRIMITIVES["trampoline-cek"] = trampolineCek;
|
||||
|
||||
// make-coroutine
|
||||
var makeCoroutine = function(thunk) { return {"suspension": NIL, "thunk": thunk, "type": "coroutine", "state": "ready"}; };
|
||||
PRIMITIVES["make-coroutine"] = makeCoroutine;
|
||||
|
||||
// eval-expr
|
||||
var evalExpr = function(expr, env) { return cekRun(makeCekState(expr, env, [])); };
|
||||
PRIMITIVES["eval-expr"] = evalExpr;
|
||||
|
||||
Reference in New Issue
Block a user