1use std::collections::BTreeMap;
10
11use serde::{Deserialize, Serialize};
12
13pub const PROTOCOL_NAME: &str = "wright/opy-hir";
15pub const PROTOCOL_MAJOR: u32 = 2;
17pub const PROTOCOL_VERSION: &str = "2.0.0";
19
20const DEFAULT_VAR_SLOTS: u32 = 128;
31
32pub fn default_var_index(name: &str) -> Option<u32> {
40 if name.is_empty() || name.len() > 2 {
41 return None;
42 }
43 let mut value: u32 = 0;
44 for byte in name.bytes() {
45 if !byte.is_ascii_uppercase() {
46 return None;
47 }
48 value = value * 26 + u32::from(byte - b'A' + 1);
49 }
50 let index = value - 1;
51 (index < DEFAULT_VAR_SLOTS).then_some(index)
52}
53
54#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
56pub struct Protocol {
57 pub name: String,
58 pub version: String,
59}
60
61#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
63pub struct Generator {
64 pub name: String,
65 pub version: String,
66 pub frontend: String,
67}
68
69#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
71pub struct SourceFile {
72 pub id: u32,
73 pub path: String,
74}
75
76#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
78pub struct Define {
79 pub name: String,
80 #[serde(default)]
81 pub is_function: bool,
82 #[serde(default)]
84 pub is_member: bool,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub span: Option<Span>,
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
91pub struct Span {
92 pub file: u32,
93 pub start: Position,
94 pub end: Position,
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
99pub struct Position {
100 pub line: u32,
101 pub col: u32,
102}
103
104#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
106pub struct Program {
107 pub protocol: Protocol,
108 pub generator: Generator,
109 pub files: Vec<SourceFile>,
110 #[serde(default)]
111 pub defines: Vec<Define>,
112 #[serde(default)]
113 pub declarations: Vec<Declaration>,
114 #[serde(default)]
115 pub rules: Vec<RuleEntry>,
116 #[serde(default, skip_serializing_if = "Option::is_none")]
118 pub settings: Option<Settings>,
119 #[serde(default)]
123 pub preprocessing: PreprocessingState,
124}
125
126#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
128pub struct PreprocessingState {
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub main_file: Option<DirectiveValue>,
131 pub allow_macro_redeclaration: bool,
132 #[serde(default)]
133 pub rule_prefix: Option<DirectiveValue>,
134 #[serde(default)]
135 pub rule_prefix_template: Option<DirectiveValue>,
136 #[serde(default)]
137 pub translations: Option<TranslationState>,
138 #[serde(default)]
139 pub optimization: OptimizationState,
140 #[serde(default)]
141 pub replacements: Vec<DirectiveValue>,
142 #[serde(default)]
143 pub suppressed_warnings: Vec<String>,
144 #[serde(default)]
145 pub directives: Vec<DirectiveRecord>,
146 #[serde(skip)]
150 pub(crate) source_file_initial_optimization: BTreeMap<u32, OptimizationState>,
151}
152
153#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
155pub struct DirectiveValue {
156 pub value: String,
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub span: Option<Span>,
159}
160
161#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
163pub struct TranslationEntry {
164 pub msgid: String,
165 #[serde(default, skip_serializing_if = "Option::is_none")]
166 pub context: Option<String>,
167 #[serde(default)]
168 pub translations: BTreeMap<String, String>,
169}
170
171#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
173pub struct TranslationState {
174 pub languages: Vec<String>,
175 #[serde(default)]
176 pub entries: Vec<TranslationEntry>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub span: Option<Span>,
179}
180
181#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
183pub struct OptimizationState {
184 pub enabled: bool,
185 pub for_size: bool,
186 pub for_size_aggressive: bool,
187 pub strict: bool,
188}
189
190impl Default for OptimizationState {
191 fn default() -> Self {
192 Self {
193 enabled: true,
194 for_size: false,
195 for_size_aggressive: false,
196 strict: false,
197 }
198 }
199}
200
201#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
204pub struct DirectiveRecord {
205 pub name: String,
206 #[serde(skip_serializing_if = "Option::is_none")]
207 pub value: Option<String>,
208 pub scope_col: u32,
209 #[serde(default)]
210 pub scope_depth: u32,
211 #[serde(default)]
212 pub state: PreprocessingSnapshot,
213 #[serde(skip_serializing_if = "Option::is_none")]
214 pub span: Option<Span>,
215}
216
217#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
218pub struct PreprocessingSnapshot {
219 pub allow_macro_redeclaration: bool,
220 pub optimization: OptimizationState,
221 #[serde(default)]
222 pub rule_prefix: Option<String>,
223 #[serde(default)]
224 pub rule_prefix_template: Option<String>,
225 #[serde(default)]
226 pub translations: Option<Vec<String>>,
227 #[serde(default)]
228 pub replacements: Vec<String>,
229}
230
231#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
233pub struct Settings {
234 #[serde(skip_serializing_if = "Option::is_none")]
235 pub span: Option<Span>,
236 #[serde(default)]
237 pub children: Vec<SettingsNode>,
238}
239
240#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
242#[serde(tag = "kind", rename_all = "camelCase")]
243pub enum SettingsNode {
244 Group {
245 name: String,
246 #[serde(default)]
247 children: Vec<SettingsNode>,
248 #[serde(skip_serializing_if = "Option::is_none")]
249 span: Option<Span>,
250 },
251 Number {
252 name: String,
253 value: f64,
254 #[serde(skip_serializing_if = "Option::is_none")]
255 span: Option<Span>,
256 },
257 Bool {
258 name: String,
259 value: bool,
260 #[serde(skip_serializing_if = "Option::is_none")]
261 span: Option<Span>,
262 },
263 String {
264 name: String,
265 value: String,
266 #[serde(skip_serializing_if = "Option::is_none")]
267 span: Option<Span>,
268 },
269 Raw {
271 name: String,
272 value: String,
273 #[serde(skip_serializing_if = "Option::is_none")]
274 span: Option<Span>,
275 },
276 List {
277 name: String,
278 #[serde(default)]
279 elements: Vec<SettingsListElement>,
280 #[serde(skip_serializing_if = "Option::is_none")]
281 span: Option<Span>,
282 },
283}
284
285impl SettingsNode {
286 pub fn span(&self) -> Option<&Span> {
288 match self {
289 SettingsNode::Group { span, .. }
290 | SettingsNode::Number { span, .. }
291 | SettingsNode::Bool { span, .. }
292 | SettingsNode::String { span, .. }
293 | SettingsNode::Raw { span, .. }
294 | SettingsNode::List { span, .. } => span.as_ref(),
295 }
296 }
297}
298
299#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
301pub struct SettingsListElement {
302 pub value: String,
305 #[serde(default, skip_serializing_if = "Option::is_none")]
308 pub evaluated: Option<String>,
309 #[serde(skip_serializing_if = "Option::is_none")]
310 pub span: Option<Span>,
311}
312
313#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
315#[serde(tag = "kind", rename_all = "camelCase")]
316pub enum Declaration {
317 GlobalVariable {
318 name: String,
319 #[serde(default)]
320 index: Option<u32>,
321 #[serde(skip_serializing_if = "Option::is_none")]
322 span: Option<Span>,
323 #[serde(default, skip_serializing_if = "Option::is_none")]
325 name_span: Option<Span>,
326 #[serde(default)]
327 initializer: Option<Box<Expr>>,
328 },
329 PlayerVariable {
330 name: String,
331 #[serde(default)]
332 index: Option<u32>,
333 #[serde(skip_serializing_if = "Option::is_none")]
334 span: Option<Span>,
335 #[serde(default, skip_serializing_if = "Option::is_none")]
337 name_span: Option<Span>,
338 #[serde(default)]
339 initializer: Option<Box<Expr>>,
340 },
341 Subroutine {
342 name: String,
343 #[serde(default)]
344 index: Option<u32>,
345 #[serde(skip_serializing_if = "Option::is_none")]
346 span: Option<Span>,
347 #[serde(default, skip_serializing_if = "Option::is_none")]
349 name_span: Option<Span>,
350 },
351 Constant {
352 name: String,
353 #[serde(skip_serializing_if = "Option::is_none")]
354 span: Option<Span>,
355 value: Box<Expr>,
356 },
357 Macro {
358 name: String,
359 #[serde(default)]
360 args: Vec<String>,
361 #[serde(skip_serializing_if = "Option::is_none")]
362 span: Option<Span>,
363 #[serde(default)]
364 body: Vec<Stmt>,
365 },
366}
367
368#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
370#[serde(untagged)]
371pub enum RuleEntry {
372 Rule(Rule),
374 SubroutineDef {
376 #[serde(rename = "kind")]
377 kind: String,
378 name: String,
379 #[serde(default, skip_serializing_if = "String::is_empty")]
380 source_name: String,
381 #[serde(skip_serializing_if = "Option::is_none")]
382 span: Option<Span>,
383 #[serde(default, skip_serializing_if = "Option::is_none")]
385 name_span: Option<Span>,
386 #[serde(default)]
387 body: Vec<Stmt>,
388 #[serde(default)]
389 annotations: Vec<Annotation>,
390 },
391}
392
393#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
395pub struct Rule {
396 pub name: String,
397 #[serde(skip_serializing_if = "Option::is_none")]
398 pub span: Option<Span>,
399 #[serde(default, skip_serializing_if = "Option::is_none")]
401 pub name_span: Option<Span>,
402 #[serde(default)]
403 pub disabled: bool,
404 #[serde(default)]
405 pub delimiter: bool,
406 #[serde(default, skip_serializing_if = "Option::is_none")]
407 pub new_page: Option<String>,
408 #[serde(default)]
409 pub annotations: Vec<Annotation>,
410 pub event: Event,
411 #[serde(default)]
412 pub conditions: Vec<Expr>,
413 #[serde(default)]
414 pub actions: Vec<Stmt>,
415}
416
417#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
419pub struct Annotation {
420 pub name: String,
421 #[serde(default)]
422 pub args: Vec<AnnotationArg>,
423 #[serde(skip_serializing_if = "Option::is_none")]
424 pub span: Option<Span>,
425}
426
427#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
428pub struct AnnotationArg {
429 pub text: String,
430 #[serde(skip_serializing_if = "Option::is_none")]
431 pub span: Option<Span>,
432}
433
434#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
436pub struct Event {
437 pub name: String,
438 #[serde(default)]
439 pub args: Vec<Expr>,
440 #[serde(skip_serializing_if = "Option::is_none")]
441 pub span: Option<Span>,
442}
443
444#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
446#[serde(tag = "kind", rename_all = "camelCase")]
447pub enum Stmt {
448 Expr {
449 expr: Box<Expr>,
450 #[serde(skip_serializing_if = "Option::is_none")]
451 span: Option<Span>,
452 },
453 Assign {
454 target: Box<Expr>,
455 value: Box<Expr>,
456 #[serde(skip_serializing_if = "Option::is_none")]
457 span: Option<Span>,
458 },
459 If {
460 branches: Vec<IfBranch>,
461 #[serde(default)]
462 r#else: Option<Vec<Stmt>>,
463 #[serde(default, skip_serializing_if = "Option::is_none")]
465 else_span: Option<Span>,
466 #[serde(default, skip_serializing_if = "Option::is_none")]
469 end_span: Option<Span>,
470 #[serde(skip_serializing_if = "Option::is_none")]
471 span: Option<Span>,
472 },
473 For {
474 variable: Box<Expr>,
475 iterable: Box<Expr>,
476 #[serde(default)]
477 body: Vec<Stmt>,
478 #[serde(skip_serializing_if = "Option::is_none")]
479 span: Option<Span>,
480 },
481 While {
482 condition: Box<Expr>,
483 #[serde(default)]
484 body: Vec<Stmt>,
485 #[serde(skip_serializing_if = "Option::is_none")]
486 span: Option<Span>,
487 },
488 DoWhile {
489 condition: Box<Expr>,
490 #[serde(default)]
491 body: Vec<Stmt>,
492 #[serde(skip_serializing_if = "Option::is_none")]
493 span: Option<Span>,
494 },
495 Switch {
496 value: Box<Expr>,
497 #[serde(default)]
498 arms: Vec<SwitchArm>,
499 #[serde(skip_serializing_if = "Option::is_none")]
500 span: Option<Span>,
501 },
502 Delete {
503 target: Box<Expr>,
504 #[serde(skip_serializing_if = "Option::is_none")]
505 span: Option<Span>,
506 },
507 Break {
508 #[serde(skip_serializing_if = "Option::is_none")]
509 span: Option<Span>,
510 },
511 Return {
512 #[serde(skip_serializing_if = "Option::is_none")]
513 span: Option<Span>,
514 },
515 Continue {
516 #[serde(skip_serializing_if = "Option::is_none")]
517 span: Option<Span>,
518 },
519 Goto {
520 #[serde(default, skip_serializing_if = "Option::is_none")]
521 label: Option<String>,
522 #[serde(default, skip_serializing_if = "Option::is_none")]
523 offset: Option<Box<Expr>>,
524 #[serde(default)]
525 rule_start: bool,
526 #[serde(skip_serializing_if = "Option::is_none")]
527 span: Option<Span>,
528 },
529 Label {
530 name: String,
531 #[serde(skip_serializing_if = "Option::is_none")]
532 span: Option<Span>,
533 },
534 CallSubroutine {
535 name: String,
536 #[serde(skip_serializing_if = "Option::is_none")]
537 span: Option<Span>,
538 },
539 Pass {
540 #[serde(skip_serializing_if = "Option::is_none")]
541 span: Option<Span>,
542 },
543}
544
545#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
547pub struct IfBranch {
548 pub condition: Box<Expr>,
549 #[serde(default)]
550 pub body: Vec<Stmt>,
551 #[serde(default, skip_serializing_if = "Option::is_none")]
553 pub marker: Option<Span>,
554}
555
556impl Stmt {
557 pub fn span(&self) -> Option<&Span> {
559 match self {
560 Stmt::Expr { span, .. }
561 | Stmt::Assign { span, .. }
562 | Stmt::If { span, .. }
563 | Stmt::For { span, .. }
564 | Stmt::While { span, .. }
565 | Stmt::DoWhile { span, .. }
566 | Stmt::Switch { span, .. }
567 | Stmt::Delete { span, .. }
568 | Stmt::Break { span }
569 | Stmt::Return { span }
570 | Stmt::Continue { span }
571 | Stmt::Goto { span, .. }
572 | Stmt::Label { span, .. }
573 | Stmt::CallSubroutine { span, .. }
574 | Stmt::Pass { span } => span.as_ref(),
575 }
576 }
577
578 pub(crate) fn span_mut(&mut self) -> &mut Option<Span> {
579 match self {
580 Stmt::Expr { span, .. }
581 | Stmt::Assign { span, .. }
582 | Stmt::If { span, .. }
583 | Stmt::For { span, .. }
584 | Stmt::While { span, .. }
585 | Stmt::DoWhile { span, .. }
586 | Stmt::Switch { span, .. }
587 | Stmt::Delete { span, .. }
588 | Stmt::Break { span }
589 | Stmt::Return { span }
590 | Stmt::Continue { span }
591 | Stmt::Goto { span, .. }
592 | Stmt::Label { span, .. }
593 | Stmt::CallSubroutine { span, .. }
594 | Stmt::Pass { span } => span,
595 }
596 }
597}
598
599#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
602#[serde(tag = "kind", rename_all = "camelCase")]
603pub enum SwitchArm {
604 Case {
605 value: Box<Expr>,
606 #[serde(default)]
607 body: Vec<Stmt>,
608 #[serde(skip_serializing_if = "Option::is_none")]
609 span: Option<Span>,
610 },
611 Default {
612 #[serde(default)]
613 body: Vec<Stmt>,
614 #[serde(skip_serializing_if = "Option::is_none")]
615 span: Option<Span>,
616 },
617}
618
619#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
621#[serde(tag = "kind", rename_all = "camelCase")]
622pub enum Expr {
623 Number {
624 value: f64,
625 text: String,
626 #[serde(skip_serializing_if = "Option::is_none")]
627 span: Option<Span>,
628 },
629 String {
630 value: String,
631 #[serde(skip_serializing_if = "Option::is_none")]
632 span: Option<Span>,
633 },
634 Bool {
635 value: bool,
636 #[serde(skip_serializing_if = "Option::is_none")]
637 span: Option<Span>,
638 },
639 Null {
640 #[serde(skip_serializing_if = "Option::is_none")]
641 span: Option<Span>,
642 },
643 Array {
644 #[serde(default)]
645 elements: Vec<Expr>,
646 #[serde(skip_serializing_if = "Option::is_none")]
647 span: Option<Span>,
648 },
649 Dict {
650 #[serde(default)]
651 entries: Vec<DictEntry>,
652 #[serde(skip_serializing_if = "Option::is_none")]
653 span: Option<Span>,
654 },
655 Comprehension {
656 element: Box<Expr>,
657 variable: String,
658 #[serde(skip_serializing_if = "Option::is_none")]
659 variable_span: Option<Span>,
660 #[serde(default, skip_serializing_if = "Option::is_none")]
661 index: Option<String>,
662 #[serde(default, skip_serializing_if = "Option::is_none")]
663 index_span: Option<Span>,
664 iterable: Box<Expr>,
665 #[serde(default, skip_serializing_if = "Option::is_none")]
666 condition: Option<Box<Expr>>,
667 #[serde(skip_serializing_if = "Option::is_none")]
668 span: Option<Span>,
669 },
670 Lambda {
671 #[serde(default)]
672 params: Vec<String>,
673 #[serde(default)]
674 param_spans: Vec<Option<Span>>,
675 body: Box<Expr>,
676 #[serde(skip_serializing_if = "Option::is_none")]
677 span: Option<Span>,
678 },
679 StringModifier {
680 modifier: String,
681 value: String,
682 #[serde(skip_serializing_if = "Option::is_none")]
683 span: Option<Span>,
684 },
685 Local {
686 name: String,
687 #[serde(skip_serializing_if = "Option::is_none")]
688 span: Option<Span>,
689 },
690 Vector {
691 x: Box<Expr>,
692 y: Box<Expr>,
693 z: Box<Expr>,
694 #[serde(skip_serializing_if = "Option::is_none")]
695 span: Option<Span>,
696 },
697 Enum {
698 #[serde(rename = "type")]
699 value_type: String,
700 value: String,
701 #[serde(default)]
706 literal: bool,
707 #[serde(skip_serializing_if = "Option::is_none")]
708 span: Option<Span>,
709 },
710 GlobalVar {
711 name: String,
712 #[serde(skip_serializing_if = "Option::is_none")]
713 span: Option<Span>,
714 },
715 PlayerVar {
716 player: Box<Expr>,
717 name: String,
718 #[serde(default, skip_serializing_if = "Option::is_none")]
721 member_span: Option<Span>,
722 #[serde(skip_serializing_if = "Option::is_none")]
723 span: Option<Span>,
724 },
725 HostPlayer {
726 #[serde(skip_serializing_if = "Option::is_none")]
727 span: Option<Span>,
728 },
729 Member {
733 receiver: Box<Expr>,
734 member: String,
735 #[serde(default, skip_serializing_if = "Option::is_none")]
736 member_span: Option<Span>,
737 #[serde(skip_serializing_if = "Option::is_none")]
738 span: Option<Span>,
739 },
740 EventPlayer {
741 #[serde(skip_serializing_if = "Option::is_none")]
742 span: Option<Span>,
743 },
744 Constant {
745 name: String,
746 #[serde(skip_serializing_if = "Option::is_none")]
747 span: Option<Span>,
748 },
749 Call {
750 name: String,
751 #[serde(default)]
752 args: Vec<Expr>,
753 #[serde(default, skip_serializing_if = "Option::is_none")]
754 debug_source: Option<String>,
755 #[serde(skip_serializing_if = "Option::is_none")]
756 span: Option<Span>,
757 },
758 ReceiverCall {
759 receiver: Box<Expr>,
760 name: String,
761 #[serde(default)]
762 args: Vec<Expr>,
763 #[serde(skip_serializing_if = "Option::is_none")]
764 span: Option<Span>,
765 },
766 MacroCall {
767 name: String,
768 #[serde(default)]
769 args: Vec<Expr>,
770 #[serde(skip_serializing_if = "Option::is_none")]
771 span: Option<Span>,
772 },
773 MacroParam {
774 name: String,
775 #[serde(skip_serializing_if = "Option::is_none")]
776 span: Option<Span>,
777 },
778 Type {
781 name: String,
782 #[serde(default)]
783 args: Vec<Expr>,
784 #[serde(skip_serializing_if = "Option::is_none")]
785 span: Option<Span>,
786 },
787 Binary {
788 op: String,
789 left: Box<Expr>,
790 right: Box<Expr>,
791 #[serde(skip_serializing_if = "Option::is_none")]
792 span: Option<Span>,
793 },
794 Conditional {
795 then_value: Box<Expr>,
796 condition: Box<Expr>,
797 else_value: Box<Expr>,
798 #[serde(skip_serializing_if = "Option::is_none")]
799 span: Option<Span>,
800 },
801 Unary {
802 op: String,
803 operand: Box<Expr>,
804 #[serde(skip_serializing_if = "Option::is_none")]
805 span: Option<Span>,
806 },
807 Index {
808 array: Box<Expr>,
809 index: Box<Expr>,
810 #[serde(skip_serializing_if = "Option::is_none")]
811 span: Option<Span>,
812 },
813 Format {
814 text: String,
815 #[serde(default)]
816 args: Vec<Expr>,
817 #[serde(skip_serializing_if = "Option::is_none")]
818 span: Option<Span>,
819 },
820}
821
822#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
824pub struct DictEntry {
825 pub key: Box<Expr>,
826 pub value: Box<Expr>,
827 #[serde(skip_serializing_if = "Option::is_none")]
828 pub span: Option<Span>,
829}
830
831impl Expr {
832 pub fn span(&self) -> Option<&Span> {
834 match self {
835 Expr::Number { span, .. }
836 | Expr::String { span, .. }
837 | Expr::Bool { span, .. }
838 | Expr::Null { span }
839 | Expr::Array { span, .. }
840 | Expr::Dict { span, .. }
841 | Expr::Comprehension { span, .. }
842 | Expr::Lambda { span, .. }
843 | Expr::StringModifier { span, .. }
844 | Expr::Local { span, .. }
845 | Expr::Vector { span, .. }
846 | Expr::Enum { span, .. }
847 | Expr::GlobalVar { span, .. }
848 | Expr::PlayerVar { span, .. }
849 | Expr::HostPlayer { span }
850 | Expr::Member { span, .. }
851 | Expr::EventPlayer { span }
852 | Expr::Constant { span, .. }
853 | Expr::Call { span, .. }
854 | Expr::ReceiverCall { span, .. }
855 | Expr::MacroCall { span, .. }
856 | Expr::MacroParam { span, .. }
857 | Expr::Type { span, .. }
858 | Expr::Binary { span, .. }
859 | Expr::Conditional { span, .. }
860 | Expr::Unary { span, .. }
861 | Expr::Index { span, .. }
862 | Expr::Format { span, .. } => span.as_ref(),
863 }
864 }
865
866 pub(crate) fn span_mut(&mut self) -> &mut Option<Span> {
867 match self {
868 Expr::Number { span, .. }
869 | Expr::String { span, .. }
870 | Expr::Bool { span, .. }
871 | Expr::Null { span }
872 | Expr::Array { span, .. }
873 | Expr::Dict { span, .. }
874 | Expr::Comprehension { span, .. }
875 | Expr::Lambda { span, .. }
876 | Expr::StringModifier { span, .. }
877 | Expr::Local { span, .. }
878 | Expr::Vector { span, .. }
879 | Expr::Enum { span, .. }
880 | Expr::GlobalVar { span, .. }
881 | Expr::PlayerVar { span, .. }
882 | Expr::HostPlayer { span }
883 | Expr::Member { span, .. }
884 | Expr::EventPlayer { span }
885 | Expr::Constant { span, .. }
886 | Expr::Call { span, .. }
887 | Expr::ReceiverCall { span, .. }
888 | Expr::MacroCall { span, .. }
889 | Expr::MacroParam { span, .. }
890 | Expr::Type { span, .. }
891 | Expr::Binary { span, .. }
892 | Expr::Conditional { span, .. }
893 | Expr::Unary { span, .. }
894 | Expr::Index { span, .. }
895 | Expr::Format { span, .. } => span,
896 }
897 }
898
899 pub fn kind_name(&self) -> &'static str {
901 match self {
902 Expr::Number { .. } => "number",
903 Expr::String { .. } => "string",
904 Expr::Bool { .. } => "bool",
905 Expr::Null { .. } => "null",
906 Expr::Array { .. } => "array",
907 Expr::Dict { .. } => "dict",
908 Expr::Comprehension { .. } => "comprehension",
909 Expr::Lambda { .. } => "lambda",
910 Expr::StringModifier { .. } => "stringModifier",
911 Expr::Local { .. } => "local",
912 Expr::Vector { .. } => "vector",
913 Expr::Enum { .. } => "enum",
914 Expr::GlobalVar { .. } => "globalVar",
915 Expr::PlayerVar { .. } => "playerVar",
916 Expr::HostPlayer { .. } => "hostPlayer",
917 Expr::Member { .. } => "member",
918 Expr::EventPlayer { .. } => "eventPlayer",
919 Expr::Constant { .. } => "constant",
920 Expr::Call { .. } => "call",
921 Expr::ReceiverCall { .. } => "receiverCall",
922 Expr::MacroCall { .. } => "macroCall",
923 Expr::MacroParam { .. } => "macroParam",
924 Expr::Type { .. } => "type",
925 Expr::Binary { .. } => "binary",
926 Expr::Conditional { .. } => "conditional",
927 Expr::Unary { .. } => "unary",
928 Expr::Index { .. } => "index",
929 Expr::Format { .. } => "format",
930 }
931 }
932}