gent/parser/
ast.rs

1//! Abstract Syntax Tree definitions for GENT
2
3use crate::Span;
4
5/// Binary operators
6#[derive(Debug, Clone, PartialEq)]
7pub enum BinaryOp {
8    // Arithmetic
9    Add,
10    Sub,
11    Mul,
12    Div,
13    Mod,
14    // Comparison
15    Eq,
16    Ne,
17    Lt,
18    Le,
19    Gt,
20    Ge,
21    // Logical
22    And,
23    Or,
24}
25
26/// Unary operators
27#[derive(Debug, Clone, PartialEq)]
28pub enum UnaryOp {
29    Not, // !
30    Neg, // -
31}
32
33/// Part of an interpolated string
34#[derive(Debug, Clone, PartialEq)]
35pub enum StringPart {
36    /// Literal text
37    Literal(String),
38    /// Interpolated expression
39    Expr(Box<Expression>),
40}
41
42/// Lambda body - either a single expression or a block
43#[derive(Debug, Clone, PartialEq)]
44pub enum LambdaBody {
45    /// Single expression: (x) => x * 2
46    Expression(Box<Expression>),
47    /// Block with statements: (x) => { return x * 2 }
48    Block(Block),
49}
50
51/// Lambda expression: (params) => body
52#[derive(Debug, Clone, PartialEq)]
53pub struct Lambda {
54    pub params: Vec<String>,
55    pub body: LambdaBody,
56    pub span: Span,
57}
58
59/// Type names in GENT
60#[derive(Debug, Clone, PartialEq)]
61pub enum TypeName {
62    String,
63    Number,
64    Boolean,
65    Object,
66    Array,
67    Any,
68}
69
70/// Field types for structured output schemas
71#[derive(Debug, Clone, PartialEq)]
72pub enum FieldType {
73    String,
74    Number,
75    Boolean,
76    Array(Box<FieldType>),
77    Object(Vec<StructField>),
78    Named(String), // reference to a struct
79}
80
81/// A field in a struct or inline object type
82#[derive(Debug, Clone, PartialEq)]
83pub struct StructField {
84    pub name: String,
85    pub field_type: FieldType,
86    pub span: Span,
87}
88
89/// Struct declaration: `struct Name { fields... }`
90#[derive(Debug, Clone, PartialEq)]
91pub struct StructDecl {
92    pub name: String,
93    pub fields: Vec<StructField>,
94    pub span: Span,
95}
96
97/// Enum declaration: `enum Name { Variant1, Variant2(type) }`
98#[derive(Debug, Clone, PartialEq)]
99pub struct EnumDecl {
100    pub name: String,
101    pub variants: Vec<EnumVariant>,
102    pub span: Span,
103}
104
105/// A variant in an enum declaration
106#[derive(Debug, Clone, PartialEq)]
107pub struct EnumVariant {
108    pub name: String,
109    pub fields: Vec<EnumField>,
110    pub span: Span,
111}
112
113/// A field in an enum variant
114#[derive(Debug, Clone, PartialEq)]
115pub struct EnumField {
116    pub name: Option<String>,
117    pub type_name: String,
118    pub span: Span,
119}
120
121/// Duration unit for timeout specifications
122#[derive(Debug, Clone, PartialEq)]
123pub enum DurationUnit {
124    Milliseconds,
125    Seconds,
126    Minutes,
127}
128
129/// Duration value with unit
130#[derive(Debug, Clone, PartialEq)]
131pub struct Duration {
132    pub value: u64,
133    pub unit: DurationUnit,
134    pub span: Span,
135}
136
137impl Duration {
138    pub fn to_millis(&self) -> u64 {
139        match self.unit {
140            DurationUnit::Milliseconds => self.value,
141            DurationUnit::Seconds => self.value * 1000,
142            DurationUnit::Minutes => self.value * 60 * 1000,
143        }
144    }
145}
146
147/// Parallel execution block declaration
148#[derive(Debug, Clone, PartialEq)]
149pub struct ParallelDecl {
150    pub name: String,
151    pub agents: Vec<Expression>,
152    pub timeout: Duration,
153    pub span: Span,
154}
155
156/// Output type specification (inline or named)
157#[derive(Debug, Clone, PartialEq)]
158pub enum OutputType {
159    Inline(Vec<StructField>),
160    Named(String),
161}
162
163/// Import statement: `import { Name1, Name2 } from "./path.gnt"`
164#[derive(Debug, Clone, PartialEq)]
165pub struct ImportStmt {
166    pub names: Vec<String>,
167    pub path: String,
168    pub span: Span,
169}
170
171/// A complete GENT program
172#[derive(Debug, Clone, PartialEq)]
173pub struct Program {
174    pub statements: Vec<Statement>,
175    pub span: Span,
176}
177
178/// A statement in GENT
179#[derive(Debug, Clone, PartialEq)]
180pub enum Statement {
181    Import(ImportStmt),
182    AgentDecl(AgentDecl),
183    ToolDecl(ToolDecl),
184    FnDecl(FnDecl),
185    StructDecl(StructDecl),
186    EnumDecl(EnumDecl),
187    ParallelDecl(ParallelDecl),
188    LetStmt(LetStmt),
189    TopLevelCall(TopLevelCall),
190}
191
192/// A top-level function call: `funcName(args...)`
193#[derive(Debug, Clone, PartialEq)]
194pub struct TopLevelCall {
195    pub name: String,
196    pub args: Vec<Expression>,
197    pub span: Span,
198}
199
200/// An agent declaration: `agent Name { fields... }`
201#[derive(Debug, Clone, PartialEq)]
202pub struct AgentDecl {
203    pub name: String,
204    pub fields: Vec<AgentField>,
205    pub tools: Vec<String>, // Tool names from `use` statements
206    pub output: Option<OutputType>,
207    pub span: Span,
208}
209
210/// A field in an agent declaration: `name: value`
211#[derive(Debug, Clone, PartialEq)]
212pub struct AgentField {
213    pub name: String,
214    pub value: Expression,
215    pub span: Span,
216}
217
218/// Tool declaration: `tool name(params) -> return_type { body }`
219#[derive(Debug, Clone, PartialEq)]
220pub struct ToolDecl {
221    pub name: String,
222    pub params: Vec<Param>,
223    pub return_type: Option<TypeName>,
224    pub body: Block,
225    pub span: Span,
226}
227
228/// Function declaration (pure, no agent access): `fn name(params) -> return_type { body }`
229#[derive(Debug, Clone, PartialEq)]
230pub struct FnDecl {
231    pub name: String,
232    pub params: Vec<Param>,
233    pub return_type: Option<TypeName>,
234    pub body: Block,
235    pub span: Span,
236}
237
238/// Parameter in a tool or function declaration
239#[derive(Debug, Clone, PartialEq)]
240pub struct Param {
241    pub name: String,
242    pub type_name: TypeName,
243    pub span: Span,
244}
245
246/// An expression in GENT
247#[derive(Debug, Clone, PartialEq)]
248pub enum Expression {
249    /// String literal: `"hello"` or interpolated string: `"Hello, ${name}!"`
250    String(Vec<StringPart>, Span),
251    /// Number literal: `42` or `3.14`
252    Number(f64, Span),
253    /// Boolean literal: `true` or `false`
254    Boolean(bool, Span),
255    /// Identifier reference: `varName`
256    Identifier(String, Span),
257    /// Null literal: `null`
258    Null(Span),
259    /// Array literal: `[1, 2, 3]`
260    Array(Vec<Expression>, Span),
261    /// Object literal: `{key: value}`
262    Object(Vec<(String, Expression)>, Span),
263    /// Binary operation: `a + b`
264    Binary(BinaryOp, Box<Expression>, Box<Expression>, Span),
265    /// Unary operation: `-x`, `!x`
266    Unary(UnaryOp, Box<Expression>, Span),
267    /// Function call: `foo(args)`
268    Call(Box<Expression>, Vec<Expression>, Span),
269    /// Member access: `obj.prop`
270    Member(Box<Expression>, String, Span),
271    /// Index access: `arr[0]`
272    Index(Box<Expression>, Box<Expression>, Span),
273    /// Range expression (start..end)
274    Range(Box<Expression>, Box<Expression>, Span),
275    /// Lambda expression: (x) => x * 2
276    Lambda(Lambda),
277    /// Match expression: match value { Pattern => result }
278    Match(MatchExpr),
279}
280
281impl Expression {
282    /// Get the span of this expression
283    pub fn span(&self) -> &Span {
284        match self {
285            Expression::String(_, span) => span,
286            Expression::Number(_, span) => span,
287            Expression::Boolean(_, span) => span,
288            Expression::Identifier(_, span) => span,
289            Expression::Null(span) => span,
290            Expression::Array(_, span) => span,
291            Expression::Object(_, span) => span,
292            Expression::Binary(_, _, _, span) => span,
293            Expression::Unary(_, _, span) => span,
294            Expression::Call(_, _, span) => span,
295            Expression::Member(_, _, span) => span,
296            Expression::Index(_, _, span) => span,
297            Expression::Range(_, _, span) => span,
298            Expression::Lambda(lambda) => &lambda.span,
299            Expression::Match(m) => &m.span,
300        }
301    }
302}
303
304/// A block of statements
305#[derive(Debug, Clone, PartialEq)]
306pub struct Block {
307    pub statements: Vec<BlockStmt>,
308    pub span: Span,
309}
310
311/// A statement within a block
312#[derive(Debug, Clone, PartialEq)]
313pub enum BlockStmt {
314    Let(LetStmt),
315    Assignment(AssignmentStmt),
316    Return(ReturnStmt),
317    If(IfStmt),
318    For(ForStmt),
319    While(WhileStmt),
320    Try(TryStmt),
321    Break(Span),
322    Continue(Span),
323    Expr(Expression),
324}
325
326/// Let statement: `let x = expr`
327#[derive(Debug, Clone, PartialEq)]
328pub struct LetStmt {
329    pub name: String,
330    pub value: Expression,
331    pub span: Span,
332}
333
334/// Assignment statement: `x = expr`
335#[derive(Debug, Clone, PartialEq)]
336pub struct AssignmentStmt {
337    pub name: String,
338    pub value: Expression,
339    pub span: Span,
340}
341
342/// Return statement: `return expr?`
343#[derive(Debug, Clone, PartialEq)]
344pub struct ReturnStmt {
345    pub value: Option<Expression>,
346    pub span: Span,
347}
348
349/// If statement: `if cond { ... } else { ... }`
350#[derive(Debug, Clone, PartialEq)]
351pub struct IfStmt {
352    pub condition: Expression,
353    pub then_block: Block,
354    pub else_block: Option<Block>,
355    pub span: Span,
356}
357
358/// For loop statement
359#[derive(Debug, Clone, PartialEq)]
360pub struct ForStmt {
361    /// Loop variable name
362    pub variable: String,
363    /// Expression to iterate over
364    pub iterable: Expression,
365    /// Loop body
366    pub body: Block,
367    /// Source location
368    pub span: Span,
369}
370
371/// While loop statement
372#[derive(Debug, Clone, PartialEq)]
373pub struct WhileStmt {
374    /// Loop condition
375    pub condition: Expression,
376    /// Loop body
377    pub body: Block,
378    /// Source location
379    pub span: Span,
380}
381
382/// Try/catch statement
383#[derive(Debug, Clone, PartialEq)]
384pub struct TryStmt {
385    /// The try block
386    pub try_block: Block,
387    /// The error variable name in catch
388    pub error_var: String,
389    /// The catch block
390    pub catch_block: Block,
391    /// Source location
392    pub span: Span,
393}
394
395/// Match expression: `match value { Pattern => result }`
396#[derive(Debug, Clone, PartialEq)]
397pub struct MatchExpr {
398    pub subject: Box<Expression>,
399    pub arms: Vec<MatchArm>,
400    pub span: Span,
401}
402
403/// A single arm in a match expression
404#[derive(Debug, Clone, PartialEq)]
405pub struct MatchArm {
406    pub pattern: MatchPattern,
407    pub body: MatchBody,
408    pub span: Span,
409}
410
411/// Pattern in a match arm
412#[derive(Debug, Clone, PartialEq)]
413pub enum MatchPattern {
414    /// Wildcard: `_`
415    Wildcard,
416    /// Enum variant: `Status.Pending` or `Result.Ok(value)`
417    EnumVariant {
418        enum_name: String,
419        variant_name: String,
420        bindings: Vec<String>,
421    },
422}
423
424/// Body of a match arm
425#[derive(Debug, Clone, PartialEq)]
426pub enum MatchBody {
427    Expression(Box<Expression>),
428    Block(Block),
429}