Skip to main content

yog_script_analyze/ast/
expr.rs

1//! Expressions (`ys-grammar.md` §3.2–3.4).
2
3use super::{Name, Pattern, Stmt, Type, VersionCond};
4use crate::source::token::Span;
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct Expr {
8    pub kind: ExprKind,
9    pub span: Span,
10}
11
12#[derive(Debug, Clone, PartialEq)]
13pub enum ExprKind {
14    Int(i64),
15    Float(f64),
16    Unit {
17        value: String,
18        unit: String,
19    },
20    Str(Vec<StrSeg>),
21    RawStr(String),
22    Char(char),
23    Bool(bool),
24    Null,
25    Ident(String),
26    This,
27    /// `base`: `this` as its base class (`base.Tick()`).
28    Base,
29    It,
30    /// `out let x`, `out i32 x`: a local declared where a method gives it.
31    Declare {
32        ty: Option<Type>,
33        name: Name,
34        mutable: bool,
35    },
36    /// `typeof(T)`: its `System.Type`.
37    TypeOf(Type),
38    /// `nameof(x.Y)`: its last name, as a string.
39    NameOf(Box<Expr>),
40    /// `checked(e)` (`checked`) or `unchecked(e)`: `e`'s whole-number
41    /// arithmetic panicking on overflow, or wrapping (C#'s).
42    Checked {
43        expr: Box<Expr>,
44        checked: bool,
45    },
46    /// `default`, `default(T)`: the type's zero value.
47    Default(Option<Type>),
48    /// `mc >= 1.21`: the running game's version.
49    Mc(VersionCond),
50    /// `(a, b)`, `(X: 1, Y: 2)`: a tuple, its items' names where written.
51    Tuple {
52        items: Vec<Expr>,
53        names: Vec<Option<Name>>,
54    },
55    /// `[a, b]`, `[k => v]`, `[..xs]`: a list, a set or a map by its target.
56    Collection(Vec<Element>),
57    /// `new Pos(1, 2, 3)`, `new(4)`, `new Battery { Count = 2 }`.
58    New {
59        ty: Option<Type>,
60        args: Option<Vec<Arg>>,
61        init: Vec<(Name, Expr)>,
62        /// A collection initializer's items, each a statement on the object
63        /// made (`members::MADE`): `$made.Add(1);`, `$made.Add(k, v);`,
64        /// `$made[k] = v;`.
65        items: Vec<super::Stmt>,
66    },
67    /// `new i32[n]`, `new i32[2, 3]`, `new i32[3][]`, `new[] { 1, 2 }`,
68    /// `new i32[,] { { 1, 2 }, { 3, 4 } }`: an array made. `elem` is its
69    /// items' type (none: the items' own), `rank` its dimensions.
70    NewArray {
71        elem: Option<Type>,
72        rank: usize,
73        sizes: Vec<Expr>,
74        init: Option<Vec<ArrayItem>>,
75    },
76    /// `x => …`, `(a, b) => …`, `{ … }` after a call (`it` its parameter).
77    Lambda {
78        params: Vec<LambdaParam>,
79        body: LambdaBody,
80        /// `async x => …`: it awaits; it gives a `Task`.
81        asynchronous: bool,
82    },
83    Unary {
84        op: UnOp,
85        expr: Box<Expr>,
86    },
87    /// `(i32)x`.
88    Cast {
89        ty: Type,
90        expr: Box<Expr>,
91    },
92    Binary {
93        op: BinOp,
94        left: Box<Expr>,
95        right: Box<Expr>,
96    },
97    Range {
98        from: Box<Expr>,
99        to: Box<Expr>,
100        inclusive: bool,
101    },
102    /// `x is Monster m`, `x is not null`.
103    Is {
104        expr: Box<Expr>,
105        pattern: Box<Pattern>,
106    },
107    /// `x as T`: `null` when it isn't one.
108    As {
109        expr: Box<Expr>,
110        ty: Type,
111    },
112    /// `x has Charge`.
113    Has {
114        expr: Box<Expr>,
115        ty: Type,
116    },
117    /// `c ? a : b`.
118    Conditional {
119        cond: Box<Expr>,
120        then: Box<Expr>,
121        otherwise: Box<Expr>,
122    },
123    /// `x with { Y = 64 }`: a copy, members changed.
124    With {
125        expr: Box<Expr>,
126        inits: Vec<(Name, Expr)>,
127    },
128    /// `x switch { … }`.
129    Switch {
130        expr: Box<Expr>,
131        arms: Vec<Arm>,
132    },
133    Call {
134        callee: Box<Expr>,
135        args: Vec<Arg>,
136    },
137    /// `a[i]`, `grid[x, y]`: an indexer's or an array's element.
138    Index {
139        expr: Box<Expr>,
140        args: Vec<Expr>,
141        /// `a?[i]`: `null` when `a` is.
142        safe: bool,
143    },
144    /// `f<T, U>` before a call: the type arguments.
145    TypeArgs {
146        expr: Box<Expr>,
147        args: Vec<Type>,
148    },
149    /// `x.Name`, `x?.Name`.
150    Member {
151        expr: Box<Expr>,
152        name: Name,
153        safe: bool,
154    },
155    /// `panic!(…)`: a built-in macro's call (a declared macro's is
156    /// expanded before the parser sees it).
157    Macro {
158        name: Name,
159        args: Vec<Expr>,
160    },
161    /// `move x`: `x` handed on, gone after.
162    Move(Box<Expr>),
163    /// `x!`: asserted not null.
164    NotNull(Box<Expr>),
165    /// What couldn't be parsed (reported already).
166    Error,
167}
168
169/// A piece of a string: text, or an interpolated `{expr}`.
170#[derive(Debug, Clone, PartialEq)]
171pub enum StrSeg {
172    Text(String),
173    Expr(Expr),
174}
175
176/// An item of an array's initializer (`new[] { … }`).
177#[derive(Debug, Clone, PartialEq)]
178pub enum ArrayItem {
179    Value(Expr),
180    /// `{ … }` of a dimension inside (`new i32[,] { { 1, 2 } }`).
181    Nested(Vec<ArrayItem>),
182}
183
184impl ArrayItem {
185    /// Each value inside, however deep.
186    pub fn each_value<'e>(&'e self, f: &mut impl FnMut(&'e Expr)) {
187        match self {
188            ArrayItem::Value(e) => f(e),
189            ArrayItem::Nested(items) => items.iter().for_each(|i| i.each_value(f)),
190        }
191    }
192}
193
194/// An element of a collection expression.
195#[derive(Debug, Clone, PartialEq)]
196pub enum Element {
197    Item(Expr),
198    Entry(Expr, Expr),
199    Spread(Expr),
200}
201
202/// A lambda's parameter: typed or not.
203#[derive(Debug, Clone, PartialEq)]
204pub struct LambdaParam {
205    pub ty: Option<Type>,
206    pub name: Name,
207}
208
209#[derive(Debug, Clone, PartialEq)]
210pub enum LambdaBody {
211    Expr(Box<Expr>),
212    Block(Vec<Stmt>),
213}
214
215/// `value` or `name: value`.
216#[derive(Debug, Clone, PartialEq)]
217pub struct Arg {
218    pub name: Option<Name>,
219    pub pass: Option<super::Pass>,
220    pub value: Expr,
221}
222
223/// `pattern when guard => value`.
224#[derive(Debug, Clone, PartialEq)]
225pub struct Arm {
226    pub pattern: Pattern,
227    pub guard: Option<Expr>,
228    pub value: Expr,
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq)]
232pub enum UnOp {
233    Neg,
234    Not,
235    /// `~x`: an integer's bits flipped.
236    BitNot,
237    /// `++x` / `--x`: the place stepped, its new value.
238    Increment,
239    Decrement,
240    /// `x++` / `x--`: the place stepped, its old value.
241    PostIncrement,
242    PostDecrement,
243    Try,
244    Await,
245    /// `^n` in an index (C#'s): the `n`th item from the end.
246    FromEnd,
247}
248
249impl UnOp {
250    /// Whether it steps a place (`++`, `--`, either side).
251    pub fn steps(self) -> bool {
252        matches!(
253            self,
254            UnOp::Increment | UnOp::Decrement | UnOp::PostIncrement | UnOp::PostDecrement
255        )
256    }
257
258    /// The operator a type declares for it: `x++` is `operator ++`, as `++x`.
259    pub fn declared(self) -> UnOp {
260        match self {
261            UnOp::PostIncrement => UnOp::Increment,
262            UnOp::PostDecrement => UnOp::Decrement,
263            op => op,
264        }
265    }
266}
267
268#[derive(Debug, Clone, Copy, PartialEq, Eq)]
269pub enum BinOp {
270    Coalesce,
271    Or,
272    And,
273    Eq,
274    NotEq,
275    Lt,
276    LtEq,
277    Gt,
278    GtEq,
279    In,
280    Add,
281    Sub,
282    Mul,
283    Div,
284    Rem,
285    /// `&`, `|`, `^`: an integer's bits, or two `bool`s both evaluated.
286    BitAnd,
287    BitOr,
288    BitXor,
289    /// `<<`, `>>`: an integer's bits shifted by a count.
290    Shl,
291    Shr,
292}