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