Files
rose-ash/plans/elm-on-sx.md
giles 985671cd76 hs: query targets, prolog hook, loop scripts, new plans, WASM regen
Hyperscript compiler/runtime:
- query target support in set/fire/put commands
- hs-set-prolog-hook! / hs-prolog-hook / hs-prolog in runtime
- runtime log-capture cleanup

Scripts: sx-loops-up/down, sx-hs-e-up/down, sx-primitives-down
Plans: datalog, elixir, elm, go, koka, minikanren, ocaml, hs-bucket-f,
       designs (breakpoint, null-safety, step-limit, tell, cookies, eval,
       plugin-system)
lib/prolog/hs-bridge.sx: initial hook-based bridge draft
lib/common-lisp/tests/runtime.sx: CL runtime tests

WASM: regenerate sx_browser.bc.js from updated hs sources

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 09:19:56 +00:00

6.3 KiB
Raw Blame History

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/<lang>/.
  • 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 anil (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, h1h6, 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
  • Portsport keyword; JS interop via SX host-call

Blockers

(none yet)

Progress log

Newest first.

(awaiting phase 1)