Skip to content

Releases: boxed/Alm

Release list

alm 0.19.1.1

Choose a tag to compare

@boxed boxed released this 02 Aug 05:55

alm implements Elm 0.19.1; the fourth component is alm's own revision.

Compiler

  • Incremental compilation, on by default — a .alm-stuff per-module cache
    that also caches the module graph, so a project is not re-read to rediscover
    it. Cold builds, warm builds and no-op builds are all faster than elm make;
    a build with nothing to do is skipped outright. wasm-gc and native are
    incremental too.
  • Faster type checking and monomorphization — structures are looked at
    rather than copied, record rows are shared, integer keys hash with FxHash.
    Monomorphization went from 2.66 s to 0.98 s on a 59k-line app, and is now
    deterministic.
  • Byte-exact syntax errors — elm's whole parse-error catalogue ported, 89
    differential fixtures, in plain text, in color and as --report=json.
  • Byte-exact type errors — elm's report machinery and pretty-printer,
    including pattern reports, record contexts and ANSI coloring.
  • --optimize, --docs=<file>, --report=json.
  • Subcommands: init, install, diff, bump, publish, reactor,
    repl.
  • Source maps for JS and wasm-gc (--source-maps), with named function
    expressions and block-scoped locals so call stacks and the debugger read
    properly.
  • A performance hint for a keyed list built without Html.Lazy.
  • Fixed record-alias constructors ignoring their declared field types.

Live reload

alm make --live serves the program, rebuilds on save and hot-swaps the new
build into the open page, keeping the running model when the new build still
agrees what a Model is. With --output it also writes the bundle, so a page
belonging to a larger app hot-swaps without knowing anything about alm.
alm reactor reloads the same way.

Runtime and backends

  • Unrolled (chunked) lists on every target — allocation is amortized rather
    than one cell per element.
  • Deforestation: foldl/foldr of a List.map compiles to a single loop
    with no intermediate list (7.6x on that chain).
  • Decision trees (Maranget) for nested case patterns with join-point
    sharing, and jump tables for flat dispatch — a JS switch, a wasm-gc
    br_table.
  • vdom: attributes and events are diffed on patch instead of re-applied,
    and the keyed reconciler has an allocation-free fast path for unchanged
    order.
  • wasm-gc: unboxed scalar lists (Int, Char, Float), effect managers,
    type-directed outgoing-port encoding, cross-module ports.
  • Effect modulesTime, Random and Http are real bundled-source
    effect modules on all three backends, and user-defined effect managers run
    everywhere.
  • WebGL rendering kernel, including WebGL.Texture.load.
  • elm/bytes on all three backends.
  • Parity fixes: native String.fromFloat exponent notation, String.length in
    UTF-16 units, String.lines line endings, min/max NaN semantics.
  • The LLVM-based wasm target is gone; the targets are js, native, wasm-gc.

Benchmarks

make bench runs every harness and rebuilds bench-report/report.html:
a real-browser js-framework-benchmark harness, pure-computation workloads, and
compile speed against elm make on public projects.

Install

binary targets
alm-0.19.1.1-macos-arm64.tar.gz js, wasm-gc, native
alm-0.19.1.1-macos-x86_64.tar.gz js, wasm-gc, native
alm-0.19.1.1-linux-x86_64.tar.gz js, wasm-gc
alm-0.19.1.1-linux-arm64.tar.gz js, wasm-gc
alm-0.19.1.1-windows-x86_64.zip js, wasm-gc

--target=native is macOS-only for now: the runtime's conservative collector
finds its roots through Darwin interfaces, and the ELF equivalents are not
written yet. The other binaries are built without that backend and say so if
you ask for it — everything else is the same compiler.

From source: cargo build --release -p alm needs LLVM 16 and the pinned rustc
that produces matching bitcode; --no-default-features drops both and builds
the js and wasm-gc compiler anywhere a Rust toolchain runs.