Files
el/crates/el-parser/src/ast.rs
T

265 lines
8.6 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,
},
}
// ── 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 { 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,
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,
},
}
// ── 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,
}