afd99f5e0d
Implements 8 new language features:
- |> pipe operator: a |> f desugars to f(a), left-associative chains
- with record update: let b = a with { field: val } — non-destructive struct update
- retry/fallback: retry N times { ... } fallback { ... } with counter-based loop codegen
- reason: AI inference primitive calling soma /v1/chat/completions at runtime
- parallel: concurrent execution block returning a Map of named results via threads
- trace: zero-cost observability block emitting TraceBegin/TraceEnd with ms timing
- requires: precondition annotation on fn, emits ContractCheck bytecode at entry
- deploy: deployment-as-syntax posting to soma /v1/deploy at runtime
All features thread through lexer → parser/AST → codegen → runtime interpreter.
299 lines
9.4 KiB
Rust
299 lines
9.4 KiB
Rust
//! Abstract syntax tree node types.
|
|
|
|
use el_lexer::Span;
|
|
|
|
// ── Test-specific nodes ───────────────────────────────────────────────────────
|
|
|
|
/// Which graph a test should execute against.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum TestTarget {
|
|
/// In-memory graph — default, zero external dependencies.
|
|
Unit,
|
|
/// Real Engram database pointed at by `ENGRAM_URL` / `ENGRAM_DB_PATH`.
|
|
E2e,
|
|
/// Run against both unit (in-memory) and e2e (real DB).
|
|
Both,
|
|
}
|
|
|
|
/// A `seed Node { ... }` or `seed Edge { ... }` statement inside a test block.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum SeedStmt {
|
|
Node {
|
|
node_type: String,
|
|
content: String,
|
|
importance: f32,
|
|
tier: Option<String>,
|
|
},
|
|
Edge {
|
|
from: String,
|
|
to: String,
|
|
relation: String,
|
|
weight: f32,
|
|
},
|
|
}
|
|
|
|
// ── Literals ──────────────────────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum Literal {
|
|
Int(i64),
|
|
Float(f64),
|
|
Str(String),
|
|
Bool(bool),
|
|
}
|
|
|
|
// ── Type expressions ──────────────────────────────────────────────────────────
|
|
|
|
/// A type annotation in source code, e.g. `String`, `[Int]`, `User?`.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum TypeExpr {
|
|
/// A named type: `Int`, `String`, `User`, …
|
|
Named(String),
|
|
/// An array type: `[T]`
|
|
Array(Box<TypeExpr>),
|
|
/// An optional type: `T?`
|
|
Optional(Box<TypeExpr>),
|
|
/// A function type: `fn(A, B) -> C`
|
|
Fn { params: Vec<TypeExpr>, return_type: Box<TypeExpr> },
|
|
/// `Result<T, E>` — built-in error-propagation type
|
|
Result { ok: Box<TypeExpr>, err: Box<TypeExpr> },
|
|
/// `Map<K, V>` — built-in key-value map type
|
|
Map { key: Box<TypeExpr>, value: Box<TypeExpr> },
|
|
/// A generic type parameter: `T`, `E` — used inside generic function signatures.
|
|
TypeParam(String),
|
|
}
|
|
|
|
// ── Patterns (for match arms) ─────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum Pattern {
|
|
/// `Status::Active`
|
|
EnumVariant { enum_name: String, variant: String, payload: Option<String> },
|
|
/// A wildcard `_`
|
|
Wildcard,
|
|
/// A literal: `42`, `"str"`, `true`
|
|
Literal(Literal),
|
|
/// A binding: `x`
|
|
Binding(String),
|
|
}
|
|
|
|
// ── Binary operators ──────────────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum BinOp {
|
|
Add, Sub, Mul, Div,
|
|
Eq, NotEq, Lt, Gt, LtEq, GtEq,
|
|
And, Or,
|
|
}
|
|
|
|
// ── Expressions ───────────────────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum Expr {
|
|
Literal(Literal),
|
|
Ident(String),
|
|
BinOp { op: BinOp, left: Box<Expr>, right: Box<Expr> },
|
|
UnaryNot(Box<Expr>),
|
|
Call { func: Box<Expr>, args: Vec<Expr> },
|
|
Block(Vec<Stmt>),
|
|
Match { subject: Box<Expr>, arms: Vec<MatchArm> },
|
|
/// `activate TypeName where "semantic query string"`
|
|
Activate { type_name: String, query: String },
|
|
/// `sealed { stmts... }` — quantum-sealed block
|
|
Sealed(Vec<Stmt>),
|
|
If { cond: Box<Expr>, then: Box<Expr>, else_: Option<Box<Expr>> },
|
|
Field { object: Box<Expr>, field: String },
|
|
/// Array constructor: `[a, b, c]`
|
|
Array(Vec<Expr>),
|
|
/// Path expression: `Status::Active` (enum variant ref)
|
|
Path { segments: Vec<String> },
|
|
/// Index expression: `arr[0]`
|
|
Index { object: Box<Expr>, index: Box<Expr> },
|
|
/// Closure: `|x: Int| x * 2` or `|x: Int| -> Int { x * 2 }`
|
|
Closure {
|
|
params: Vec<Param>,
|
|
return_type: Option<TypeExpr>,
|
|
body: Box<Expr>,
|
|
span: Span,
|
|
},
|
|
/// Try operator: `expr?` — unwraps Result, propagates error
|
|
Try(Box<Expr>),
|
|
/// Map literal: `{"key": value, ...}`
|
|
MapLiteral(Vec<(Expr, Expr)>),
|
|
/// Struct literal: `Point { x: 10, y: 20 }`
|
|
StructLit {
|
|
type_name: String,
|
|
fields: Vec<(String, Expr)>,
|
|
span: Span,
|
|
},
|
|
/// Record update: `a with { field: new_val }`
|
|
With {
|
|
base: Box<Expr>,
|
|
updates: Vec<(String, Expr)>,
|
|
},
|
|
/// AI inference: `reason "query"`
|
|
Reason {
|
|
query: String,
|
|
},
|
|
/// Concurrent execution: `parallel { name: expr, ... }`
|
|
Parallel {
|
|
entries: Vec<(String, Expr)>,
|
|
},
|
|
/// Trace block: `trace "label" { stmts }`
|
|
Trace {
|
|
label: String,
|
|
body: Vec<Stmt>,
|
|
},
|
|
}
|
|
|
|
// ── Match arm ─────────────────────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct MatchArm {
|
|
pub pattern: Pattern,
|
|
pub body: Expr,
|
|
pub span: Span,
|
|
}
|
|
|
|
// ── Decorators ────────────────────────────────────────────────────────────────
|
|
|
|
/// A decorator applied to a function: `@name` or `@name(args)`
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct Decorator {
|
|
pub name: String,
|
|
pub args: Vec<Expr>,
|
|
pub span: Span,
|
|
}
|
|
|
|
// ── Protocol ──────────────────────────────────────────────────────────────────
|
|
|
|
/// A method signature inside a protocol definition.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct ProtocolMethod {
|
|
pub name: String,
|
|
pub params: Vec<Param>,
|
|
pub return_type: TypeExpr,
|
|
pub span: Span,
|
|
}
|
|
|
|
// ── Statements ────────────────────────────────────────────────────────────────
|
|
|
|
/// A named parameter in a function definition.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct Param {
|
|
pub name: String,
|
|
pub type_ann: TypeExpr,
|
|
pub span: Span,
|
|
}
|
|
|
|
/// A field in a type definition.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct Field {
|
|
pub name: String,
|
|
pub type_ann: TypeExpr,
|
|
pub span: Span,
|
|
}
|
|
|
|
/// A variant in an enum definition.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct Variant {
|
|
pub name: String,
|
|
/// Payload type, if any (e.g. `Pending(String)`)
|
|
pub payload: Option<TypeExpr>,
|
|
pub span: Span,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub enum Stmt {
|
|
/// `let name: Type = expr`
|
|
Let {
|
|
name: String,
|
|
type_ann: Option<TypeExpr>,
|
|
value: Expr,
|
|
span: Span,
|
|
},
|
|
/// `return expr`
|
|
Return(Expr, Span),
|
|
/// A bare expression used as a statement (usually a call).
|
|
Expr(Expr, Span),
|
|
/// `fn name<T, E>(params) -> ReturnType [requires cond] { body }` (with optional decorators)
|
|
FnDef {
|
|
name: String,
|
|
decorators: Vec<Decorator>,
|
|
/// Generic type parameters, e.g. `["T", "E"]` for `fn foo<T, E>`.
|
|
type_params: Vec<String>,
|
|
params: Vec<Param>,
|
|
return_type: TypeExpr,
|
|
/// Optional precondition: `requires expr`
|
|
requires: Option<Box<Expr>>,
|
|
body: Vec<Stmt>,
|
|
span: Span,
|
|
},
|
|
/// `type Name { fields... }`
|
|
TypeDef {
|
|
name: String,
|
|
fields: Vec<Field>,
|
|
span: Span,
|
|
},
|
|
/// `enum Name { variants... }`
|
|
EnumDef {
|
|
name: String,
|
|
variants: Vec<Variant>,
|
|
span: Span,
|
|
},
|
|
/// `test "name" [target: unit|e2e|both] { body }`
|
|
TestDef {
|
|
name: String,
|
|
target: TestTarget,
|
|
body: Vec<Stmt>,
|
|
span: Span,
|
|
},
|
|
/// `seed Node { ... }` or `seed Edge { ... }`
|
|
Seed(SeedStmt, Span),
|
|
/// `assert <expr>`
|
|
Assert(Expr, Span),
|
|
/// `import std::collections::Map` or `from pkg import { A, B }`
|
|
Import {
|
|
path: Vec<String>,
|
|
names: Vec<String>,
|
|
alias: Option<String>,
|
|
span: Span,
|
|
},
|
|
/// `protocol Name { method sigs... }`
|
|
ProtocolDef {
|
|
name: String,
|
|
methods: Vec<ProtocolMethod>,
|
|
span: Span,
|
|
},
|
|
/// `impl Protocol for TypeName { fn ... }`
|
|
ImplDef {
|
|
protocol_name: String,
|
|
type_name: String,
|
|
methods: Vec<Stmt>,
|
|
span: Span,
|
|
},
|
|
/// `retry N times { ... } fallback { ... }`
|
|
Retry {
|
|
count: Expr,
|
|
body: Vec<Stmt>,
|
|
fallback: Option<Vec<Stmt>>,
|
|
span: Span,
|
|
},
|
|
/// `deploy fn_name to "/route" via target`
|
|
Deploy {
|
|
fn_name: String,
|
|
route: String,
|
|
target: String,
|
|
span: Span,
|
|
},
|
|
}
|
|
|
|
// ── Top-level program ─────────────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct Program {
|
|
pub stmts: Vec<Stmt>,
|
|
/// The original source, kept for diagnostics and source maps.
|
|
pub source: String,
|
|
}
|