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/2usesstate_lookupmap for O(1) access - Transition lookups:
Document.get_transitions_from_state/2usestransitions_by_sourcemap - Built during validation: Maps constructed only for valid documents via
Document.build_lookup_maps/1
Compound and Parallel State Entry
- Leaf state storage:
Configurationstores only leaf states, computes ancestors dynamically - Optimized ancestor computation:
Configuration.active_ancestors/2uses O(1) document lookups - Efficient MapSet operations: Direct construction vs incremental building where possible
- History state integration:
HistoryTrackeruses 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.