Add Morphir interpreter as WebAssembly Component Model component#1272
Closed
DamianReeves wants to merge 13 commits intoremixedfrom
Closed
Add Morphir interpreter as WebAssembly Component Model component#1272DamianReeves wants to merge 13 commits intoremixedfrom
DamianReeves wants to merge 13 commits intoremixedfrom
Conversation
Design for exposing the Morphir interpreter as a WebAssembly Component Model component using ComponentizeJS. Defines WIT interface with stateless evaluation and stateful ir-store resource.
10 bite-sized tasks covering package scaffolding, WIT definition, Elm entry point, JS glue, mise build tasks, test fixture, integration tests, and validation.
Replace JSON string args/returns with index-based flat morphir-value tree (workaround for WIT's lack of recursive types). Add fq-name record, eval-error variant. Update implementation plan with conversion layer in JS glue and typed integration tests.
Implements the bridge between WIT component exports and the Elm Worker: - morphirValueToJson/jsonToMorphirValue: convert between WIT flat indexed tree and nested Elm IR Value codec JSON format - fqName conversion between WIT record and Elm codec/Worker formats - Elm app management with synchronous port communication - WIT eval_.evaluate for stateless evaluation - WIT types.IrStore resource class with constructor, uri, evaluate, reload - Result/error mapping between Elm Worker JSON and WIT eval-error variant
Fix three issues preventing jco componentize from building the WASM component:
1. Fix jco CLI flag: --output -> -o (jco uses short flag)
2. Fix eval export: jco expects `export { eval_ as eval }` since "eval" is
a JS reserved word but the WIT interface name
3. Bundle Elm IIFE output into single ESM file: Elm compiles to an IIFE
wrapping `(function(scope){...}(this))` which isn't ESM. The build task
now reads the Elm output, replaces `this` with a scope object, and
concatenates it with the JS glue into a single ESM bundle.
4. Break up deeply nested && chains: Elm's compiler generates pattern match
conditions with 100+ levels of parenthesis nesting. SpiderMonkey's JS
engine (used by ComponentizeJS) has a ~50-frame recursion limit for
expression parsing. The build task post-processes the Elm output to
flatten these into sequential `var _c = a; _c = _c && b; ...` checks.
Test the interpreter bundle's eval.evaluate (stateless) and types.IrStore (stateful) interfaces with 11 test cases covering addInts, isPositive, error handling for unknown functions and invalid IR, store URI management, reload, and repeated evaluation. Also patch _Process_sleep(0) in the build script to be synchronous, which is needed to test the Elm port communication outside the WASM runtime (where setTimeout is inherently sync in StarlingMonkey).
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
5 tasks
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.
Summary
Exposes the Morphir interpreter as a WebAssembly Component Model component using ComponentizeJS. This enables embedding Morphir evaluation in any runtime that supports the Component Model standard — Rust, Go, Python, .NET, and browsers — without rewriting the interpreter.
New package:
@morphir/interpreter-wasm(packages/morphir-interpreter-wasm/)WIT Interface
Defines
morphir:interpreterwith:eval.evaluate— stateless one-shot evaluation (IR JSON + typed FQName + typed args)types.ir-store— stateful resource: load IR once, evaluate many times,reloadto replace IRmorphir-value— index-based flat tree representation (workaround for WIT's lack of recursive types). Covers all Morphir value types: bool, int, float, string, decimal, char, list, tuple, record, constructor, uniteval-error— structured error variants: invalid-ir, reference-not-found, argument-error, pattern-mismatch, type-error, variable-not-found, otherfq-name— fully qualified name with package-path, module-path, local-nameArchitecture
jco componentizewraps JS+SpiderMonkey into a WASM componentjco transpileproduces browser-compatible ESM outputFiles
packages/morphir-interpreter-wasm/wit/interpreter.wit— WIT interface definitionpackages/morphir-interpreter-wasm/src/Morphir/Interpreter/Worker.elm— Elm port module entry pointpackages/morphir-interpreter-wasm/src/interpreter.js— JS glue with value conversion.mise/tasks/build/interpreter-{elm,wasm,browser}.ts— build tasks.mise/tasks/test/interpreter-wasm.ts— test taskdocs/plans/2026-02-25-wasm-interpreter-{design,plan}.md— design & implementation docsTest plan