Predicator.Visitors.InstructionsVisitor (predicator v3.7.0)

View Source

Visitor that converts AST nodes to stack machine instructions.

This visitor implements post-order traversal to generate instruction lists that can be executed by the stack-based evaluator. Instructions are generated in the correct order for stack-based evaluation.

Source positions

Internally the traversal pairs every instruction with the source position of the AST node that emitted it. visit/2 discards those positions and returns the plain instruction list; visit_with_positions/2 returns both. The instruction list is identical either way - positions never enter the instruction format itself, so cross-language interchange and stored compiled artifacts are unaffected (ADR-0001).

Both entry points accept either a positioned AST or the position-free shape Predicator 3.6 produced, normalizing with Predicator.Parser.ensure_positions/1 on the way in.

Examples

iex> ast = {:literal, 42}
iex> Predicator.Visitors.InstructionsVisitor.visit(ast, [])
[["lit", 42]]

iex> ast = {:identifier, "score"}
iex> Predicator.Visitors.InstructionsVisitor.visit(ast, [])
[["load", "score"]]

iex> ast = {:comparison, :gt, {:identifier, "score"}, {:literal, 85}}
iex> Predicator.Visitors.InstructionsVisitor.visit(ast, [])
[["load", "score"], ["lit", 85], ["compare", "GT"]]

iex> ast = {:logical_and, {:literal, true}, {:literal, false}}
iex> Predicator.Visitors.InstructionsVisitor.visit(ast, [])
[["lit", true], ["jump_if_falsy_or_pop", 2], ["lit", false]]

iex> ast = {:function_call, "len", [{:identifier, "name"}]}
iex> Predicator.Visitors.InstructionsVisitor.visit(ast, [])
[["load", "name"], ["call", "len", 1]]

Summary

Types

One instruction paired with the source position of the node that emitted it.

Functions

Visits an AST node and returns stack machine instructions.

Returns the instruction list and a side table mapping each instruction's 0-based index to the source position of the AST node that emitted it.

Types

annotated()

@type annotated() :: {[binary() | term()], Predicator.Types.position() | nil}

One instruction paired with the source position of the node that emitted it.

Functions

visit(ast_node, opts \\ [])

@spec visit(
  Predicator.Parser.ast() | Predicator.Parser.bare_ast(),
  keyword()
) :: [[binary() | term()]]

Visits an AST node and returns stack machine instructions.

Uses post-order traversal to ensure operands are pushed onto the stack before operators are applied.

Parameters

  • ast_node - The AST node to convert to instructions
  • opts - Optional visitor options (currently unused)

Returns

List of instructions in the format [["operation", ...args]]

visit_with_positions(ast_node, opts \\ [])

@spec visit_with_positions(
  Predicator.Parser.ast() | Predicator.Parser.bare_ast(),
  keyword()
) :: {[[binary() | term()]], Predicator.Types.position_table()}

Returns the instruction list and a side table mapping each instruction's 0-based index to the source position of the AST node that emitted it.

Nodes carrying a nil position contribute no entry, so a position-free AST yields an empty table. The instruction list is identical to visit/2's.

Examples

iex> ast = {:comparison, :gt, {:identifier, "score", {1, 1}}, {:literal, 85, {1, 9}}, {1, 7}}
iex> Predicator.Visitors.InstructionsVisitor.visit_with_positions(ast)
{[["load", "score"], ["lit", 85], ["compare", "GT"]],
 %{0 => {1, 1}, 1 => {1, 9}, 2 => {1, 7}}}

iex> Predicator.Visitors.InstructionsVisitor.visit_with_positions({:literal, 42})
{[["lit", 42]], %{}}