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,
303 #[serde(skip_serializing_if = "Option::is_none")]
304 pub span: Option<Span>,
305}
306
307#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
309#[serde(tag = "kind", rename_all = "camelCase")]
310pub enum Declaration {
311 GlobalVariable {
312 name: String,
313 #[serde(default)]
314 index: Option<u32>,
315 #[serde(skip_serializing_if = "Option::is_none")]
316 span: Option<Span>,
317 #[serde(default, skip_serializing_if = "Option::is_none")]
319 name_span: Option<Span>,
320 #[serde(default)]
321 initializer: Option<Box<Expr>>,
322 },
323 PlayerVariable {
324 name: String,
325 #[serde(default)]
326 index: Option<u32>,
327 #[serde(skip_serializing_if = "Option::is_none")]
328 span: Option<Span>,
329 #[serde(default, skip_serializing_if = "Option::is_none")]
331 name_span: Option<Span>,
332 #[serde(default)]
333 initializer: Option<Box<Expr>>,
334 },
335 Subroutine {
336 name: String,
337 #[serde(default)]
338 index: Option<u32>,
339 #[serde(skip_serializing_if = "Option::is_none")]
340 span: Option<Span>,
341 #[serde(default, skip_serializing_if = "Option::is_none")]
343 name_span: Option<Span>,
344 },
345 Constant {
346 name: String,
347 #[serde(skip_serializing_if = "Option::is_none")]
348 span: Option<Span>,
349 value: Box<Expr>,
350 },
351 Macro {
352 name: String,
353 #[serde(default)]
354 args: Vec<String>,
355 #[serde(skip_serializing_if = "Option::is_none")]
356 span: Option<Span>,
357 #[serde(default)]
358 body: Vec<Stmt>,
359 },
360}
361
362#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
364#[serde(untagged)]
365pub enum RuleEntry {
366 Rule(Rule),
368 SubroutineDef {
370 #[serde(rename = "kind")]
371 kind: String,
372 name: String,
373 #[serde(default, skip_serializing_if = "String::is_empty")]
374 source_name: String,
375 #[serde(skip_serializing_if = "Option::is_none")]
376 span: Option<Span>,
377 #[serde(default, skip_serializing_if = "Option::is_none")]
379 name_span: Option<Span>,
380 #[serde(default)]
381 body: Vec<Stmt>,
382 #[serde(default)]
383 annotations: Vec<Annotation>,
384 },
385}
386
387#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
389pub struct Rule {
390 pub name: String,
391 #[serde(skip_serializing_if = "Option::is_none")]
392 pub span: Option<Span>,
393 #[serde(default, skip_serializing_if = "Option::is_none")]
395 pub name_span: Option<Span>,
396 #[serde(default)]
397 pub disabled: bool,
398 #[serde(default)]
399 pub delimiter: bool,
400 #[serde(default, skip_serializing_if = "Option::is_none")]
401 pub new_page: Option<String>,
402 #[serde(default)]
403 pub annotations: Vec<Annotation>,
404 pub event: Event,
405 #[serde(default)]
406 pub conditions: Vec<Expr>,
407 #[serde(default)]
408 pub actions: Vec<Stmt>,
409}
410
411#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
413pub struct Annotation {
414 pub name: String,
415 #[serde(default)]
416 pub args: Vec<AnnotationArg>,
417 #[serde(skip_serializing_if = "Option::is_none")]
418 pub span: Option<Span>,
419}
420
421#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
422pub struct AnnotationArg {
423 pub text: String,
424 #[serde(skip_serializing_if = "Option::is_none")]
425 pub span: Option<Span>,
426}
427
428#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
430pub struct Event {
431 pub name: String,
432 #[serde(default)]
433 pub args: Vec<Expr>,
434 #[serde(skip_serializing_if = "Option::is_none")]
435 pub span: Option<Span>,
436}
437
438#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
440#[serde(tag = "kind", rename_all = "camelCase")]
441pub enum Stmt {
442 Expr {
443 expr: Box<Expr>,
444 #[serde(skip_serializing_if = "Option::is_none")]
445 span: Option<Span>,
446 },
447 Assign {
448 target: Box<Expr>,
449 value: Box<Expr>,
450 #[serde(skip_serializing_if = "Option::is_none")]
451 span: Option<Span>,
452 },
453 If {
454 branches: Vec<IfBranch>,
455 #[serde(default)]
456 r#else: Option<Vec<Stmt>>,
457 #[serde(default, skip_serializing_if = "Option::is_none")]
459 else_span: Option<Span>,
460 #[serde(default, skip_serializing_if = "Option::is_none")]
463 end_span: Option<Span>,
464 #[serde(skip_serializing_if = "Option::is_none")]
465 span: Option<Span>,
466 },
467 For {
468 variable: Box<Expr>,
469 iterable: Box<Expr>,
470 #[serde(default)]
471 body: Vec<Stmt>,
472 #[serde(skip_serializing_if = "Option::is_none")]
473 span: Option<Span>,
474 },
475 While {
476 condition: Box<Expr>,
477 #[serde(default)]
478 body: Vec<Stmt>,
479 #[serde(skip_serializing_if = "Option::is_none")]
480 span: Option<Span>,
481 },
482 DoWhile {
483 condition: Box<Expr>,
484 #[serde(default)]
485 body: Vec<Stmt>,
486 #[serde(skip_serializing_if = "Option::is_none")]
487 span: Option<Span>,
488 },
489 Switch {
490 value: Box<Expr>,
491 #[serde(default)]
492 arms: Vec<SwitchArm>,
493 #[serde(skip_serializing_if = "Option::is_none")]
494 span: Option<Span>,
495 },
496 Delete {
497 target: Box<Expr>,
498 #[serde(skip_serializing_if = "Option::is_none")]
499 span: Option<Span>,
500 },
501 Break {
502 #[serde(skip_serializing_if = "Option::is_none")]
503 span: Option<Span>,
504 },
505 Return {
506 #[serde(skip_serializing_if = "Option::is_none")]
507 span: Option<Span>,
508 },
509 Continue {
510 #[serde(skip_serializing_if = "Option::is_none")]
511 span: Option<Span>,
512 },
513 Goto {
514 #[serde(default, skip_serializing_if = "Option::is_none")]
515 label: Option<String>,
516 #[serde(default, skip_serializing_if = "Option::is_none")]
517 offset: Option<Box<Expr>>,
518 #[serde(default)]
519 rule_start: bool,
520 #[serde(skip_serializing_if = "Option::is_none")]
521 span: Option<Span>,
522 },
523 Label {
524 name: String,
525 #[serde(skip_serializing_if = "Option::is_none")]
526 span: Option<Span>,
527 },
528 CallSubroutine {
529 name: String,
530 #[serde(skip_serializing_if = "Option::is_none")]
531 span: Option<Span>,
532 },
533 Pass {
534 #[serde(skip_serializing_if = "Option::is_none")]
535 span: Option<Span>,
536 },
537}
538
539#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
541pub struct IfBranch {
542 pub condition: Box<Expr>,
543 #[serde(default)]
544 pub body: Vec<Stmt>,
545 #[serde(default, skip_serializing_if = "Option::is_none")]
547 pub marker: Option<Span>,
548}
549
550impl Stmt {
551 pub fn span(&self) -> Option<&Span> {
553 match self {
554 Stmt::Expr { span, .. }
555 | Stmt::Assign { span, .. }
556 | Stmt::If { span, .. }
557 | Stmt::For { span, .. }
558 | Stmt::While { span, .. }
559 | Stmt::DoWhile { span, .. }
560 | Stmt::Switch { span, .. }
561 | Stmt::Delete { span, .. }
562 | Stmt::Break { span }
563 | Stmt::Return { span }
564 | Stmt::Continue { span }
565 | Stmt::Goto { span, .. }
566 | Stmt::Label { span, .. }
567 | Stmt::CallSubroutine { span, .. }
568 | Stmt::Pass { span } => span.as_ref(),
569 }
570 }
571
572 pub(crate) fn span_mut(&mut self) -> &mut Option<Span> {
573 match self {
574 Stmt::Expr { span, .. }
575 | Stmt::Assign { span, .. }
576 | Stmt::If { span, .. }
577 | Stmt::For { span, .. }
578 | Stmt::While { span, .. }
579 | Stmt::DoWhile { span, .. }
580 | Stmt::Switch { span, .. }
581 | Stmt::Delete { span, .. }
582 | Stmt::Break { span }
583 | Stmt::Return { span }
584 | Stmt::Continue { span }
585 | Stmt::Goto { span, .. }
586 | Stmt::Label { span, .. }
587 | Stmt::CallSubroutine { span, .. }
588 | Stmt::Pass { span } => span,
589 }
590 }
591}
592
593#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
596#[serde(tag = "kind", rename_all = "camelCase")]
597pub enum SwitchArm {
598 Case {
599 value: Box<Expr>,
600 #[serde(default)]
601 body: Vec<Stmt>,
602 #[serde(skip_serializing_if = "Option::is_none")]
603 span: Option<Span>,
604 },
605 Default {
606 #[serde(default)]
607 body: Vec<Stmt>,
608 #[serde(skip_serializing_if = "Option::is_none")]
609 span: Option<Span>,
610 },
611}
612
613#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
615#[serde(tag = "kind", rename_all = "camelCase")]
616pub enum Expr {
617 Number {
618 value: f64,
619 text: String,
620 #[serde(skip_serializing_if = "Option::is_none")]
621 span: Option<Span>,
622 },
623 String {
624 value: String,
625 #[serde(skip_serializing_if = "Option::is_none")]
626 span: Option<Span>,
627 },
628 Bool {
629 value: bool,
630 #[serde(skip_serializing_if = "Option::is_none")]
631 span: Option<Span>,
632 },
633 Null {
634 #[serde(skip_serializing_if = "Option::is_none")]
635 span: Option<Span>,
636 },
637 Array {
638 #[serde(default)]
639 elements: Vec<Expr>,
640 #[serde(skip_serializing_if = "Option::is_none")]
641 span: Option<Span>,
642 },
643 Dict {
644 #[serde(default)]
645 entries: Vec<DictEntry>,
646 #[serde(skip_serializing_if = "Option::is_none")]
647 span: Option<Span>,
648 },
649 Comprehension {
650 element: Box<Expr>,
651 variable: String,
652 #[serde(skip_serializing_if = "Option::is_none")]
653 variable_span: Option<Span>,
654 #[serde(default, skip_serializing_if = "Option::is_none")]
655 index: Option<String>,
656 #[serde(default, skip_serializing_if = "Option::is_none")]
657 index_span: Option<Span>,
658 iterable: Box<Expr>,
659 #[serde(default, skip_serializing_if = "Option::is_none")]
660 condition: Option<Box<Expr>>,
661 #[serde(skip_serializing_if = "Option::is_none")]
662 span: Option<Span>,
663 },
664 Lambda {
665 #[serde(default)]
666 params: Vec<String>,
667 #[serde(default)]
668 param_spans: Vec<Option<Span>>,
669 body: Box<Expr>,
670 #[serde(skip_serializing_if = "Option::is_none")]
671 span: Option<Span>,
672 },
673 StringModifier {
674 modifier: String,
675 value: String,
676 #[serde(skip_serializing_if = "Option::is_none")]
677 span: Option<Span>,
678 },
679 Local {
680 name: String,
681 #[serde(skip_serializing_if = "Option::is_none")]
682 span: Option<Span>,
683 },
684 Vector {
685 x: Box<Expr>,
686 y: Box<Expr>,
687 z: Box<Expr>,
688 #[serde(skip_serializing_if = "Option::is_none")]
689 span: Option<Span>,
690 },
691 Enum {
692 #[serde(rename = "type")]
693 value_type: String,
694 value: String,
695 #[serde(default)]
700 literal: bool,
701 #[serde(skip_serializing_if = "Option::is_none")]
702 span: Option<Span>,
703 },
704 GlobalVar {
705 name: String,
706 #[serde(skip_serializing_if = "Option::is_none")]
707 span: Option<Span>,
708 },
709 PlayerVar {
710 player: Box<Expr>,
711 name: String,
712 #[serde(default, skip_serializing_if = "Option::is_none")]
715 member_span: Option<Span>,
716 #[serde(skip_serializing_if = "Option::is_none")]
717 span: Option<Span>,
718 },
719 HostPlayer {
720 #[serde(skip_serializing_if = "Option::is_none")]
721 span: Option<Span>,
722 },
723 Member {
727 receiver: Box<Expr>,
728 member: String,
729 #[serde(default, skip_serializing_if = "Option::is_none")]
730 member_span: Option<Span>,
731 #[serde(skip_serializing_if = "Option::is_none")]
732 span: Option<Span>,
733 },
734 EventPlayer {
735 #[serde(skip_serializing_if = "Option::is_none")]
736 span: Option<Span>,
737 },
738 Constant {
739 name: String,
740 #[serde(skip_serializing_if = "Option::is_none")]
741 span: Option<Span>,
742 },
743 Call {
744 name: String,
745 #[serde(default)]
746 args: Vec<Expr>,
747 #[serde(default, skip_serializing_if = "Option::is_none")]
748 debug_source: Option<String>,
749 #[serde(skip_serializing_if = "Option::is_none")]
750 span: Option<Span>,
751 },
752 ReceiverCall {
753 receiver: Box<Expr>,
754 name: String,
755 #[serde(default)]
756 args: Vec<Expr>,
757 #[serde(skip_serializing_if = "Option::is_none")]
758 span: Option<Span>,
759 },
760 MacroCall {
761 name: String,
762 #[serde(default)]
763 args: Vec<Expr>,
764 #[serde(skip_serializing_if = "Option::is_none")]
765 span: Option<Span>,
766 },
767 MacroParam {
768 name: String,
769 #[serde(skip_serializing_if = "Option::is_none")]
770 span: Option<Span>,
771 },
772 Type {
775 name: String,
776 #[serde(default)]
777 args: Vec<Expr>,
778 #[serde(skip_serializing_if = "Option::is_none")]
779 span: Option<Span>,
780 },
781 Binary {
782 op: String,
783 left: Box<Expr>,
784 right: Box<Expr>,
785 #[serde(skip_serializing_if = "Option::is_none")]
786 span: Option<Span>,
787 },
788 Conditional {
789 then_value: Box<Expr>,
790 condition: Box<Expr>,
791 else_value: Box<Expr>,
792 #[serde(skip_serializing_if = "Option::is_none")]
793 span: Option<Span>,
794 },
795 Unary {
796 op: String,
797 operand: Box<Expr>,
798 #[serde(skip_serializing_if = "Option::is_none")]
799 span: Option<Span>,
800 },
801 Index {
802 array: Box<Expr>,
803 index: Box<Expr>,
804 #[serde(skip_serializing_if = "Option::is_none")]
805 span: Option<Span>,
806 },
807 Format {
808 text: String,
809 #[serde(default)]
810 args: Vec<Expr>,
811 #[serde(skip_serializing_if = "Option::is_none")]
812 span: Option<Span>,
813 },
814}
815
816#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
818pub struct DictEntry {
819 pub key: Box<Expr>,
820 pub value: Box<Expr>,
821 #[serde(skip_serializing_if = "Option::is_none")]
822 pub span: Option<Span>,
823}
824
825impl Expr {
826 pub fn span(&self) -> Option<&Span> {
828 match self {
829 Expr::Number { span, .. }
830 | Expr::String { span, .. }
831 | Expr::Bool { span, .. }
832 | Expr::Null { span }
833 | Expr::Array { span, .. }
834 | Expr::Dict { span, .. }
835 | Expr::Comprehension { span, .. }
836 | Expr::Lambda { span, .. }
837 | Expr::StringModifier { span, .. }
838 | Expr::Local { span, .. }
839 | Expr::Vector { span, .. }
840 | Expr::Enum { span, .. }
841 | Expr::GlobalVar { span, .. }
842 | Expr::PlayerVar { span, .. }
843 | Expr::HostPlayer { span }
844 | Expr::Member { span, .. }
845 | Expr::EventPlayer { span }
846 | Expr::Constant { span, .. }
847 | Expr::Call { span, .. }
848 | Expr::ReceiverCall { span, .. }
849 | Expr::MacroCall { span, .. }
850 | Expr::MacroParam { span, .. }
851 | Expr::Type { span, .. }
852 | Expr::Binary { span, .. }
853 | Expr::Conditional { span, .. }
854 | Expr::Unary { span, .. }
855 | Expr::Index { span, .. }
856 | Expr::Format { span, .. } => span.as_ref(),
857 }
858 }
859
860 pub(crate) fn span_mut(&mut self) -> &mut Option<Span> {
861 match self {
862 Expr::Number { span, .. }
863 | Expr::String { span, .. }
864 | Expr::Bool { span, .. }
865 | Expr::Null { span }
866 | Expr::Array { span, .. }
867 | Expr::Dict { span, .. }
868 | Expr::Comprehension { span, .. }
869 | Expr::Lambda { span, .. }
870 | Expr::StringModifier { span, .. }
871 | Expr::Local { span, .. }
872 | Expr::Vector { span, .. }
873 | Expr::Enum { span, .. }
874 | Expr::GlobalVar { span, .. }
875 | Expr::PlayerVar { span, .. }
876 | Expr::HostPlayer { span }
877 | Expr::Member { span, .. }
878 | Expr::EventPlayer { span }
879 | Expr::Constant { span, .. }
880 | Expr::Call { span, .. }
881 | Expr::ReceiverCall { span, .. }
882 | Expr::MacroCall { span, .. }
883 | Expr::MacroParam { span, .. }
884 | Expr::Type { span, .. }
885 | Expr::Binary { span, .. }
886 | Expr::Conditional { span, .. }
887 | Expr::Unary { span, .. }
888 | Expr::Index { span, .. }
889 | Expr::Format { span, .. } => span,
890 }
891 }
892
893 pub fn kind_name(&self) -> &'static str {
895 match self {
896 Expr::Number { .. } => "number",
897 Expr::String { .. } => "string",
898 Expr::Bool { .. } => "bool",
899 Expr::Null { .. } => "null",
900 Expr::Array { .. } => "array",
901 Expr::Dict { .. } => "dict",
902 Expr::Comprehension { .. } => "comprehension",
903 Expr::Lambda { .. } => "lambda",
904 Expr::StringModifier { .. } => "stringModifier",
905 Expr::Local { .. } => "local",
906 Expr::Vector { .. } => "vector",
907 Expr::Enum { .. } => "enum",
908 Expr::GlobalVar { .. } => "globalVar",
909 Expr::PlayerVar { .. } => "playerVar",
910 Expr::HostPlayer { .. } => "hostPlayer",
911 Expr::Member { .. } => "member",
912 Expr::EventPlayer { .. } => "eventPlayer",
913 Expr::Constant { .. } => "constant",
914 Expr::Call { .. } => "call",
915 Expr::ReceiverCall { .. } => "receiverCall",
916 Expr::MacroCall { .. } => "macroCall",
917 Expr::MacroParam { .. } => "macroParam",
918 Expr::Type { .. } => "type",
919 Expr::Binary { .. } => "binary",
920 Expr::Conditional { .. } => "conditional",
921 Expr::Unary { .. } => "unary",
922 Expr::Index { .. } => "index",
923 Expr::Format { .. } => "format",
924 }
925 }
926}