Skip to main content

yog_script_analyze/ast/
mod.rs

1//! The syntax tree of a Yog Script source (`docs/design/ys-grammar.md` §2).
2
3mod expr;
4mod patch;
5
6pub use expr::{
7    Arg, Arm, BinOp, Block, Cond, Expr, ExprKind, Pattern, Stmt, StrSeg, Type, TypeKind, UnOp,
8};
9pub use patch::{Callee, Local, Method, Patch, PatchItem, Point, Selector};
10
11use crate::source::token::Span;
12
13/// A name as written, and where.
14#[derive(Debug, Clone, PartialEq)]
15pub struct Name {
16    pub text: String,
17    pub span: Span,
18}
19
20/// A source file.
21#[derive(Debug, Clone, PartialEq, Default)]
22pub struct File {
23    pub decls: Vec<Decl>,
24}
25
26/// What a declaration is marked with.
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum Modifier {
29    Server,
30    Client,
31    Shared,
32    Saved,
33    Synced,
34    Tune,
35    Pub,
36}
37
38/// A declaration, its documentation and modifiers.
39#[derive(Debug, Clone, PartialEq)]
40pub struct Decl {
41    pub doc: Vec<String>,
42    pub modifiers: Vec<Modifier>,
43    pub kind: DeclKind,
44    pub span: Span,
45}
46
47#[derive(Debug, Clone, PartialEq)]
48pub enum DeclKind {
49    /// `use a.b.{c, d}` / `use a.b as e`.
50    Use {
51        path: Vec<Name>,
52        items: Vec<Name>,
53        alias: Option<Name>,
54    },
55    /// `mod charge { version = "1.0.0" … }`.
56    Mod {
57        name: Name,
58        props: Vec<Prop>,
59    },
60    Fn(FnDecl),
61    Let {
62        pattern: Pattern,
63        ty: Option<Type>,
64        value: Expr,
65    },
66    Var(VarDecl),
67    Const {
68        name: Name,
69        ty: Option<Type>,
70        value: Expr,
71    },
72    /// `val x => expr`: computed on every read.
73    Val {
74        name: Name,
75        ty: Option<Type>,
76        value: Expr,
77    },
78    /// `unit Energy` / `unit FE = Energy * 1`.
79    Unit {
80        name: Name,
81        value: Option<Expr>,
82    },
83    Type {
84        name: Name,
85        generics: Vec<Generic>,
86        ty: Type,
87    },
88    Record {
89        name: Name,
90        generics: Vec<Generic>,
91        fields: Vec<Param>,
92        body: Vec<Decl>,
93    },
94    Union {
95        name: Name,
96        generics: Vec<Generic>,
97        variants: Vec<Variant>,
98        body: Vec<Decl>,
99    },
100    Enum {
101        name: Name,
102        cases: Vec<Name>,
103        body: Vec<Decl>,
104    },
105    Extend {
106        ty: Type,
107        adds: Option<Type>,
108        body: Vec<Decl>,
109    },
110    /// `block Charger { … }`, `item Battery { … }`, a mod's own kinds.
111    Content {
112        kind: Name,
113        name: Name,
114        base: Option<Type>,
115        body: Vec<Decl>,
116    },
117    /// `recipe Battery shaped { "RIR" … R = @item:… }`.
118    Recipe {
119        result: Type,
120        kind: Name,
121        rows: Vec<String>,
122        keys: Vec<Prop>,
123    },
124    /// A property in a content or mod body: `hardness = 2.0`, `tooltip => …`.
125    Prop(Prop),
126    /// `slots inventory[4] of Battery`.
127    Slots {
128        name: Name,
129        size: Expr,
130        of: Option<Type>,
131    },
132    /// `player state { … }`.
133    State {
134        scope: Name,
135        body: Vec<Decl>,
136    },
137    Screen {
138        name: Name,
139        params: Vec<Param>,
140        ui: String,
141        body: Vec<Decl>,
142    },
143    /// `action dump() { … }` in a screen: runs on the server.
144    Action(FnDecl),
145    Command {
146        name: String,
147        body: Vec<Decl>,
148    },
149    /// `on player.join(p) { … }`, `on use(p) { … }`.
150    On {
151        event: Vec<Name>,
152        params: Vec<Name>,
153        body: Block,
154    },
155    Test {
156        name: String,
157        body: Block,
158    },
159    Version {
160        cond: VersionCond,
161        then: Vec<Decl>,
162        otherwise: Option<Vec<Decl>>,
163    },
164    Native {
165        library: String,
166        fns: Vec<FnDecl>,
167    },
168    Patch(Patch),
169}
170
171/// `name = value` (or `name => value`, computed).
172#[derive(Debug, Clone, PartialEq)]
173pub struct Prop {
174    pub name: Name,
175    pub value: Expr,
176    pub computed: bool,
177}
178
179#[derive(Debug, Clone, PartialEq)]
180pub struct FnDecl {
181    pub name: Name,
182    pub generics: Vec<Generic>,
183    pub params: Vec<Param>,
184    pub ret: Option<Type>,
185    pub requires: Option<Expr>,
186    /// None: a signature only (`native`).
187    pub body: Option<FnBody>,
188}
189
190#[derive(Debug, Clone, PartialEq)]
191pub enum FnBody {
192    Block(Block),
193    Expr(Expr),
194}
195
196/// A parameter (or a record's field): typed except where the grammar lets
197/// it be inferred.
198#[derive(Debug, Clone, PartialEq)]
199pub struct Param {
200    pub var: bool,
201    pub name: Name,
202    pub ty: Option<Type>,
203    pub default: Option<Expr>,
204}
205
206#[derive(Debug, Clone, PartialEq)]
207pub struct VarDecl {
208    pub name: Name,
209    pub ty: Option<Type>,
210    pub value: Option<Expr>,
211    /// `was power: Int`: what an old save calls it.
212    pub was: Option<(Name, Option<Type>)>,
213}
214
215/// `T` or `T: Base`.
216#[derive(Debug, Clone, PartialEq)]
217pub struct Generic {
218    pub name: Name,
219    pub bound: Option<Type>,
220}
221
222#[derive(Debug, Clone, PartialEq)]
223pub struct Variant {
224    pub name: Name,
225    pub fields: Vec<Param>,
226}
227
228/// `mc >= 1.21`, `mc 1.20.1..1.21.4`.
229#[derive(Debug, Clone, PartialEq)]
230pub enum VersionCond {
231    Compare { op: BinOp, version: String },
232    Range { from: String, to: String },
233}