Search documentation of Metastatic

# Metastatic.Analysis.ControlFlow.Result (Metastatic v0.2.0)

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

## Types

cfg()
cfg_edge()
cfg_node()
node_id()
t()

## Functions

new(cfg)

Creates a new result from a CFG.

to_d3_json(result)

Exports CFG to D3.js-compatible JSON format.

to_dot(result)

Exports CFG to DOT format for visualization.

to_map(result, opts \\ [])

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