Skip to main content

abyss_core/
ast.rs

1/// Represents line and column information for debugging purposes.
2#[derive(Debug, Clone)]
3pub struct LineInfo {
4    pub line: usize,
5    pub column: usize,
6}
7
8impl LineInfo {
9    /// Creates a `LineInfo` from explicit 1-based line and column values.
10    pub fn new(line: usize, column: usize) -> Self {
11        LineInfo { line, column }
12    }
13}
14
15/// Represents the abstract syntax tree (AST) for the language.
16#[derive(Debug, Clone)]
17pub enum AST {
18    Statement(Box<AST>, Option<LineInfo>),
19    Omen(bool, Option<LineInfo>),
20    Arcana(i64, Option<LineInfo>),
21    Aether(f64, Option<LineInfo>),
22    Rune(String, Option<LineInfo>),
23    Abyss(Option<LineInfo>),
24    Add(Box<AST>, Box<AST>, Option<LineInfo>),
25    Sub(Box<AST>, Box<AST>, Option<LineInfo>),
26    Mul(Box<AST>, Box<AST>, Option<LineInfo>),
27    Div(Box<AST>, Box<AST>, Option<LineInfo>),
28    Mod(Box<AST>, Box<AST>, Option<LineInfo>),
29    PowArcana(Box<AST>, Box<AST>, Option<LineInfo>),
30    PowAether(Box<AST>, Box<AST>, Option<LineInfo>),
31    Equal(Box<AST>, Box<AST>, Option<LineInfo>),
32    NotEqual(Box<AST>, Box<AST>, Option<LineInfo>),
33    LessThan(Box<AST>, Box<AST>, Option<LineInfo>),
34    LessThanOrEqual(Box<AST>, Box<AST>, Option<LineInfo>),
35    GreaterThan(Box<AST>, Box<AST>, Option<LineInfo>),
36    GreaterThanOrEqual(Box<AST>, Box<AST>, Option<LineInfo>),
37    LogicalAnd(Box<AST>, Box<AST>, Option<LineInfo>),
38    LogicalOr(Box<AST>, Box<AST>, Option<LineInfo>),
39    LogicalNot(Box<AST>, Option<LineInfo>),
40    VarAssign {
41        name: String,
42        value: Box<AST>,
43        var_type: Type,
44        is_morph: bool,
45        line_info: Option<LineInfo>,
46    },
47    Assignment {
48        name: String,
49        value: Box<AST>,
50        op: AssignmentOp,
51        line_info: Option<LineInfo>,
52    },
53    Var(String, Option<LineInfo>),
54    Reveal(Box<AST>, Option<LineInfo>),
55    Oracle {
56        is_match: bool,
57        conditionals: Vec<ConditionalAssignment>,
58        branches: Vec<AST>,
59        line_info: Option<LineInfo>,
60    },
61    OracleBranch {
62        pattern: Vec<AST>,
63        guard: Option<Box<AST>>,
64        body: Box<AST>,
65        line_info: Option<LineInfo>,
66    },
67    OracleDontCareItem(Option<LineInfo>),
68    /// Scroll-shape pattern that destructures a `scroll` scrutinee into
69    /// its elements. Each element is one of: `OracleDontCareItem`,
70    /// `OracleScrollRest`, `Var(name)` (binding), or any other AST node
71    /// (treated as a literal expression to compare against).
72    OracleScrollPattern {
73        elements: Vec<AST>,
74        line_info: Option<LineInfo>,
75    },
76    /// Rest segment inside an `OracleScrollPattern`. `name = Some("rest")`
77    /// for `..rest` (binds the unmatched tail to a fresh sub-scroll);
78    /// `name = None` for `..` (anonymous, drops the tail).
79    OracleScrollRest {
80        name: Option<String>,
81        line_info: Option<LineInfo>,
82    },
83    /// Artifact-shape pattern that matches a `TypeName { field, … }`
84    /// scrutinee. Each `(field_name, sub_pattern)` entry pulls the named
85    /// field out of the artifact and matches it against `sub_pattern`
86    /// (typically `Var` for binding, a literal for compare, or
87    /// `OracleDontCareItem` to ignore). Fields not listed here are not
88    /// matched against — the pattern is non-exhaustive by default, so
89    /// users can pick out only the fields they care about.
90    OracleArtifactPattern {
91        type_name: String,
92        fields: Vec<(String, AST)>,
93        line_info: Option<LineInfo>,
94    },
95    /// Lexicon-shape pattern that matches a `{ "key": value, … }`
96    /// scrutinee. Each `(key, sub_pattern)` entry pulls the named entry
97    /// out of the lexicon and matches it against `sub_pattern`. Keys not
98    /// listed here are not matched against — the pattern is
99    /// non-exhaustive by default, mirroring the artifact pattern's
100    /// "pick what you need" ergonomics.
101    OracleLexiconPattern {
102        entries: Vec<(String, AST)>,
103        line_info: Option<LineInfo>,
104    },
105    Block(Vec<AST>, Option<LineInfo>),
106    Comment(String, Option<LineInfo>),
107    Orbit {
108        params: Vec<AST>,
109        body: Box<AST>,
110        line_info: Option<LineInfo>,
111    },
112    OrbitParam {
113        name: String,
114        start: Box<AST>,
115        end: Box<AST>,
116        op: String,
117        line_info: Option<LineInfo>,
118    },
119    Resume(Option<String>, Option<LineInfo>),
120    Eject(Option<String>, Option<LineInfo>),
121    Engrave {
122        name: String,
123        params: Vec<AST>,
124        return_type: Type,
125        body: Box<AST>,
126        method_target: Option<ArtifactMethodTarget>,
127        line_info: Option<LineInfo>,
128    },
129    EngraveParam {
130        name: String,
131        param_type: Type,
132        is_morph: bool,
133        line_info: Option<LineInfo>,
134    },
135    FuncCall {
136        name: String,
137        args: Vec<AST>,
138        line_info: Option<LineInfo>,
139    },
140    ListLiteral {
141        elements: Vec<AST>,
142        line_info: Option<LineInfo>,
143    },
144    MapLiteral {
145        entries: Vec<(String, AST)>,
146        line_info: Option<LineInfo>,
147    },
148    IndexAccess {
149        target: Box<AST>,
150        index: Box<AST>,
151        line_info: Option<LineInfo>,
152    },
153    IndexAssignment {
154        target: Box<AST>,
155        index: Box<AST>,
156        value: Box<AST>,
157        line_info: Option<LineInfo>,
158    },
159    ArtifactDef {
160        name: String,
161        fields: Vec<ArtifactField>,
162        line_info: Option<LineInfo>,
163    },
164    ArtifactLiteral {
165        type_name: String,
166        fields: Vec<(String, AST)>,
167        line_info: Option<LineInfo>,
168    },
169    FieldAccess {
170        target: Box<AST>,
171        field: String,
172        line_info: Option<LineInfo>,
173    },
174    FieldAssignment {
175        target: Box<AST>,
176        field: String,
177        value: Box<AST>,
178        line_info: Option<LineInfo>,
179    },
180    MethodCall {
181        receiver: Box<AST>,
182        method: String,
183        args: Vec<AST>,
184        line_info: Option<LineInfo>,
185    },
186}
187
188#[derive(Debug, Clone)]
189pub struct ArtifactField {
190    pub name: String,
191    pub field_type: Type,
192    pub line_info: Option<LineInfo>,
193}
194
195#[derive(Debug, Clone)]
196pub struct ArtifactMethodTarget {
197    pub artifact: String,
198    pub requires_morph: bool,
199}
200
201/// Represents a conditional assignment within an oracle statement.
202#[derive(Debug, Clone)]
203pub struct ConditionalAssignment {
204    pub variable: String,
205    pub expression: Box<AST>,
206    pub line_info: Option<LineInfo>,
207}
208
209/// Represents the type of a variable or expression.
210#[derive(Debug, Clone, PartialEq, Eq, Hash)]
211pub enum Type {
212    Arcana,
213    Aether,
214    Rune,
215    Omen,
216    Abyss,
217    Scroll,
218    Lexicon,
219    Materia,
220    Glyph,
221    Artifact(String),
222}
223
224/// Represents an assignment operation.
225#[derive(Debug, Clone)]
226pub enum AssignmentOp {
227    Assign,
228    AddAssign,
229    SubAssign,
230    MulAssign,
231    DivAssign,
232    ModAssign,
233    PowArcanaAssign,
234    PowAetherAssign,
235}