v4.2.4

Released 2026-05-26 · GitHub release · CHANGELOG

A maintenance release: two codegen fixes, plus a large internal change with no effect on generated code. framec’s own parser and several scanners are now Frame state machines (dogfooding), and the compile pipeline is FSM-driven — every internal refactor was verified to produce byte-identical output to 4.2.3 except for the two fixes below.

Highlights

  • push$ -> $State codegen fixed (#42). Inline push-with-transition emitted a call to a non-existent _transition() on Python, GDScript, JavaScript, and TypeScript, and the W414 reachability check ignored the edge. It now lowers through the compartment model like every other transition, and reachability counts it.
  • Multi-line domain: default literals fixed (#41). A dict or array default that spanned multiple physical lines was split at the first newline into stray field declarations; it is now captured whole.
  • The parser is now a Frame state machine (RFC-0039 — Parser as composed Frame state machines). A SystemBackbone Frame system owns and drives parsing, calling the recursive-descent parse_* methods as native oracles. framec’s own front-end grammar is now expressed in Frame. No change to generated code.
  • The compile pipeline and several scanners are FSM-driven (RFC-0035). compile_ast_based is sequenced by a pipeline FSM (one state per phase), and the domain: line scanner, the assembler’s call-site lexer, the transition-metadata parser, and the Erlang paren-balance scanner are now Frame FSMs. No change to generated code.

Every internal refactor was checked against the code it replaced with the full 17-backend matrix and the structural fuzz corpus, both green.