Skip to main content

yog_script_analyze/ast/
decl.rs

1//! Declarations (`ys-grammar.md` §2): the mod, types, members, content,
2//! components and systems, events.
3
4use super::{Block, Expr, Generic, Name, Patch, Type, Where};
5use crate::source::token::Span;
6
7/// What a declaration is marked with.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Modifier {
10    Public,
11    Private,
12    Internal,
13    Static,
14    Const,
15    Readonly,
16    Async,
17    Server,
18    Client,
19    Shared,
20    Saved,
21    Synced,
22    Tune,
23    Protected,
24    Abstract,
25    Virtual,
26    Override,
27    Sealed,
28    /// `ref struct`: holds borrows, never on the heap.
29    Ref,
30    /// Its body is elsewhere: a `[Service]` method's, on the bus.
31    Extern,
32    /// Its body is generated: a `[LoggerMessage]` method's.
33    Partial,
34    /// `required`: a `new` of its type sets it (in its initializer), unless
35    /// the constructor called is `[SetsRequiredMembers]`.
36    Required,
37    /// `new`: hides a member of its name it inherits (`new bool Add(T item)`).
38    New,
39}
40
41/// `[Obsolete("…")]`.
42#[derive(Debug, Clone, PartialEq)]
43pub struct Attribute {
44    pub path: Vec<Name>,
45    pub args: Vec<super::Arg>,
46}
47
48/// A declaration, its attributes, documentation and modifiers.
49#[derive(Debug, Clone, PartialEq)]
50pub struct Decl {
51    pub attributes: Vec<Attribute>,
52    pub doc: Vec<String>,
53    pub modifiers: Vec<Modifier>,
54    pub kind: DeclKind,
55    pub span: Span,
56}
57
58impl Decl {
59    pub fn has(&self, m: Modifier) -> bool {
60        self.modifiers.contains(&m)
61    }
62}
63
64/// A type's name and what follows it: generics, its primary constructor,
65/// what it implements, the constraints, the components it has.
66#[derive(Debug, Clone, PartialEq, Default)]
67pub struct TypeHeader {
68    pub generics: Vec<Generic>,
69    pub ctor: Option<Vec<Param>>,
70    pub bases: Vec<Type>,
71    pub constraints: Vec<Where>,
72    pub has: Vec<Expr>,
73}
74
75#[derive(Debug, Clone, PartialEq)]
76pub enum DeclKind {
77    /// `using Yog.Ui;`, `using static Yog.Chat;`, `global using …;`.
78    Using {
79        path: Vec<Name>,
80        global: bool,
81        statics: bool,
82    },
83    /// `namespace A.B;` (the rest of the file: `body` None) or `namespace A.B { … }`.
84    Namespace {
85        path: Vec<Name>,
86        body: Option<Vec<Decl>>,
87    },
88    /// `using Grid = Dictionary<Pos, i32>;`.
89    Alias {
90        name: Name,
91        ty: Type,
92    },
93    /// `mod Charge { Version = "1.0.0"; … }`: its properties, and members —
94    /// its constructor runs when the mod loads.
95    Mod {
96        name: Name,
97        body: Vec<Decl>,
98    },
99    /// `public event Action<Player> Joined;`.
100    Event {
101        ty: Type,
102        name: Name,
103    },
104    Method(Method),
105    /// `delegate R Name<…>(params);`: a type of methods, its signature
106    /// what calling one takes and gives (`Invoke`'s).
107    Delegate(Method),
108    Field(Field),
109    /// `Ticks Left { get; set; }`, `Energy Room => …;`.
110    Property {
111        ty: Type,
112        name: Name,
113        accessors: Vec<Accessor>,
114        value: Option<Expr>,
115        /// The interface it implements explicitly (`bool
116        /// ICollection<T>.IsReadOnly => false;`).
117        explicit: Option<Type>,
118    },
119    /// `T this[i32 index] { get; set; }`: what `x[i]` reads and writes.
120    Indexer(super::Indexer),
121    /// `static R operator +(A a, B b)`, `static implicit operator R(A a)`.
122    Operator(super::Operator),
123    Ctor(Ctor),
124    /// `class`, `struct`, `record`, `interface`: which is `word`;
125    /// `value`: copied by value (a struct, a `record struct`).
126    Type {
127        word: Name,
128        name: Name,
129        value: bool,
130        header: TypeHeader,
131        body: Vec<Decl>,
132    },
133    /// `enum Mode { Idle, Charging(i32 Rate) }`, `enum Tier : u8 { Wood = 1 }`.
134    Enum {
135        name: Name,
136        generics: Vec<Generic>,
137        base: Option<Type>,
138        variants: Vec<Variant>,
139        body: Vec<Decl>,
140    },
141    /// `unit Energy;` / `unit FE = Energy * 1;`.
142    Unit {
143        name: Name,
144        value: Option<Expr>,
145    },
146    /// `block Charger has Charge(1000) { … }`, `recipe Battery : Shaped { … }`,
147    /// a mod's own kinds.
148    Content {
149        kind: Name,
150        name: Name,
151        header: TypeHeader,
152        body: Vec<Decl>,
153    },
154    Component {
155        name: Name,
156        header: TypeHeader,
157        body: Vec<Decl>,
158    },
159    /// `server system Solar(Charge charge, Block block) every 1t { … }`.
160    System {
161        name: Name,
162        params: Vec<Param>,
163        every: Option<Expr>,
164        body: Block,
165    },
166    Extend {
167        ty: Type,
168        header: TypeHeader,
169        body: Vec<Decl>,
170    },
171    /// `Version = "1.0.0";` in a mod body, `Pattern = […];` in a recipe's
172    /// (a block's or an item's is an error: its file's).
173    Prop(Prop),
174    Screen {
175        name: Name,
176        header: TypeHeader,
177        ui: String,
178        body: Vec<Decl>,
179    },
180    Command {
181        name: String,
182        body: Vec<Decl>,
183    },
184    Test {
185        name: String,
186        body: Block,
187    },
188    Patch(Patch),
189    /// `targets mc 1.20.1..26.2;`: the game versions a `.yns` is for.
190    Targets(VersionCond),
191}
192
193/// `Name = value;`.
194#[derive(Debug, Clone, PartialEq)]
195pub struct Prop {
196    pub name: Name,
197    pub value: Expr,
198}
199
200/// `i32 Area(i32 w, i32 h) => w * h;`; `ret` None: `void`.
201#[derive(Debug, Clone, PartialEq)]
202pub struct Method {
203    pub ret: Option<Type>,
204    pub name: Name,
205    /// The interface it implements explicitly (`void ICollection<T>.Add(T
206    /// item)`): reached only through that interface.
207    pub explicit: Option<Type>,
208    pub generics: Vec<Generic>,
209    pub params: Vec<Param>,
210    pub constraints: Vec<Where>,
211    pub requires: Option<Expr>,
212    /// None: a signature only (`native`, an interface's).
213    pub body: Option<MethodBody>,
214}
215
216#[derive(Debug, Clone, PartialEq)]
217pub enum MethodBody {
218    Block(Block),
219    Expr(Expr),
220}
221
222/// `saved synced Energy Energy in 0..capacity = 0 was Power: i32;`.
223#[derive(Debug, Clone, PartialEq)]
224pub struct Field {
225    pub ty: Type,
226    pub name: Name,
227    pub bound: Option<Expr>,
228    pub value: Option<Expr>,
229    /// What an old save calls it.
230    pub was: Option<(Name, Option<Type>)>,
231}
232
233/// `get;`, `set { … }`, `init;`.
234#[derive(Debug, Clone, PartialEq)]
235pub struct Accessor {
236    pub name: Name,
237    pub body: Option<MethodBody>,
238}
239
240/// `public Timer() : this(20t) { … }`.
241#[derive(Debug, Clone, PartialEq)]
242pub struct Ctor {
243    pub name: Name,
244    pub params: Vec<Param>,
245    /// `: this(…)` / `: base(…)`: the constructor run first.
246    pub chain: Option<(Chain, Vec<super::Arg>)>,
247    pub body: Block,
248}
249
250/// Which constructor a constructor runs first.
251#[derive(Debug, Clone, Copy, PartialEq, Eq)]
252pub enum Chain {
253    This,
254    Base,
255}
256
257/// `Player target = source.Player`.
258#[derive(Debug, Clone, PartialEq)]
259pub struct Param {
260    /// `this T x`, a static method's first: it extends `T` (C#'s extension
261    /// method: `xs.Where(…)` is `Enumerable.Where(xs, …)`).
262    pub extension: bool,
263    /// `params T[] rest`, the last: the call's arguments past the others
264    /// go in it (C#'s).
265    pub params: bool,
266    pub pass: Option<super::Pass>,
267    /// `in 'a T x`: the borrow's lifetime.
268    pub lifetime: Option<Name>,
269    pub ty: Type,
270    pub name: Name,
271    pub default: Option<Expr>,
272}
273
274#[derive(Debug, Clone, PartialEq)]
275pub struct Variant {
276    /// Its `///` lines.
277    pub doc: Vec<String>,
278    pub name: Name,
279    pub fields: Vec<Param>,
280    /// `Wood = 1`: its number.
281    pub value: Option<Expr>,
282}
283
284/// `mc >= 1.21`, `mc 1.20.1..1.21.4`.
285#[derive(Debug, Clone, PartialEq)]
286pub enum VersionCond {
287    Compare { op: super::BinOp, version: String },
288    Range { from: String, to: String },
289}