Search documentation of Metastatic

# Metastatic.Analysis.Purity (Metastatic v0.13.2)

View Source

Function purity analysis at the MetaAST level.

Analyzes code to determine if it's pure (no side effects) or impure (has side effects like I/O, mutations, random operations, etc.).

Works across all supported languages by operating on the unified MetaAST representation.

## Purity Definition

A pure function:

- Always returns the same output for the same input (deterministic)
- Has no side effects (no I/O, no mutations, no global state access)
- Doesn't depend on external state

An impure function has one or more of:

- I/O operations (print, file access, network, database)
- Mutations (modifying variables, especially in loops)
- Non-deterministic operations (random, time/date)
- Exception handling (raising/catching exceptions)

## Usage

    alias Metastatic.{Document, Analysis.Purity}

    # Analyze a document
    ast = {:binary_op, :arithmetic, :+, {:variable, "x"}, {:literal, :integer, 5}}
    doc = Document.new(ast, :elixir)
    {:ok, result} = Purity.analyze(doc)

    result.pure?              # => true
    result.effects            # => []
    result.confidence         # => :high
    result.summary            # => "Function is pure"

## Examples

    # Pure arithmetic
    iex> ast = {:binary_op, [category: :arithmetic, operator: :+], [{:literal, [subtype: :integer], 1}, {:literal, [subtype: :integer], 2}]}
    iex> doc = Metastatic.Document.new(ast, :python)
    iex> {:ok, result} = Metastatic.Analysis.Purity.analyze(doc)
    iex> result.pure?
    true

    # Impure I/O
    iex> ast = {:function_call, [name: "print"], [{:literal, [subtype: :string], "hello"}]}
    iex> doc = Metastatic.Document.new(ast, :python)
    iex> {:ok, result} = Metastatic.Analysis.Purity.analyze(doc)
    iex> result.pure?
    false
    iex> result.effects
    [:io]

## Summary

### Functions

analyze(doc)

Analyzes a document for purity.

analyze!(doc)

Analyzes a document for purity.

## Functions

# analyze(doc)

    @spec analyze(Metastatic.Document.t()) :: {:ok, term()} | {:error, term()}

Analyzes a document for purity.

Accepts either:

- A `Metastatic.Document` struct
- A `{language, native_ast}` tuple

Returns `{:ok, result}` where result is a `Metastatic.Analysis.Purity.Result` struct.

## Examples

    # Using Document
    iex> ast = {:literal, [subtype: :integer], 42}
    iex> doc = Metastatic.Document.new(ast, :elixir)
    iex> {:ok, result} = Metastatic.Analysis.Purity.analyze(doc)
    iex> result.pure?
    true

    # Using {language, native_ast} tuple
    iex> python_ast = %{"_type" => "Constant", "value" => 42}
    iex> {:ok, result} = Metastatic.Analysis.Purity.analyze(:python, python_ast)
    iex> result.pure?
    true

# analyze!(doc)

    @spec analyze!(Metastatic.Document.t()) :: term()

Analyzes a document for purity.

Accepts either:

- A `Metastatic.Document` struct
- A `{language, native_ast}` tuple

Returns `{:ok, result}` where result is a `Metastatic.Analysis.Purity.Result` struct.

## Examples

    # Using Document
    iex> ast = {:literal, [subtype: :integer], 42}
    iex> doc = Metastatic.Document.new(ast, :elixir)
    iex> {:ok, result} = Metastatic.Analysis.Purity.analyze(doc)
    iex> result.pure?
    true

    # Using {language, native_ast} tuple
    iex> python_ast = %{"_type" => "Constant", "value" => 42}
    iex> {:ok, result} = Metastatic.Analysis.Purity.analyze(:python, python_ast)
    iex> result.pure?
    true

Unlike not-banged version, this one either returns a result or raises