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}
33
34/// `[Obsolete("…")]`.
35#[derive(Debug, Clone, PartialEq)]
36pub struct Attribute {
37    pub path: Vec<Name>,
38    pub args: Vec<super::Arg>,
39}
40
41/// A declaration, its attributes, documentation and modifiers.
42#[derive(Debug, Clone, PartialEq)]
43pub struct Decl {
44    pub attributes: Vec<Attribute>,
45    pub doc: Vec<String>,
46    pub modifiers: Vec<Modifier>,
47    pub kind: DeclKind,
48    pub span: Span,
49}
50
51impl Decl {
52    pub fn has(&self, m: Modifier) -> bool {
53        self.modifiers.contains(&m)
54    }
55}
56
57/// A type's name and what follows it: generics, its primary constructor,
58/// what it implements, the constraints, the components it has.
59#[derive(Debug, Clone, PartialEq, Default)]
60pub struct TypeHeader {
61    pub generics: Vec<Generic>,
62    pub ctor: Option<Vec<Param>>,
63    pub bases: Vec<Type>,
64    pub constraints: Vec<Where>,
65    pub has: Vec<Expr>,
66}
67
68#[derive(Debug, Clone, PartialEq)]
69pub enum DeclKind {
70    /// `using Yog.Ui;`, `using static Yog.Chat;`, `global using …;`.
71    Using {
72        path: Vec<Name>,
73        global: bool,
74        statics: bool,
75    },
76    /// `namespace A.B;` (the rest of the file: `body` None) or `namespace A.B { … }`.
77    Namespace {
78        path: Vec<Name>,
79        body: Option<Vec<Decl>>,
80    },
81    /// `using Grid = Dictionary<Pos, i32>;`.
82    Alias {
83        name: Name,
84        ty: Type,
85    },
86    /// `mod Charge { Version = "1.0.0"; … }`: its properties, and members —
87    /// its constructor runs when the mod loads.
88    Mod {
89        name: Name,
90        body: Vec<Decl>,
91    },
92    /// `public event Action<Player> Joined;`.
93    Event {
94        ty: Type,
95        name: Name,
96    },
97    Method(Method),
98    Field(Field),
99    /// `Ticks Left { get; set; }`, `Energy Room => …;`.
100    Property {
101        ty: Type,
102        name: Name,
103        accessors: Vec<Accessor>,
104        value: Option<Expr>,
105    },
106    /// `T this[i32 index] { get; set; }`: what `x[i]` reads and writes.
107    Indexer(super::Indexer),
108    Ctor(Ctor),
109    /// `class`, `struct`, `record`, `interface`: which is `word`;
110    /// `value`: copied by value (a struct, a `record struct`).
111    Type {
112        word: Name,
113        name: Name,
114        value: bool,
115        header: TypeHeader,
116        body: Vec<Decl>,
117    },
118    /// `enum Mode { Idle, Charging(i32 Rate) }`, `enum Tier : u8 { Wood = 1 }`.
119    Enum {
120        name: Name,
121        generics: Vec<Generic>,
122        base: Option<Type>,
123        variants: Vec<Variant>,
124        body: Vec<Decl>,
125    },
126    /// `unit Energy;` / `unit FE = Energy * 1;`.
127    Unit {
128        name: Name,
129        value: Option<Expr>,
130    },
131    /// `block Charger has Charge(1000) { … }`, `recipe Battery : Shaped { … }`,
132    /// a mod's own kinds.
133    Content {
134        kind: Name,
135        name: Name,
136        header: TypeHeader,
137        body: Vec<Decl>,
138    },
139    Component {
140        name: Name,
141        header: TypeHeader,
142        body: Vec<Decl>,
143    },
144    /// `server system Solar(Charge charge, Block block) every 1t { … }`.
145    System {
146        name: Name,
147        params: Vec<Param>,
148        every: Option<Expr>,
149        body: Block,
150    },
151    Extend {
152        ty: Type,
153        header: TypeHeader,
154        body: Vec<Decl>,
155    },
156    /// `Hardness = 2.0f;` in a content or mod body.
157    Prop(Prop),
158    Screen {
159        name: Name,
160        header: TypeHeader,
161        ui: String,
162        body: Vec<Decl>,
163    },
164    Command {
165        name: String,
166        body: Vec<Decl>,
167    },
168    Test {
169        name: String,
170        body: Block,
171    },
172    Patch(Patch),
173    /// `targets mc 1.20.1..26.2;`: the game versions a `.yns` is for.
174    Targets(VersionCond),
175}
176
177/// `Name = value;`.
178#[derive(Debug, Clone, PartialEq)]
179pub struct Prop {
180    pub name: Name,
181    pub value: Expr,
182}
183
184/// `i32 Area(i32 w, i32 h) => w * h;`; `ret` None: `void`.
185#[derive(Debug, Clone, PartialEq)]
186pub struct Method {
187    pub ret: Option<Type>,
188    pub name: Name,
189    pub generics: Vec<Generic>,
190    pub params: Vec<Param>,
191    pub constraints: Vec<Where>,
192    pub requires: Option<Expr>,
193    /// None: a signature only (`native`, an interface's).
194    pub body: Option<MethodBody>,
195}
196
197#[derive(Debug, Clone, PartialEq)]
198pub enum MethodBody {
199    Block(Block),
200    Expr(Expr),
201}
202
203/// `saved synced Energy Energy in 0..capacity = 0 was Power: i32;`.
204#[derive(Debug, Clone, PartialEq)]
205pub struct Field {
206    pub ty: Type,
207    pub name: Name,
208    pub bound: Option<Expr>,
209    pub value: Option<Expr>,
210    /// What an old save calls it.
211    pub was: Option<(Name, Option<Type>)>,
212}
213
214/// `get;`, `set { … }`, `init;`.
215#[derive(Debug, Clone, PartialEq)]
216pub struct Accessor {
217    pub name: Name,
218    pub body: Option<MethodBody>,
219}
220
221/// `public Timer() : this(20t) { … }`.
222#[derive(Debug, Clone, PartialEq)]
223pub struct Ctor {
224    pub name: Name,
225    pub params: Vec<Param>,
226    /// `: this(…)` / `: base(…)`: the constructor run first.
227    pub chain: Option<(Chain, Vec<super::Arg>)>,
228    pub body: Block,
229}
230
231/// Which constructor a constructor runs first.
232#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub enum Chain {
234    This,
235    Base,
236}
237
238/// `Player target = source.Player`.
239#[derive(Debug, Clone, PartialEq)]
240pub struct Param {
241    pub pass: Option<super::Pass>,
242    /// `in 'a T x`: the borrow's lifetime.
243    pub lifetime: Option<Name>,
244    pub ty: Type,
245    pub name: Name,
246    pub default: Option<Expr>,
247}
248
249#[derive(Debug, Clone, PartialEq)]
250pub struct Variant {
251    pub name: Name,
252    pub fields: Vec<Param>,
253    /// `Wood = 1`: its number.
254    pub value: Option<Expr>,
255}
256
257/// `mc >= 1.21`, `mc 1.20.1..1.21.4`.
258#[derive(Debug, Clone, PartialEq)]
259pub enum VersionCond {
260    Compare { op: super::BinOp, version: String },
261    Range { from: String, to: String },
262}