Repository navigation
evaluateAsync yields under the relations and inside a user function's body (evaluatesOperands flag) - #423
Closed
enumeratio wants to merge 1 commit into
Closed
evaluateAsync yields under the relations and inside a user function's body (evaluatesOperands flag)#423enumeratio wants to merge 1 commit into
evaluateAsync yields under the relations and inside a user function's body (evaluatesOperands flag)#423enumeratio wants to merge 1 commit into
Conversation
…ndler (the relations) yield and abort under evaluateAsync; await the body statements of a user function; tests, CHANGELOG, ROADMAP. Part of cortex-js#392 - boxed-function: await each held operand for an operator with the flag (not under .N(), not when an operand is Missing); a user function awaits arguments and body statements - function-utils: awaitStatements option on apply; one suspended application per literal - relations: Equal, NotEqual, Less, LessEqual, IdenticallyEqual set the flag - tests: evaluate-async-evaluates-operands
arnog
added a commit
that referenced
this pull request
Oct 9, 2026
… function's body Part of #392, contributed by enumeratio. `Equal`, `NotEqual`, `Less` and `LessEqual` get an `evaluateAsync` handler that awaits each operand in order, with the same early stop as `evaluate()` (a chain stops at the first `False` pair) and the same exact re-read of a near tie under `.N()`. A user function's body statements run with `evaluateStatementsAsync` under `evaluateAsync`, and its arguments are awaited. A lazy operator can declare `evaluatesOperands: true` when its handler demands and evaluates every held operand; the asynchronous route then awaits them and runs the handler on the values. The flag is set on `IdenticallyEqual`. Changes to the PR after review: the chainable relations use a twin instead of the flag, so a chain keeps its short circuit; the flag route hands over the written operand only at absent positions; the recursion guards release their counts at return and the in-flight set is keyed by the body scope, so a suspended application holds back neither a concurrent symbolic call nor another engine; the callee is read once before the arguments; the memo store after an await is guarded by the dependency snapshot.
Member
|
Thank you, this landed on
The remaining items you listed (the two |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #392. Both of these now reject about 50 ms after the abort, where before each ran to the end:
evaluatesOperands, a new opt-in flag on alazyoperator definition, defaulting tofalse. It says theevaluatehandler only evaluates its held operands and reads nothing else of them. UnderevaluateAsync, an operator with the flag and noevaluateAsynchandler has its held operands awaited in order, and then its synchronous handler runs on the values.selectsOperands,scopedand quoting operators never take this route.We set the flag on
Equal,NotEqual,Less,LessEqualandIdenticallyEqual. That also coversGreaterandGreaterEqual, which canonicalize toLessandLessEqual. We leftIsSameandSamewithout it because they compare structure.There are two cases where the relations still read the operand as written, so those stay on the synchronous handler:
.N(): a near-tie re-reads the operand to decide exactly.Missing: its declared type decides what it means.A chain of three or more operands awaits all of them, where
evaluate()stops at the firstFalsepair. The answer is the same, but the later operands still run.User functions: the body statements run with
evaluateStatementsAsync(), asBlockdoes, and the arguments are awaited. This applies on both the operator-definition route and the function-value route. Two kinds of application stay synchronous, because the body's scope has room for one suspended frame:ROADMAP lists what's left: the two
Nforms that raise the precision, and the lazy operators we haven't audited for the flag.