Metastatic.Analysis.ControlFlow.Result (Metastatic v0.10.4)

View Source

Result structure for control flow graph analysis.

Contains the control flow graph with nodes, edges, entry/exit points, and analysis results like reachability and cycles.

Fields

  • :cfg - The control flow graph structure
  • :entry_node - ID of the entry node
  • :exit_nodes - List of exit node IDs
  • :reachable_nodes - Set of reachable node IDs
  • :has_cycles? - Boolean indicating if graph contains cycles
  • :node_count - Total number of nodes
  • :edge_count - Total number of edges

Examples

iex> cfg = %{nodes: %{0 => %{type: :entry}}, edges: [], entry: 0, exits: [0]}
iex> result = Metastatic.Analysis.ControlFlow.Result.new(cfg)
iex> result.node_count
1

Summary

Functions

Creates a new result from a CFG.

Exports CFG to D3.js-compatible JSON format.

Exports CFG to DOT format for visualization.

Converts result to JSON-compatible map.

Types

cfg()

@type cfg() :: %{
  nodes: %{required(node_id()) => cfg_node()},
  edges: [cfg_edge()],
  entry: node_id(),
  exits: [node_id()]
}

cfg_edge()

@type cfg_edge() :: {from :: node_id(), to :: node_id(), condition :: atom() | nil}

cfg_node()

@type cfg_node() :: %{
  id: node_id(),
  type: :entry | :exit | :statement | :conditional | :loop,
  ast: term(),
  predecessors: [node_id()],
  successors: [node_id()]
}

node_id()

@type node_id() :: non_neg_integer()

t()

@type t() :: %Metastatic.Analysis.ControlFlow.Result{
  cfg: cfg(),
  edge_count: non_neg_integer(),
  entry_node: node_id(),
  exit_nodes: [node_id()],
  has_cycles?: boolean(),
  node_count: non_neg_integer(),
  reachable_nodes: MapSet.t(node_id())
}

Functions

new(cfg)

@spec new(cfg()) :: t()

Creates a new result from a CFG.

Examples

iex> cfg = %{nodes: %{0 => %{id: 0, type: :entry, ast: nil, predecessors: [], successors: []}}, edges: [], entry: 0, exits: [0]}
iex> result = Metastatic.Analysis.ControlFlow.Result.new(cfg)
iex> result.entry_node
0

to_d3_json(result)

@spec to_d3_json(t()) :: map()

Exports CFG to D3.js-compatible JSON format.

Returns a map with nodes and links arrays suitable for D3.js force-directed graphs.

Examples

iex> cfg = %{nodes: %{0 => %{id: 0, type: :entry, ast: nil, predecessors: [], successors: [1]}, 1 => %{id: 1, type: :exit, ast: nil, predecessors: [0], successors: []}}, edges: [{0, 1, nil}], entry: 0, exits: [1]}
iex> result = Metastatic.Analysis.ControlFlow.Result.new(cfg)
iex> json = Metastatic.Analysis.ControlFlow.Result.to_d3_json(result)
iex> is_list(json.nodes)
true
iex> is_list(json.links)
true

to_dot(result)

@spec to_dot(t()) :: String.t()

Exports CFG to DOT format for visualization.

Examples

iex> cfg = %{nodes: %{0 => %{id: 0, type: :entry, ast: nil, predecessors: [], successors: [1]}, 1 => %{id: 1, type: :exit, ast: nil, predecessors: [0], successors: []}}, edges: [{0, 1, nil}], entry: 0, exits: [1]}
iex> result = Metastatic.Analysis.ControlFlow.Result.new(cfg)
iex> dot = Metastatic.Analysis.ControlFlow.Result.to_dot(result)
iex> String.contains?(dot, "digraph")
true

to_map(result, opts \\ [])

@spec to_map(
  t(),
  keyword()
) :: map()

Converts result to JSON-compatible map.

Options

  • :format - Output format (:standard or :d3). Default: :standard

Examples

iex> cfg = %{nodes: %{}, edges: [], entry: 0, exits: []}
iex> result = Metastatic.Analysis.ControlFlow.Result.new(cfg)
iex> map = Metastatic.Analysis.ControlFlow.Result.to_map(result)
iex> is_map(map)
true

iex> cfg = %{nodes: %{0 => %{id: 0, type: :entry, ast: nil, predecessors: [], successors: []}}, edges: [], entry: 0, exits: [0]}
iex> result = Metastatic.Analysis.ControlFlow.Result.new(cfg)
iex> map = Metastatic.Analysis.ControlFlow.Result.to_map(result, format: :d3)
iex> Map.has_key?(map, :nodes) and Map.has_key?(map, :links)
true