Std.Fsm
View source →The structured FSM surface reuses the generic family parser.
Types
-
type GraphEdge = GraphEdge -
type EventSpec = EventSpec -
type Transition = Row -
type AtomTransition -
type FsmAction = Keep | Next | StopChecked callback result for the preferred typed FSM surface. Constructors are ordinary Cure values;
action_to_beamis the single private-shape lowering point to the tuple vocabulary required bygen_statem.
Functions
-
# fn action_to_beam(action: FsmAction(s, d)) -> BeamTerm
-
# fn add_atom(value: Atom, values: List(Atom)) -> List(Atom)
-
# fn add_event(event: Syntax, payload: List(Syntax), found: List(EventSpec)) -> List(EventSpec)
-
# fn add_optional_syntax_name(value: Option(Syntax), found: List(Syntax)) -> List(Syntax)
-
# fn add_syntax_name(value: Syntax, found: List(Syntax)) -> List(Syntax)
-
# fn all_atoms_in(values: List(Atom), catalogue: List(Atom)) -> Bool
-
# fn atom_in(value: Atom, values: List(Atom)) -> Bool
-
# fn captured_parameter_patterns(parameters: List(Syntax)) -> List(Syntax)
-
# fn captured_parameter_types(parameters: List(Syntax)) -> List(Syntax)
-
# fn compact_deadlock(states: List(Atom), terminals: List(Atom), edges: List(GraphEdge)) -> Bool
-
# fn compact_edge_in(from: Option(Atom), event: Atom, edges: List(GraphEdge)) -> Bool
-
# fn compact_edges(transitions: List(TransitionDefinitionSyntax)) -> List(GraphEdge)
-
# fn compact_outgoing(state: Atom, edges: List(GraphEdge)) -> Bool
-
# fn contains_event(values: List(EventSpec), expected: Atom) -> Bool
-
# fn contains_syntax_name(values: List(Syntax), expected: Atom) -> Bool
-
# fn derive_fsm_family(name: ModuleNameSyntax, definition: FsmDefinitionSyntax) -> Syntax
Expand the structured
fsmfamily into agen_statemmodule.The event type is a companion of the machine, so it is declared INSIDE the generated module as
Event-- the same place the transition-table emitter puts itsState/Event/Data. Declaring it beside the machine instead would bind a name nobody wrote into the enclosing scope, and two sibling modules each holding anfsmwould collide on it. -
# fn derive_transition_table(name: ModuleNameSyntax, data: TypeSyntax, definition: TransitionTableDefinitionSyntax) -> Syntax
-
# fn dispatch(s: Type, e: Type, transitions: List(Transition(s, e)), state: s, event: e, data: a) -> Tuple(Atom, s, a)
-
# fn dispatch_atom(transitions: List(Transition(Atom, Atom)), state: Atom, event: Atom, data: a) -> Tuple(Atom, Atom, a)
Exact encoder for atom-labelled transition tables. Keeping it separate lets the ordinary
dispatchalgebra remain generic. -
# fn duplicate_compact_edge(edges: List(GraphEdge)) -> Bool
-
# fn emit_fsm_parts(name_syntax: Syntax, state_type: Syntax, event_declarations: List(Syntax), event_body: Syntax) -> Syntax
-
# fn emit_transition_table(name: Syntax, data: Syntax, initial: Syntax, states: List(Syntax), events: List(EventSpec), transitions: List(TransitionDefinitionSyntax)) -> Syntax
-
# fn emit_typed_fsm_parts(name_syntax: Syntax, data_type: Syntax, state_name_type: Syntax, initial_state: Syntax, event_declarations: List(Syntax), event_body: Syntax) -> Syntax
-
# fn event_pattern(event: Syntax, parameters: List(Syntax)) -> Syntax
-
# fn event_variants(values: List(EventSpec)) -> List(Syntax)
-
# fn expand_reachable(edges: List(GraphEdge), reachable: List(Atom)) -> List(Atom)
-
# fn explicit_response_arms(transitions: List(TransitionDefinitionSyntax)) -> List(Syntax)
-
# fn explicit_transition_arms(transitions: List(TransitionDefinitionSyntax)) -> List(Syntax)
-
# fn find_event(values: List(EventSpec), expected: Atom) -> Option(EventSpec)
-
# fn first_explicit_source(transitions: List(TransitionDefinitionSyntax)) -> Option(Syntax)
-
# fn first_state(transitions: List(Transition(Atom, Atom))) -> Atom
Compatibility helper for the original atom-labelled transition-table macro. Typed callers use
first_state_or, whose fallback has the same state type as the table. -
# fn first_state_or(s: Type, e: Type, transitions: List(Transition(s, e)), fallback: s) -> s
-
# fn fsm_handler(body: Syntax) -> Syntax
checked block, so normalize each arm here in ordinary source-level syntax.
-
# fn fsm_handler_arm(arm: Syntax) -> Syntax
-
# fn fsm_handler_arm_node(values: List(Attr), children: List(Syntax)) -> Syntax
-
# fn fsm_handler_arms(arms: List(Syntax)) -> List(Syntax)
-
# fn fsm_handler_node(values: List(Attr), children: List(Syntax)) -> Syntax
-
# fn keep(s: Type, data: d) -> FsmAction(s, d)
-
# fn next(state: s, data: d) -> FsmAction(s, d)
-
# fn option_present(a: Type, value: Option(a)) -> Bool
-
# fn optional_payload(payload: Option(List(Syntax))) -> List(Syntax)
-
# fn optional_syntax_key(value: Option(Syntax)) -> Option(Atom)
-
# fn payload_types_equal(left: List(Syntax), right: List(Syntax)) -> Bool
-
# fn reachable_atoms(fuel: List(Atom), reachable: List(Atom), edges: List(GraphEdge)) -> List(Atom)
At most |states| monotone passes are needed to saturate a finite graph. Recursing on the shrinking catalogue is visibly structural to the totality checker, unlike a conventional BFS whose work queue can grow.
-
# fn response_arm(edge: TransitionDefinitionSyntax, state_pattern: Syntax) -> Syntax
-
# fn same_optional_atom(left: Option(Atom), right: Option(Atom)) -> Bool
-
# fn select_initial(explicit: Option(Syntax), transitions: List(TransitionDefinitionSyntax)) -> Option(Syntax)
-
# fn stop(s: Type, reason: ExitReason, data: d) -> FsmAction(s, d)
-
# fn syntax_constructor(value: Syntax) -> Syntax
-
# fn syntax_key(value: Syntax) -> Option(Atom)
-
# fn syntax_keys(values: List(Syntax)) -> List(Atom)
-
# fn syntax_name(value: Syntax) -> Option(String)
-
# fn syntax_name_atom(value: Syntax) -> Option(Atom)
Constructor keys include arity (
:Opened/0) for duplicate checking. Public graph metadata instead preserves the identifier the author wrote. -
# fn syntax_variants(values: List(Syntax)) -> List(Syntax)
-
# fn transition(s: Type, e: Type, from: s, event: e, to: s) -> Transition(s, e)
A transition row is ordinary data. The macro surface above expands rows to this checked ADT so users can compose, inspect, and transform tables with normal Cure functions.
-
# fn transition_arm(edge: TransitionDefinitionSyntax, state_pattern: Syntax) -> Syntax
-
# fn transition_decision(transitions: List(TransitionDefinitionSyntax)) -> Syntax
Compile the table as one linear tuple match. Explicit rows are emitted before wildcard rows, which gives them precedence through ordinary pattern ordering. The previous nested state/event decision duplicated its complete fallback twice per row; moderately sized FSMs therefore produced an exponential Syntax value and exhausted computed-macro normalization.
-
# fn transition_events(transitions: List(TransitionDefinitionSyntax), found: List(EventSpec)) -> List(EventSpec)
-
# fn transition_metadata(transitions: List(TransitionDefinitionSyntax)) -> List(Syntax)
Emit the graph as ordinary generated data. Tooling and tests can inspect exactly the rows which drive
decide/3, without keeping a second table in host code. Wildcard rows have a distinct constructor so callers cannot accidentally mistake them for a concrete source state. -
# fn transition_response_decision(transitions: List(TransitionDefinitionSyntax)) -> Syntax
responds?/2shares the same ordered patterns asdecide/3. It answers whether the compiled graph has a row for a state/event shape; guards are deliberately not evaluated because they may depend on transition data. -
# fn transition_states(transitions: List(TransitionDefinitionSyntax), found: List(Syntax)) -> List(Syntax)
-
# fn transition_update(update: Option(ExpressionSyntax)) -> Syntax
-
# fn validate_compact_graph(initial: Syntax, states: List(Syntax), terminals: List(Syntax), transitions: List(TransitionDefinitionSyntax)) -> Option(Atom)
-
# fn validate_event_payloads(transitions: List(TransitionDefinitionSyntax), found: List(EventSpec)) -> Option(Atom)
-
# fn wildcard_response_arms(transitions: List(TransitionDefinitionSyntax)) -> List(Syntax)
-
# fn wildcard_transition_arms(transitions: List(TransitionDefinitionSyntax)) -> List(Syntax)