Architecture
Statifier follows a clean Parse → Validate → Optimize architecture with modular components and efficient data structures.
Core Components
Statifier.Parser.SCXML
- SAX-based XML parser with location tracking (parse phase)Statifier.Validator
- Modular validation orchestrator with focused sub-validators (validate + optimize phases)Statifier.Validator.HistoryStateValidator
- Dedicated validator for history state constraints and W3C complianceStatifier.FeatureDetector
- SCXML feature detection for test validation and capability trackingStatifier.Interpreter
- Synchronous state chart interpreter with compound state and history supportStatifier.StateChart
- Runtime container with event queues and history trackingStatifier.HistoryTracker
- Core history state tracking with efficient MapSet operationsStatifier.Configuration
- Active state management (leaf states only)Statifier.Event
- Event representation with origin tracking
Data Structures
Statifier.Document
- Root SCXML document with states, metadata, O(1) lookup maps, and history helper functionsStatifier.State
- Individual states with transitions, hierarchical nesting, and history type supportStatifier.Transition
- State transitions with event, conditions, targets (list for multiple target support), and source optimizationStatifier.Data
- Datamodel elements with IDs and expressions
Architecture Flow
The implementation follows a clean Parse → Validate → Optimize architecture:
elixir
# 1. Parse Phase: XML → Document structure
{:ok, document} = Statifier.Parser.SCXML.parse(xml_string)
# 2. Validate + Optimize Phase: Check semantics + build lookup maps
{:ok, optimized_document, warnings} = Statifier.Validator.validate(document)
# 3. Interpret Phase: Use optimized document for runtime
{:ok, state_chart} = Statifier.Interpreter.initialize(optimized_document)
Benefits:
- Parsers focus purely on structure (supports future JSON/YAML parsers)
- Validation catches semantic errors before optimization
- Only valid documents get expensive optimization treatment
- Clear separation of concerns across phases
Performance Optimizations
O(1) State and Transition Lookups
- State lookups:
Document.find_state/2
usesstate_lookup
map for O(1) access - Transition lookups:
Document.get_transitions_from_state/2
usestransitions_by_source
map - Built during validation: Maps constructed only for valid documents via
Document.build_lookup_maps/1
Compound and Parallel State Entry
- Leaf state storage:
Configuration
stores only leaf states, computes ancestors dynamically - Optimized ancestor computation:
Configuration.active_ancestors/2
uses O(1) document lookups - Efficient MapSet operations: Direct construction vs incremental building where possible
- History state integration:
HistoryTracker
uses same O(1) lookups for efficient recording/restoration
Parse → Validate → Optimize Flow
- SAX-based parsing: Memory-efficient XML processing with accurate location tracking
- Modular validation: Focused sub-validators (StateValidator, TransitionValidator, etc.)
- Lazy optimization: Expensive operations only performed on valid documents
- Source field optimization: Transitions include source state for faster event processing
This architecture ensures Statifier remains performant while maintaining clean code organization and comprehensive W3C SCXML compliance.