Skip to content

Latest commit

 

History

History
119 lines (93 loc) · 4.5 KB

File metadata and controls

119 lines (93 loc) · 4.5 KB

Statifier

CI Hex.pm Version Hex Downloads Hex Docs License

A W3C SCXML-conformant statecharts engine for Elixir. Ground-up rewrite of statifier v1.x, built against the SCION and W3C conformance corpora from day one.

Why a rewrite

v1 works, but its interpreter re-derived the SCXML semantics instead of porting the spec's algorithm, and the divergences account for nearly all of its remaining conformance failures. v2 is:

  • a literal port of W3C SCXML Appendix D - same functions, same names
  • a pure functional core returning effects - one semantics for every API, sessions and timers layered on top
  • predicator as the datamodel - safe, non-evaluative expressions; no ECMAScript, no eval
  • built corpus-first - 186+ SCION/W3C conformance tests and a forward-only regression ratchet inherited from v1, with the generator committed this time

Installation

Add statifier to your dependencies:

def deps do
  [
    {:statifier, "~> 2.0"}
  ]
end

Releases follow SemVer; CHANGELOG.md is the upgrade briefing, and its [2.0.0] section is written as a migration document for 1.x users. (The pre-release SHA-pinning contract ended with 2.0.0 - ADR-0066.) Persisted position and recording blobs refuse with a typed error on a format-version or chart-identity mismatch rather than misreading.

Quick start

Compile an SCXML document, initialize it, and send it events. Effects come back as data - the engine never performs them for you:

source = """
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="off">
  <state id="off">
    <transition event="toggle" target="on"/>
  </state>
  <state id="on">
    <transition event="toggle" target="off"/>
  </state>
</scxml>
"""

{:ok, machine} = Statifier.compile(source)
{machine_state, _effects} = Statifier.initialize(machine)

Statifier.active_leaf_states(machine_state)
#=> MapSet.new(["off"])

{:ok, machine_state, _effects} = Statifier.send_event(machine_state, "toggle")

Statifier.active_leaf_states(machine_state)
#=> MapSet.new(["on"])

That four-function surface (compile/2, initialize/2, send_event/2, active_leaf_states/1) is the whole entry point; sessions, durable timers, persistence, and telemetry layer on top of it.

Documentation

Published guides on hexdocs:

Architecture Decision Records live in the repository at docs/adr/.

Development

mix deps.get
mix quality --profile loop   # fast inner loop
mix quality                  # full gate (required green before commit)

Issue tracking is beads (bd ready to find work). Workflow, model roles, and worktree conventions: docs/workflow.md.

License

MIT - see LICENSE.