Packages
Secure BEAM sandbox runtime for LLM code mode and MCP aggregation. Run concurrent LLM/tool clients safely while agents orchestrate approved tools, call upstream MCP/OpenAPI servers, and transform data.
Current section
Files
Jump to
Current section
Files
lib/ptc_runner/lisp/core_ast.ex
defmodule PtcRunner.Lisp.CoreAST do
@moduledoc """
Core, validated AST for PTC-Lisp.
This module defines the type specifications for the intermediate
representation that the analyzer produces. The interpreter evaluates
CoreAST to produce results.
## Pipeline
```
source → Parser → RawAST → Analyze → CoreAST → Eval → result
```
"""
@type literal ::
nil
| boolean()
| number()
| {:string, String.t()}
| {:keyword, atom()}
@type fn_params :: [pattern()] | {:variadic, [pattern()], pattern()}
@type t ::
literal
# Collections
| {:vector, [t()]}
| {:map, [{t(), t()}]}
| {:set, [t()]}
# Variables and namespace access
| {:var, atom()}
| {:ctx, atom()}
# Function call: f(args...)
| {:call, t(), [t()]}
# Let bindings: (let [p1 v1 p2 v2 ...] body)
| {:let, [binding()], t()}
# Conditionals
| {:if, t(), t(), t()}
# Anonymous function
| {:fn, fn_params(), t()}
# Sequential evaluation (special forms, not calls)
| {:do, [t()]}
# Short-circuit logic (special forms, not calls)
| {:and, [t()]}
| {:or, [t()]}
# Predicates
| {:where, field_path(), where_op(), t() | nil}
| {:pred_combinator, :all_of | :any_of | :none_of, [t()]}
# Control flow signals
| {:return, t()}
| {:fail, t()}
# Builtin call (other tools)
| {:builtin_call, String.t(), t()}
# Tool invocation via ctx namespace: (ctx/tool-name args...)
| {:ctx_call, atom(), [t()]}
# Define binding in user namespace: (def name value)
| {:def, atom(), t()}
# Tail recursion: loop and recur
| {:loop, [binding()], t()}
| {:recur, [t()]}
@type binding :: {:binding, pattern(), t()}
@type pattern ::
{:var, atom()}
| {:destructure, {:keys, [atom()], keyword()}}
| {:destructure, {:map, [atom()], [{atom(), atom()}], keyword()}}
| {:destructure, {:as, atom(), pattern()}}
| {:destructure, {:seq, [pattern()]}}
# Rest pattern: [a b & rest] binds rest to remaining elements
| {:destructure, {:seq_rest, [pattern()], pattern()}}
@type field_path :: {:field, [field_segment()]}
@type field_segment :: {:keyword, atom()} | {:string, String.t()}
@type where_op ::
:eq
| :not_eq
| :gt
| :lt
| :gte
| :lte
| :includes
| :in
| :truthy
end