Skip to main content

atoxide_parser/
ast.rs

1//! Abstract Syntax Tree types for the Ato language.
2
3use atoxide_lexer::Span;
4use serde::{Deserialize, Serialize};
5
6/// A complete Ato source file.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct File {
9    pub statements: Vec<Statement>,
10    pub span: Span,
11}
12
13/// A statement in the Ato language.
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
15pub enum Statement {
16    /// `#pragma experiment("NAME")`
17    Pragma(PragmaStmt),
18    /// `import X` or `from "path" import X`
19    Import(ImportStmt),
20    /// `import X from "path"` (deprecated form)
21    DepImport(DepImportStmt),
22    /// `module M:`, `component C:`, `interface I:`
23    BlockDef(BlockDef),
24    /// `x = value`
25    Assignment(Assignment),
26    /// `x += value` or `x -= value`
27    CumAssignment(CumAssignment),
28    /// `x |= value` or `x &= value`
29    SetAssignment(SetAssignment),
30    /// `a ~ b`
31    Connection(Connection),
32    /// `a ~> b ~> c` or `a <~ b <~ c`
33    DirectedConnection(DirectedConnection),
34    /// `x -> Type`
35    Retype(Retype),
36    /// `pin name`
37    PinDeclaration(PinDeclaration),
38    /// `signal name`
39    SignalDef(SignalDef),
40    /// `assert x within 1V to 2V`
41    Assert(AssertStmt),
42    /// `field: type`
43    Declaration(Declaration),
44    /// String literal as statement (docstring)
45    StringStmt(StringStmt),
46    /// `pass`
47    Pass(PassStmt),
48    /// `trait name<arg=value>`
49    Trait(TraitStmt),
50    /// `for item in container: body`
51    For(ForStmt),
52}
53
54impl Statement {
55    pub fn span(&self) -> Span {
56        match self {
57            Statement::Pragma(s) => s.span,
58            Statement::Import(s) => s.span,
59            Statement::DepImport(s) => s.span,
60            Statement::BlockDef(s) => s.span,
61            Statement::Assignment(s) => s.span,
62            Statement::CumAssignment(s) => s.span,
63            Statement::SetAssignment(s) => s.span,
64            Statement::Connection(s) => s.span,
65            Statement::DirectedConnection(s) => s.span,
66            Statement::Retype(s) => s.span,
67            Statement::PinDeclaration(s) => s.span,
68            Statement::SignalDef(s) => s.span,
69            Statement::Assert(s) => s.span,
70            Statement::Declaration(s) => s.span,
71            Statement::StringStmt(s) => s.span,
72            Statement::Pass(s) => s.span,
73            Statement::Trait(s) => s.span,
74            Statement::For(s) => s.span,
75        }
76    }
77}
78
79// === Pragma ===
80
81#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82pub struct PragmaStmt {
83    pub content: String,
84    pub span: Span,
85}
86
87// === Imports ===
88
89#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
90pub struct ImportStmt {
91    /// Optional `from "path"` source
92    pub from_path: Option<StringLiteral>,
93    /// List of imported type references
94    pub imports: Vec<TypeRef>,
95    pub span: Span,
96}
97
98#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
99pub struct DepImportStmt {
100    /// The imported type
101    pub type_ref: TypeRef,
102    /// The source path
103    pub from_path: StringLiteral,
104    pub span: Span,
105}
106
107// === Block Definitions ===
108
109#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
110pub struct BlockDef {
111    pub kind: BlockKind,
112    pub name: Identifier,
113    /// Optional `from Base` super type
114    pub super_type: Option<TypeRef>,
115    pub body: Vec<Statement>,
116    pub span: Span,
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
120pub enum BlockKind {
121    Module,
122    Component,
123    Interface,
124}
125
126// === Assignments ===
127
128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub struct Assignment {
130    pub target: AssignTarget,
131    pub value: Assignable,
132    pub span: Span,
133}
134
135#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
136pub enum AssignTarget {
137    FieldRef(FieldRef),
138    Declaration(Declaration),
139}
140
141#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
142pub struct CumAssignment {
143    pub target: AssignTarget,
144    pub operator: CumOperator,
145    pub value: Expression,
146    pub span: Span,
147}
148
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
150pub enum CumOperator {
151    Add, // +=
152    Sub, // -=
153}
154
155#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
156pub struct SetAssignment {
157    pub target: AssignTarget,
158    pub operator: SetOperator,
159    pub value: Expression,
160    pub span: Span,
161}
162
163#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
164pub enum SetOperator {
165    Or,  // |=
166    And, // &=
167}
168
169#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
170pub enum Assignable {
171    String(StringLiteral),
172    New(NewExpr),
173    Physical(PhysicalLiteral),
174    Arithmetic(Expression),
175    Boolean(BoolLiteral),
176}
177
178// === Connections ===
179
180#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
181pub struct Connection {
182    pub left: Connectable,
183    pub right: Connectable,
184    pub span: Span,
185}
186
187#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
188pub struct DirectedConnection {
189    pub direction: ConnectionDirection,
190    pub elements: Vec<Connectable>,
191    pub span: Span,
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
195pub enum ConnectionDirection {
196    Forward,  // ~>
197    Backward, // <~
198}
199
200#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
201pub enum Connectable {
202    FieldRef(FieldRef),
203    SignalDef(SignalDef),
204    PinDef(PinDeclaration),
205}
206
207// === Retype ===
208
209#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
210pub struct Retype {
211    pub field: FieldRef,
212    pub new_type: TypeRef,
213    pub span: Span,
214}
215
216// === Declarations ===
217
218#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
219pub struct Declaration {
220    pub field: FieldRef,
221    pub type_info: Identifier,
222    pub span: Span,
223}
224
225#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
226pub struct PinDeclaration {
227    pub name: PinName,
228    pub span: Span,
229}
230
231#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
232pub enum PinName {
233    Identifier(Identifier),
234    Number(NumberLiteral),
235    String(StringLiteral),
236}
237
238#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
239pub struct SignalDef {
240    pub name: Identifier,
241    pub span: Span,
242}
243
244// === Assert ===
245
246#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
247pub struct AssertStmt {
248    pub comparison: Comparison,
249    pub span: Span,
250}
251
252#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
253pub struct Comparison {
254    pub left: Expression,
255    pub operations: Vec<CompareOp>,
256    pub span: Span,
257}
258
259#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
260pub struct CompareOp {
261    pub kind: CompareOpKind,
262    pub right: Expression,
263    pub span: Span,
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
267pub enum CompareOpKind {
268    LessThan,
269    GreaterThan,
270    LessEq,
271    GreaterEq,
272    Within,
273    Is,
274}
275
276// === String/Pass Statements ===
277
278#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
279pub struct StringStmt {
280    pub value: StringLiteral,
281    pub span: Span,
282}
283
284#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
285pub struct PassStmt {
286    pub span: Span,
287}
288
289// === Trait ===
290
291#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
292pub struct TraitStmt {
293    /// Optional target field
294    pub target: Option<FieldRef>,
295    pub type_ref: TypeRef,
296    /// Optional constructor name
297    pub constructor: Option<Identifier>,
298    /// Optional template arguments
299    pub template: Option<Template>,
300    pub span: Span,
301}
302
303// === For Loop ===
304
305#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
306pub struct ForStmt {
307    pub variable: Identifier,
308    pub iterable: Iterable,
309    pub body: Vec<Statement>,
310    pub span: Span,
311}
312
313#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
314#[allow(clippy::large_enum_variant)]
315pub enum Iterable {
316    FieldRef {
317        field: FieldRef,
318        slice: Option<Slice>,
319    },
320    List(Vec<FieldRef>),
321}
322
323// === Expressions ===
324
325#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
326#[allow(clippy::large_enum_variant)]
327pub enum Expression {
328    /// Binary operation
329    Binary(Box<BinaryExpr>),
330    /// Unary operation (e.g., -x)
331    Unary(Box<UnaryExpr>),
332    /// Literal value
333    Literal(Literal),
334    /// Field reference (a.b.c, a[0])
335    FieldRef(FieldRef),
336    /// Grouped expression: (expr)
337    Group(Box<Expression>),
338    /// Function call: name(args)
339    FunctionCall(FunctionCall),
340}
341
342impl Expression {
343    pub fn span(&self) -> Span {
344        match self {
345            Expression::Binary(e) => e.span,
346            Expression::Unary(e) => e.span,
347            Expression::Literal(l) => l.span(),
348            Expression::FieldRef(f) => f.span,
349            Expression::Group(e) => e.span(),
350            Expression::FunctionCall(f) => f.span,
351        }
352    }
353}
354
355#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
356pub struct BinaryExpr {
357    pub left: Expression,
358    pub operator: BinaryOp,
359    pub right: Expression,
360    pub span: Span,
361}
362
363#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
364pub enum BinaryOp {
365    Add,    // +
366    Sub,    // -
367    Mul,    // *
368    Div,    // /
369    Power,  // **
370    BitOr,  // |
371    BitAnd, // &
372}
373
374#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
375pub struct UnaryExpr {
376    pub operator: UnaryOp,
377    pub operand: Expression,
378    pub span: Span,
379}
380
381#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
382pub enum UnaryOp {
383    Neg, // -
384    Pos, // +
385}
386
387#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
388pub struct FunctionCall {
389    pub name: Identifier,
390    pub args: Vec<Expression>,
391    pub span: Span,
392}
393
394// === Literals ===
395
396#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
397#[allow(clippy::large_enum_variant)]
398pub enum Literal {
399    Number(NumberLiteral),
400    String(StringLiteral),
401    Bool(BoolLiteral),
402    Physical(PhysicalLiteral),
403}
404
405impl Literal {
406    pub fn span(&self) -> Span {
407        match self {
408            Literal::Number(n) => n.span,
409            Literal::String(s) => s.span,
410            Literal::Bool(b) => b.span,
411            Literal::Physical(p) => p.span(),
412        }
413    }
414}
415
416#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
417pub struct NumberLiteral {
418    pub value: String,
419    pub span: Span,
420}
421
422#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
423pub struct StringLiteral {
424    pub value: String,
425    pub span: Span,
426}
427
428#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
429pub struct BoolLiteral {
430    pub value: bool,
431    pub span: Span,
432}
433
434/// Physical quantity literal (number with optional unit)
435#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
436pub enum PhysicalLiteral {
437    /// Simple quantity: `5V`, `10kohm`
438    Quantity(Quantity),
439    /// Range: `1V to 2V`
440    Range(QuantityRange),
441    /// Bilateral tolerance: `5V +/- 10%`
442    Bilateral(BilateralQuantity),
443}
444
445impl PhysicalLiteral {
446    pub fn span(&self) -> Span {
447        match self {
448            PhysicalLiteral::Quantity(q) => q.span,
449            PhysicalLiteral::Range(r) => r.span,
450            PhysicalLiteral::Bilateral(b) => b.span,
451        }
452    }
453}
454
455#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
456pub struct Quantity {
457    pub number: NumberLiteral,
458    pub unit: Option<Identifier>,
459    pub span: Span,
460}
461
462#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
463pub struct QuantityRange {
464    pub from: Quantity,
465    pub to: Quantity,
466    pub span: Span,
467}
468
469#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
470pub struct BilateralQuantity {
471    pub base: Quantity,
472    pub tolerance: Tolerance,
473    pub span: Span,
474}
475
476#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
477pub struct Tolerance {
478    pub value: String,
479    pub is_percent: bool,
480    pub unit: Option<Identifier>,
481    pub span: Span,
482}
483
484// === New Expression ===
485
486#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
487pub struct NewExpr {
488    pub type_ref: TypeRef,
489    /// Optional array count: `new Type[10]`
490    pub count: Option<NumberLiteral>,
491    /// Optional template args: `new Type<param=value>`
492    pub template: Option<Template>,
493    pub span: Span,
494}
495
496#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
497pub struct Template {
498    pub args: Vec<TemplateArg>,
499    pub span: Span,
500}
501
502#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
503pub struct TemplateArg {
504    pub name: Identifier,
505    pub value: Literal,
506    pub span: Span,
507}
508
509// === References ===
510
511#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
512pub struct FieldRef {
513    pub parts: Vec<FieldRefPart>,
514    /// Optional trailing pin reference: `.1`
515    pub pin_ref: Option<NumberLiteral>,
516    pub span: Span,
517}
518
519#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
520pub struct FieldRefPart {
521    pub name: Identifier,
522    /// Optional array index: `[0]`
523    pub index: Option<NumberLiteral>,
524    pub span: Span,
525}
526
527#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
528pub struct TypeRef {
529    pub parts: Vec<Identifier>,
530    pub span: Span,
531}
532
533#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
534pub struct Slice {
535    pub start: Option<NumberLiteral>,
536    pub stop: Option<NumberLiteral>,
537    pub step: Option<NumberLiteral>,
538    pub span: Span,
539}
540
541// === Identifier ===
542
543#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
544pub struct Identifier {
545    pub name: String,
546    pub span: Span,
547}