Skip to content

Pass exec/2 commands to the javascript host in the wasm version#177

Open
jeswr wants to merge 1 commit into
eyereasoner:masterfrom
jeswr:wasm-exec-await
Open

Pass exec/2 commands to the javascript host in the wasm version#177
jeswr wants to merge 1 commit into
eyereasoner:masterfrom
jeswr:wasm-exec-await

Conversation

@jeswr

@jeswr jeswr commented Jul 4, 2026

Copy link
Copy Markdown
Member

What

Wraps exec/2 in the same :- if(current_prolog_flag(emscripten, true)) conditional already used for userInput/2, so that in wasm builds the sub-reasoner invocations of the graph scoped builtins are passed to the JavaScript host via await/2 instead of calling shell/2 (which does not exist under Emscripten). Native builds keep the existing shell/2 definition verbatim.

This is the small patch proposed in eyereasoner/eye-js#873 ("Left for @josd" / upstream ask): all eight graph-literal-scoped builtins — log:collectAllIn, log:forAllIn, log:ifThenElseIn, log:conclusion, log:satisfiable, e:call, e:fail, e:findall — funnel through exec/2, so this one conditional makes them all bridgeable for any wasm embedder, and makes the sub-reasoner-spawn contract explicit rather than something each embedder has to shim in at image-build time.

Host protocol

Per your preference for a structured term over a raw shell string, the emscripten branch splits the command line and yields

await(exec(Args, File), Response)

where Args is the argv of the command as a list of atoms (e.g. [eye, '--nope', '--quiet', Tmp1, '--query', Tmp2]) and File is the target of its stdout redirection. The host is expected to run the command — for the graph scoped builtins, the eye sub-reasoner on a fresh wasm instance, which is the isolation analogue of the process spawn — write its standard output to File in the requesting instance's filesystem, and answer "ok". Any other response, and any command without a stdout redirection (e.g. arbitrary e:exec shell commands, which a wasm host cannot honour), raises exec_error(A) just like a non-zero exit does natively; the scoped builtins already wrap exec/2 in catch/3 and treat that as failure.

Validation

No native swipl was available here, so validation ran under swipl-wasm (where the emscripten branch is live and both conditional branches must parse):

  • consulting the patched eye.pl in swipl-wasm produces no errors or warnings;
  • the exact repro from log:collectAllIn error eye-js#873 (graph-literal-scoped log:collectAllIn), run through qsave_programd images of this patched source with a JS host answering the exec(Args, File) yields by booting fresh sub-instances, returns (:x) a :Result. — identical to native EYE, with the expected two sub-reasoner invocations per scope evaluation.

The native branch is byte-identical to the current definition, so non-wasm behaviour is unchanged; a native CI run is still the authoritative check there.

Reference host

eye-js is the reference consumer: eyereasoner/eye-js#1956 currently injects an equivalent (string-based) redefinition of exec/2 at pvm-generation time; once a release contains this patch, eye-js can drop that build-time shim and consume the structured yield directly (a small follow-up on their side). VERSION/RELEASE/eye.zip are deliberately untouched — left to your release flow.

Prepared agent-assisted for @jeswr.

In the wasm version there is no shell/2, so the graph scoped builtins
(log:collectAllIn, log:forAllIn, log:ifThenElseIn, log:conclusion,
log:satisfiable, e:call, e:fail and e:findall) could not spawn their
eye sub-reasoner. Following the userInput/2 precedent, exec/2 now
yields exec(Args, File) to the javascript host via await/2 under the
emscripten condition, where Args is the argv of the command and File
is the target of its stdout redirection.

See eyereasoner/eye-js#873

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 4, 2026 21:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants