View Source cure_fsm_runtime (cure v0.1.0)

Cure Programming Language - FSM Runtime System

The FSM runtime system provides a comprehensive execution environment for finite state machines in the Cure programming language. It implements a complete FSM execution model with state transitions, guard evaluation, action execution, and performance optimizations, all built on top of the BEAM virtual machine.

Core Features

FSM Process Management

  • FSM Lifecycle: Complete process management with start/stop operations
  • Event Processing: Synchronous and asynchronous event handling
  • Batch Operations: Optimized batch event processing for performance
  • State Inspection: Runtime state introspection and debugging support

Execution Engine

  • Guard Compilation: Compiled guard expressions with instruction-based evaluation
  • Action System: Compiled action execution with state mutation support
  • Transition Engine: Optimized state transition processing with O(1) lookup
  • Timeout Support: Built-in timeout handling with automatic state transitions

Performance Optimizations

  • Compiled Guards/Actions: Pre-compiled instruction sequences for efficiency
  • Flat Transition Maps: O(1) transition lookup using optimized data structures
  • Memory Management: Automatic event history trimming to prevent memory leaks
  • Performance Statistics: Real-time performance monitoring and metrics

Registry System

  • FSM Type Registration: Global registry for FSM type definitions
  • Dynamic Lookup: Runtime FSM definition resolution
  • Type Management: Registration, unregistration, and type enumeration

Architecture

The FSM runtime is built as a gen_server behavior that manages individual FSM instances. Each FSM process maintains its own state, transition table, timeout handlers, and performance statistics.

%% Start a traffic light FSM
{ok, FSM} = cure_fsm_runtime:start_fsm(traffic_light, #{}).

%% Send events to the FSM
cure_fsm_runtime:send_event(FSM, timer_expired),
cure_fsm_runtime:send_event(FSM, emergency_stop).

%% Get current state
{ok, State} = cure_fsm_runtime:get_state(FSM).

Event Processing Model

Events are processed through a multi-stage pipeline:

  1. Event Reception: Events arrive via gen_server casts/calls
  2. Transition Lookup: O(1) lookup in flat transition map
  3. Guard Evaluation: Compiled guard instruction execution
  4. Action Execution: Compiled action instruction execution with state updates
  5. State Transition: Atomic state change with history tracking
  6. Timeout Management: Automatic timeout setting/clearing

Compilation Pipeline

FSM definitions undergo compilation from AST to optimized runtime format:

  • Transition Compilation: Nested AST transitions → flat lookup maps
  • Guard Compilation: AST expressions → instruction sequences
  • Action Compilation: AST actions → stack-based instructions
  • Timeout Compilation: Timeout definitions → runtime timeout handlers

Performance Characteristics

  • Event Processing: < 10μs per event (compiled guards/actions)
  • State Transitions: O(1) lookup time
  • Memory Usage: Bounded with automatic history trimming
  • Throughput: > 100K events/second per FSM instance
  • Batch Processing: Up to 10x improvement for bulk operations

Error Handling

The runtime provides comprehensive error handling:

  • Guard Failures: Safe evaluation with automatic fallback to false
  • Action Errors: Safe execution with state preservation on failure
  • Timeout Handling: Robust timeout management with cleanup
  • Type Safety: Runtime type checking and validation

Integration

The FSM runtime integrates with:

  • Cure Compiler: Receives compiled FSM definitions from type checker
  • Guard Compiler: Uses compiled guard expressions for efficiency
  • Action Compiler: Executes compiled action instruction sequences
  • BEAM Runtime: Built on standard OTP gen_server behavior

Summary

Functions

Clears all FSM type definitions from the global registry.

Clears any existing timeout for the FSM.

Compiles an FSM definition from AST format to optimized runtime format.

Retrieves comprehensive FSM information for debugging and introspection.

Retrieves performance statistics for an FSM instance.

Returns a list of all registered FSM type names.

Retrieves the current state of an FSM instance.

Looks up an FSM definition by type name in the global registry.

Registers a new FSM type definition in the global registry.

Sends multiple events to an FSM in a single operation for improved performance.

Sends an event to an FSM instance without event data.

Sends an event with associated data to an FSM instance.

Sets a timeout for the FSM that will trigger the specified event after the given time.

Starts a new FSM instance with the specified type and initial data.

Starts a new FSM instance with the specified type, initial data, and options.

Stops an FSM instance gracefully.

Removes an FSM type definition from the global registry.

Functions

clear_fsm_registry()

Clears all FSM type definitions from the global registry.

Returns

  • ok - Registry cleared successfully

Warning

This function removes ALL registered FSM types. Use with caution.

Example

cure_fsm_runtime:clear_fsm_registry().

clear_timeout(FSMPid)

Clears any existing timeout for the FSM.

Arguments

  • FSMPid - The PID of the FSM process

Returns

  • ok - Timeout cleared successfully (asynchronous)

Example

cure_fsm_runtime:clear_timeout(FSMPid).

code_change(OldVsn, State, Extra)

compile_fsm_definition(FSMDef)

Compiles an FSM definition from AST format to optimized runtime format.

This function transforms a parsed FSM definition into an efficient runtime representation with pre-compiled guards, actions, and optimized transition lookups.

Arguments

  • FSMDef - FSM definition record from the parser containing:
    • name - FSM type name
    • states - List of state names
    • initial - Initial state name
    • state_defs - List of state definition records

Returns

  • #fsm_definition{} - Compiled FSM definition ready for runtime execution

Compilation Process

  1. Transition Compilation: Creates flat lookup maps from nested AST
  2. Guard Compilation: Compiles guard expressions to instruction sequences
  3. Action Compilation: Compiles action expressions to stack-based instructions
  4. Timeout Compilation: Extracts and organizes timeout definitions

Example

CompiledDef = cure_fsm_runtime:compile_fsm_definition(ParsedFSM),
cure_fsm_runtime:register_fsm_type(my_fsm, CompiledDef).

get_current_state(FSMPid)

get_fsm_info(FSMPid)

Retrieves comprehensive FSM information for debugging and introspection.

Arguments

  • FSMPid - The PID of the FSM process

Returns

  • {ok, Info} - Map containing FSM information:
    • fsm_type - The FSM type name
    • current_state - Current state name
    • data - Current state data
    • event_history - List of recent events (newest first)
  • {error, Reason} - Error retrieving information

Example

{ok, #{fsm_type := Type, current_state := State}} = 
    cure_fsm_runtime:get_fsm_info(FSMPid).

get_performance_stats(FSMPid)

Retrieves performance statistics for an FSM instance.

Arguments

  • FSMPid - The PID of the FSM process

Returns

  • {ok, Stats} - Performance statistics record containing:
    • events_processed - Total number of events processed
    • avg_event_time - Average event processing time (microseconds)
    • max_event_time - Maximum event processing time (microseconds)
    • memory_usage - Current memory usage (bytes)
    • last_updated - Timestamp of last update
  • {error, Reason} - Error retrieving statistics

Example

{ok, Stats} = cure_fsm_runtime:get_performance_stats(FSMPid),
AvgTime = Stats#fsm_perf_stats.avg_event_time.

get_registered_fsm_types()

Returns a list of all registered FSM type names.

Returns

  • List of FSM type names (atoms)

Example

Types = cure_fsm_runtime:get_registered_fsm_types(),
%% Types might be [counter, traffic_light, state_machine]

get_state(FSMPid)

Retrieves the current state of an FSM instance.

Arguments

  • FSMPid - The PID of the FSM process

Returns

  • {ok, State} - The current state name (atom)
  • {error, Reason} - Error retrieving state

Example

{ok, CurrentState} = cure_fsm_runtime:get_state(FSMPid).

handle_call/3

handle_cast/2

handle_info/2

init/1

list_running_fsms()

lookup_fsm/1

lookup_fsm_definition(FSMType)

Looks up an FSM definition by type name in the global registry.

Arguments

  • FSMType - The FSM type name to look up (atom)

Returns

  • {ok, Definition} - FSM definition found
  • {error, not_found} - FSM type not registered

Example

case cure_fsm_runtime:lookup_fsm_definition(counter) of
    {ok, Definition} -> cure_utils:debug("Found FSM definition~n");
    {error, not_found} -> cure_utils:debug("FSM type not registered~n")
end.

receive_message(FsmPid)

receive_message(FsmPid, Timeout)

register_fsm_type(FSMType, Definition)

Registers a new FSM type definition in the global registry.

Arguments

  • FSMType - The FSM type name (atom)
  • Definition - Compiled FSM definition record

Returns

  • ok - FSM type registered successfully

Example

Definition = #fsm_definition{name = counter, ...},
ok = cure_fsm_runtime:register_fsm_type(counter, Definition).

register_fsm_type(FSMType, States, InitialState, Transitions)

send_batch_events(FSMPid, Events)

Sends multiple events to an FSM in a single operation for improved performance.

Arguments

  • FSMPid - The PID of the FSM process
  • Events - List of events to send. Each event can be:
    • An atom (event without data)
    • A tuple {Event, Data} (event with data)

Returns

  • ok - Batch sent successfully (asynchronous)

Performance

Batch processing can provide 5-10x performance improvement over individual event sends when processing large numbers of events.

Example

Events = [start, {increment, 5}, stop],
cure_fsm_runtime:send_batch_events(FSMPid, Events).

send_event(FSMPid, Event)

Sends an event to an FSM instance without event data.

This is a convenience function that calls send_event/3 with undefined event data.

Arguments

  • FSMPid - The PID of the target FSM process
  • Event - The event to send (atom)

Returns

  • ok - Event sent successfully (asynchronous)

Example

cure_fsm_runtime:send_event(FSMPid, start).

send_event(FSMPid, Event, Data)

Sends an event with associated data to an FSM instance.

Arguments

  • FSMPid - The PID of the target FSM process
  • Event - The event to send (atom)
  • Data - Event data to accompany the event

Returns

  • ok - Event sent successfully (asynchronous)

Example

cure_fsm_runtime:send_event(FSMPid, button_pressed, #{button => ok}).

send_message(FsmPid, Message)

send_message(FsmPid, Message, Options)

set_timeout(FSMPid, Timeout, Event)

Sets a timeout for the FSM that will trigger the specified event after the given time.

Arguments

  • FSMPid - The PID of the FSM process
  • Timeout - Timeout in milliseconds
  • Event - Event to trigger when timeout occurs

Returns

  • ok - Timeout set successfully (asynchronous)

Example

cure_fsm_runtime:set_timeout(FSMPid, 5000, timeout_expired).

spawn_fsm(FSMType)

spawn_fsm(FsmType, FsmDef, InitArgs)

spawn_fsm(FsmType, FsmDef, InitArgs, Options)

start_fsm(FSMType, InitialData)

Starts a new FSM instance with the specified type and initial data.

This is a convenience function that calls start_fsm/3 with an empty options list.

Arguments

  • FSMType - The registered FSM type name (atom)
  • InitialData - Initial state data for the FSM instance

Returns

  • {ok, Pid} - Success with the FSM process PID
  • {error, {fsm_type_not_found, FSMType}} - FSM type not registered
  • {error, Reason} - Other gen_server startup errors

Example

{ok, FSM} = cure_fsm_runtime:start_fsm(counter, #{count => 0}).

start_fsm(FSMType, InitialData, Options)

Starts a new FSM instance with the specified type, initial data, and options.

Arguments

  • FSMType - The registered FSM type name (atom)
  • InitialData - Initial state data for the FSM instance
  • Options - List of startup options (currently unused)

Returns

  • {ok, Pid} - Success with the FSM process PID
  • {error, {fsm_type_not_found, FSMType}} - FSM type not registered
  • {error, Reason} - Other gen_server startup errors

Example

{ok, FSM} = cure_fsm_runtime:start_fsm(traffic_light, #{}, []).

stop_fsm(FSMPid)

Stops an FSM instance gracefully.

Arguments

  • FSMPid - The PID of the FSM process to stop

Returns

  • ok - FSM stopped successfully
  • {error, Reason} - Error stopping the FSM

Example

ok = cure_fsm_runtime:stop_fsm(FSMPid).

terminate/2

unregister_fsm_type(FSMType)

Removes an FSM type definition from the global registry.

Arguments

  • FSMType - The FSM type name to unregister (atom)

Returns

  • true - FSM type unregistered successfully (or did not exist)

Example

cure_fsm_runtime:unregister_fsm_type(old_counter).