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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user