zscript_parser/hir/
mod.rs

1use std::collections::HashMap;
2
3use bitflags::bitflags;
4use vec1::Vec1;
5
6use super::interner::{NameSymbol, StringSymbol};
7use crate::ir_common::*;
8use crate::Span;
9
10#[cfg(feature = "serialize")]
11use serde::Serialize;
12
13pub mod lower;
14
15#[cfg_attr(feature = "serialize", derive(Serialize))]
16#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
17#[derive(Debug, Clone, PartialEq)]
18pub enum TopLevelDefinitionKind {
19    Class(ClassDefinition),
20    Struct(StructDefinition),
21    MixinClass(MixinClassDefinition),
22    Enum(EnumDefinition),
23    Const(ConstDefinition),
24}
25#[cfg_attr(feature = "serialize", derive(Serialize))]
26#[derive(Debug, Clone, PartialEq)]
27pub struct TopLevelDefinition {
28    pub span: Span,
29    pub archive_num: usize,
30    #[cfg_attr(feature = "serialize", serde(flatten))]
31    pub kind: TopLevelDefinitionKind,
32}
33
34impl TopLevelDefinition {
35    pub fn name(&self) -> &Identifier {
36        match &self.kind {
37            TopLevelDefinitionKind::Class(c) => &c.name,
38            TopLevelDefinitionKind::Struct(s) => &s.name,
39            TopLevelDefinitionKind::MixinClass(m) => &m.name,
40            TopLevelDefinitionKind::Enum(e) => &e.name,
41            TopLevelDefinitionKind::Const(c) => &c.name,
42        }
43    }
44}
45
46#[cfg_attr(feature = "serialize", derive(Serialize))]
47#[derive(Debug, Clone, PartialEq)]
48pub struct TopLevel {
49    pub definitions: HashMap<NameSymbol, Vec1<TopLevelDefinition>>,
50}
51
52bitflags! {
53    #[cfg_attr(feature = "serialize", derive(Serialize))]
54    pub struct ClassDefinitionFlags: u8 {
55        const ABSTRACT = 1 << 0;
56        const NATIVE   = 1 << 1;
57        const UI       = 1 << 2;
58        const PLAY     = 1 << 3;
59    }
60}
61
62#[cfg_attr(feature = "serialize", derive(Serialize))]
63#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
64#[derive(Debug, Clone, PartialEq)]
65pub enum ClassInnerKind {
66    FunctionDeclaration(FunctionDeclaration),
67    MemberDeclaration(MemberDeclaration),
68    Enum(EnumDefinition),
69    Struct(StructDefinition),
70    Const(ConstDefinition),
71    Property(PropertyDefinition),
72    Flag(FlagDefinition),
73    StaticConstArray(StaticConstArray),
74}
75#[cfg_attr(feature = "serialize", derive(Serialize))]
76#[derive(Debug, Clone, PartialEq)]
77pub struct ClassInner {
78    pub span: Span,
79    #[cfg_attr(feature = "serialize", serde(flatten))]
80    pub kind: ClassInnerKind,
81}
82
83impl ClassInner {
84    pub fn name(&self) -> &Identifier {
85        match &self.kind {
86            ClassInnerKind::FunctionDeclaration(x) => &x.name,
87            ClassInnerKind::MemberDeclaration(x) => &x.name,
88            ClassInnerKind::Enum(x) => &x.name,
89            ClassInnerKind::Struct(x) => &x.name,
90            ClassInnerKind::Const(x) => &x.name,
91            ClassInnerKind::Property(x) => &x.name,
92            ClassInnerKind::StaticConstArray(x) => &x.name,
93            ClassInnerKind::Flag(x) => &x.flag_name,
94        }
95    }
96}
97
98#[cfg_attr(feature = "serialize", derive(Serialize))]
99#[derive(Debug, Clone, PartialEq)]
100pub struct ClassDefinition {
101    pub doc_comment: Option<StringSymbol>,
102    pub span: Span,
103    pub name: Identifier,
104    pub ancestor: Option<Identifier>,
105    pub flags: ClassDefinitionFlags,
106    pub states: Vec<StatesItem>,
107    pub defaults: Vec<DefaultStatement>,
108    pub version: Option<VersionInfo>,
109    pub replaces: Option<DottableId>,
110    pub inners: HashMap<NameSymbol, Vec1<ClassInner>>,
111}
112
113#[cfg_attr(feature = "serialize", derive(Serialize))]
114#[derive(Debug, Clone, PartialEq)]
115pub struct MixinClassDefinition {
116    pub doc_comment: Option<StringSymbol>,
117    pub span: Span,
118    pub name: Identifier,
119    pub states: Vec<StatesItem>,
120    pub defaults: Vec<DefaultStatement>,
121    pub inners: HashMap<NameSymbol, Vec1<ClassInner>>,
122}
123
124bitflags! {
125    #[cfg_attr(feature = "serialize", derive(Serialize))]
126    pub struct StructDefinitionFlags: u8 {
127        const CLEAR_SCOPE = 1 << 0;
128        const ABSTRACT    = 1 << 1;
129        const NATIVE      = 1 << 2;
130        const UI          = 1 << 3;
131        const PLAY        = 1 << 4;
132    }
133}
134
135#[cfg_attr(feature = "serialize", derive(Serialize))]
136#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
137#[derive(Debug, Clone, PartialEq)]
138pub enum StructInnerKind {
139    FunctionDeclaration(FunctionDeclaration),
140    MemberDeclaration(MemberDeclaration),
141    Enum(EnumDefinition),
142    Const(ConstDefinition),
143    StaticConstArray(StaticConstArray),
144}
145#[cfg_attr(feature = "serialize", derive(Serialize))]
146#[derive(Debug, Clone, PartialEq)]
147pub struct StructInner {
148    pub span: Span,
149    #[cfg_attr(feature = "serialize", serde(flatten))]
150    pub kind: StructInnerKind,
151}
152
153impl StructInner {
154    pub fn name(&self) -> &Identifier {
155        match &self.kind {
156            StructInnerKind::FunctionDeclaration(x) => &x.name,
157            StructInnerKind::MemberDeclaration(x) => &x.name,
158            StructInnerKind::Enum(x) => &x.name,
159            StructInnerKind::Const(x) => &x.name,
160            StructInnerKind::StaticConstArray(x) => &x.name,
161        }
162    }
163}
164
165#[cfg_attr(feature = "serialize", derive(Serialize))]
166#[derive(Debug, Clone, PartialEq)]
167pub struct StructDefinition {
168    pub doc_comment: Option<StringSymbol>,
169    pub span: Span,
170    pub name: Identifier,
171    pub flags: StructDefinitionFlags,
172    pub version: Option<VersionInfo>,
173    pub inners: HashMap<NameSymbol, Vec1<StructInner>>,
174}
175
176#[cfg_attr(feature = "serialize", derive(Serialize))]
177#[derive(Debug, Clone, PartialEq)]
178pub struct StaticConstArray {
179    pub doc_comment: Option<StringSymbol>,
180    pub span: Span,
181    pub arr_type: Type,
182    pub name: Identifier,
183    pub exprs: ExprList,
184}
185
186bitflags! {
187    #[cfg_attr(feature = "serialize", derive(Serialize))]
188    pub struct FunctionFlags: u16 {
189        const NATIVE        = 1 << 0;
190        const STATIC        = 1 << 1;
191        const PRIVATE       = 1 << 2;
192        const PROTECTED     = 1 << 3;
193        const FINAL         = 1 << 4;
194        const TRANSIENT     = 1 << 5;
195        const VIRTUAL       = 1 << 6;
196        const OVERRIDE      = 1 << 7;
197        const ABSTRACT      = 1 << 8;
198        const VAR_ARG       = 1 << 9;
199        const UI            = 1 << 10;
200        const PLAY          = 1 << 11;
201        const CLEAR_SCOPE   = 1 << 12;
202        const VIRTUAL_SCOPE = 1 << 13;
203    }
204}
205
206#[cfg_attr(feature = "serialize", derive(Serialize))]
207#[derive(Debug, Clone, Copy, PartialEq)]
208pub struct Deprecated {
209    pub version: VersionInfo,
210    pub message: Option<StringConst>,
211}
212
213bitflags! {
214    #[cfg_attr(feature = "serialize", derive(Serialize))]
215    pub struct ActionFlags: u8 {
216        const ACTOR   = 1 << 0;
217        const OVERLAY = 1 << 1;
218        const WEAPON  = 1 << 2;
219        const ITEM    = 1 << 3;
220    }
221}
222
223#[cfg_attr(feature = "serialize", derive(Serialize))]
224#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
225#[derive(Debug, Clone, PartialEq)]
226pub enum Type {
227    SingleUserType(Identifier),
228    DottedUserType(DottableId),
229    NativeType(Identifier),
230    ReadonlyType(Identifier),
231    ReadonlyNativeType(Identifier),
232    Class(Option<DottableId>),
233    Map(Box<(Type, Type)>),
234    Array(Box<Type>, Option<Expression>),
235    DynArray(Box<Type>),
236    Let,
237
238    Error,
239}
240
241#[cfg_attr(feature = "serialize", derive(Serialize))]
242#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
243#[derive(Debug, Clone, PartialEq)]
244pub enum TypeListOrVoidKind {
245    TypeList(Vec1<Type>),
246    Void,
247}
248#[cfg_attr(feature = "serialize", derive(Serialize))]
249#[derive(Debug, Clone, PartialEq)]
250pub struct TypeListOrVoid {
251    pub span: Span,
252    #[cfg_attr(feature = "serialize", serde(flatten))]
253    pub kind: TypeListOrVoidKind,
254}
255
256bitflags! {
257    #[cfg_attr(feature = "serialize", derive(Serialize))]
258    pub struct FuncParamFlags: u8 {
259        const IN       = 1 << 0;
260        const OUT      = 1 << 1;
261        const OPTIONAL = 1 << 2;
262    }
263}
264
265#[cfg_attr(feature = "serialize", derive(Serialize))]
266#[derive(Debug, Clone, PartialEq)]
267pub struct FuncParam {
268    pub span: Span,
269    pub flags: FuncParamFlags,
270    pub param_type: Type,
271    pub name: Identifier,
272    pub init: Option<Expression>,
273}
274
275#[cfg_attr(feature = "serialize", derive(Serialize))]
276#[derive(Debug, Clone, PartialEq)]
277pub struct FuncParams {
278    pub span: Span,
279    pub args: Vec<FuncParam>,
280    pub variadic: bool,
281}
282
283#[cfg_attr(feature = "serialize", derive(Serialize))]
284#[derive(Debug, Clone, PartialEq)]
285pub struct FunctionDeclaration {
286    pub doc_comment: Option<StringSymbol>,
287    pub span: Span,
288    pub name: Identifier,
289    pub constant: bool,
290    pub flags: FunctionFlags,
291    pub deprecated: Option<Deprecated>,
292    pub version: VersionInfo,
293    pub action: Option<ActionFlags>,
294    pub return_types: TypeListOrVoid,
295    pub params: FuncParams,
296    pub body: Option<CompoundStatement>,
297}
298
299bitflags! {
300    #[cfg_attr(feature = "serialize", derive(Serialize))]
301    pub struct MemberFlags: u16 {
302        const NATIVE      = 1 << 0;
303        const PRIVATE     = 1 << 1;
304        const PROTECTED   = 1 << 2;
305        const TRANSIENT   = 1 << 3;
306        const READ_ONLY   = 1 << 4;
307        const INTERNAL    = 1 << 5;
308        const VAR_ARG     = 1 << 6;
309        const UI          = 1 << 7;
310        const PLAY        = 1 << 8;
311
312        // only allowed in classes, not structs
313        const META        = 1 << 9;
314
315        // only allowed within the base archive
316        const CLEAR_SCOPE = 1 << 10;
317    }
318}
319
320#[cfg_attr(feature = "serialize", derive(Serialize))]
321#[derive(Debug, Clone, PartialEq)]
322pub struct MemberDeclaration {
323    pub doc_comment: Option<StringSymbol>,
324    pub span: Span,
325    pub flags: MemberFlags,
326    pub deprecated: Option<Deprecated>,
327    pub version: VersionInfo,
328    pub member_type: Type,
329    pub name: Identifier,
330}
331
332#[cfg_attr(feature = "serialize", derive(Serialize))]
333#[derive(Debug, Clone, PartialEq)]
334pub struct CompoundStatement {
335    pub span: Option<Span>,
336    pub statements: Vec<Statement>,
337}
338
339#[cfg_attr(feature = "serialize", derive(Serialize))]
340#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
341#[derive(Debug, Clone, PartialEq)]
342pub enum StatementKind {
343    Labeled(LabeledStatement),
344    Compound(CompoundStatement),
345    Expression(Expression),
346    If {
347        cond: Expression,
348        body: CompoundStatement,
349        else_body: Option<CompoundStatement>,
350    },
351    Switch {
352        val: Expression,
353        body: CompoundStatement,
354    },
355    Loop(CompoundStatement),
356    Break,
357    Continue,
358    Return(Option<ExprList>),
359    LocalVariableDefinition(LocalVariableDefinition),
360    MultiAssign {
361        assignees: ExprList,
362        rhs: Expression,
363    },
364    StaticConstArray(StaticConstArray),
365}
366#[cfg_attr(feature = "serialize", derive(Serialize))]
367#[derive(Debug, Clone, PartialEq)]
368pub struct Statement {
369    pub span: Option<Span>,
370    #[cfg_attr(feature = "serialize", serde(flatten))]
371    pub kind: StatementKind,
372}
373
374#[cfg_attr(feature = "serialize", derive(Serialize))]
375#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
376#[derive(Debug, Clone, PartialEq)]
377pub enum VarInit {
378    Single(Expression),
379    Compound(ExprList),
380}
381
382#[cfg_attr(feature = "serialize", derive(Serialize))]
383#[derive(Debug, Clone, PartialEq)]
384pub struct LocalVariableDefinition {
385    pub span: Span,
386    pub var_type: Type,
387    pub name: Identifier,
388    pub init: Option<VarInit>,
389}
390
391#[cfg_attr(feature = "serialize", derive(Serialize))]
392#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
393#[derive(Debug, Clone, PartialEq)]
394pub enum StateLineActionKind {
395    Call {
396        func: Identifier,
397        args: Option<Vec<FunctionCallArg>>,
398    },
399    Anonymous(CompoundStatement),
400}
401#[cfg_attr(feature = "serialize", derive(Serialize))]
402#[derive(Debug, Clone, PartialEq)]
403pub struct StateLineAction {
404    pub span: Span,
405    #[cfg_attr(feature = "serialize", serde(flatten))]
406    pub kind: StateLineActionKind,
407}
408
409bitflags! {
410    #[cfg_attr(feature = "serialize", derive(Serialize))]
411    pub struct StateLineFlags: u8 {
412        const BRIGHT    = 1 << 1;
413        const FAST      = 1 << 2;
414        const SLOW      = 1 << 3;
415        const NO_DELAY  = 1 << 4;
416        const CAN_RAISE = 1 << 5;
417    }
418}
419
420#[cfg_attr(feature = "serialize", derive(Serialize))]
421#[derive(Debug, Clone, PartialEq)]
422pub struct StateLine {
423    pub span: Span,
424    pub sprite: NonWhitespace,
425    pub frames: NonWhitespace,
426    pub duration: Expression,
427    pub flags: StateLineFlags,
428    pub action_flags: Option<ActionFlags>,
429    pub offset: Option<(Expression, Expression)>,
430    pub light: Option<Vec1<StringConst>>,
431    pub action: Option<StateLineAction>,
432}
433
434#[cfg_attr(feature = "serialize", derive(Serialize))]
435#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
436#[derive(Debug, Clone, PartialEq)]
437pub enum StateGotoTargetKind {
438    Unscoped(DottableId),
439    Scoped(Identifier, DottableId),
440    Super(DottableId),
441}
442#[cfg_attr(feature = "serialize", derive(Serialize))]
443#[derive(Debug, Clone, PartialEq)]
444pub struct StateGotoTarget {
445    pub span: Span,
446    #[cfg_attr(feature = "serialize", serde(flatten))]
447    pub kind: StateGotoTargetKind,
448}
449
450#[cfg_attr(feature = "serialize", derive(Serialize))]
451#[cfg_attr(feature = "serialize", serde(tag = "kind", content = "data"))]
452#[derive(Debug, Clone, PartialEq)]
453pub enum StatesItemKind {
454    Label(NonWhitespace),
455    Line(Box<StateLine>),
456    Stop,
457    Wait,
458    Fail,
459    Loop,
460    Goto {
461        target: StateGotoTarget,
462        offset: Option<Expression>,
463    },
464}
465#[cfg_attr(feature = "serialize", derive(Serialize))]
466#[derive(Debug, Clone, PartialEq)]
467pub struct StatesItem {
468    pub span: Span,
469    #[cfg_attr(feature = "serialize", serde(flatten))]
470    pub kind: StatesItemKind,
471}