spec: promises — delay/force/delay-force/make-promise/promise?

25 tests pass on OCaml (4357 total) and JS. Promise represented as
mutable dict {:_promise true :forced :thunk :value}; delay-force
adds :_iterative for chain-following semantics.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 08:21:45 +00:00
parent 835b5314ce
commit e44cb89ab4
5 changed files with 306 additions and 3 deletions

View File

@@ -31,7 +31,7 @@
// =========================================================================
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
var SX_VERSION = "2026-05-01T07:58:35Z";
var SX_VERSION = "2026-05-01T08:18:20Z";
function isNil(x) { return x === NIL || x === null || x === undefined; }
function isSxTruthy(x) { return x !== false && !isNil(x); }
@@ -2253,6 +2253,46 @@ PRIMITIVES["step-eval-list"] = stepEvalList;
})(); };
PRIMITIVES["sf-define-type"] = sfDefineType;
// sf-delay
var sfDelay = function(args, env) { return (function() {
var thunk = makeLambda([], first(args), env);
return {"forced": false, "value": NIL, "thunk": thunk, "_promise": true};
})(); };
PRIMITIVES["sf-delay"] = sfDelay;
// sf-delay-force
var sfDelayForce = function(args, env) { return (function() {
var thunk = makeLambda([], first(args), env);
return {"_iterative": true, "forced": false, "value": NIL, "thunk": thunk, "_promise": true};
})(); };
PRIMITIVES["sf-delay-force"] = sfDelayForce;
// promise?
var promise_p = function(v) { return (isSxTruthy(isDict(v)) && get(v, "_promise", false)); };
PRIMITIVES["promise?"] = promise_p;
// make-promise
var makePromise = function(v) { return {"forced": true, "value": v, "_promise": true}; };
PRIMITIVES["make-promise"] = makePromise;
// force
var force = function(p) { return (isSxTruthy(!isSxTruthy(promise_p(p))) ? p : (isSxTruthy(get(p, "forced", false)) ? get(p, "value", NIL) : (function() {
var result = apply(get(p, "thunk", NIL), []);
return (function() {
var final_ = (isSxTruthy((isSxTruthy(get(p, "_iterative", false)) && promise_p(result))) ? force(result) : result);
p["forced"] = true;
p["value"] = final_;
return final_;
})();
})())); };
PRIMITIVES["force"] = force;
// (register-special-form! ...)
registerSpecialForm("delay", sfDelay);
// (register-special-form! ...)
registerSpecialForm("delay-force", sfDelayForce);
// values
var values = function() { var vs = Array.prototype.slice.call(arguments, 0); return (isSxTruthy(sxEq(len(vs), 1)) ? first(vs) : {"_values": true, "_list": vs}); };
PRIMITIVES["values"] = values;