Statifier.StateHierarchy (statifier v1.9.0)

View Source

State hierarchy analysis and navigation utilities for SCXML state charts.

Provides functions for traversing state hierarchies, computing ancestor relationships, and analyzing state containment. This module contains hierarchy operations extracted from the Interpreter module for better organization and potential optimization.

Summary

Functions

Check if two states are in different regions of the same parallel state.

Compute the Least Common Compound Ancestor (LCCA) of two states.

Check if a state is a descendant of another state in the hierarchy.

Check if a transition exits a parallel region.

Find parent states that have history children and need history recorded.

Get all ancestor state IDs for a given state.

Get the complete ancestor path from a state to the root, including the state itself.

Get all parallel ancestors of a state.

Functions

are_in_parallel_regions?(document, active_state, source_state)

@spec are_in_parallel_regions?(Statifier.Document.t(), String.t(), String.t()) ::
  boolean()

Check if two states are in different regions of the same parallel state.

Returns true if the states are descendants of different child regions within the same parallel ancestor. Uses cached parallel region data when available.

compute_lcca(source_state_id, target_state_id, document)

@spec compute_lcca(String.t(), String.t(), Statifier.Document.t()) :: String.t() | nil

Compute the Least Common Compound Ancestor (LCCA) of two states.

Returns the deepest compound state that is an ancestor of both states, or nil if no common compound ancestor exists. Uses O(1) cache lookup when available, falls back to O(depth) computation.

Examples

iex> StateHierarchy.compute_lcca("child1", "child2", document)
"parent_compound"

descendant_of?(document, state_id, ancestor_id)

@spec descendant_of?(Statifier.Document.t(), String.t(), String.t()) :: boolean()

Check if a state is a descendant of another state in the hierarchy.

Uses O(1) cache lookup when available, falls back to O(depth) traversal.

Examples

iex> StateHierarchy.descendant_of?(document, "child", "parent")
true

iex> StateHierarchy.descendant_of?(document, "sibling1", "sibling2")
false

exits_parallel_region?(source_state, target_state, document)

@spec exits_parallel_region?(String.t(), String.t(), Statifier.Document.t()) ::
  boolean()

Check if a transition exits a parallel region.

Returns true if the target state is outside any parallel region that contains the source state.

find_parents_with_history(exiting_states, document)

@spec find_parents_with_history([String.t()], Statifier.Document.t()) :: [String.t()]

Find parent states that have history children and need history recorded.

Used during state exit to determine which states need their history recorded.

get_all_ancestors(state, document)

@spec get_all_ancestors(Statifier.State.t(), Statifier.Document.t()) :: [String.t()]

Get all ancestor state IDs for a given state.

Returns a list of ancestor state IDs, from immediate parent to root.

get_ancestor_path(state_id, document)

@spec get_ancestor_path(String.t(), Statifier.Document.t()) :: [String.t()]

Get the complete ancestor path from a state to the root, including the state itself.

Returns a list of state IDs from the root down to the given state. Uses O(1) cache lookup when available, falls back to O(depth) traversal.

Examples

iex> StateHierarchy.get_ancestor_path("leaf", document)
["root", "parent", "leaf"]

get_parallel_ancestors(document, state_id)

@spec get_parallel_ancestors(Statifier.Document.t(), String.t()) :: [String.t()]

Get all parallel ancestors of a state.

Returns a list of parallel state IDs that are ancestors of the given state. Uses O(1) cache lookup when available, falls back to O(depth) traversal.