1use ecow::EcoString;
2
3use crate::program::{CallKind, DotAccessKind, ReceiverCoercion};
4use crate::types::Type;
5
6const CHILDREN_INLINE_CAP: usize = 4;
7
8pub struct Children<'a> {
9 inline: [Option<&'a Expression>; CHILDREN_INLINE_CAP],
10 inline_len: usize,
11 heap: Vec<&'a Expression>,
12}
13
14impl<'a> Children<'a> {
15 pub fn new() -> Self {
16 Children {
17 inline: [None; CHILDREN_INLINE_CAP],
18 inline_len: 0,
19 heap: Vec::new(),
20 }
21 }
22
23 pub fn push(&mut self, expression: &'a Expression) {
24 if self.heap.is_empty() && self.inline_len < CHILDREN_INLINE_CAP {
25 self.inline[self.inline_len] = Some(expression);
26 self.inline_len += 1;
27 } else {
28 self.heap.push(expression);
29 }
30 }
31
32 pub fn iter(&self) -> impl Iterator<Item = &'a Expression> + '_ {
33 self.inline[..self.inline_len]
34 .iter()
35 .filter_map(|slot| *slot)
36 .chain(self.heap.iter().copied())
37 }
38}
39
40impl Default for Children<'_> {
41 fn default() -> Self {
42 Children::new()
43 }
44}
45
46impl<'a> Extend<&'a Expression> for Children<'a> {
47 fn extend<T: IntoIterator<Item = &'a Expression>>(&mut self, iter: T) {
48 for expression in iter {
49 self.push(expression);
50 }
51 }
52}
53
54impl<'a> FromIterator<&'a Expression> for Children<'a> {
55 fn from_iter<T: IntoIterator<Item = &'a Expression>>(iter: T) -> Self {
56 let mut children = Children::new();
57 children.extend(iter);
58 children
59 }
60}
61
62pub struct ChildrenIntoIter<'a> {
63 inline: [Option<&'a Expression>; CHILDREN_INLINE_CAP],
64 pos: usize,
65 inline_len: usize,
66 heap: std::vec::IntoIter<&'a Expression>,
67}
68
69impl<'a> Iterator for ChildrenIntoIter<'a> {
70 type Item = &'a Expression;
71
72 fn next(&mut self) -> Option<&'a Expression> {
73 if self.pos < self.inline_len {
74 let item = self.inline[self.pos];
75 self.pos += 1;
76 item
77 } else {
78 self.heap.next()
79 }
80 }
81}
82
83impl<'a> IntoIterator for Children<'a> {
84 type Item = &'a Expression;
85 type IntoIter = ChildrenIntoIter<'a>;
86
87 fn into_iter(self) -> ChildrenIntoIter<'a> {
88 ChildrenIntoIter {
89 inline: self.inline,
90 pos: 0,
91 inline_len: self.inline_len,
92 heap: self.heap.into_iter(),
93 }
94 }
95}
96
97macro_rules! children {
98 () => { Children::new() };
99 ($($expression:expr),+ $(,)?) => {{
100 let mut __children = Children::new();
101 $( __children.push($expression); )+
102 __children
103 }};
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum DeadCodeCause {
108 Return,
109 Break,
110 Continue,
111 DivergingIf,
112 DivergingMatch,
113 InfiniteLoop,
114 DivergingCall,
115}
116
117#[derive(Clone, PartialEq)]
118pub struct Binding {
119 pub pattern: Pattern,
120 pub annotation: Option<Annotation>,
121 pub typed_pattern: Option<TypedPattern>,
122 pub ty: Type,
123 pub mutable: bool,
124}
125
126impl std::fmt::Debug for Binding {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 let mut s = f.debug_struct("Binding");
129 s.field("pattern", &self.pattern);
130 s.field("annotation", &self.annotation);
131 s.field("typed_pattern", &self.typed_pattern);
132 s.field("ty", &self.ty);
133 if self.mutable {
134 s.field("mutable", &self.mutable);
135 }
136 s.finish()
137 }
138}
139
140pub type BindingId = u32;
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub enum BindingKind {
144 Let { mutable: bool },
145 Parameter { mutable: bool },
146 MatchArm,
147 IfLet,
148 WhileLet,
149}
150
151impl BindingKind {
152 pub fn is_mutable(&self) -> bool {
153 matches!(
154 self,
155 BindingKind::Let { mutable: true } | BindingKind::Parameter { mutable: true }
156 )
157 }
158
159 pub fn is_param(&self) -> bool {
160 matches!(self, BindingKind::Parameter { .. })
161 }
162
163 pub fn is_match_arm(&self) -> bool {
164 matches!(self, BindingKind::MatchArm)
165 }
166
167 pub fn is_pattern_position(&self) -> bool {
168 matches!(
169 self,
170 BindingKind::MatchArm | BindingKind::IfLet | BindingKind::WhileLet
171 )
172 }
173}
174
175#[derive(Clone, PartialEq)]
176pub struct MatchArm {
177 pub pattern: Pattern,
178 pub guard: Option<Box<Expression>>,
179 pub typed_pattern: Option<TypedPattern>,
180 pub expression: Box<Expression>,
181}
182
183impl MatchArm {
184 pub fn has_guard(&self) -> bool {
185 self.guard.is_some()
186 }
187}
188
189impl std::fmt::Debug for MatchArm {
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 let mut s = f.debug_struct("MatchArm");
192 s.field("pattern", &self.pattern);
193 if self.guard.is_some() {
194 s.field("guard", &self.guard);
195 }
196 s.field("expression", &self.expression);
197 s.finish()
198 }
199}
200
201#[derive(Debug, Clone, Copy, PartialEq, Eq)]
202pub enum MatchOrigin {
203 Explicit,
204 IfLet { else_span: Option<Span> },
205}
206
207#[derive(Debug, Clone, PartialEq)]
208pub struct SelectArm {
209 pub pattern: SelectArmPattern,
210}
211
212#[derive(Debug, Clone, PartialEq)]
213pub enum SelectArmPattern {
214 Receive {
215 binding: Box<Pattern>,
216 typed_pattern: Option<TypedPattern>,
217 receive_expression: Box<Expression>,
218 body: Box<Expression>,
219 },
220 Send {
221 send_expression: Box<Expression>,
222 body: Box<Expression>,
223 },
224 MatchReceive {
225 receive_expression: Box<Expression>,
226 arms: Vec<MatchArm>,
227 },
228 WildCard {
229 body: Box<Expression>,
230 },
231}
232
233#[derive(Debug, Clone, PartialEq)]
234pub enum RestPattern {
235 Absent,
236 Discard(Span),
237 Bind { name: EcoString, span: Span },
238}
239
240impl RestPattern {
241 pub fn is_present(&self) -> bool {
242 !matches!(self, RestPattern::Absent)
243 }
244}
245
246#[derive(Debug, Clone, PartialEq)]
247pub enum Pattern {
248 Literal {
249 literal: Literal,
250 ty: Type,
251 span: Span,
252 },
253 Unit {
254 ty: Type,
255 span: Span,
256 },
257 EnumVariant {
258 identifier: EcoString,
259 fields: Vec<Self>,
260 rest: bool,
261 ty: Type,
262 span: Span,
263 },
264 Struct {
265 identifier: EcoString,
266 fields: Vec<StructFieldPattern>,
267 rest: bool,
268 ty: Type,
269 span: Span,
270 },
271 Tuple {
272 elements: Vec<Self>,
273 span: Span,
274 },
275 WildCard {
276 span: Span,
277 },
278 Identifier {
279 identifier: EcoString,
280 span: Span,
281 },
282 Slice {
283 prefix: Vec<Self>,
284 rest: RestPattern,
285 element_ty: Type,
286 span: Span,
287 },
288 Or {
289 patterns: Vec<Self>,
290 span: Span,
291 },
292 AsBinding {
293 pattern: Box<Self>,
294 name: EcoString,
295 span: Span,
296 },
297}
298
299#[derive(Clone, Copy)]
301pub enum PatternKind {
302 Literal,
303 Unit,
304 EnumVariant,
305 Struct,
306 Tuple,
307 WildCard,
308 Identifier,
309 Slice,
310 Or,
311 AsBinding,
312}
313
314impl PatternKind {
315 pub const COUNT: usize = PatternKind::AsBinding as usize + 1;
317}
318
319impl Pattern {
320 pub fn kind(&self) -> PatternKind {
321 match self {
322 Pattern::Literal { .. } => PatternKind::Literal,
323 Pattern::Unit { .. } => PatternKind::Unit,
324 Pattern::EnumVariant { .. } => PatternKind::EnumVariant,
325 Pattern::Struct { .. } => PatternKind::Struct,
326 Pattern::Tuple { .. } => PatternKind::Tuple,
327 Pattern::WildCard { .. } => PatternKind::WildCard,
328 Pattern::Identifier { .. } => PatternKind::Identifier,
329 Pattern::Slice { .. } => PatternKind::Slice,
330 Pattern::Or { .. } => PatternKind::Or,
331 Pattern::AsBinding { .. } => PatternKind::AsBinding,
332 }
333 }
334
335 pub fn get_span(&self) -> Span {
336 match self {
337 Pattern::Identifier { span, .. } => *span,
338 Pattern::Literal { span, .. } => *span,
339 Pattern::EnumVariant { span, .. } => *span,
340 Pattern::Struct { span, .. } => *span,
341 Pattern::WildCard { span } => *span,
342 Pattern::Unit { span, .. } => *span,
343 Pattern::Tuple { span, .. } => *span,
344 Pattern::Slice { span, .. } => *span,
345 Pattern::Or { span, .. } => *span,
346 Pattern::AsBinding { span, .. } => *span,
347 }
348 }
349
350 pub fn get_type(&self) -> Option<Type> {
351 match self {
352 Pattern::Identifier { .. } => None,
353 Pattern::Literal { ty, .. } => Some(ty.clone()),
354 Pattern::EnumVariant { ty, .. } => Some(ty.clone()),
355 Pattern::Struct { ty, .. } => Some(ty.clone()),
356 Pattern::WildCard { .. } => None,
357 Pattern::Unit { ty, .. } => Some(ty.clone()),
358 Pattern::Tuple { .. } => None,
359 Pattern::Slice { .. } => None,
360 Pattern::Or { .. } => None,
361 Pattern::AsBinding { pattern, .. } => pattern.get_type(),
362 }
363 }
364
365 pub fn is_identifier(&self) -> bool {
366 matches!(self, Pattern::Identifier { .. } | Pattern::AsBinding { .. })
367 }
368
369 pub fn get_identifier(&self) -> Option<EcoString> {
370 match self {
371 Pattern::Identifier { identifier, .. } => Some(identifier.clone()),
372 Pattern::AsBinding { name, .. } => Some(name.clone()),
373 _ => None,
374 }
375 }
376}
377
378#[derive(Debug, Clone, PartialEq)]
379pub struct StructFieldPattern {
380 pub name: EcoString,
381 pub value: Pattern,
382}
383
384#[derive(Debug, Clone, PartialEq)]
385pub enum TypedPattern {
386 Wildcard,
387 Literal(Literal),
388 Const {
392 qualified_name: EcoString,
393 ty: Type,
394 value: Option<Literal>,
395 },
396 EnumVariant {
397 enum_name: EcoString,
398 variant_name: EcoString,
399 variant_fields: Vec<EnumFieldDefinition>,
400 fields: Vec<TypedPattern>,
401 type_args: Vec<Type>,
402 field_types: Box<[Type]>,
403 },
404 EnumStructVariant {
405 enum_name: EcoString,
406 variant_name: EcoString,
407 variant_fields: Vec<EnumFieldDefinition>,
408 pattern_fields: Vec<(EcoString, TypedPattern)>,
409 type_args: Vec<Type>,
410 },
411 Struct {
412 struct_name: EcoString,
413 struct_fields: Vec<StructFieldDefinition>,
414 pattern_fields: Vec<(EcoString, TypedPattern)>,
415 type_args: Vec<Type>,
416 },
417 Slice {
418 prefix: Vec<TypedPattern>,
419 has_rest: bool,
420 element_type: Type,
421 },
422 Tuple {
423 arity: usize,
424 elements: Vec<TypedPattern>,
425 },
426 Or {
427 alternatives: Vec<TypedPattern>,
428 },
429}
430
431#[derive(Debug, Clone, PartialEq)]
432pub struct FunctionDefinition {
433 pub name: EcoString,
434 pub name_span: Span,
435 pub generics: Vec<Generic>,
436 pub params: Vec<Binding>,
437 pub body: Box<Expression>,
438 pub return_type: Type,
439 pub annotation: Annotation,
440 pub ty: Type,
441}
442
443#[derive(Clone, Copy)]
444pub struct FunctionDefinitionView<'a> {
445 pub name: &'a EcoString,
446 pub name_span: Span,
447 pub generics: &'a [Generic],
448 pub params: &'a [Binding],
449 pub body: &'a Expression,
450 pub return_type: &'a Type,
451}
452
453#[derive(Debug, Clone, PartialEq)]
454pub enum VariantFields {
455 Unit,
456 Tuple(Vec<EnumFieldDefinition>),
457 Struct(Vec<EnumFieldDefinition>),
458}
459
460impl VariantFields {
461 pub fn is_empty(&self) -> bool {
462 match self {
463 VariantFields::Unit => true,
464 VariantFields::Tuple(fields) | VariantFields::Struct(fields) => fields.is_empty(),
465 }
466 }
467
468 pub fn len(&self) -> usize {
469 match self {
470 VariantFields::Unit => 0,
471 VariantFields::Tuple(fields) | VariantFields::Struct(fields) => fields.len(),
472 }
473 }
474
475 pub fn iter(&self) -> std::slice::Iter<'_, EnumFieldDefinition> {
476 match self {
477 VariantFields::Unit => [].iter(),
478 VariantFields::Tuple(fields) | VariantFields::Struct(fields) => fields.iter(),
479 }
480 }
481
482 pub fn is_struct(&self) -> bool {
483 matches!(self, VariantFields::Struct(_))
484 }
485}
486
487impl<'a> IntoIterator for &'a VariantFields {
488 type Item = &'a EnumFieldDefinition;
489 type IntoIter = std::slice::Iter<'a, EnumFieldDefinition>;
490
491 fn into_iter(self) -> Self::IntoIter {
492 self.iter()
493 }
494}
495
496#[derive(Debug, Clone, PartialEq)]
497pub struct EnumVariant {
498 pub doc: Option<String>,
499 pub name: EcoString,
500 pub name_span: Span,
501 pub fields: VariantFields,
502}
503
504#[derive(Debug, Clone, PartialEq)]
505pub struct EnumFieldDefinition {
506 pub name: EcoString,
507 pub name_span: Span,
508 pub annotation: Annotation,
509 pub ty: Type,
510}
511
512#[derive(Debug, Clone, PartialEq)]
513pub struct Attribute {
514 pub name: String,
515 pub args: Vec<AttributeArg>,
516 pub span: Span,
517}
518
519#[derive(Debug, Clone, PartialEq)]
520#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
521pub enum AttributeArg {
522 Flag(String),
524 NegatedFlag(String),
526 String(String),
528 Raw(String),
530}
531
532#[derive(Debug, Clone, Copy, PartialEq)]
533#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
534pub enum StructKind {
535 Record,
536 Tuple,
537}
538
539#[derive(Debug, Clone, PartialEq)]
540pub struct StructFieldDefinition {
541 pub doc: Option<String>,
542 pub attributes: Vec<Attribute>,
543 pub name: EcoString,
544 pub name_span: Span,
545 pub annotation: Annotation,
546 pub visibility: Visibility,
547 pub ty: Type,
548 pub embedded: bool,
549}
550
551#[derive(Debug, Clone, PartialEq)]
552pub struct StructFieldAssignment {
553 pub name: EcoString,
554 pub name_span: Span,
555 pub value: Box<Expression>,
556}
557
558#[derive(Debug, Clone, PartialEq)]
559pub enum StructSpread {
560 None,
561 From(Box<Expression>),
562 ZeroFill { span: Span },
563}
564
565impl StructSpread {
566 pub fn is_none(&self) -> bool {
567 matches!(self, Self::None)
568 }
569
570 pub fn is_some(&self) -> bool {
571 !self.is_none()
572 }
573
574 pub fn span(&self) -> Option<Span> {
575 match self {
576 Self::None => None,
577 Self::From(e) => Some(e.get_span()),
578 Self::ZeroFill { span } => Some(*span),
579 }
580 }
581
582 pub fn as_expression(&self) -> Option<&Expression> {
583 match self {
584 Self::From(e) => Some(e),
585 Self::None | Self::ZeroFill { .. } => None,
586 }
587 }
588}
589
590#[derive(Debug, Clone, PartialEq)]
591#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
592pub enum Annotation {
593 Constructor {
594 name: EcoString,
595 params: Vec<Self>,
596 span: Span,
597 },
598 Function {
599 params: Vec<Self>,
600 return_type: Box<Self>,
601 span: Span,
602 },
603 Tuple {
604 elements: Vec<Self>,
605 span: Span,
606 },
607 Unknown,
608 Opaque {
609 span: Span,
610 },
611}
612
613impl Annotation {
614 pub fn unit() -> Self {
615 Self::Constructor {
616 name: "Unit".into(),
617 params: vec![],
618 span: Span::dummy(),
619 }
620 }
621
622 pub fn get_span(&self) -> Span {
623 match self {
624 Self::Constructor { span, .. } => *span,
625 Self::Function { span, .. } => *span,
626 Self::Tuple { span, .. } => *span,
627 Self::Opaque { span } => *span,
628 Self::Unknown => Span::dummy(),
629 }
630 }
631
632 pub fn get_name(&self) -> Option<String> {
633 match self {
634 Self::Constructor { name, .. } => Some(name.to_string()),
635 _ => None,
636 }
637 }
638
639 pub fn is_unit(&self) -> bool {
640 matches!(self, Self::Constructor { name, params, .. } if name == "Unit" && params.is_empty())
641 }
642
643 pub fn is_unknown(&self) -> bool {
644 matches!(self, Self::Unknown)
645 }
646
647 pub fn is_opaque(&self) -> bool {
648 matches!(self, Self::Opaque { .. })
649 }
650}
651
652#[derive(Debug, Clone, PartialEq)]
653pub struct Generic {
654 pub name: EcoString,
655 pub bounds: Vec<Annotation>,
656 pub span: Span,
657}
658
659#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
660#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
661pub struct Span {
662 pub file_id: u32,
663 pub byte_offset: u32,
664 pub byte_length: u32,
665}
666
667impl Span {
668 pub fn new(file_id: u32, byte_offset: u32, byte_length: u32) -> Self {
669 Span {
670 file_id,
671 byte_offset,
672 byte_length,
673 }
674 }
675
676 pub fn dummy() -> Self {
677 Span {
678 file_id: 0,
679 byte_offset: 0,
680 byte_length: 0,
681 }
682 }
683
684 pub fn is_dummy(&self) -> bool {
685 self.byte_length == 0
686 }
687
688 pub fn end(&self) -> u32 {
689 self.byte_offset + self.byte_length
690 }
691
692 pub fn merge(self, other: Span) -> Span {
693 Span::new(
694 self.file_id,
695 self.byte_offset,
696 other.end() - self.byte_offset,
697 )
698 }
699}
700
701#[derive(Debug, Clone, PartialEq)]
702#[allow(clippy::large_enum_variant)]
703pub enum Expression {
704 Literal {
705 literal: Literal,
706 ty: Type,
707 span: Span,
708 },
709 Function {
710 doc: Option<String>,
711 attributes: Vec<Attribute>,
712 name: EcoString,
713 name_span: Span,
714 generics: Vec<Generic>,
715 params: Vec<Binding>,
716 return_annotation: Annotation,
717 return_type: Type,
718 visibility: Visibility,
719 body: Box<Expression>,
720 ty: Type,
721 span: Span,
722 },
723 Lambda {
724 params: Vec<Binding>,
725 return_annotation: Annotation,
726 body: Box<Expression>,
727 ty: Type,
728 span: Span,
729 },
730 Block {
731 items: Vec<Expression>,
732 ty: Type,
733 span: Span,
734 },
735 Let {
736 binding: Box<Binding>,
737 value: Box<Expression>,
738 mutable: bool,
739 mut_span: Option<Span>,
740 else_block: Option<Box<Expression>>,
741 else_span: Option<Span>,
742 typed_pattern: Option<TypedPattern>,
743 ty: Type,
744 span: Span,
745 },
746 Identifier {
747 value: EcoString,
748 ty: Type,
749 span: Span,
750 binding_id: Option<BindingId>,
751 qualified: Option<EcoString>,
752 },
753 Call {
754 expression: Box<Expression>,
755 args: Vec<Expression>,
756 spread: Box<Option<Expression>>,
757 type_args: Vec<Annotation>,
758 ty: Type,
759 span: Span,
760 call_kind: Option<CallKind>,
761 },
762 If {
763 condition: Box<Expression>,
764 consequence: Box<Expression>,
765 alternative: Box<Expression>,
766 ty: Type,
767 span: Span,
768 },
769 IfLet {
770 pattern: Pattern,
771 scrutinee: Box<Expression>,
772 consequence: Box<Expression>,
773 alternative: Box<Expression>,
774 typed_pattern: Option<TypedPattern>,
775 else_span: Option<Span>,
776 ty: Type,
777 span: Span,
778 },
779 Match {
780 subject: Box<Expression>,
781 arms: Vec<MatchArm>,
782 origin: MatchOrigin,
783 ty: Type,
784 span: Span,
785 },
786 Tuple {
787 elements: Vec<Expression>,
788 ty: Type,
789 span: Span,
790 },
791 StructCall {
792 name: EcoString,
793 field_assignments: Vec<StructFieldAssignment>,
794 spread: StructSpread,
795 ty: Type,
796 span: Span,
797 },
798 DotAccess {
799 expression: Box<Expression>,
800 member: EcoString,
801 ty: Type,
802 span: Span,
803 dot_access_kind: Option<DotAccessKind>,
804 receiver_coercion: Option<ReceiverCoercion>,
805 },
806 Assignment {
807 target: Box<Expression>,
808 value: Box<Expression>,
809 compound_operator: Option<BinaryOperator>,
810 span: Span,
811 },
812 Return {
813 expression: Box<Expression>,
814 ty: Type,
815 span: Span,
816 },
817 Propagate {
818 expression: Box<Expression>,
819 ty: Type,
820 span: Span,
821 },
822 TryBlock {
823 items: Vec<Expression>,
824 ty: Type,
825 try_keyword_span: Span,
826 span: Span,
827 },
828 RecoverBlock {
829 items: Vec<Expression>,
830 ty: Type,
831 recover_keyword_span: Span,
832 span: Span,
833 },
834 ImplBlock {
835 annotation: Annotation,
836 receiver_name: EcoString,
837 methods: Vec<Expression>,
838 generics: Vec<Generic>,
839 ty: Type,
840 span: Span,
841 },
842 Binary {
843 operator: BinaryOperator,
844 left: Box<Expression>,
845 right: Box<Expression>,
846 ty: Type,
847 span: Span,
848 },
849 Unary {
850 operator: UnaryOperator,
851 expression: Box<Expression>,
852 ty: Type,
853 span: Span,
854 },
855 Paren {
856 expression: Box<Expression>,
857 ty: Type,
858 span: Span,
859 },
860 Const {
861 doc: Option<String>,
862 identifier: EcoString,
863 identifier_span: Span,
864 annotation: Option<Annotation>,
865 expression: Box<Expression>,
866 visibility: Visibility,
867 ty: Type,
868 span: Span,
869 },
870 VariableDeclaration {
871 doc: Option<String>,
872 name: EcoString,
873 name_span: Span,
874 annotation: Annotation,
875 visibility: Visibility,
876 ty: Type,
877 span: Span,
878 },
879 RawGo {
880 text: String,
881 },
882 Loop {
883 body: Box<Expression>,
884 ty: Type,
885 span: Span,
886 needs_label: bool,
887 },
888 While {
889 condition: Box<Expression>,
890 body: Box<Expression>,
891 span: Span,
892 needs_label: bool,
893 },
894 WhileLet {
895 pattern: Pattern,
896 scrutinee: Box<Expression>,
897 body: Box<Expression>,
898 typed_pattern: Option<TypedPattern>,
899 span: Span,
900 needs_label: bool,
901 },
902 For {
903 binding: Box<Binding>,
904 iterable: Box<Expression>,
905 body: Box<Expression>,
906 span: Span,
907 needs_label: bool,
908 binding_id: Option<BindingId>,
909 },
910 Break {
911 value: Option<Box<Expression>>,
912 span: Span,
913 },
914 Continue {
915 span: Span,
916 },
917 Enum {
918 doc: Option<String>,
919 attributes: Vec<Attribute>,
920 name: EcoString,
921 name_span: Span,
922 generics: Vec<Generic>,
923 variants: Vec<EnumVariant>,
924 visibility: Visibility,
925 span: Span,
926 },
927 Struct {
928 doc: Option<String>,
929 attributes: Vec<Attribute>,
930 name: EcoString,
931 name_span: Span,
932 generics: Vec<Generic>,
933 fields: Vec<StructFieldDefinition>,
934 kind: StructKind,
935 visibility: Visibility,
936 span: Span,
937 },
938 TypeAlias {
939 doc: Option<String>,
940 attributes: Vec<Attribute>,
941 name: EcoString,
942 name_span: Span,
943 generics: Vec<Generic>,
944 annotation: Annotation,
945 ty: Type,
946 visibility: Visibility,
947 span: Span,
948 },
949 ModuleImport {
950 name: EcoString,
951 name_span: Span,
952 alias: Option<ImportAlias>,
953 span: Span,
954 },
955 Reference {
956 expression: Box<Expression>,
957 ty: Type,
958 span: Span,
959 },
960 Interface {
961 doc: Option<String>,
962 name: EcoString,
963 name_span: Span,
964 generics: Vec<Generic>,
965 parents: Vec<ParentInterface>,
966 method_signatures: Vec<Expression>,
967 visibility: Visibility,
968 span: Span,
969 },
970 IndexedAccess {
971 expression: Box<Expression>,
972 index: Box<Expression>,
973 ty: Type,
974 span: Span,
975 from_colon_syntax: bool,
976 },
977 Task {
978 expression: Box<Expression>,
979 ty: Type,
980 span: Span,
981 },
982 Defer {
983 expression: Box<Expression>,
984 ty: Type,
985 span: Span,
986 },
987 Select {
988 arms: Vec<SelectArm>,
989 ty: Type,
990 span: Span,
991 },
992 Unit {
993 ty: Type,
994 span: Span,
995 },
996 Range {
997 start: Option<Box<Expression>>,
998 end: Option<Box<Expression>>,
999 inclusive: bool,
1000 ty: Type,
1001 span: Span,
1002 },
1003 Cast {
1004 expression: Box<Expression>,
1005 target_type: Annotation,
1006 ty: Type,
1007 span: Span,
1008 },
1009 NoOp,
1010}
1011
1012#[derive(Clone, Copy)]
1014pub enum ExpressionKind {
1015 Literal,
1016 Function,
1017 Lambda,
1018 Block,
1019 Let,
1020 Identifier,
1021 Call,
1022 If,
1023 IfLet,
1024 Match,
1025 Tuple,
1026 StructCall,
1027 DotAccess,
1028 Assignment,
1029 Return,
1030 Propagate,
1031 TryBlock,
1032 RecoverBlock,
1033 ImplBlock,
1034 Binary,
1035 Unary,
1036 Paren,
1037 Const,
1038 VariableDeclaration,
1039 RawGo,
1040 Loop,
1041 While,
1042 WhileLet,
1043 For,
1044 Break,
1045 Continue,
1046 Enum,
1047 Struct,
1048 TypeAlias,
1049 ModuleImport,
1050 Reference,
1051 Interface,
1052 IndexedAccess,
1053 Task,
1054 Defer,
1055 Select,
1056 Unit,
1057 Range,
1058 Cast,
1059 NoOp,
1060}
1061
1062impl ExpressionKind {
1063 pub const COUNT: usize = ExpressionKind::NoOp as usize + 1;
1065}
1066
1067impl Expression {
1068 pub fn kind(&self) -> ExpressionKind {
1069 match self {
1070 Expression::Literal { .. } => ExpressionKind::Literal,
1071 Expression::Function { .. } => ExpressionKind::Function,
1072 Expression::Lambda { .. } => ExpressionKind::Lambda,
1073 Expression::Block { .. } => ExpressionKind::Block,
1074 Expression::Let { .. } => ExpressionKind::Let,
1075 Expression::Identifier { .. } => ExpressionKind::Identifier,
1076 Expression::Call { .. } => ExpressionKind::Call,
1077 Expression::If { .. } => ExpressionKind::If,
1078 Expression::IfLet { .. } => ExpressionKind::IfLet,
1079 Expression::Match { .. } => ExpressionKind::Match,
1080 Expression::Tuple { .. } => ExpressionKind::Tuple,
1081 Expression::StructCall { .. } => ExpressionKind::StructCall,
1082 Expression::DotAccess { .. } => ExpressionKind::DotAccess,
1083 Expression::Assignment { .. } => ExpressionKind::Assignment,
1084 Expression::Return { .. } => ExpressionKind::Return,
1085 Expression::Propagate { .. } => ExpressionKind::Propagate,
1086 Expression::TryBlock { .. } => ExpressionKind::TryBlock,
1087 Expression::RecoverBlock { .. } => ExpressionKind::RecoverBlock,
1088 Expression::ImplBlock { .. } => ExpressionKind::ImplBlock,
1089 Expression::Binary { .. } => ExpressionKind::Binary,
1090 Expression::Unary { .. } => ExpressionKind::Unary,
1091 Expression::Paren { .. } => ExpressionKind::Paren,
1092 Expression::Const { .. } => ExpressionKind::Const,
1093 Expression::VariableDeclaration { .. } => ExpressionKind::VariableDeclaration,
1094 Expression::RawGo { .. } => ExpressionKind::RawGo,
1095 Expression::Loop { .. } => ExpressionKind::Loop,
1096 Expression::While { .. } => ExpressionKind::While,
1097 Expression::WhileLet { .. } => ExpressionKind::WhileLet,
1098 Expression::For { .. } => ExpressionKind::For,
1099 Expression::Break { .. } => ExpressionKind::Break,
1100 Expression::Continue { .. } => ExpressionKind::Continue,
1101 Expression::Enum { .. } => ExpressionKind::Enum,
1102 Expression::Struct { .. } => ExpressionKind::Struct,
1103 Expression::TypeAlias { .. } => ExpressionKind::TypeAlias,
1104 Expression::ModuleImport { .. } => ExpressionKind::ModuleImport,
1105 Expression::Reference { .. } => ExpressionKind::Reference,
1106 Expression::Interface { .. } => ExpressionKind::Interface,
1107 Expression::IndexedAccess { .. } => ExpressionKind::IndexedAccess,
1108 Expression::Task { .. } => ExpressionKind::Task,
1109 Expression::Defer { .. } => ExpressionKind::Defer,
1110 Expression::Select { .. } => ExpressionKind::Select,
1111 Expression::Unit { .. } => ExpressionKind::Unit,
1112 Expression::Range { .. } => ExpressionKind::Range,
1113 Expression::Cast { .. } => ExpressionKind::Cast,
1114 Expression::NoOp => ExpressionKind::NoOp,
1115 }
1116 }
1117
1118 pub fn is_noop(&self) -> bool {
1119 matches!(self, Expression::NoOp)
1120 }
1121
1122 pub fn is_block(&self) -> bool {
1123 matches!(self, Expression::Block { .. })
1124 }
1125
1126 pub fn is_range(&self) -> bool {
1127 matches!(self, Expression::Range { .. })
1128 }
1129
1130 pub fn is_conditional(&self) -> bool {
1131 matches!(
1132 self,
1133 Expression::If { .. }
1134 | Expression::IfLet { .. }
1135 | Expression::Match {
1136 origin: MatchOrigin::IfLet { .. },
1137 ..
1138 }
1139 )
1140 }
1141
1142 pub fn is_control_flow(&self) -> bool {
1143 matches!(
1144 self,
1145 Expression::If { .. }
1146 | Expression::Match { .. }
1147 | Expression::Select { .. }
1148 | Expression::For { .. }
1149 | Expression::While { .. }
1150 | Expression::WhileLet { .. }
1151 | Expression::Loop { .. }
1152 )
1153 }
1154
1155 pub fn callee_name(&self) -> Option<String> {
1156 let Expression::Call { expression, .. } = self else {
1157 return None;
1158 };
1159 match expression.as_ref() {
1160 Expression::Identifier { value, .. } => Some(value.to_string()),
1161 Expression::DotAccess {
1162 expression: base,
1163 member,
1164 ..
1165 } => {
1166 if let Expression::Identifier { value, .. } = base.as_ref() {
1167 Some(format!("{}.{}", value, member))
1168 } else {
1169 None
1170 }
1171 }
1172 _ => None,
1173 }
1174 }
1175
1176 pub fn to_function_signature(&self) -> FunctionDefinition {
1177 match self {
1178 Expression::Function {
1179 name,
1180 name_span,
1181 generics,
1182 params,
1183 return_annotation,
1184 return_type,
1185 ty,
1186 ..
1187 } => FunctionDefinition {
1188 name: name.clone(),
1189 name_span: *name_span,
1190 generics: generics.clone(),
1191 params: params.clone(),
1192 body: Box::new(Expression::NoOp),
1193 return_type: return_type.clone(),
1194 annotation: return_annotation.clone(),
1195 ty: ty.clone(),
1196 },
1197 _ => panic!("to_function_signature called on non-Function expression"),
1198 }
1199 }
1200
1201 pub fn function_definition_view(&self) -> FunctionDefinitionView<'_> {
1202 match self {
1203 Expression::Function {
1204 name,
1205 name_span,
1206 generics,
1207 params,
1208 return_type,
1209 body,
1210 ..
1211 } => FunctionDefinitionView {
1212 name,
1213 name_span: *name_span,
1214 generics,
1215 params,
1216 body,
1217 return_type,
1218 },
1219 _ => panic!("function_definition_view called on non-Function expression"),
1220 }
1221 }
1222
1223 pub fn as_option_constructor(&self) -> Option<std::result::Result<(), ()>> {
1224 let variant = match self {
1225 Expression::Identifier { value, .. } => Some(value.as_str()),
1226 _ => None,
1227 }?;
1228
1229 match variant {
1230 "Option.Some" | "Some" => Some(Ok(())),
1231 "Option.None" | "None" => Some(Err(())),
1232 _ => None,
1233 }
1234 }
1235
1236 pub fn is_none_literal(&self) -> bool {
1237 matches!(self.as_option_constructor(), Some(Err(())))
1238 }
1239
1240 pub fn as_result_constructor(&self) -> Option<std::result::Result<(), ()>> {
1241 let variant = match self {
1242 Expression::Identifier { value, .. } => Some(value.as_str()),
1243 _ => None,
1244 }?;
1245
1246 match variant {
1247 "Result.Ok" | "Ok" => Some(Ok(())),
1248 "Result.Err" | "Err" => Some(Err(())),
1249 _ => None,
1250 }
1251 }
1252
1253 pub fn as_partial_constructor(&self) -> Option<&'static str> {
1254 let variant = match self {
1255 Expression::Identifier { value, .. } => Some(value.as_str()),
1256 _ => None,
1257 }?;
1258
1259 match variant {
1260 "Partial.Ok" => Some("Ok"),
1261 "Partial.Err" => Some("Err"),
1262 "Partial.Both" => Some("Both"),
1263 _ => None,
1264 }
1265 }
1266
1267 pub fn get_type(&self) -> Type {
1268 match self {
1269 Self::Literal { ty, .. }
1270 | Self::Function { ty, .. }
1271 | Self::Lambda { ty, .. }
1272 | Self::Block { ty, .. }
1273 | Self::Let { ty, .. }
1274 | Self::Identifier { ty, .. }
1275 | Self::Call { ty, .. }
1276 | Self::If { ty, .. }
1277 | Self::IfLet { ty, .. }
1278 | Self::Match { ty, .. }
1279 | Self::Tuple { ty, .. }
1280 | Self::StructCall { ty, .. }
1281 | Self::DotAccess { ty, .. }
1282 | Self::Return { ty, .. }
1283 | Self::Propagate { ty, .. }
1284 | Self::TryBlock { ty, .. }
1285 | Self::RecoverBlock { ty, .. }
1286 | Self::Binary { ty, .. }
1287 | Self::Paren { ty, .. }
1288 | Self::Unary { ty, .. }
1289 | Self::Const { ty, .. }
1290 | Self::VariableDeclaration { ty, .. }
1291 | Self::Defer { ty, .. }
1292 | Self::Reference { ty, .. }
1293 | Self::IndexedAccess { ty, .. }
1294 | Self::Task { ty, .. }
1295 | Self::Select { ty, .. }
1296 | Self::Unit { ty, .. }
1297 | Self::Loop { ty, .. }
1298 | Self::Range { ty, .. }
1299 | Self::Cast { ty, .. } => ty.clone(),
1300 Self::Enum { .. }
1301 | Self::Struct { .. }
1302 | Self::Assignment { .. }
1303 | Self::ImplBlock { .. }
1304 | Self::TypeAlias { .. }
1305 | Self::ModuleImport { .. }
1306 | Self::Interface { .. }
1307 | Self::NoOp
1308 | Self::RawGo { .. }
1309 | Self::While { .. }
1310 | Self::WhileLet { .. }
1311 | Self::For { .. } => Type::ignored(),
1312 Self::Break { .. } | Self::Continue { .. } => Type::Never,
1313 }
1314 }
1315
1316 pub fn get_span(&self) -> Span {
1317 match self {
1318 Self::Literal { span, .. }
1319 | Self::Function { span, .. }
1320 | Self::Lambda { span, .. }
1321 | Self::Block { span, .. }
1322 | Self::Let { span, .. }
1323 | Self::Identifier { span, .. }
1324 | Self::Call { span, .. }
1325 | Self::If { span, .. }
1326 | Self::IfLet { span, .. }
1327 | Self::Match { span, .. }
1328 | Self::Tuple { span, .. }
1329 | Self::Enum { span, .. }
1330 | Self::Struct { span, .. }
1331 | Self::StructCall { span, .. }
1332 | Self::DotAccess { span, .. }
1333 | Self::Assignment { span, .. }
1334 | Self::Return { span, .. }
1335 | Self::Propagate { span, .. }
1336 | Self::TryBlock { span, .. }
1337 | Self::RecoverBlock { span, .. }
1338 | Self::ImplBlock { span, .. }
1339 | Self::Binary { span, .. }
1340 | Self::Paren { span, .. }
1341 | Self::Unary { span, .. }
1342 | Self::Const { span, .. }
1343 | Self::VariableDeclaration { span, .. }
1344 | Self::Defer { span, .. }
1345 | Self::Reference { span, .. }
1346 | Self::IndexedAccess { span, .. }
1347 | Self::Task { span, .. }
1348 | Self::Select { span, .. }
1349 | Self::Loop { span, .. }
1350 | Self::TypeAlias { span, .. }
1351 | Self::ModuleImport { span, .. }
1352 | Self::Interface { span, .. }
1353 | Self::Unit { span, .. }
1354 | Self::While { span, .. }
1355 | Self::WhileLet { span, .. }
1356 | Self::For { span, .. }
1357 | Self::Break { span, .. }
1358 | Self::Continue { span, .. }
1359 | Self::Range { span, .. }
1360 | Self::Cast { span, .. } => *span,
1361 Self::NoOp | Self::RawGo { .. } => Span::dummy(),
1362 }
1363 }
1364
1365 pub fn contains_break(&self) -> bool {
1366 match self {
1367 Expression::Break { .. } => true,
1368
1369 Expression::Loop { .. }
1370 | Expression::While { .. }
1371 | Expression::WhileLet { .. }
1372 | Expression::For { .. } => false,
1373
1374 Expression::Block { items, .. } => items.iter().any(Self::contains_break),
1375
1376 Expression::TryBlock { items, .. } => items.iter().any(Self::contains_break),
1377 Expression::RecoverBlock { items, .. } => items.iter().any(Self::contains_break),
1378
1379 Expression::If {
1380 condition,
1381 consequence,
1382 alternative,
1383 ..
1384 } => {
1385 condition.contains_break()
1386 || consequence.contains_break()
1387 || alternative.contains_break()
1388 }
1389
1390 Expression::IfLet {
1391 scrutinee,
1392 consequence,
1393 alternative,
1394 ..
1395 } => {
1396 scrutinee.contains_break()
1397 || consequence.contains_break()
1398 || alternative.contains_break()
1399 }
1400
1401 Expression::Match { subject, arms, .. } => {
1402 subject.contains_break() || arms.iter().any(|arm| arm.expression.contains_break())
1403 }
1404
1405 Expression::Paren { expression, .. } => expression.contains_break(),
1406
1407 Expression::Binary { left, right, .. } => {
1408 left.contains_break() || right.contains_break()
1409 }
1410
1411 Expression::Unary { expression, .. } => expression.contains_break(),
1412
1413 Expression::Call {
1414 expression,
1415 args,
1416 spread,
1417 ..
1418 } => {
1419 expression.contains_break()
1420 || args.iter().any(Self::contains_break)
1421 || spread.as_ref().as_ref().is_some_and(Self::contains_break)
1422 }
1423
1424 Expression::Function { .. } | Expression::Lambda { .. } => false,
1425
1426 Expression::Select { arms, .. } => arms.iter().any(|arm| match &arm.pattern {
1427 SelectArmPattern::Receive { body, .. } => body.contains_break(),
1428 SelectArmPattern::Send { body, .. } => body.contains_break(),
1429 SelectArmPattern::MatchReceive { arms, .. } => {
1430 arms.iter().any(|a| a.expression.contains_break())
1431 }
1432 SelectArmPattern::WildCard { body } => body.contains_break(),
1433 }),
1434
1435 Expression::Cast { expression, .. } => expression.contains_break(),
1436
1437 Expression::Let {
1438 value, else_block, ..
1439 } => value.contains_break() || else_block.as_ref().is_some_and(|e| e.contains_break()),
1440
1441 Expression::Assignment { value, .. } => value.contains_break(),
1442
1443 _ => false,
1444 }
1445 }
1446
1447 pub fn diverges(&self) -> Option<DeadCodeCause> {
1448 match self {
1449 Expression::Return { .. } => Some(DeadCodeCause::Return),
1450 Expression::Break { .. } => Some(DeadCodeCause::Break),
1451 Expression::Continue { .. } => Some(DeadCodeCause::Continue),
1452
1453 Expression::If {
1454 consequence,
1455 alternative,
1456 ..
1457 } => {
1458 if consequence.diverges().is_some() && alternative.diverges().is_some() {
1459 Some(DeadCodeCause::DivergingIf)
1460 } else {
1461 None
1462 }
1463 }
1464
1465 Expression::IfLet {
1466 consequence,
1467 alternative,
1468 ..
1469 } => {
1470 if consequence.diverges().is_some() && alternative.diverges().is_some() {
1471 Some(DeadCodeCause::DivergingIf)
1472 } else {
1473 None
1474 }
1475 }
1476
1477 Expression::Match { arms, .. } => {
1478 if !arms.is_empty() && arms.iter().all(|arm| arm.expression.diverges().is_some()) {
1479 Some(DeadCodeCause::DivergingMatch)
1480 } else {
1481 None
1482 }
1483 }
1484
1485 Expression::Block { items, .. } => {
1486 for item in items {
1487 if let Some(cause) = item.diverges() {
1488 return Some(cause);
1489 }
1490 }
1491 None
1492 }
1493
1494 Expression::TryBlock { items, .. } | Expression::RecoverBlock { items, .. } => {
1495 for item in items {
1496 if let Some(cause) = item.diverges() {
1497 return Some(cause);
1498 }
1499 }
1500 None
1501 }
1502
1503 Expression::Paren { expression, .. } | Expression::Cast { expression, .. } => {
1504 expression.diverges()
1505 }
1506
1507 Expression::Loop { body, .. } => {
1508 if !body.contains_break() {
1509 Some(DeadCodeCause::InfiniteLoop)
1510 } else {
1511 None
1512 }
1513 }
1514
1515 Expression::Call { ty, .. } if ty.is_never() => Some(DeadCodeCause::DivergingCall),
1516
1517 _ => None,
1518 }
1519 }
1520
1521 pub fn children(&self) -> Children<'_> {
1526 match self {
1527 Expression::Literal { literal, .. } => match literal {
1528 Literal::Slice(elements) => elements.iter().collect(),
1529 Literal::FormatString(parts) => parts
1530 .iter()
1531 .filter_map(|p| match p {
1532 FormatStringPart::Expression(e) => Some(e.as_ref()),
1533 FormatStringPart::Text(_) => None,
1534 })
1535 .collect(),
1536 _ => Children::new(),
1537 },
1538 Expression::Function { body, .. } => children![body],
1539 Expression::Lambda { body, .. } => children![body],
1540 Expression::Block { items, .. } => items.iter().collect(),
1541 Expression::Let {
1542 value, else_block, ..
1543 } => {
1544 let mut c = children![value.as_ref()];
1545 if let Some(eb) = else_block {
1546 c.push(eb);
1547 }
1548 c
1549 }
1550 Expression::Identifier { .. } => Children::new(),
1551 Expression::Call {
1552 expression,
1553 args,
1554 spread,
1555 ..
1556 } => {
1557 let mut c = children![expression.as_ref()];
1558 c.extend(args);
1559 if let Some(s) = spread.as_ref() {
1560 c.push(s);
1561 }
1562 c
1563 }
1564 Expression::If {
1565 condition,
1566 consequence,
1567 alternative,
1568 ..
1569 } => children![condition, consequence, alternative],
1570 Expression::IfLet {
1571 scrutinee,
1572 consequence,
1573 alternative,
1574 ..
1575 } => children![scrutinee, consequence, alternative],
1576 Expression::Match { subject, arms, .. } => {
1577 let mut c = children![subject.as_ref()];
1578 for arm in arms {
1579 if let Some(guard) = &arm.guard {
1580 c.push(guard);
1581 }
1582 c.push(&arm.expression);
1583 }
1584 c
1585 }
1586 Expression::Tuple { elements, .. } => elements.iter().collect(),
1587 Expression::StructCall {
1588 field_assignments,
1589 spread,
1590 ..
1591 } => {
1592 let mut c: Children = field_assignments.iter().map(|f| f.value.as_ref()).collect();
1593 if let Some(s) = spread.as_expression() {
1594 c.push(s);
1595 }
1596 c
1597 }
1598 Expression::DotAccess { expression, .. } => children![expression],
1599 Expression::Assignment { target, value, .. } => children![target, value],
1600 Expression::Return { expression, .. } => children![expression],
1601 Expression::Propagate { expression, .. } => children![expression],
1602 Expression::TryBlock { items, .. } | Expression::RecoverBlock { items, .. } => {
1603 items.iter().collect()
1604 }
1605 Expression::ImplBlock { methods, .. } => methods.iter().collect(),
1606 Expression::Binary { left, right, .. } => children![left, right],
1607 Expression::Unary { expression, .. } => children![expression],
1608 Expression::Paren { expression, .. } => children![expression],
1609 Expression::Const { expression, .. } => children![expression],
1610 Expression::Loop { body, .. } => children![body],
1611 Expression::While {
1612 condition, body, ..
1613 } => children![condition, body],
1614 Expression::WhileLet {
1615 scrutinee, body, ..
1616 } => children![scrutinee, body],
1617 Expression::For { iterable, body, .. } => children![iterable, body],
1618 Expression::Break { value, .. } => value
1619 .as_ref()
1620 .map(|v| children![v.as_ref()])
1621 .unwrap_or_default(),
1622 Expression::Reference { expression, .. } => children![expression],
1623 Expression::IndexedAccess {
1624 expression, index, ..
1625 } => children![expression, index],
1626 Expression::Task { expression, .. } => children![expression],
1627 Expression::Defer { expression, .. } => children![expression],
1628 Expression::Select { arms, .. } => {
1629 let mut c = Children::new();
1630 for arm in arms {
1631 match &arm.pattern {
1632 SelectArmPattern::Receive {
1633 receive_expression,
1634 body,
1635 ..
1636 } => {
1637 c.push(receive_expression.as_ref());
1638 c.push(body.as_ref());
1639 }
1640 SelectArmPattern::Send {
1641 send_expression,
1642 body,
1643 } => {
1644 c.push(send_expression.as_ref());
1645 c.push(body.as_ref());
1646 }
1647 SelectArmPattern::MatchReceive {
1648 receive_expression,
1649 arms: match_arms,
1650 } => {
1651 c.push(receive_expression.as_ref());
1652 for ma in match_arms {
1653 if let Some(guard) = &ma.guard {
1654 c.push(guard);
1655 }
1656 c.push(&ma.expression);
1657 }
1658 }
1659 SelectArmPattern::WildCard { body } => {
1660 c.push(body.as_ref());
1661 }
1662 }
1663 }
1664 c
1665 }
1666 Expression::Range { start, end, .. } => {
1667 let mut c = Children::new();
1668 if let Some(s) = start {
1669 c.push(s.as_ref());
1670 }
1671 if let Some(e) = end {
1672 c.push(e.as_ref());
1673 }
1674 c
1675 }
1676 Expression::Cast { expression, .. } => children![expression],
1677 Expression::Interface {
1678 method_signatures, ..
1679 } => method_signatures.iter().collect(),
1680 Expression::Unit { .. }
1681 | Expression::Continue { .. }
1682 | Expression::Enum { .. }
1683 | Expression::Struct { .. }
1684 | Expression::TypeAlias { .. }
1685 | Expression::VariableDeclaration { .. }
1686 | Expression::ModuleImport { .. }
1687 | Expression::RawGo { .. }
1688 | Expression::NoOp => Children::new(),
1689 }
1690 }
1691
1692 pub fn unwrap_parens(&self) -> &Expression {
1693 match self {
1694 Expression::Paren { expression, .. } => expression.unwrap_parens(),
1695 other => other,
1696 }
1697 }
1698
1699 pub fn binding_id(&self) -> Option<BindingId> {
1700 match self.unwrap_parens() {
1701 Expression::Identifier { binding_id, .. } => *binding_id,
1702 _ => None,
1703 }
1704 }
1705
1706 pub fn as_integer(&self) -> Option<u64> {
1707 match self.unwrap_parens() {
1708 Expression::Literal {
1709 literal: Literal::Integer { value, .. },
1710 ..
1711 } => Some(*value),
1712 _ => None,
1713 }
1714 }
1715
1716 #[inline]
1718 pub fn deref_inner(&self) -> Option<&Expression> {
1719 match self {
1720 Expression::Unary {
1721 operator: UnaryOperator::Deref,
1722 expression,
1723 ..
1724 } => Some(expression),
1725 _ => None,
1726 }
1727 }
1728
1729 pub fn as_dotted_path(&self) -> Option<String> {
1730 match self {
1731 Expression::Identifier { value, .. } => Some(value.to_string()),
1732 Expression::DotAccess {
1733 expression, member, ..
1734 } => Some(format!("{}.{}", expression.as_dotted_path()?, member)),
1735 _ => None,
1736 }
1737 }
1738
1739 pub fn root_identifier(&self) -> Option<&str> {
1740 match self {
1741 Expression::Identifier { value, .. } => Some(value),
1742 Expression::DotAccess { expression, .. } => expression.root_identifier(),
1743 _ => None,
1744 }
1745 }
1746
1747 pub fn is_empty_collection(&self) -> bool {
1748 matches!(
1749 self,
1750 Expression::Literal {
1751 literal: Literal::Slice(elements),
1752 ..
1753 } if elements.is_empty()
1754 )
1755 }
1756
1757 pub fn is_all_literals(&self) -> bool {
1758 match self.unwrap_parens() {
1759 Expression::Literal { literal, .. } => match literal {
1760 Literal::Slice(elements) => elements.iter().all(|e| e.is_all_literals()),
1761 Literal::FormatString(parts) => parts.iter().all(|p| match p {
1762 FormatStringPart::Text(_) => true,
1763 FormatStringPart::Expression(e) => e.is_all_literals(),
1764 }),
1765 _ => true,
1766 },
1767 Expression::Tuple { elements, .. } => elements.iter().all(|e| e.is_all_literals()),
1768 Expression::Unit { .. } => true,
1769 _ => false,
1770 }
1771 }
1772
1773 pub fn get_var_name(&self) -> Option<String> {
1774 match self {
1775 Expression::Identifier { value, .. } => Some(value.to_string()),
1776 Expression::DotAccess { expression, .. } => expression.get_var_name(),
1777 Expression::Assignment { target, .. } => target.get_var_name(),
1778 Expression::IndexedAccess { expression, .. } => expression.get_var_name(),
1779 Expression::Paren { expression, .. } => expression.get_var_name(),
1780 Expression::Reference { expression, .. } => expression.get_var_name(),
1781 Expression::Unary {
1782 operator,
1783 expression,
1784 ..
1785 } => {
1786 if operator == &UnaryOperator::Deref {
1787 expression.get_var_name()
1788 } else {
1789 None
1790 }
1791 }
1792 _ => None,
1793 }
1794 }
1795
1796 pub fn is_function(&self) -> bool {
1797 matches!(self, Expression::Function { .. })
1798 }
1799
1800 pub fn set_public(self) -> Self {
1801 match self {
1802 Expression::Enum {
1803 doc,
1804 attributes,
1805 name,
1806 name_span,
1807 generics,
1808 variants,
1809 span,
1810 ..
1811 } => Expression::Enum {
1812 doc,
1813 attributes,
1814 name,
1815 name_span,
1816 generics,
1817 variants,
1818 visibility: Visibility::Public,
1819 span,
1820 },
1821 Expression::Struct {
1822 doc,
1823 attributes,
1824 name,
1825 name_span,
1826 generics,
1827 fields,
1828 kind,
1829 span,
1830 ..
1831 } => {
1832 let fields = if kind == StructKind::Tuple {
1833 fields
1834 .into_iter()
1835 .map(|f| StructFieldDefinition {
1836 visibility: Visibility::Public,
1837 ..f
1838 })
1839 .collect()
1840 } else {
1841 fields
1842 };
1843 Expression::Struct {
1844 doc,
1845 attributes,
1846 name,
1847 name_span,
1848 generics,
1849 fields,
1850 kind,
1851 visibility: Visibility::Public,
1852 span,
1853 }
1854 }
1855 Expression::Function {
1856 doc,
1857 attributes,
1858 name,
1859 name_span,
1860 generics,
1861 params,
1862 return_annotation,
1863 return_type,
1864 body,
1865 ty,
1866 span,
1867 ..
1868 } => Expression::Function {
1869 doc,
1870 attributes,
1871 name,
1872 name_span,
1873 generics,
1874 params,
1875 return_annotation,
1876 return_type,
1877 visibility: Visibility::Public,
1878 body,
1879 ty,
1880 span,
1881 },
1882 Expression::Const {
1883 doc,
1884 identifier,
1885 identifier_span,
1886 annotation,
1887 expression,
1888 ty,
1889 span,
1890 ..
1891 } => Expression::Const {
1892 doc,
1893 identifier,
1894 identifier_span,
1895 annotation,
1896 expression,
1897 visibility: Visibility::Public,
1898 ty,
1899 span,
1900 },
1901 Expression::VariableDeclaration {
1902 doc,
1903 name,
1904 name_span,
1905 annotation,
1906 ty,
1907 span,
1908 ..
1909 } => Expression::VariableDeclaration {
1910 doc,
1911 name,
1912 name_span,
1913 annotation,
1914 visibility: Visibility::Public,
1915 ty,
1916 span,
1917 },
1918 Expression::TypeAlias {
1919 doc,
1920 attributes,
1921 name,
1922 name_span,
1923 generics,
1924 annotation,
1925 ty,
1926 span,
1927 ..
1928 } => Expression::TypeAlias {
1929 doc,
1930 attributes,
1931 name,
1932 name_span,
1933 generics,
1934 annotation,
1935 ty,
1936 visibility: Visibility::Public,
1937 span,
1938 },
1939 Expression::Interface {
1940 doc,
1941 name,
1942 name_span,
1943 generics,
1944 parents,
1945 method_signatures,
1946 span,
1947 ..
1948 } => Expression::Interface {
1949 doc,
1950 name,
1951 name_span,
1952 generics,
1953 parents,
1954 method_signatures,
1955 visibility: Visibility::Public,
1956 span,
1957 },
1958 expression => expression,
1959 }
1960 }
1961
1962 pub fn has_else(&self) -> bool {
1963 match self {
1964 Self::Block { items, .. } if items.is_empty() => false,
1965 Self::Unit { .. } => false,
1966 Self::If { alternative, .. } | Self::IfLet { alternative, .. } => {
1967 alternative.has_else()
1968 }
1969 _ => true,
1970 }
1971 }
1972}
1973
1974#[derive(Debug, Clone, PartialEq)]
1975pub enum Literal {
1976 Integer {
1977 value: u64,
1978 text: Option<String>,
1979 },
1980 Float {
1981 value: f64,
1982 text: Option<String>,
1983 },
1984 Imaginary(f64),
1986 Boolean(bool),
1987 String {
1988 value: String,
1989 raw: bool,
1990 },
1991 FormatString(Vec<FormatStringPart>),
1992 Char(String),
1993 Slice(Vec<Expression>),
1994}
1995
1996#[derive(Debug, Clone, PartialEq)]
1997pub enum FormatStringPart {
1998 Text(String),
1999 Expression(Box<Expression>),
2000}
2001
2002#[derive(Debug, Clone, PartialEq)]
2003pub enum UnaryOperator {
2004 Negative,
2005 Not,
2006 BitwiseNot,
2007 Deref,
2008}
2009
2010#[derive(Debug, Clone, Copy, PartialEq)]
2011pub enum BinaryOperator {
2012 Addition,
2013 Subtraction,
2014 Multiplication,
2015 Division,
2016 BitwiseAnd,
2017 BitwiseOr,
2018 BitwiseXor,
2019 BitwiseAndNot,
2020 ShiftLeft,
2021 ShiftRight,
2022 LessThan,
2023 LessThanOrEqual,
2024 GreaterThan,
2025 GreaterThanOrEqual,
2026 Remainder,
2027 Equal,
2028 NotEqual,
2029 And,
2030 Or,
2031 Pipeline,
2032}
2033
2034impl BinaryOperator {
2035 pub fn compound_assignment_symbol(&self) -> Option<&'static str> {
2039 match self {
2040 BinaryOperator::Addition => Some("+="),
2041 BinaryOperator::Subtraction => Some("-="),
2042 BinaryOperator::Multiplication => Some("*="),
2043 BinaryOperator::Division => Some("/="),
2044 BinaryOperator::Remainder => Some("%="),
2045 BinaryOperator::BitwiseAnd => Some("&="),
2046 BinaryOperator::BitwiseOr => Some("|="),
2047 BinaryOperator::BitwiseXor => Some("^="),
2048 BinaryOperator::BitwiseAndNot => Some("&^="),
2049 BinaryOperator::ShiftLeft => Some("<<="),
2050 BinaryOperator::ShiftRight => Some(">>="),
2051 _ => None,
2052 }
2053 }
2054}
2055
2056impl std::fmt::Display for BinaryOperator {
2057 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2058 let symbol = match self {
2059 BinaryOperator::Addition => "+",
2060 BinaryOperator::Subtraction => "-",
2061 BinaryOperator::Multiplication => "*",
2062 BinaryOperator::Division => "/",
2063 BinaryOperator::Remainder => "%",
2064 BinaryOperator::BitwiseAnd => "&",
2065 BinaryOperator::BitwiseOr => "|",
2066 BinaryOperator::BitwiseXor => "^",
2067 BinaryOperator::BitwiseAndNot => "&^",
2068 BinaryOperator::ShiftLeft => "<<",
2069 BinaryOperator::ShiftRight => ">>",
2070 BinaryOperator::Equal => "==",
2071 BinaryOperator::NotEqual => "!=",
2072 BinaryOperator::LessThan => "<",
2073 BinaryOperator::LessThanOrEqual => "<=",
2074 BinaryOperator::GreaterThan => ">",
2075 BinaryOperator::GreaterThanOrEqual => ">=",
2076 BinaryOperator::And => "&&",
2077 BinaryOperator::Or => "||",
2078 BinaryOperator::Pipeline => "|>",
2079 };
2080 write!(f, "{}", symbol)
2081 }
2082}
2083
2084#[derive(Debug, Clone, PartialEq)]
2085pub struct ParentInterface {
2086 pub annotation: Annotation,
2087 pub ty: Type,
2088 pub span: Span,
2089}
2090
2091#[derive(Debug, Clone, Copy, PartialEq)]
2092#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2093pub enum Visibility {
2094 Public,
2095 Private,
2096}
2097
2098impl Visibility {
2099 pub fn is_public(&self) -> bool {
2100 matches!(self, Visibility::Public)
2101 }
2102}
2103
2104#[derive(Debug, Clone, PartialEq)]
2105pub enum ImportAlias {
2106 Named(EcoString, Span),
2107 Blank(Span),
2108}