# Elm-on-SX: Elm 0.19 on the CEK/VM Compile Elm source to SX AST; the existing CEK evaluator runs it. The unique angle: SX's reactive island system (`defisland`, signals, `provide`/`context`) is a natural host for The Elm Architecture — Model/Update/View maps almost directly onto SX's reactive runtime. This is the only language in the set that targets SX's browser-side reactivity rather than the server-side evaluator. End-state goal: **core Elm programs running in the browser via SX islands**, with The Elm Architecture wired to SX signals. Not a full Elm compiler — no exhaustiveness checking, no module system, no type inference — but a faithful runtime that can run Elm programs written in idiomatic style. ## Ground rules - **Scope:** only touch `lib/elm/**` and `plans/elm-on-sx.md`. Do **not** edit `spec/`, `hosts/`, `shared/`, or other `lib//`. - **Shared-file issues** go under "Blockers" below with a minimal repro; do not fix here. - **SX files:** use `sx-tree` MCP tools only. - **Architecture:** Elm source → Elm AST → SX AST. No standalone Elm evaluator. - **Type system:** defer. Focus on runtime semantics. Type errors surface at eval time. - **Commits:** one feature per commit. Keep `## Progress log` updated and tick boxes. ## Architecture sketch ``` Elm source text │ ▼ lib/elm/tokenizer.sx — numbers, strings, idents, operators, indentation-sensitive lexer │ ▼ lib/elm/parser.sx — Elm AST: module, import, type alias, type, let, case, lambda, │ if, list/tuple/record literals, pipe operator |> ▼ lib/elm/transpile.sx — Elm AST → SX AST │ ▼ lib/elm/runtime.sx — TEA runtime: Program, sandbox, element; Cmd/Sub wrappers; │ Html.* shims; Browser.* shims ▼ SX island / reactive runtime (browser) ``` Key semantic mappings: - `Model` → SX signal (`make-signal`) - `update : Msg -> Model -> Model` → SX signal updater (called on each message) - `view : Model -> Html Msg` → SX component (re-renders on model signal change) - `Cmd` → SX `perform` IO request - `Sub` → SX event listener registered via `dom-listen` - `Maybe a` → `nil` (Nothing) or value (Just a) — uses ADTs from Phase 6 of primitives - `Result a b` → ADT `(Ok val)` / `(Err err)` ## Roadmap ### Phase 1 — tokenizer + parser - [ ] Tokenizer: keywords (`module`, `import`, `type`, `alias`, `let`, `in`, `if`, `then`, `else`, `case`, `of`, `port`), indentation tokens (indent/dedent/newline), string literals, number literals, operators (`|>`, `>>`, `<<`, `<|`, `++`, `::`), type vars - [ ] Parser: module declaration, imports, type aliases, union types, function definitions with pattern matching, `let`/`in`, `case`/`of`, `if`/`then`/`else`, lambda `\x -> e`, list literals `[1,2,3]`, tuple literals `(a,b)`, record literals `{x=1, y=2}`, record update `{ r | x = 1 }`, pipe operator `|>` - [ ] Skip for phase 1: ports, subscriptions, effects manager, type annotations - [ ] Tests in `lib/elm/tests/parse.sx` ### Phase 2 — transpile: expressions + pattern matching - [ ] `elm-eval-ast` entry - [ ] Arithmetic, string `++`, comparison, boolean ops - [ ] Lambda → SX `fn`; function application - [ ] `let`/`in` → SX `let` - [ ] `if`/`then`/`else` → SX `if` - [ ] `case`/`of` with constructor, literal, tuple, list, wildcard patterns → SX `cond` using ADT match (Phase 6 primitives) - [ ] List ops: `List.map`, `List.filter`, `List.foldl`, `List.foldr` - [ ] `Maybe` and `Result` as ADTs - [ ] 30+ eval tests in `lib/elm/tests/eval.sx` ### Phase 3 — The Elm Architecture runtime - [ ] `Browser.sandbox` — pure TEA loop (no Cmds, no Subs) `{ init : model, update : msg -> model -> model, view : model -> Html msg }` Wires to: SX signal for model, SX component for view, message dispatch on user events - [ ] `Html.*` shims: `div`, `p`, `button`, `input`, `text`, `h1`–`h6`, `ul`, `li`, `a`, `span`, `img` — emit SX component calls - [ ] `Html.Attributes.*`: `class`, `id`, `href`, `src`, `type_`, `placeholder`, `value` - [ ] `Html.Events.*`: `onClick`, `onInput`, `onSubmit`, `onBlur`, `onFocus` - [ ] `Browser.element` — adds `init` returning `(model, Cmd msg)`, `subscriptions` - [ ] Demo: counter app (`init=0`, `update Increment m = m+1`, `view` shows count + button) ### Phase 4 — Cmds and Subs - [ ] `Cmd` — mapped to SX `perform` IO requests. `Cmd.none`, `Cmd.batch` - [ ] `Http.get`/`Http.post` → SX fetch IO - [ ] `Sub` — mapped to SX `dom-listen`. `Sub.none`, `Sub.batch` - [ ] `Browser.Events.onClick`, `onKeyPress`, `onAnimationFrame` - [ ] `Time.every` — periodic subscription via SX timer IO - [ ] `Task.perform`/`Task.attempt` — single-shot async operations ### Phase 5 — standard library - [ ] `String.*` — `length`, `append`, `concat`, `split`, `join`, `trim`, `toUpper`, `toLower`, `contains`, `startsWith`, `endsWith`, `replace`, `toInt`, `toFloat`, `fromInt`, `fromFloat` - [ ] `List.*` — `map`, `filter`, `foldl`, `foldr`, `head`, `tail`, `isEmpty`, `length`, `reverse`, `append`, `concat`, `member`, `sort`, `sortBy`, `indexedMap`, `range` - [ ] `Dict.*` — SX immutable dict; `fromList`, `toList`, `get`, `insert`, `remove`, `update`, `member`, `keys`, `values`, `map`, `filter`, `foldl` - [ ] `Set.*` — SX set primitive (Phase 18); `fromList`, `toList`, `member`, `insert`, `remove`, `union`, `intersect`, `diff` - [ ] `Maybe.*` — `withDefault`, `map`, `andThen`, `map2` - [ ] `Result.*` — `withDefault`, `map`, `andThen`, `mapError`, `toMaybe` - [ ] `Tuple.*` — `first`, `second`, `pair`, `mapFirst`, `mapSecond` - [ ] `Basics.*` — `identity`, `always`, `not`, `xor`, `modBy`, `remainderBy`, `clamp`, `min`, `max`, `abs`, `sqrt`, `logBase`, `e`, `pi`, `floor`, `ceiling`, `round`, `truncate`, `toFloat`, `isNaN`, `isInfinite`, `compare` - [ ] `Random.*` — seed-based PRNG via SX IO perform ### Phase 6 — full browser integration - [ ] `Browser.application` — URL routing, `onUrlChange`, `onUrlRequest` - [ ] `Browser.Navigation.*` — `pushUrl`, `replaceUrl`, `back`, `forward` - [ ] `Url.Parser.*` — path segment parsing - [ ] `Json.Decode.*` — JSON decoder combinators - [ ] `Json.Encode.*` — JSON encoder - [ ] `Ports` — `port` keyword; JS interop via SX `host-call` ## Blockers _(none yet)_ ## Progress log _Newest first._ _(awaiting phase 1)_