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(Debug, Clone, PartialEq)]
444pub enum VariantFields {
445 Unit,
446 Tuple(Vec<EnumFieldDefinition>),
447 Struct(Vec<EnumFieldDefinition>),
448}
449
450impl VariantFields {
451 pub fn is_empty(&self) -> bool {
452 match self {
453 VariantFields::Unit => true,
454 VariantFields::Tuple(fields) | VariantFields::Struct(fields) => fields.is_empty(),
455 }
456 }
457
458 pub fn len(&self) -> usize {
459 match self {
460 VariantFields::Unit => 0,
461 VariantFields::Tuple(fields) | VariantFields::Struct(fields) => fields.len(),
462 }
463 }
464
465 pub fn iter(&self) -> std::slice::Iter<'_, EnumFieldDefinition> {
466 match self {
467 VariantFields::Unit => [].iter(),
468 VariantFields::Tuple(fields) | VariantFields::Struct(fields) => fields.iter(),
469 }
470 }
471
472 pub fn is_struct(&self) -> bool {
473 matches!(self, VariantFields::Struct(_))
474 }
475}
476
477impl<'a> IntoIterator for &'a VariantFields {
478 type Item = &'a EnumFieldDefinition;
479 type IntoIter = std::slice::Iter<'a, EnumFieldDefinition>;
480
481 fn into_iter(self) -> Self::IntoIter {
482 self.iter()
483 }
484}
485
486#[derive(Debug, Clone, PartialEq)]
487pub struct EnumVariant {
488 pub doc: Option<String>,
489 pub name: EcoString,
490 pub name_span: Span,
491 pub fields: VariantFields,
492}
493
494#[derive(Debug, Clone, PartialEq)]
495pub struct EnumFieldDefinition {
496 pub name: EcoString,
497 pub name_span: Span,
498 pub annotation: Annotation,
499 pub ty: Type,
500}
501
502#[derive(Debug, Clone, PartialEq)]
503pub struct Attribute {
504 pub name: String,
505 pub args: Vec<AttributeArg>,
506 pub span: Span,
507}
508
509#[derive(Debug, Clone, PartialEq)]
510#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
511pub enum AttributeArg {
512 Flag(String),
514 NegatedFlag(String),
516 String(String),
518 Raw(String),
520}
521
522#[derive(Debug, Clone, Copy, PartialEq)]
523#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
524pub enum StructKind {
525 Record,
526 Tuple,
527}
528
529#[derive(Debug, Clone, PartialEq)]
530pub struct StructFieldDefinition {
531 pub doc: Option<String>,
532 pub attributes: Vec<Attribute>,
533 pub name: EcoString,
534 pub name_span: Span,
535 pub annotation: Annotation,
536 pub visibility: Visibility,
537 pub ty: Type,
538 pub embedded: bool,
539}
540
541#[derive(Debug, Clone, PartialEq)]
542pub struct StructFieldAssignment {
543 pub name: EcoString,
544 pub name_span: Span,
545 pub value: Box<Expression>,
546}
547
548#[derive(Debug, Clone, PartialEq)]
549pub enum StructSpread {
550 None,
551 From(Box<Expression>),
552 ZeroFill { span: Span },
553}
554
555impl StructSpread {
556 pub fn is_none(&self) -> bool {
557 matches!(self, Self::None)
558 }
559
560 pub fn is_some(&self) -> bool {
561 !self.is_none()
562 }
563
564 pub fn span(&self) -> Option<Span> {
565 match self {
566 Self::None => None,
567 Self::From(e) => Some(e.get_span()),
568 Self::ZeroFill { span } => Some(*span),
569 }
570 }
571
572 pub fn as_expression(&self) -> Option<&Expression> {
573 match self {
574 Self::From(e) => Some(e),
575 Self::None | Self::ZeroFill { .. } => None,
576 }
577 }
578}
579
580#[derive(Debug, Clone, PartialEq)]
581#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
582pub enum Annotation {
583 Constructor {
584 name: EcoString,
585 params: Vec<Self>,
586 span: Span,
587 },
588 Function {
589 params: Vec<Self>,
590 return_type: Box<Self>,
591 span: Span,
592 },
593 Tuple {
594 elements: Vec<Self>,
595 span: Span,
596 },
597 Unknown,
598 Opaque {
599 span: Span,
600 },
601}
602
603impl Annotation {
604 pub fn unit() -> Self {
605 Self::Constructor {
606 name: "Unit".into(),
607 params: vec![],
608 span: Span::dummy(),
609 }
610 }
611
612 pub fn get_span(&self) -> Span {
613 match self {
614 Self::Constructor { span, .. } => *span,
615 Self::Function { span, .. } => *span,
616 Self::Tuple { span, .. } => *span,
617 Self::Opaque { span } => *span,
618 Self::Unknown => Span::dummy(),
619 }
620 }
621
622 pub fn get_name(&self) -> Option<String> {
623 match self {
624 Self::Constructor { name, .. } => Some(name.to_string()),
625 _ => None,
626 }
627 }
628
629 pub fn is_unit(&self) -> bool {
630 matches!(self, Self::Constructor { name, params, .. } if name == "Unit" && params.is_empty())
631 }
632
633 pub fn is_unknown(&self) -> bool {
634 matches!(self, Self::Unknown)
635 }
636
637 pub fn is_opaque(&self) -> bool {
638 matches!(self, Self::Opaque { .. })
639 }
640}
641
642#[derive(Debug, Clone, PartialEq)]
643pub struct Generic {
644 pub name: EcoString,
645 pub bounds: Vec<Annotation>,
646 pub span: Span,
647}
648
649#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
650#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
651pub struct Span {
652 pub file_id: u32,
653 pub byte_offset: u32,
654 pub byte_length: u32,
655}
656
657impl Span {
658 pub fn new(file_id: u32, byte_offset: u32, byte_length: u32) -> Self {
659 Span {
660 file_id,
661 byte_offset,
662 byte_length,
663 }
664 }
665
666 pub fn dummy() -> Self {
667 Span {
668 file_id: 0,
669 byte_offset: 0,
670 byte_length: 0,
671 }
672 }
673
674 pub fn is_dummy(&self) -> bool {
675 self.byte_length == 0
676 }
677
678 pub fn end(&self) -> u32 {
679 self.byte_offset + self.byte_length
680 }
681
682 pub fn merge(self, other: Span) -> Span {
683 Span::new(
684 self.file_id,
685 self.byte_offset,
686 other.end() - self.byte_offset,
687 )
688 }
689}
690
691#[derive(Debug, Clone, PartialEq)]
692#[allow(clippy::large_enum_variant)]
693pub enum Expression {
694 Literal {
695 literal: Literal,
696 ty: Type,
697 span: Span,
698 },
699 Function {
700 doc: Option<String>,
701 attributes: Vec<Attribute>,
702 name: EcoString,
703 name_span: Span,
704 generics: Vec<Generic>,
705 params: Vec<Binding>,
706 return_annotation: Annotation,
707 return_type: Type,
708 visibility: Visibility,
709 body: Box<Expression>,
710 ty: Type,
711 span: Span,
712 },
713 Lambda {
714 params: Vec<Binding>,
715 return_annotation: Annotation,
716 body: Box<Expression>,
717 ty: Type,
718 span: Span,
719 },
720 Block {
721 items: Vec<Expression>,
722 ty: Type,
723 span: Span,
724 },
725 Let {
726 binding: Box<Binding>,
727 value: Box<Expression>,
728 mutable: bool,
729 mut_span: Option<Span>,
730 else_block: Option<Box<Expression>>,
731 else_span: Option<Span>,
732 typed_pattern: Option<TypedPattern>,
733 ty: Type,
734 span: Span,
735 },
736 Identifier {
737 value: EcoString,
738 ty: Type,
739 span: Span,
740 binding_id: Option<BindingId>,
741 qualified: Option<EcoString>,
742 },
743 Call {
744 expression: Box<Expression>,
745 args: Vec<Expression>,
746 spread: Box<Option<Expression>>,
747 type_args: Vec<Annotation>,
748 ty: Type,
749 span: Span,
750 call_kind: Option<CallKind>,
751 },
752 If {
753 condition: Box<Expression>,
754 consequence: Box<Expression>,
755 alternative: Box<Expression>,
756 ty: Type,
757 span: Span,
758 },
759 IfLet {
760 pattern: Pattern,
761 scrutinee: Box<Expression>,
762 consequence: Box<Expression>,
763 alternative: Box<Expression>,
764 typed_pattern: Option<TypedPattern>,
765 else_span: Option<Span>,
766 ty: Type,
767 span: Span,
768 },
769 Match {
770 subject: Box<Expression>,
771 arms: Vec<MatchArm>,
772 origin: MatchOrigin,
773 ty: Type,
774 span: Span,
775 },
776 Tuple {
777 elements: Vec<Expression>,
778 ty: Type,
779 span: Span,
780 },
781 StructCall {
782 name: EcoString,
783 field_assignments: Vec<StructFieldAssignment>,
784 spread: StructSpread,
785 ty: Type,
786 span: Span,
787 },
788 DotAccess {
789 expression: Box<Expression>,
790 member: EcoString,
791 ty: Type,
792 span: Span,
793 dot_access_kind: Option<DotAccessKind>,
794 receiver_coercion: Option<ReceiverCoercion>,
795 },
796 Assignment {
797 target: Box<Expression>,
798 value: Box<Expression>,
799 compound_operator: Option<BinaryOperator>,
800 span: Span,
801 },
802 Return {
803 expression: Box<Expression>,
804 ty: Type,
805 span: Span,
806 },
807 Propagate {
808 expression: Box<Expression>,
809 ty: Type,
810 span: Span,
811 },
812 TryBlock {
813 items: Vec<Expression>,
814 ty: Type,
815 try_keyword_span: Span,
816 span: Span,
817 },
818 RecoverBlock {
819 items: Vec<Expression>,
820 ty: Type,
821 recover_keyword_span: Span,
822 span: Span,
823 },
824 ImplBlock {
825 annotation: Annotation,
826 receiver_name: EcoString,
827 methods: Vec<Expression>,
828 generics: Vec<Generic>,
829 ty: Type,
830 span: Span,
831 },
832 Binary {
833 operator: BinaryOperator,
834 left: Box<Expression>,
835 right: Box<Expression>,
836 ty: Type,
837 span: Span,
838 },
839 Unary {
840 operator: UnaryOperator,
841 expression: Box<Expression>,
842 ty: Type,
843 span: Span,
844 },
845 Paren {
846 expression: Box<Expression>,
847 ty: Type,
848 span: Span,
849 },
850 Const {
851 doc: Option<String>,
852 identifier: EcoString,
853 identifier_span: Span,
854 annotation: Option<Annotation>,
855 expression: Box<Expression>,
856 visibility: Visibility,
857 ty: Type,
858 span: Span,
859 },
860 VariableDeclaration {
861 doc: Option<String>,
862 name: EcoString,
863 name_span: Span,
864 annotation: Annotation,
865 visibility: Visibility,
866 ty: Type,
867 span: Span,
868 },
869 RawGo {
870 text: String,
871 },
872 Loop {
873 body: Box<Expression>,
874 ty: Type,
875 span: Span,
876 needs_label: bool,
877 },
878 While {
879 condition: Box<Expression>,
880 body: Box<Expression>,
881 span: Span,
882 needs_label: bool,
883 },
884 WhileLet {
885 pattern: Pattern,
886 scrutinee: Box<Expression>,
887 body: Box<Expression>,
888 typed_pattern: Option<TypedPattern>,
889 span: Span,
890 needs_label: bool,
891 },
892 For {
893 binding: Box<Binding>,
894 iterable: Box<Expression>,
895 body: Box<Expression>,
896 span: Span,
897 needs_label: bool,
898 binding_id: Option<BindingId>,
899 },
900 Break {
901 value: Option<Box<Expression>>,
902 span: Span,
903 },
904 Continue {
905 span: Span,
906 },
907 Enum {
908 doc: Option<String>,
909 attributes: Vec<Attribute>,
910 name: EcoString,
911 name_span: Span,
912 generics: Vec<Generic>,
913 variants: Vec<EnumVariant>,
914 visibility: Visibility,
915 span: Span,
916 },
917 Struct {
918 doc: Option<String>,
919 attributes: Vec<Attribute>,
920 name: EcoString,
921 name_span: Span,
922 generics: Vec<Generic>,
923 fields: Vec<StructFieldDefinition>,
924 kind: StructKind,
925 visibility: Visibility,
926 span: Span,
927 },
928 TypeAlias {
929 doc: Option<String>,
930 attributes: Vec<Attribute>,
931 name: EcoString,
932 name_span: Span,
933 generics: Vec<Generic>,
934 annotation: Annotation,
935 ty: Type,
936 visibility: Visibility,
937 span: Span,
938 },
939 ModuleImport {
940 name: EcoString,
941 name_span: Span,
942 alias: Option<ImportAlias>,
943 span: Span,
944 },
945 Reference {
946 expression: Box<Expression>,
947 ty: Type,
948 span: Span,
949 },
950 Interface {
951 doc: Option<String>,
952 name: EcoString,
953 name_span: Span,
954 generics: Vec<Generic>,
955 parents: Vec<ParentInterface>,
956 method_signatures: Vec<Expression>,
957 visibility: Visibility,
958 span: Span,
959 },
960 IndexedAccess {
961 expression: Box<Expression>,
962 index: Box<Expression>,
963 ty: Type,
964 span: Span,
965 from_colon_syntax: bool,
966 },
967 Task {
968 expression: Box<Expression>,
969 ty: Type,
970 span: Span,
971 },
972 Defer {
973 expression: Box<Expression>,
974 ty: Type,
975 span: Span,
976 },
977 Select {
978 arms: Vec<SelectArm>,
979 ty: Type,
980 span: Span,
981 },
982 Unit {
983 ty: Type,
984 span: Span,
985 },
986 Range {
987 start: Option<Box<Expression>>,
988 end: Option<Box<Expression>>,
989 inclusive: bool,
990 ty: Type,
991 span: Span,
992 },
993 Cast {
994 expression: Box<Expression>,
995 target_type: Annotation,
996 ty: Type,
997 span: Span,
998 },
999 NoOp,
1000}
1001
1002#[derive(Clone, Copy)]
1004pub enum ExpressionKind {
1005 Literal,
1006 Function,
1007 Lambda,
1008 Block,
1009 Let,
1010 Identifier,
1011 Call,
1012 If,
1013 IfLet,
1014 Match,
1015 Tuple,
1016 StructCall,
1017 DotAccess,
1018 Assignment,
1019 Return,
1020 Propagate,
1021 TryBlock,
1022 RecoverBlock,
1023 ImplBlock,
1024 Binary,
1025 Unary,
1026 Paren,
1027 Const,
1028 VariableDeclaration,
1029 RawGo,
1030 Loop,
1031 While,
1032 WhileLet,
1033 For,
1034 Break,
1035 Continue,
1036 Enum,
1037 Struct,
1038 TypeAlias,
1039 ModuleImport,
1040 Reference,
1041 Interface,
1042 IndexedAccess,
1043 Task,
1044 Defer,
1045 Select,
1046 Unit,
1047 Range,
1048 Cast,
1049 NoOp,
1050}
1051
1052impl ExpressionKind {
1053 pub const COUNT: usize = ExpressionKind::NoOp as usize + 1;
1055}
1056
1057impl Expression {
1058 pub fn kind(&self) -> ExpressionKind {
1059 match self {
1060 Expression::Literal { .. } => ExpressionKind::Literal,
1061 Expression::Function { .. } => ExpressionKind::Function,
1062 Expression::Lambda { .. } => ExpressionKind::Lambda,
1063 Expression::Block { .. } => ExpressionKind::Block,
1064 Expression::Let { .. } => ExpressionKind::Let,
1065 Expression::Identifier { .. } => ExpressionKind::Identifier,
1066 Expression::Call { .. } => ExpressionKind::Call,
1067 Expression::If { .. } => ExpressionKind::If,
1068 Expression::IfLet { .. } => ExpressionKind::IfLet,
1069 Expression::Match { .. } => ExpressionKind::Match,
1070 Expression::Tuple { .. } => ExpressionKind::Tuple,
1071 Expression::StructCall { .. } => ExpressionKind::StructCall,
1072 Expression::DotAccess { .. } => ExpressionKind::DotAccess,
1073 Expression::Assignment { .. } => ExpressionKind::Assignment,
1074 Expression::Return { .. } => ExpressionKind::Return,
1075 Expression::Propagate { .. } => ExpressionKind::Propagate,
1076 Expression::TryBlock { .. } => ExpressionKind::TryBlock,
1077 Expression::RecoverBlock { .. } => ExpressionKind::RecoverBlock,
1078 Expression::ImplBlock { .. } => ExpressionKind::ImplBlock,
1079 Expression::Binary { .. } => ExpressionKind::Binary,
1080 Expression::Unary { .. } => ExpressionKind::Unary,
1081 Expression::Paren { .. } => ExpressionKind::Paren,
1082 Expression::Const { .. } => ExpressionKind::Const,
1083 Expression::VariableDeclaration { .. } => ExpressionKind::VariableDeclaration,
1084 Expression::RawGo { .. } => ExpressionKind::RawGo,
1085 Expression::Loop { .. } => ExpressionKind::Loop,
1086 Expression::While { .. } => ExpressionKind::While,
1087 Expression::WhileLet { .. } => ExpressionKind::WhileLet,
1088 Expression::For { .. } => ExpressionKind::For,
1089 Expression::Break { .. } => ExpressionKind::Break,
1090 Expression::Continue { .. } => ExpressionKind::Continue,
1091 Expression::Enum { .. } => ExpressionKind::Enum,
1092 Expression::Struct { .. } => ExpressionKind::Struct,
1093 Expression::TypeAlias { .. } => ExpressionKind::TypeAlias,
1094 Expression::ModuleImport { .. } => ExpressionKind::ModuleImport,
1095 Expression::Reference { .. } => ExpressionKind::Reference,
1096 Expression::Interface { .. } => ExpressionKind::Interface,
1097 Expression::IndexedAccess { .. } => ExpressionKind::IndexedAccess,
1098 Expression::Task { .. } => ExpressionKind::Task,
1099 Expression::Defer { .. } => ExpressionKind::Defer,
1100 Expression::Select { .. } => ExpressionKind::Select,
1101 Expression::Unit { .. } => ExpressionKind::Unit,
1102 Expression::Range { .. } => ExpressionKind::Range,
1103 Expression::Cast { .. } => ExpressionKind::Cast,
1104 Expression::NoOp => ExpressionKind::NoOp,
1105 }
1106 }
1107
1108 pub fn is_noop(&self) -> bool {
1109 matches!(self, Expression::NoOp)
1110 }
1111
1112 pub fn is_block(&self) -> bool {
1113 matches!(self, Expression::Block { .. })
1114 }
1115
1116 pub fn is_range(&self) -> bool {
1117 matches!(self, Expression::Range { .. })
1118 }
1119
1120 pub fn is_conditional(&self) -> bool {
1121 matches!(
1122 self,
1123 Expression::If { .. }
1124 | Expression::IfLet { .. }
1125 | Expression::Match {
1126 origin: MatchOrigin::IfLet { .. },
1127 ..
1128 }
1129 )
1130 }
1131
1132 pub fn is_control_flow(&self) -> bool {
1133 matches!(
1134 self,
1135 Expression::If { .. }
1136 | Expression::Match { .. }
1137 | Expression::Select { .. }
1138 | Expression::For { .. }
1139 | Expression::While { .. }
1140 | Expression::WhileLet { .. }
1141 | Expression::Loop { .. }
1142 )
1143 }
1144
1145 pub fn callee_name(&self) -> Option<String> {
1146 let Expression::Call { expression, .. } = self else {
1147 return None;
1148 };
1149 match expression.as_ref() {
1150 Expression::Identifier { value, .. } => Some(value.to_string()),
1151 Expression::DotAccess {
1152 expression: base,
1153 member,
1154 ..
1155 } => {
1156 if let Expression::Identifier { value, .. } = base.as_ref() {
1157 Some(format!("{}.{}", value, member))
1158 } else {
1159 None
1160 }
1161 }
1162 _ => None,
1163 }
1164 }
1165
1166 pub fn to_function_signature(&self) -> FunctionDefinition {
1167 match self {
1168 Expression::Function {
1169 name,
1170 name_span,
1171 generics,
1172 params,
1173 return_annotation,
1174 return_type,
1175 ty,
1176 ..
1177 } => FunctionDefinition {
1178 name: name.clone(),
1179 name_span: *name_span,
1180 generics: generics.clone(),
1181 params: params.clone(),
1182 body: Box::new(Expression::NoOp),
1183 return_type: return_type.clone(),
1184 annotation: return_annotation.clone(),
1185 ty: ty.clone(),
1186 },
1187 _ => panic!("to_function_signature called on non-Function expression"),
1188 }
1189 }
1190
1191 pub fn to_function_definition(&self) -> FunctionDefinition {
1192 match self {
1193 Expression::Function {
1194 name,
1195 name_span,
1196 generics,
1197 params,
1198 return_annotation,
1199 return_type,
1200 body,
1201 ty,
1202 ..
1203 } => FunctionDefinition {
1204 name: name.clone(),
1205 name_span: *name_span,
1206 generics: generics.clone(),
1207 params: params.clone(),
1208 body: body.clone(),
1209 return_type: return_type.clone(),
1210 annotation: return_annotation.clone(),
1211 ty: ty.clone(),
1212 },
1213 _ => panic!("to_function_definition called on non-Function expression"),
1214 }
1215 }
1216
1217 pub fn as_option_constructor(&self) -> Option<std::result::Result<(), ()>> {
1218 let variant = match self {
1219 Expression::Identifier { value, .. } => Some(value.as_str()),
1220 _ => None,
1221 }?;
1222
1223 match variant {
1224 "Option.Some" | "Some" => Some(Ok(())),
1225 "Option.None" | "None" => Some(Err(())),
1226 _ => None,
1227 }
1228 }
1229
1230 pub fn is_none_literal(&self) -> bool {
1231 matches!(self.as_option_constructor(), Some(Err(())))
1232 }
1233
1234 pub fn as_result_constructor(&self) -> Option<std::result::Result<(), ()>> {
1235 let variant = match self {
1236 Expression::Identifier { value, .. } => Some(value.as_str()),
1237 _ => None,
1238 }?;
1239
1240 match variant {
1241 "Result.Ok" | "Ok" => Some(Ok(())),
1242 "Result.Err" | "Err" => Some(Err(())),
1243 _ => None,
1244 }
1245 }
1246
1247 pub fn as_partial_constructor(&self) -> Option<&'static str> {
1248 let variant = match self {
1249 Expression::Identifier { value, .. } => Some(value.as_str()),
1250 _ => None,
1251 }?;
1252
1253 match variant {
1254 "Partial.Ok" => Some("Ok"),
1255 "Partial.Err" => Some("Err"),
1256 "Partial.Both" => Some("Both"),
1257 _ => None,
1258 }
1259 }
1260
1261 pub fn get_type(&self) -> Type {
1262 match self {
1263 Self::Literal { ty, .. }
1264 | Self::Function { ty, .. }
1265 | Self::Lambda { ty, .. }
1266 | Self::Block { ty, .. }
1267 | Self::Let { ty, .. }
1268 | Self::Identifier { ty, .. }
1269 | Self::Call { ty, .. }
1270 | Self::If { ty, .. }
1271 | Self::IfLet { ty, .. }
1272 | Self::Match { ty, .. }
1273 | Self::Tuple { ty, .. }
1274 | Self::StructCall { ty, .. }
1275 | Self::DotAccess { ty, .. }
1276 | Self::Return { ty, .. }
1277 | Self::Propagate { ty, .. }
1278 | Self::TryBlock { ty, .. }
1279 | Self::RecoverBlock { ty, .. }
1280 | Self::Binary { ty, .. }
1281 | Self::Paren { ty, .. }
1282 | Self::Unary { ty, .. }
1283 | Self::Const { ty, .. }
1284 | Self::VariableDeclaration { ty, .. }
1285 | Self::Defer { ty, .. }
1286 | Self::Reference { ty, .. }
1287 | Self::IndexedAccess { ty, .. }
1288 | Self::Task { ty, .. }
1289 | Self::Select { ty, .. }
1290 | Self::Unit { ty, .. }
1291 | Self::Loop { ty, .. }
1292 | Self::Range { ty, .. }
1293 | Self::Cast { ty, .. } => ty.clone(),
1294 Self::Enum { .. }
1295 | Self::Struct { .. }
1296 | Self::Assignment { .. }
1297 | Self::ImplBlock { .. }
1298 | Self::TypeAlias { .. }
1299 | Self::ModuleImport { .. }
1300 | Self::Interface { .. }
1301 | Self::NoOp
1302 | Self::RawGo { .. }
1303 | Self::While { .. }
1304 | Self::WhileLet { .. }
1305 | Self::For { .. } => Type::ignored(),
1306 Self::Break { .. } | Self::Continue { .. } => Type::Never,
1307 }
1308 }
1309
1310 pub fn get_span(&self) -> Span {
1311 match self {
1312 Self::Literal { span, .. }
1313 | Self::Function { span, .. }
1314 | Self::Lambda { span, .. }
1315 | Self::Block { span, .. }
1316 | Self::Let { span, .. }
1317 | Self::Identifier { span, .. }
1318 | Self::Call { span, .. }
1319 | Self::If { span, .. }
1320 | Self::IfLet { span, .. }
1321 | Self::Match { span, .. }
1322 | Self::Tuple { span, .. }
1323 | Self::Enum { span, .. }
1324 | Self::Struct { span, .. }
1325 | Self::StructCall { span, .. }
1326 | Self::DotAccess { span, .. }
1327 | Self::Assignment { span, .. }
1328 | Self::Return { span, .. }
1329 | Self::Propagate { span, .. }
1330 | Self::TryBlock { span, .. }
1331 | Self::RecoverBlock { span, .. }
1332 | Self::ImplBlock { span, .. }
1333 | Self::Binary { span, .. }
1334 | Self::Paren { span, .. }
1335 | Self::Unary { span, .. }
1336 | Self::Const { span, .. }
1337 | Self::VariableDeclaration { span, .. }
1338 | Self::Defer { span, .. }
1339 | Self::Reference { span, .. }
1340 | Self::IndexedAccess { span, .. }
1341 | Self::Task { span, .. }
1342 | Self::Select { span, .. }
1343 | Self::Loop { span, .. }
1344 | Self::TypeAlias { span, .. }
1345 | Self::ModuleImport { span, .. }
1346 | Self::Interface { span, .. }
1347 | Self::Unit { span, .. }
1348 | Self::While { span, .. }
1349 | Self::WhileLet { span, .. }
1350 | Self::For { span, .. }
1351 | Self::Break { span, .. }
1352 | Self::Continue { span, .. }
1353 | Self::Range { span, .. }
1354 | Self::Cast { span, .. } => *span,
1355 Self::NoOp | Self::RawGo { .. } => Span::dummy(),
1356 }
1357 }
1358
1359 pub fn contains_break(&self) -> bool {
1360 match self {
1361 Expression::Break { .. } => true,
1362
1363 Expression::Loop { .. }
1364 | Expression::While { .. }
1365 | Expression::WhileLet { .. }
1366 | Expression::For { .. } => false,
1367
1368 Expression::Block { items, .. } => items.iter().any(Self::contains_break),
1369
1370 Expression::TryBlock { items, .. } => items.iter().any(Self::contains_break),
1371 Expression::RecoverBlock { items, .. } => items.iter().any(Self::contains_break),
1372
1373 Expression::If {
1374 condition,
1375 consequence,
1376 alternative,
1377 ..
1378 } => {
1379 condition.contains_break()
1380 || consequence.contains_break()
1381 || alternative.contains_break()
1382 }
1383
1384 Expression::IfLet {
1385 scrutinee,
1386 consequence,
1387 alternative,
1388 ..
1389 } => {
1390 scrutinee.contains_break()
1391 || consequence.contains_break()
1392 || alternative.contains_break()
1393 }
1394
1395 Expression::Match { subject, arms, .. } => {
1396 subject.contains_break() || arms.iter().any(|arm| arm.expression.contains_break())
1397 }
1398
1399 Expression::Paren { expression, .. } => expression.contains_break(),
1400
1401 Expression::Binary { left, right, .. } => {
1402 left.contains_break() || right.contains_break()
1403 }
1404
1405 Expression::Unary { expression, .. } => expression.contains_break(),
1406
1407 Expression::Call {
1408 expression,
1409 args,
1410 spread,
1411 ..
1412 } => {
1413 expression.contains_break()
1414 || args.iter().any(Self::contains_break)
1415 || spread.as_ref().as_ref().is_some_and(Self::contains_break)
1416 }
1417
1418 Expression::Function { .. } | Expression::Lambda { .. } => false,
1419
1420 Expression::Select { arms, .. } => arms.iter().any(|arm| match &arm.pattern {
1421 SelectArmPattern::Receive { body, .. } => body.contains_break(),
1422 SelectArmPattern::Send { body, .. } => body.contains_break(),
1423 SelectArmPattern::MatchReceive { arms, .. } => {
1424 arms.iter().any(|a| a.expression.contains_break())
1425 }
1426 SelectArmPattern::WildCard { body } => body.contains_break(),
1427 }),
1428
1429 Expression::Cast { expression, .. } => expression.contains_break(),
1430
1431 Expression::Let {
1432 value, else_block, ..
1433 } => value.contains_break() || else_block.as_ref().is_some_and(|e| e.contains_break()),
1434
1435 Expression::Assignment { value, .. } => value.contains_break(),
1436
1437 _ => false,
1438 }
1439 }
1440
1441 pub fn diverges(&self) -> Option<DeadCodeCause> {
1442 match self {
1443 Expression::Return { .. } => Some(DeadCodeCause::Return),
1444 Expression::Break { .. } => Some(DeadCodeCause::Break),
1445 Expression::Continue { .. } => Some(DeadCodeCause::Continue),
1446
1447 Expression::If {
1448 consequence,
1449 alternative,
1450 ..
1451 } => {
1452 if consequence.diverges().is_some() && alternative.diverges().is_some() {
1453 Some(DeadCodeCause::DivergingIf)
1454 } else {
1455 None
1456 }
1457 }
1458
1459 Expression::IfLet {
1460 consequence,
1461 alternative,
1462 ..
1463 } => {
1464 if consequence.diverges().is_some() && alternative.diverges().is_some() {
1465 Some(DeadCodeCause::DivergingIf)
1466 } else {
1467 None
1468 }
1469 }
1470
1471 Expression::Match { arms, .. } => {
1472 if !arms.is_empty() && arms.iter().all(|arm| arm.expression.diverges().is_some()) {
1473 Some(DeadCodeCause::DivergingMatch)
1474 } else {
1475 None
1476 }
1477 }
1478
1479 Expression::Block { items, .. } => {
1480 for item in items {
1481 if let Some(cause) = item.diverges() {
1482 return Some(cause);
1483 }
1484 }
1485 None
1486 }
1487
1488 Expression::TryBlock { items, .. } | Expression::RecoverBlock { items, .. } => {
1489 for item in items {
1490 if let Some(cause) = item.diverges() {
1491 return Some(cause);
1492 }
1493 }
1494 None
1495 }
1496
1497 Expression::Paren { expression, .. } | Expression::Cast { expression, .. } => {
1498 expression.diverges()
1499 }
1500
1501 Expression::Loop { body, .. } => {
1502 if !body.contains_break() {
1503 Some(DeadCodeCause::InfiniteLoop)
1504 } else {
1505 None
1506 }
1507 }
1508
1509 Expression::Call { ty, .. } if ty.is_never() => Some(DeadCodeCause::DivergingCall),
1510
1511 _ => None,
1512 }
1513 }
1514
1515 pub fn children(&self) -> Children<'_> {
1520 match self {
1521 Expression::Literal { literal, .. } => match literal {
1522 Literal::Slice(elements) => elements.iter().collect(),
1523 Literal::FormatString(parts) => parts
1524 .iter()
1525 .filter_map(|p| match p {
1526 FormatStringPart::Expression(e) => Some(e.as_ref()),
1527 FormatStringPart::Text(_) => None,
1528 })
1529 .collect(),
1530 _ => Children::new(),
1531 },
1532 Expression::Function { body, .. } => children![body],
1533 Expression::Lambda { body, .. } => children![body],
1534 Expression::Block { items, .. } => items.iter().collect(),
1535 Expression::Let {
1536 value, else_block, ..
1537 } => {
1538 let mut c = children![value.as_ref()];
1539 if let Some(eb) = else_block {
1540 c.push(eb);
1541 }
1542 c
1543 }
1544 Expression::Identifier { .. } => Children::new(),
1545 Expression::Call {
1546 expression,
1547 args,
1548 spread,
1549 ..
1550 } => {
1551 let mut c = children![expression.as_ref()];
1552 c.extend(args);
1553 if let Some(s) = spread.as_ref() {
1554 c.push(s);
1555 }
1556 c
1557 }
1558 Expression::If {
1559 condition,
1560 consequence,
1561 alternative,
1562 ..
1563 } => children![condition, consequence, alternative],
1564 Expression::IfLet {
1565 scrutinee,
1566 consequence,
1567 alternative,
1568 ..
1569 } => children![scrutinee, consequence, alternative],
1570 Expression::Match { subject, arms, .. } => {
1571 let mut c = children![subject.as_ref()];
1572 for arm in arms {
1573 if let Some(guard) = &arm.guard {
1574 c.push(guard);
1575 }
1576 c.push(&arm.expression);
1577 }
1578 c
1579 }
1580 Expression::Tuple { elements, .. } => elements.iter().collect(),
1581 Expression::StructCall {
1582 field_assignments,
1583 spread,
1584 ..
1585 } => {
1586 let mut c: Children = field_assignments.iter().map(|f| f.value.as_ref()).collect();
1587 if let Some(s) = spread.as_expression() {
1588 c.push(s);
1589 }
1590 c
1591 }
1592 Expression::DotAccess { expression, .. } => children![expression],
1593 Expression::Assignment { target, value, .. } => children![target, value],
1594 Expression::Return { expression, .. } => children![expression],
1595 Expression::Propagate { expression, .. } => children![expression],
1596 Expression::TryBlock { items, .. } | Expression::RecoverBlock { items, .. } => {
1597 items.iter().collect()
1598 }
1599 Expression::ImplBlock { methods, .. } => methods.iter().collect(),
1600 Expression::Binary { left, right, .. } => children![left, right],
1601 Expression::Unary { expression, .. } => children![expression],
1602 Expression::Paren { expression, .. } => children![expression],
1603 Expression::Const { expression, .. } => children![expression],
1604 Expression::Loop { body, .. } => children![body],
1605 Expression::While {
1606 condition, body, ..
1607 } => children![condition, body],
1608 Expression::WhileLet {
1609 scrutinee, body, ..
1610 } => children![scrutinee, body],
1611 Expression::For { iterable, body, .. } => children![iterable, body],
1612 Expression::Break { value, .. } => value
1613 .as_ref()
1614 .map(|v| children![v.as_ref()])
1615 .unwrap_or_default(),
1616 Expression::Reference { expression, .. } => children![expression],
1617 Expression::IndexedAccess {
1618 expression, index, ..
1619 } => children![expression, index],
1620 Expression::Task { expression, .. } => children![expression],
1621 Expression::Defer { expression, .. } => children![expression],
1622 Expression::Select { arms, .. } => {
1623 let mut c = Children::new();
1624 for arm in arms {
1625 match &arm.pattern {
1626 SelectArmPattern::Receive {
1627 receive_expression,
1628 body,
1629 ..
1630 } => {
1631 c.push(receive_expression.as_ref());
1632 c.push(body.as_ref());
1633 }
1634 SelectArmPattern::Send {
1635 send_expression,
1636 body,
1637 } => {
1638 c.push(send_expression.as_ref());
1639 c.push(body.as_ref());
1640 }
1641 SelectArmPattern::MatchReceive {
1642 receive_expression,
1643 arms: match_arms,
1644 } => {
1645 c.push(receive_expression.as_ref());
1646 for ma in match_arms {
1647 if let Some(guard) = &ma.guard {
1648 c.push(guard);
1649 }
1650 c.push(&ma.expression);
1651 }
1652 }
1653 SelectArmPattern::WildCard { body } => {
1654 c.push(body.as_ref());
1655 }
1656 }
1657 }
1658 c
1659 }
1660 Expression::Range { start, end, .. } => {
1661 let mut c = Children::new();
1662 if let Some(s) = start {
1663 c.push(s.as_ref());
1664 }
1665 if let Some(e) = end {
1666 c.push(e.as_ref());
1667 }
1668 c
1669 }
1670 Expression::Cast { expression, .. } => children![expression],
1671 Expression::Interface {
1672 method_signatures, ..
1673 } => method_signatures.iter().collect(),
1674 Expression::Unit { .. }
1675 | Expression::Continue { .. }
1676 | Expression::Enum { .. }
1677 | Expression::Struct { .. }
1678 | Expression::TypeAlias { .. }
1679 | Expression::VariableDeclaration { .. }
1680 | Expression::ModuleImport { .. }
1681 | Expression::RawGo { .. }
1682 | Expression::NoOp => Children::new(),
1683 }
1684 }
1685
1686 pub fn unwrap_parens(&self) -> &Expression {
1687 match self {
1688 Expression::Paren { expression, .. } => expression.unwrap_parens(),
1689 other => other,
1690 }
1691 }
1692
1693 pub fn binding_id(&self) -> Option<BindingId> {
1694 match self.unwrap_parens() {
1695 Expression::Identifier { binding_id, .. } => *binding_id,
1696 _ => None,
1697 }
1698 }
1699
1700 pub fn as_integer(&self) -> Option<u64> {
1701 match self.unwrap_parens() {
1702 Expression::Literal {
1703 literal: Literal::Integer { value, .. },
1704 ..
1705 } => Some(*value),
1706 _ => None,
1707 }
1708 }
1709
1710 #[inline]
1712 pub fn deref_inner(&self) -> Option<&Expression> {
1713 match self {
1714 Expression::Unary {
1715 operator: UnaryOperator::Deref,
1716 expression,
1717 ..
1718 } => Some(expression),
1719 _ => None,
1720 }
1721 }
1722
1723 pub fn as_dotted_path(&self) -> Option<String> {
1724 match self {
1725 Expression::Identifier { value, .. } => Some(value.to_string()),
1726 Expression::DotAccess {
1727 expression, member, ..
1728 } => Some(format!("{}.{}", expression.as_dotted_path()?, member)),
1729 _ => None,
1730 }
1731 }
1732
1733 pub fn root_identifier(&self) -> Option<&str> {
1734 match self {
1735 Expression::Identifier { value, .. } => Some(value),
1736 Expression::DotAccess { expression, .. } => expression.root_identifier(),
1737 _ => None,
1738 }
1739 }
1740
1741 pub fn is_empty_collection(&self) -> bool {
1742 matches!(
1743 self,
1744 Expression::Literal {
1745 literal: Literal::Slice(elements),
1746 ..
1747 } if elements.is_empty()
1748 )
1749 }
1750
1751 pub fn is_all_literals(&self) -> bool {
1752 match self.unwrap_parens() {
1753 Expression::Literal { literal, .. } => match literal {
1754 Literal::Slice(elements) => elements.iter().all(|e| e.is_all_literals()),
1755 Literal::FormatString(parts) => parts.iter().all(|p| match p {
1756 FormatStringPart::Text(_) => true,
1757 FormatStringPart::Expression(e) => e.is_all_literals(),
1758 }),
1759 _ => true,
1760 },
1761 Expression::Tuple { elements, .. } => elements.iter().all(|e| e.is_all_literals()),
1762 Expression::Unit { .. } => true,
1763 _ => false,
1764 }
1765 }
1766
1767 pub fn get_var_name(&self) -> Option<String> {
1768 match self {
1769 Expression::Identifier { value, .. } => Some(value.to_string()),
1770 Expression::DotAccess { expression, .. } => expression.get_var_name(),
1771 Expression::Assignment { target, .. } => target.get_var_name(),
1772 Expression::IndexedAccess { expression, .. } => expression.get_var_name(),
1773 Expression::Paren { expression, .. } => expression.get_var_name(),
1774 Expression::Reference { expression, .. } => expression.get_var_name(),
1775 Expression::Unary {
1776 operator,
1777 expression,
1778 ..
1779 } => {
1780 if operator == &UnaryOperator::Deref {
1781 expression.get_var_name()
1782 } else {
1783 None
1784 }
1785 }
1786 _ => None,
1787 }
1788 }
1789
1790 pub fn is_function(&self) -> bool {
1791 matches!(self, Expression::Function { .. })
1792 }
1793
1794 pub fn set_public(self) -> Self {
1795 match self {
1796 Expression::Enum {
1797 doc,
1798 attributes,
1799 name,
1800 name_span,
1801 generics,
1802 variants,
1803 span,
1804 ..
1805 } => Expression::Enum {
1806 doc,
1807 attributes,
1808 name,
1809 name_span,
1810 generics,
1811 variants,
1812 visibility: Visibility::Public,
1813 span,
1814 },
1815 Expression::Struct {
1816 doc,
1817 attributes,
1818 name,
1819 name_span,
1820 generics,
1821 fields,
1822 kind,
1823 span,
1824 ..
1825 } => {
1826 let fields = if kind == StructKind::Tuple {
1827 fields
1828 .into_iter()
1829 .map(|f| StructFieldDefinition {
1830 visibility: Visibility::Public,
1831 ..f
1832 })
1833 .collect()
1834 } else {
1835 fields
1836 };
1837 Expression::Struct {
1838 doc,
1839 attributes,
1840 name,
1841 name_span,
1842 generics,
1843 fields,
1844 kind,
1845 visibility: Visibility::Public,
1846 span,
1847 }
1848 }
1849 Expression::Function {
1850 doc,
1851 attributes,
1852 name,
1853 name_span,
1854 generics,
1855 params,
1856 return_annotation,
1857 return_type,
1858 body,
1859 ty,
1860 span,
1861 ..
1862 } => Expression::Function {
1863 doc,
1864 attributes,
1865 name,
1866 name_span,
1867 generics,
1868 params,
1869 return_annotation,
1870 return_type,
1871 visibility: Visibility::Public,
1872 body,
1873 ty,
1874 span,
1875 },
1876 Expression::Const {
1877 doc,
1878 identifier,
1879 identifier_span,
1880 annotation,
1881 expression,
1882 ty,
1883 span,
1884 ..
1885 } => Expression::Const {
1886 doc,
1887 identifier,
1888 identifier_span,
1889 annotation,
1890 expression,
1891 visibility: Visibility::Public,
1892 ty,
1893 span,
1894 },
1895 Expression::VariableDeclaration {
1896 doc,
1897 name,
1898 name_span,
1899 annotation,
1900 ty,
1901 span,
1902 ..
1903 } => Expression::VariableDeclaration {
1904 doc,
1905 name,
1906 name_span,
1907 annotation,
1908 visibility: Visibility::Public,
1909 ty,
1910 span,
1911 },
1912 Expression::TypeAlias {
1913 doc,
1914 attributes,
1915 name,
1916 name_span,
1917 generics,
1918 annotation,
1919 ty,
1920 span,
1921 ..
1922 } => Expression::TypeAlias {
1923 doc,
1924 attributes,
1925 name,
1926 name_span,
1927 generics,
1928 annotation,
1929 ty,
1930 visibility: Visibility::Public,
1931 span,
1932 },
1933 Expression::Interface {
1934 doc,
1935 name,
1936 name_span,
1937 generics,
1938 parents,
1939 method_signatures,
1940 span,
1941 ..
1942 } => Expression::Interface {
1943 doc,
1944 name,
1945 name_span,
1946 generics,
1947 parents,
1948 method_signatures,
1949 visibility: Visibility::Public,
1950 span,
1951 },
1952 expression => expression,
1953 }
1954 }
1955
1956 pub fn has_else(&self) -> bool {
1957 match self {
1958 Self::Block { items, .. } if items.is_empty() => false,
1959 Self::Unit { .. } => false,
1960 Self::If { alternative, .. } | Self::IfLet { alternative, .. } => {
1961 alternative.has_else()
1962 }
1963 _ => true,
1964 }
1965 }
1966}
1967
1968#[derive(Debug, Clone, PartialEq)]
1969pub enum Literal {
1970 Integer {
1971 value: u64,
1972 text: Option<String>,
1973 },
1974 Float {
1975 value: f64,
1976 text: Option<String>,
1977 },
1978 Imaginary(f64),
1980 Boolean(bool),
1981 String {
1982 value: String,
1983 raw: bool,
1984 },
1985 FormatString(Vec<FormatStringPart>),
1986 Char(String),
1987 Slice(Vec<Expression>),
1988}
1989
1990#[derive(Debug, Clone, PartialEq)]
1991pub enum FormatStringPart {
1992 Text(String),
1993 Expression(Box<Expression>),
1994}
1995
1996#[derive(Debug, Clone, PartialEq)]
1997pub enum UnaryOperator {
1998 Negative,
1999 Not,
2000 BitwiseNot,
2001 Deref,
2002}
2003
2004#[derive(Debug, Clone, Copy, PartialEq)]
2005pub enum BinaryOperator {
2006 Addition,
2007 Subtraction,
2008 Multiplication,
2009 Division,
2010 BitwiseAnd,
2011 BitwiseOr,
2012 BitwiseXor,
2013 BitwiseAndNot,
2014 ShiftLeft,
2015 ShiftRight,
2016 LessThan,
2017 LessThanOrEqual,
2018 GreaterThan,
2019 GreaterThanOrEqual,
2020 Remainder,
2021 Equal,
2022 NotEqual,
2023 And,
2024 Or,
2025 Pipeline,
2026}
2027
2028impl BinaryOperator {
2029 pub fn compound_assignment_symbol(&self) -> Option<&'static str> {
2033 match self {
2034 BinaryOperator::Addition => Some("+="),
2035 BinaryOperator::Subtraction => Some("-="),
2036 BinaryOperator::Multiplication => Some("*="),
2037 BinaryOperator::Division => Some("/="),
2038 BinaryOperator::Remainder => Some("%="),
2039 BinaryOperator::BitwiseAnd => Some("&="),
2040 BinaryOperator::BitwiseOr => Some("|="),
2041 BinaryOperator::BitwiseXor => Some("^="),
2042 BinaryOperator::BitwiseAndNot => Some("&^="),
2043 BinaryOperator::ShiftLeft => Some("<<="),
2044 BinaryOperator::ShiftRight => Some(">>="),
2045 _ => None,
2046 }
2047 }
2048}
2049
2050impl std::fmt::Display for BinaryOperator {
2051 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2052 let symbol = match self {
2053 BinaryOperator::Addition => "+",
2054 BinaryOperator::Subtraction => "-",
2055 BinaryOperator::Multiplication => "*",
2056 BinaryOperator::Division => "/",
2057 BinaryOperator::Remainder => "%",
2058 BinaryOperator::BitwiseAnd => "&",
2059 BinaryOperator::BitwiseOr => "|",
2060 BinaryOperator::BitwiseXor => "^",
2061 BinaryOperator::BitwiseAndNot => "&^",
2062 BinaryOperator::ShiftLeft => "<<",
2063 BinaryOperator::ShiftRight => ">>",
2064 BinaryOperator::Equal => "==",
2065 BinaryOperator::NotEqual => "!=",
2066 BinaryOperator::LessThan => "<",
2067 BinaryOperator::LessThanOrEqual => "<=",
2068 BinaryOperator::GreaterThan => ">",
2069 BinaryOperator::GreaterThanOrEqual => ">=",
2070 BinaryOperator::And => "&&",
2071 BinaryOperator::Or => "||",
2072 BinaryOperator::Pipeline => "|>",
2073 };
2074 write!(f, "{}", symbol)
2075 }
2076}
2077
2078#[derive(Debug, Clone, PartialEq)]
2079pub struct ParentInterface {
2080 pub annotation: Annotation,
2081 pub ty: Type,
2082 pub span: Span,
2083 pub impl_keyword_span: Option<Span>,
2084}
2085
2086#[derive(Debug, Clone, Copy, PartialEq)]
2087#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2088pub enum Visibility {
2089 Public,
2090 Private,
2091}
2092
2093impl Visibility {
2094 pub fn is_public(&self) -> bool {
2095 matches!(self, Visibility::Public)
2096 }
2097}
2098
2099#[derive(Debug, Clone, PartialEq)]
2100pub enum ImportAlias {
2101 Named(EcoString, Span),
2102 Blank(Span),
2103}