Metastatic.Adapters.Python.ToMeta (Metastatic v0.10.4)

View Source

Transform Python AST (M1) to MetaAST (M2).

Implements the abstraction function α_Python that lifts Python-specific AST structures to the meta-level representation.

Transformation Strategy

Python's AST is represented as nested maps with "_type" keys. We pattern match on these structures and transform them to MetaAST tuples.

M2.1 (Core Layer)

  • Literals: Constant nodes → {:literal, type, value}
  • Variables: Name nodes → {:variable, name}
  • Binary operators: BinOp → {:binary_op, category, op, left, right}
  • Unary operators: UnaryOp → {:unary_op, category, op, operand}
  • Function calls: Call → {:function_call, name, args}
  • Conditionals: If, IfExp → {:conditional, condition, then, else}
  • Blocks: Module, multiple statements → {:block, statements}
  • Early returns: Return, Break, Continue → {:early_return, kind, value}

M2.2 (Extended Layer)

  • Loops: While → {:loop, :while, condition, body}
  • Loops: For → {:loop, :for_each, iterator, collection, body}
  • Lambdas: Lambda → {:lambda, params, captures, body}
  • Collection ops: Simple ListComp → {:collection_op, :map, lambda, collection}
  • Exception handling: Try → {:exception_handling, try_block, rescue_clauses, finally_block}

Metadata Preservation

The transformation preserves Python-specific information:

  • :lineno - line number
  • :col_offset - column offset
  • :python_node_type - original Python AST node type

This enables high-fidelity round-trips (M1 → M2 → M1).

Summary

Functions

Transform Python AST to MetaAST.

Functions

transform(node)

@spec transform(map()) :: {:ok, term(), map()} | {:error, String.t()}

Transform Python AST to MetaAST.

Returns {:ok, meta_ast, metadata} on success or {:error, reason} on failure.

New 3-Tuple Format

All MetaAST nodes are uniform 3-element tuples:

{type_atom, keyword_meta, children_or_value}

Examples

iex> transform(%{"_type" => "Constant", "value" => 42})
{:ok, {:literal, [subtype: :integer], 42}, %{}}

iex> transform(%{"_type" => "Name", "id" => "x"})
{:ok, {:variable, [], "x"}, %{}}

iex> transform(%{"_type" => "BinOp", "op" => %{"_type" => "Add"}, ...})
{:ok, {:binary_op, [category: :arithmetic, operator: :+], [left, right]}, %{}}