Skip to main content

oak_valkyrie/ast/
mod.rs

1#[doc = include_str!("readme.md")]
2use crate::kind::ValkyrieSyntaxKind;
3use core::range::Range;
4use serde::{self, Deserialize, Serialize};
5
6/// Represents an identifier in Valkyrie source code.
7///
8/// Identifiers are names used for variables, functions, types, and other named entities.
9/// Each identifier carries its textual representation and source location information.
10///
11/// # Examples
12///
13/// ```rust
14/// #![feature(new_range_api)]
15/// use core::range::Range;
16/// use oak_valkyrie::ast::Identifier;
17///
18/// let ident = Identifier { name: "main".to_string(), span: (0..4).into() };
19/// assert_eq!(ident.name, "main");
20/// ```
21#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
22pub struct Identifier {
23    /// The textual name of the identifier
24    pub name: String,
25    /// Source code span where this identifier appears
26    #[serde(with = "oak_core::serde_range")]
27    pub span: Range<usize>,
28}
29
30/// Strongly-typed AST root node representing the entire Valkyrie source file.
31///
32/// This is the top-level structure that contains all items (functions, statements, etc.)
33/// parsed from a Valkyrie source file.
34#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
35pub struct ValkyrieRoot {
36    /// Collection of top-level items in the Valkyrie file
37    pub items: Vec<Item>,
38}
39
40/// Top-level items that can appear in a Valkyrie source file.
41///
42/// These represent the main constructs that can exist at the module level,
43/// such as function definitions and statements.
44#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
45pub enum Item {
46    /// A standalone statement
47    Statement(Statement),
48    /// A namespace definition
49    Namespace(Namespace),
50    /// A class definition
51    Class(Class),
52    /// A widget definition
53    Widget(Widget),
54    /// A type function definition
55    TypeFunction(TypeFunction),
56    /// A micro definition
57    Micro(MicroDefinition),
58}
59
60/// Represents a type function definition (mezzo) in Valkyrie source code.
61#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
62pub struct TypeFunction {
63    /// The name identifier of the type function
64    pub name: Identifier,
65    /// Parameters of the type function
66    pub params: Vec<Param>,
67    /// The body of the type function
68    pub body: Block,
69    /// Source code span where this type function appears
70    #[serde(with = "oak_core::serde_range")]
71    pub span: Range<usize>,
72}
73
74/// Represents a class definition in Valkyrie source code.
75#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
76pub struct Class {
77    /// The name identifier of the class
78    pub name: Identifier,
79    /// List of items within the class
80    pub items: Vec<Item>,
81    /// Source code span where this class appears
82    #[serde(with = "oak_core::serde_range")]
83    pub span: Range<usize>,
84}
85
86/// Represents a widget definition in Valkyrie source code.
87#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
88pub struct Widget {
89    /// The name identifier of the widget
90    pub name: Identifier,
91    /// List of items within the widget
92    pub items: Vec<Item>,
93    /// Source code span where this widget appears
94    #[serde(with = "oak_core::serde_range")]
95    pub span: Range<usize>,
96}
97
98/// Represents a namespace definition in Valkyrie source code.
99///
100/// Namespaces are used to organize code and prevent naming conflicts.
101#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
102pub struct Namespace {
103    /// The name identifier of the namespace
104    pub name: Identifier,
105    /// List of items within the namespace
106    pub items: Vec<Item>,
107    /// Source code span where this namespace appears
108    #[serde(with = "oak_core::serde_range")]
109    pub span: Range<usize>,
110}
111
112/// Represents a micro definition in Valkyrie source code.
113///
114/// Micro definitions are specialized constructs in the Valkyrie language.
115#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
116pub struct MicroDefinition {
117    /// The name identifier of the micro definition
118    pub name: Identifier,
119    /// List of function parameters
120    pub params: Vec<Param>,
121    /// The optional return type of the function
122    pub return_type: Option<String>,
123    /// The function body containing executable statements
124    pub body: Block,
125    /// Source code span where this micro definition appears
126    #[serde(with = "oak_core::serde_range")]
127    pub span: Range<usize>,
128}
129
130/// Represents a function parameter with its type annotation.
131///
132/// Parameters define the inputs that a function can accept, with their respective types.
133#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
134pub struct Param {
135    /// The parameter name identifier
136    pub name: Identifier,
137    /// The type annotation for this parameter
138    pub ty: String,
139    /// Source code span where this parameter appears
140    #[serde(with = "oak_core::serde_range")]
141    pub span: Range<usize>,
142}
143
144/// Represents a block of statements enclosed in braces.
145///
146/// Blocks are fundamental control structures in Valkyrie that group statements together.
147/// They create new scopes and can be used as expressions.
148#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
149pub struct Block {
150    /// Collection of statements within the block
151    pub statements: Vec<Statement>,
152    /// Source code span where this block appears
153    #[serde(with = "oak_core::serde_range")]
154    pub span: Range<usize>,
155}
156
157/// Represents different types of statements in Valkyrie source code.
158///
159/// Statements are executable instructions that don't return values.
160/// They form the body of functions and other code blocks.
161#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
162pub enum Statement {
163    /// A variable binding statement with `let` keyword
164    ///
165    /// Contains the variable name, initialization expression, and source location
166    Let {
167        /// Whether the variable is mutable
168        is_mutable: bool,
169        /// The variable name identifier
170        name: Identifier,
171        /// The initialization expression
172        expr: Expr,
173        /// Source code span where this statement appears
174        #[serde(with = "oak_core::serde_range")]
175        span: Range<usize>,
176    },
177    /// An expression statement that may end with a semicolon
178    ///
179    /// Contains the expression, whether it ends with semicolon, and source location
180    ExprStmt {
181        /// The expression being evaluated
182        expr: Expr,
183        /// Whether this statement ends with a semicolon
184        semi: bool,
185        /// Source code span where this statement appears
186        #[serde(with = "oak_core::serde_range")]
187        span: Range<usize>,
188    },
189}
190
191/// Represents different types of expressions in Valkyrie source code.
192///
193/// Expressions are code constructs that evaluate to values. They can be simple
194/// like identifiers and literals, or complex like function calls and binary operations.
195#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
196pub enum Expr {
197    /// An identifier that refers to a variable, function, or other named entity
198    Ident(Identifier),
199    /// A string or numeric literal value
200    ///
201    /// Contains the literal value as a string and its source location
202    Literal {
203        /// The string representation of the literal value
204        value: String,
205        /// Source code span where this literal appears
206        #[serde(with = "oak_core::serde_range")]
207        span: Range<usize>,
208    },
209    /// A boolean literal (true or false)
210    ///
211    /// Contains the boolean value and its source location
212    Bool {
213        /// The boolean value
214        value: bool,
215        /// Source code span where this boolean appears
216        #[serde(with = "oak_core::serde_range")]
217        span: Range<usize>,
218    },
219    /// A unary operation expression (e.g., !x, -y)
220    ///
221    /// Contains the operator, operand expression, and source location
222    Unary {
223        /// The unary operator kind
224        op: ValkyrieSyntaxKind,
225        /// The operand expression
226        expr: Box<Expr>,
227        /// Source code span where this unary expression appears
228        #[serde(with = "oak_core::serde_range")]
229        span: Range<usize>,
230    },
231    /// A binary operation expression (e.g., x + y, a == b)
232    ///
233    /// Contains the left operand, operator, right operand, and source location
234    Binary {
235        /// The left operand expression
236        left: Box<Expr>,
237        /// The binary operator kind
238        op: ValkyrieSyntaxKind,
239        /// The right operand expression
240        right: Box<Expr>,
241        /// Source code span where this binary expression appears
242        #[serde(with = "oak_core::serde_range")]
243        span: Range<usize>,
244    },
245    /// A function call expression
246    ///
247    /// Contains the function being called, argument expressions, and source location
248    Call {
249        /// The expression that evaluates to the function being called
250        callee: Box<Expr>,
251        /// List of argument expressions
252        args: Vec<Expr>,
253        /// Source code span where this function call appears
254        #[serde(with = "oak_core::serde_range")]
255        span: Range<usize>,
256    },
257    /// A field access expression (e.g., obj.field)
258    ///
259    /// Contains the object expression, field name, and source location
260    Field {
261        /// The expression that evaluates to the object containing the field
262        receiver: Box<Expr>,
263        /// The field name identifier
264        field: Identifier,
265        /// Source code span where this field access appears
266        #[serde(with = "oak_core::serde_range")]
267        span: Range<usize>,
268    },
269    /// An array/slice indexing expression (e.g., arr[i])
270    ///
271    /// Contains the array expression, index expression, and source location
272    Index {
273        /// The expression that evaluates to the array or slice
274        receiver: Box<Expr>,
275        /// The index expression
276        index: Box<Expr>,
277        /// Source code span where this indexing expression appears
278        #[serde(with = "oak_core::serde_range")]
279        span: Range<usize>,
280    },
281    /// A parenthesized expression
282    ///
283    /// Contains the wrapped expression and source location
284    Paren {
285        /// The expression wrapped in parentheses
286        expr: Box<Expr>,
287        /// Source code span where this parenthesized expression appears
288        #[serde(with = "oak_core::serde_range")]
289        span: Range<usize>,
290    },
291    /// A block expression that can be used as a value
292    Block(Block),
293    /// An anonymous class definition
294    AnonymousClass {
295        /// List of parent types/traits
296        parents: Vec<String>,
297        /// List of fields and methods
298        items: Vec<Item>,
299        /// Source code span where this anonymous class appears
300        #[serde(with = "oak_core::serde_range")]
301        span: Range<usize>,
302    },
303    /// An if-else expression
304    If {
305        /// The condition expression
306        condition: Box<Expr>,
307        /// The then-branch block
308        then_branch: Block,
309        /// The optional else-branch block
310        else_branch: Option<Block>,
311        /// Source code span where this if expression appears
312        #[serde(with = "oak_core::serde_range")]
313        span: Range<usize>,
314    },
315    /// A match expression
316    Match {
317        /// The expression being matched
318        scrutinee: Box<Expr>,
319        /// List of match arms
320        arms: Vec<MatchArm>,
321        /// Source code span where this match expression appears
322        #[serde(with = "oak_core::serde_range")]
323        span: Range<usize>,
324    },
325    /// A loop expression
326    Loop {
327        /// Optional loop label
328        label: Option<String>,
329        /// The loop body block
330        body: Block,
331        /// Source code span where this loop expression appears
332        #[serde(with = "oak_core::serde_range")]
333        span: Range<usize>,
334    },
335    /// A return expression
336    Return {
337        /// The optional return value
338        expr: Option<Box<Expr>>,
339        /// Source code span where this return expression appears
340        #[serde(with = "oak_core::serde_range")]
341        span: Range<usize>,
342    },
343    /// A break expression
344    Break {
345        /// Optional break label
346        label: Option<String>,
347        /// Optional break value
348        expr: Option<Box<Expr>>,
349        /// Source code span where this break expression appears
350        #[serde(with = "oak_core::serde_range")]
351        span: Range<usize>,
352    },
353    /// A continue expression
354    Continue {
355        /// Optional continue label
356        label: Option<String>,
357        /// Source code span where this continue expression appears
358        #[serde(with = "oak_core::serde_range")]
359        span: Range<usize>,
360    },
361    /// A yield expression
362    Yield {
363        /// Optional yield value
364        expr: Option<Box<Expr>>,
365        /// Whether this is a yield-from expression
366        yield_from: bool,
367        /// Source code span where this yield expression appears
368        #[serde(with = "oak_core::serde_range")]
369        span: Range<usize>,
370    },
371    /// A raise/throw expression
372    Raise {
373        /// The exception expression to raise
374        expr: Box<Expr>,
375        /// Source code span where this raise expression appears
376        #[serde(with = "oak_core::serde_range")]
377        span: Range<usize>,
378    },
379    /// A catch expression
380    Catch {
381        /// The expression to try
382        expr: Box<Expr>,
383        /// List of catch arms
384        arms: Vec<MatchArm>,
385        /// Source code span where this catch expression appears
386        #[serde(with = "oak_core::serde_range")]
387        span: Range<usize>,
388    },
389    /// An object creation or trailing closure call (e.g., Point { x: 1 })
390    Object {
391        /// The name or expression being "called" with a block
392        callee: Box<Expr>,
393        /// The block contents
394        block: Block,
395        /// Source code span
396        #[serde(with = "oak_core::serde_range")]
397        span: Range<usize>,
398    },
399}
400
401/// Represents an arm in a match or catch expression.
402#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
403pub struct MatchArm {
404    /// The pattern to match
405    pub pattern: Pattern,
406    /// Optional guard expression
407    pub guard: Option<Expr>,
408    /// The body expression
409    pub body: Expr,
410    /// Source code span where this match arm appears
411    #[serde(with = "oak_core::serde_range")]
412    pub span: Range<usize>,
413}
414
415/// Represents different types of patterns in Valkyrie.
416#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
417pub enum Pattern {
418    /// A wildcard pattern (_)
419    Wildcard {
420        #[serde(with = "oak_core::serde_range")]
421        span: Range<usize>,
422    },
423    /// A variable pattern
424    Variable {
425        name: Identifier,
426        #[serde(with = "oak_core::serde_range")]
427        span: Range<usize>,
428    },
429    /// A literal pattern
430    Literal {
431        value: String,
432        #[serde(with = "oak_core::serde_range")]
433        span: Range<usize>,
434    },
435}