Skip to main content

aura_lang/parser/
ast.rs

1//! Aura AST (SPEC §3.1). Zero-copy: names and strings are slices of the source.
2
3use crate::lexer::token::StrPart;
4use crate::span::Span;
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct Module<'a> {
8    pub imports: Vec<Import<'a>>,
9    pub stmts: Vec<Stmt<'a>>,
10    pub span: Span,
11}
12
13#[derive(Debug, Clone, PartialEq)]
14pub struct Import<'a> {
15    pub source: ImportSource<'a>,
16    pub alias: &'a str,
17    pub span: Span,
18}
19
20#[derive(Debug, Clone, PartialEq)]
21pub enum ImportSource<'a> {
22    /// github/actions/rust-cache@v1.2 (version is mandatory, D8)
23    Registry {
24        path: &'a str,
25        version: &'a str,
26    },
27    File(&'a str),
28}
29
30#[derive(Debug, Clone, PartialEq)]
31pub enum Stmt<'a> {
32    /// `[shadow] name = expr` (D7)
33    Assign {
34        name: &'a str,
35        shadow: bool,
36        value: Expr<'a>,
37        span: Span,
38    },
39    /// `key: expr` | `key:` + an object block - inside domain/component
40    Property {
41        key: &'a str,
42        value: Expr<'a>,
43        span: Span,
44    },
45    /// `assert cond[, "msg"]` (D5)
46    Assert {
47        cond: Expr<'a>,
48        message: Option<Expr<'a>>,
49        span: Span,
50    },
51    TypeDecl(SchemaDeclaration<'a>),
52    /// D18: `[pub] enum Name` — a closed set of allowed string values
53    EnumDecl(EnumDeclaration<'a>),
54    /// `[pub] def ...` - public is exported to the module's importers (D12)
55    FuncDecl {
56        name: &'a str,
57        params: Vec<&'a str>,
58        /// D17: a code body — statements, like a module or a block.
59        body: Vec<Stmt<'a>>,
60        public: bool,
61        span: Span,
62    },
63    Block(BlockDeclaration<'a>),
64    Expr(Expr<'a>),
65}
66
67/// D18: `enum Tier "frontend" "backend" end` — a validation constraint, not a
68/// wrapper type: values stay ordinary strings and serialize as such.
69#[derive(Debug, Clone, PartialEq)]
70pub struct EnumDeclaration<'a> {
71    pub name: &'a str,
72    pub members: Vec<&'a str>,
73    /// `pub enum` — visible to the module's importers (D12)
74    pub public: bool,
75    pub span: Span,
76}
77
78#[derive(Debug, Clone, PartialEq)]
79pub struct SchemaDeclaration<'a> {
80    pub name: &'a str,
81    pub fields: Vec<SchemaField<'a>>,
82    /// `pub type` - the schema is visible to the module's importers (D12)
83    pub public: bool,
84    pub span: Span,
85}
86
87/// A schema field. `default = Some(expr)` makes the field optional: if omitted at
88/// `new`, the default expression is evaluated in the instantiation scope. A field
89/// with no default is required (E0511 if missing). No nullable (`?`) fields yet.
90#[derive(Debug, Clone, PartialEq)]
91pub struct SchemaField<'a> {
92    pub name: &'a str,
93    pub ty: TypeName<'a>,
94    pub default: Option<Expr<'a>>,
95}
96
97#[derive(Debug, Clone, Copy, PartialEq)]
98pub enum TypeName<'a> {
99    String,
100    Int,
101    Float,
102    Bool,
103    List,
104    Object,
105    Custom(&'a str),
106}
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub enum BlockKind {
110    Domain,
111}
112
113#[derive(Debug, Clone, PartialEq)]
114pub struct BlockDeclaration<'a> {
115    pub kind: BlockKind,
116    /// `"production-eu"` | `name` - an arbitrary expression
117    pub label: Expr<'a>,
118    pub body: Vec<Stmt<'a>>,
119    pub span: Span,
120}
121
122#[derive(Debug, Clone, PartialEq)]
123pub enum LitValue<'a> {
124    Int(i64),
125    Float(f64),
126    Str(&'a str),
127    /// Raw parts; `#{...}` sub-expressions are parsed at evaluation time (Phase 3)
128    InterpStr(Vec<StrPart<'a>>),
129    Bool(bool),
130    Null,
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134pub enum UnaryOp {
135    Neg,
136    Not,
137}
138
139#[derive(Debug, Clone, Copy, PartialEq, Eq)]
140pub enum BinOp {
141    Add,
142    Sub,
143    Mul,
144    Div,
145    Rem,
146    Eq,
147    Ne,
148    Lt,
149    Gt,
150    Le,
151    Ge,
152    And,
153    Or,
154}
155
156#[derive(Debug, Clone, PartialEq)]
157pub enum Expr<'a> {
158    Literal(LitValue<'a>, Span),
159    Variable(&'a str, Span),
160    Unary {
161        op: UnaryOp,
162        rhs: Box<Expr<'a>>,
163        span: Span,
164    },
165    Binary {
166        op: BinOp,
167        lhs: Box<Expr<'a>>,
168        rhs: Box<Expr<'a>>,
169        span: Span,
170    },
171    Ternary {
172        cond: Box<Expr<'a>>,
173        then: Box<Expr<'a>>,
174        otherwise: Box<Expr<'a>>,
175        span: Span,
176    },
177    /// `cond \n (bool -> value)+ else -> value \n end` (D14). Left of each `->`
178    /// must be Bool; `else` is mandatory. First true arm wins.
179    Cond {
180        arms: Vec<(Expr<'a>, Expr<'a>)>,
181        otherwise: Box<Expr<'a>>,
182        span: Span,
183    },
184    Call {
185        callee: Box<Expr<'a>>,
186        args: Vec<Expr<'a>>,
187        span: Span,
188    },
189    MethodCall {
190        recv: Box<Expr<'a>>,
191        method: &'a str,
192        args: Vec<Expr<'a>>,
193        /// Trailing-lambda: `xs.map (a, b) -> ... end`
194        lambda: Option<Box<Expr<'a>>>,
195        span: Span,
196    },
197    FieldAccess {
198        recv: Box<Expr<'a>>,
199        field: &'a str,
200        span: Span,
201    },
202    /// List indexing `xs[0]` (bracket=true) or a dynamic object key
203    /// `obj."#{name}"` (bracket=false, D11). Brackets are forbidden on objects (E0318).
204    Index {
205        recv: Box<Expr<'a>>,
206        key: Box<Expr<'a>>,
207        bracket: bool,
208        span: Span,
209    },
210    ObjectLiteral(ObjectBody<'a>),
211    ListLiteral(Vec<Expr<'a>>, Span),
212    Lambda {
213        params: Vec<&'a str>,
214        body: LambdaBody<'a>,
215        span: Span,
216    },
217    /// Only through `new` (D4)
218    /// `schema_alias` - an imported schema `new mod.Name` (D12)
219    SchemaInstance {
220        schema: &'a str,
221        schema_alias: Option<&'a str>,
222        body: ObjectBody<'a>,
223        span: Span,
224    },
225}
226
227#[derive(Debug, Clone, PartialEq)]
228pub struct ObjectBody<'a> {
229    pub props: Vec<(&'a str, Expr<'a>, Span)>,
230}
231
232#[derive(Debug, Clone, PartialEq)]
233pub enum LambdaBody<'a> {
234    Expr(Box<Expr<'a>>),
235    /// D17: a code body — statements, like a `def` body.
236    Block(Vec<Stmt<'a>>),
237}