1use crate::node::Node;
2use fe_common::{Span, Spanned};
3use indenter::indented;
4use serde::{Deserialize, Serialize};
5pub use smol_str::SmolStr;
6use std::fmt;
7use std::fmt::Formatter;
8use std::fmt::Write;
9use vec1::Vec1;
10
11#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
12pub struct Module {
13 pub body: Vec<ModuleStmt>,
14}
15
16#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
17pub enum ModuleStmt {
18 Pragma(Node<Pragma>),
19 Use(Node<Use>),
20 TypeAlias(Node<TypeAlias>),
21 Contract(Node<Contract>),
22 Constant(Node<ConstantDecl>),
23 Struct(Node<Struct>),
24 Enum(Node<Enum>),
25 Trait(Node<Trait>),
26 Impl(Node<Impl>),
27 Function(Node<Function>),
28 Attribute(Node<SmolStr>),
29 ParseError(Span),
30}
31
32#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
33pub struct Pragma {
34 pub version_requirement: Node<SmolStr>,
35}
36
37#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
38pub struct Path {
39 pub segments: Vec<Node<SmolStr>>,
40}
41
42impl Path {
43 pub fn remove_last(&self) -> Path {
44 Path {
45 segments: self.segments[0..self.segments.len() - 1].to_vec(),
46 }
47 }
48}
49
50#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
51pub struct Use {
52 pub tree: Node<UseTree>,
53}
54
55#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
56pub enum UseTree {
57 Glob {
58 prefix: Path,
59 },
60 Nested {
61 prefix: Path,
62 children: Vec<Node<UseTree>>,
63 },
64 Simple {
65 path: Path,
66 rename: Option<Node<SmolStr>>,
67 },
68}
69
70#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
71pub struct ConstantDecl {
72 pub name: Node<SmolStr>,
73 pub typ: Node<TypeDesc>,
74 pub value: Node<Expr>,
75 pub pub_qual: Option<Span>,
76}
77
78#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
79pub struct TypeAlias {
80 pub name: Node<SmolStr>,
81 pub typ: Node<TypeDesc>,
82 pub pub_qual: Option<Span>,
83}
84
85#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
86pub struct Contract {
87 pub name: Node<SmolStr>,
88 pub fields: Vec<Node<Field>>,
89 pub body: Vec<ContractStmt>,
90 pub pub_qual: Option<Span>,
91}
92
93#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
94pub struct Struct {
95 pub name: Node<SmolStr>,
96 pub fields: Vec<Node<Field>>,
97 pub functions: Vec<Node<Function>>,
98 pub pub_qual: Option<Span>,
99}
100
101#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
102pub struct Enum {
103 pub name: Node<SmolStr>,
104 pub variants: Vec<Node<Variant>>,
105 pub functions: Vec<Node<Function>>,
106 pub pub_qual: Option<Span>,
107}
108
109#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
110pub struct Trait {
111 pub name: Node<SmolStr>,
112 pub functions: Vec<Node<FunctionSignature>>,
113 pub pub_qual: Option<Span>,
114}
115
116#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
117pub struct Impl {
118 pub impl_trait: Node<SmolStr>,
119 pub receiver: Node<TypeDesc>,
120 pub functions: Vec<Node<Function>>,
121}
122
123#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
124pub enum TypeDesc {
125 Unit,
126 Base {
128 base: SmolStr,
129 },
130 Path(Path),
131 Tuple {
132 items: Vec1<Node<TypeDesc>>,
133 },
134 Generic {
135 base: Node<SmolStr>,
138 args: Node<Vec<GenericArg>>,
139 },
140 SelfType,
141}
142
143#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
144pub enum GenericArg {
145 TypeDesc(Node<TypeDesc>),
146 Int(Node<usize>),
147 ConstExpr(Node<Expr>),
148}
149
150impl Spanned for GenericArg {
151 fn span(&self) -> Span {
152 match self {
153 GenericArg::TypeDesc(node) => node.span,
154 GenericArg::Int(node) => node.span,
155 GenericArg::ConstExpr(node) => node.span,
156 }
157 }
158}
159
160#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
161pub enum GenericParameter {
162 Unbounded(Node<SmolStr>),
163 Bounded {
164 name: Node<SmolStr>,
165 bound: Node<TypeDesc>,
166 },
167}
168
169impl GenericParameter {
170 pub fn name(&self) -> SmolStr {
171 self.name_node().kind
172 }
173
174 pub fn name_node(&self) -> Node<SmolStr> {
175 match self {
176 GenericParameter::Unbounded(node) => node.clone(),
177 GenericParameter::Bounded { name, .. } => name.clone(),
178 }
179 }
180}
181
182impl Spanned for GenericParameter {
183 fn span(&self) -> Span {
184 match self {
185 GenericParameter::Unbounded(node) => node.span,
186 GenericParameter::Bounded { name, bound } => name.span + bound.span,
187 }
188 }
189}
190
191#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
193pub struct Field {
194 pub is_pub: bool,
195 pub is_const: bool,
196 pub attributes: Vec<Node<SmolStr>>,
197 pub name: Node<SmolStr>,
198 pub typ: Node<TypeDesc>,
199 pub value: Option<Node<Expr>>,
200}
201
202#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
204pub struct Variant {
205 pub name: Node<SmolStr>,
206 pub kind: VariantKind,
207}
208
209#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
211pub enum VariantKind {
212 Unit,
222
223 Tuple(Vec<Node<TypeDesc>>),
233}
234
235#[allow(clippy::large_enum_variant)]
236#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
237pub enum ContractStmt {
238 Function(Node<Function>),
239}
240
241#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
242pub struct FunctionSignature {
243 pub pub_: Option<Span>,
245 pub unsafe_: Option<Span>,
246 pub name: Node<SmolStr>,
247 pub generic_params: Node<Vec<GenericParameter>>,
248 pub args: Vec<Node<FunctionArg>>,
249 pub return_type: Option<Node<TypeDesc>>,
250}
251
252#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
253pub struct Function {
254 pub sig: Node<FunctionSignature>,
255 pub body: Vec<Node<FuncStmt>>,
256}
257
258#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
259#[allow(clippy::large_enum_variant)]
260pub enum FunctionArg {
261 Regular {
262 mut_: Option<Span>,
263 label: Option<Node<SmolStr>>,
264 name: Node<SmolStr>,
265 typ: Node<TypeDesc>,
266 },
267 Self_ {
268 mut_: Option<Span>,
269 },
270}
271impl FunctionArg {
272 pub fn label_span(&self) -> Option<Span> {
273 match self {
274 Self::Regular { label, .. } => label.as_ref().map(|label| label.span),
275 Self::Self_ { .. } => None,
276 }
277 }
278
279 pub fn name_span(&self) -> Option<Span> {
280 match self {
281 Self::Regular { name, .. } => Some(name.span),
282 Self::Self_ { .. } => None,
283 }
284 }
285
286 pub fn typ_span(&self) -> Option<Span> {
287 match self {
288 Self::Regular { typ, .. } => Some(typ.span),
289 Self::Self_ { .. } => None,
290 }
291 }
292}
293
294#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
295pub enum FuncStmt {
296 Return {
297 value: Option<Node<Expr>>,
298 },
299 VarDecl {
300 mut_: Option<Span>,
301 target: Node<VarDeclTarget>,
302 typ: Node<TypeDesc>,
303 value: Option<Node<Expr>>,
304 },
305 ConstantDecl {
306 name: Node<SmolStr>,
307 typ: Node<TypeDesc>,
308 value: Node<Expr>,
309 },
310 Assign {
311 target: Node<Expr>,
312 value: Node<Expr>,
313 },
314 AugAssign {
315 target: Node<Expr>,
316 op: Node<BinOperator>,
317 value: Node<Expr>,
318 },
319 For {
320 target: Node<SmolStr>,
321 iter: Node<Expr>,
322 body: Vec<Node<FuncStmt>>,
323 },
324 While {
325 test: Node<Expr>,
326 body: Vec<Node<FuncStmt>>,
327 },
328 If {
329 test: Node<Expr>,
330 body: Vec<Node<FuncStmt>>,
331 or_else: Vec<Node<FuncStmt>>,
332 },
333 Match {
334 expr: Node<Expr>,
335 arms: Vec<Node<MatchArm>>,
336 },
337 Assert {
338 test: Node<Expr>,
339 msg: Option<Node<Expr>>,
340 },
341 Expr {
342 value: Node<Expr>,
343 },
344 Break,
345 Continue,
346 Revert {
347 error: Option<Node<Expr>>,
348 },
349 Unsafe(Vec<Node<FuncStmt>>),
350}
351
352#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
353pub struct MatchArm {
354 pub pat: Node<Pattern>,
355 pub body: Vec<Node<FuncStmt>>,
356}
357
358#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
359pub enum Pattern {
360 WildCard,
362 Rest,
364 Literal(Node<LiteralPattern>),
366 Tuple(Vec<Node<Pattern>>),
368 Path(Node<Path>),
370 PathTuple(Node<Path>, Vec<Node<Pattern>>),
372 PathStruct {
375 path: Node<Path>,
376 fields: Vec<(Node<SmolStr>, Node<Pattern>)>,
377 has_rest: bool,
378 },
379 Or(Vec<Node<Pattern>>),
381}
382
383impl Pattern {
384 pub fn is_rest(&self) -> bool {
385 matches!(self, Pattern::Rest)
386 }
387}
388
389#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
390pub enum LiteralPattern {
391 Bool(bool),
392}
393
394#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
395pub enum VarDeclTarget {
396 Name(SmolStr),
397 Tuple(Vec<Node<VarDeclTarget>>),
398}
399
400#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
401pub enum Expr {
402 Ternary {
403 if_expr: Box<Node<Expr>>,
404 test: Box<Node<Expr>>,
405 else_expr: Box<Node<Expr>>,
406 },
407 BoolOperation {
408 left: Box<Node<Expr>>,
409 op: Node<BoolOperator>,
410 right: Box<Node<Expr>>,
411 },
412 BinOperation {
413 left: Box<Node<Expr>>,
414 op: Node<BinOperator>,
415 right: Box<Node<Expr>>,
416 },
417 UnaryOperation {
418 op: Node<UnaryOperator>,
419 operand: Box<Node<Expr>>,
420 },
421 CompOperation {
422 left: Box<Node<Expr>>,
423 op: Node<CompOperator>,
424 right: Box<Node<Expr>>,
425 },
426 Attribute {
427 value: Box<Node<Expr>>,
428 attr: Node<SmolStr>,
429 },
430 Subscript {
431 value: Box<Node<Expr>>,
432 index: Box<Node<Expr>>,
433 },
434 Call {
435 func: Box<Node<Expr>>,
436 generic_args: Option<Node<Vec<GenericArg>>>,
437 args: Node<Vec<Node<CallArg>>>,
438 },
439 List {
440 elts: Vec<Node<Expr>>,
441 },
442 Repeat {
443 value: Box<Node<Expr>>,
444 len: Box<Node<GenericArg>>,
445 },
446 Tuple {
447 elts: Vec<Node<Expr>>,
448 },
449 Bool(bool),
450 Name(SmolStr),
451 Path(Path),
452 Num(SmolStr),
453 Str(SmolStr),
454 Unit,
455}
456
457#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
458pub struct CallArg {
459 pub label: Option<Node<SmolStr>>,
460 pub value: Node<Expr>,
461}
462
463#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
464pub enum BoolOperator {
465 And,
466 Or,
467}
468
469#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
470pub enum BinOperator {
471 Add,
472 Sub,
473 Mult,
474 Div,
475 Mod,
476 Pow,
477 LShift,
478 RShift,
479 BitOr,
480 BitXor,
481 BitAnd,
482}
483
484#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
485pub enum UnaryOperator {
486 Invert,
487 Not,
488 USub,
489}
490
491#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
492pub enum CompOperator {
493 Eq,
494 NotEq,
495 Lt,
496 LtE,
497 Gt,
498 GtE,
499}
500
501impl Node<Contract> {
502 pub fn name(&self) -> &str {
503 &self.kind.name.kind
504 }
505}
506
507impl Node<Struct> {
508 pub fn name(&self) -> &str {
509 &self.kind.name.kind
510 }
511}
512
513impl Node<Enum> {
514 pub fn name(&self) -> &str {
515 &self.kind.name.kind
516 }
517}
518
519impl Node<Variant> {
520 pub fn name(&self) -> &str {
521 &self.kind.name.kind
522 }
523}
524
525impl Node<Trait> {
526 pub fn name(&self) -> &str {
527 &self.kind.name.kind
528 }
529}
530
531impl Node<Field> {
532 pub fn name(&self) -> &str {
533 &self.kind.name.kind
534 }
535}
536
537impl Node<Function> {
538 pub fn name(&self) -> &str {
539 &self.kind.sig.kind.name.kind
540 }
541}
542
543impl Node<FunctionArg> {
544 pub fn name(&self) -> &str {
545 match &self.kind {
546 FunctionArg::Regular { name, .. } => &name.kind,
547 FunctionArg::Self_ { .. } => "self",
548 }
549 }
550
551 pub fn name_span(&self) -> Span {
552 match &self.kind {
553 FunctionArg::Regular { name, .. } => name.span,
554 FunctionArg::Self_ { .. } => self.span,
555 }
556 }
557}
558
559impl Node<TypeAlias> {
560 pub fn name(&self) -> &str {
561 &self.kind.name.kind
562 }
563}
564
565impl Spanned for ModuleStmt {
566 fn span(&self) -> Span {
567 match self {
568 ModuleStmt::Pragma(inner) => inner.span,
569 ModuleStmt::Use(inner) => inner.span,
570 ModuleStmt::Trait(inner) => inner.span,
571 ModuleStmt::Impl(inner) => inner.span,
572 ModuleStmt::TypeAlias(inner) => inner.span,
573 ModuleStmt::Contract(inner) => inner.span,
574 ModuleStmt::Constant(inner) => inner.span,
575 ModuleStmt::Struct(inner) => inner.span,
576 ModuleStmt::Enum(inner) => inner.span,
577 ModuleStmt::Function(inner) => inner.span,
578 ModuleStmt::Attribute(inner) => inner.span,
579 ModuleStmt::ParseError(span) => *span,
580 }
581 }
582}
583
584impl Spanned for ContractStmt {
585 fn span(&self) -> Span {
586 match self {
587 ContractStmt::Function(inner) => inner.span,
588 }
589 }
590}
591
592impl fmt::Display for Module {
593 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
594 let (uses, rest): (Vec<&ModuleStmt>, Vec<&ModuleStmt>) = self
595 .body
596 .iter()
597 .partition(|&stmt| matches!(stmt, ModuleStmt::Use(_) | ModuleStmt::Pragma(_)));
598 for stmt in &uses {
599 writeln!(f, "{stmt}")?;
600 }
601 if !uses.is_empty() && !rest.is_empty() {
602 writeln!(f)?;
603 }
604 let mut delim = "";
605 for stmt in rest {
606 writeln!(f, "{delim}{stmt}")?;
607 delim = "\n";
608 }
609 Ok(())
610 }
611}
612
613impl fmt::Display for ModuleStmt {
614 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
615 match self {
616 ModuleStmt::Pragma(node) => write!(f, "{}", node.kind),
617 ModuleStmt::Use(node) => write!(f, "{}", node.kind),
618 ModuleStmt::Trait(node) => write!(f, "{}", node.kind),
619 ModuleStmt::Impl(node) => write!(f, "{}", node.kind),
620 ModuleStmt::TypeAlias(node) => write!(f, "{}", node.kind),
621 ModuleStmt::Contract(node) => write!(f, "{}", node.kind),
622 ModuleStmt::Constant(node) => write!(f, "{}", node.kind),
623 ModuleStmt::Struct(node) => write!(f, "{}", node.kind),
624 ModuleStmt::Enum(node) => write!(f, "{}", node.kind),
625 ModuleStmt::Function(node) => write!(f, "{}", node.kind),
626 ModuleStmt::Attribute(node) => writeln!(f, "#{}", node.kind),
627 ModuleStmt::ParseError(span) => {
628 write!(f, "# PARSE ERROR: {}..{}", span.start, span.end)
629 }
630 }
631 }
632}
633
634impl fmt::Display for Pragma {
635 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
636 write!(f, "pragma {}", self.version_requirement.kind)
637 }
638}
639
640impl fmt::Display for Use {
641 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
642 write!(f, "use {}", self.tree.kind)
644 }
645}
646
647impl fmt::Display for UseTree {
648 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
649 match self {
650 UseTree::Glob { prefix } => write!(f, "{prefix}::*"),
651 UseTree::Simple { path, rename } => {
652 if let Some(rename) = rename {
653 write!(f, "{} as {}", path, rename.kind)
654 } else {
655 write!(f, "{path}")
656 }
657 }
658 UseTree::Nested { prefix, children } => {
659 write!(f, "{}::{{{}}}", prefix, node_comma_joined(children))
660 }
661 }
662 }
663}
664
665impl fmt::Display for Path {
666 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
667 let joined_names = self
668 .segments
669 .iter()
670 .map(|name| name.kind.as_ref())
671 .collect::<Vec<_>>()
672 .join("::");
673 write!(f, "{joined_names}")?;
674
675 Ok(())
676 }
677}
678
679impl fmt::Display for ConstantDecl {
680 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
681 let ConstantDecl {
682 name,
683 typ,
684 value,
685 pub_qual,
686 } = self;
687 if pub_qual.is_some() {
688 write!(f, "pub ")?;
689 }
690 write!(f, "const {}: {} = {}", name.kind, typ.kind, value.kind)
691 }
692}
693
694impl fmt::Display for Trait {
695 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
696 writeln!(f, "trait {}:", self.name.kind)?;
697
698 Ok(())
699 }
700}
701
702impl fmt::Display for Impl {
703 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
704 writeln!(
705 f,
706 "impl {} for {}",
707 self.impl_trait.kind, self.receiver.kind
708 )?;
709
710 Ok(())
711 }
712}
713
714impl fmt::Display for TypeAlias {
715 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
716 let TypeAlias {
717 name,
718 typ,
719 pub_qual,
720 } = self;
721 if pub_qual.is_some() {
722 write!(f, "pub ")?;
723 }
724 write!(f, "type {} = {}", name.kind, typ.kind)
725 }
726}
727
728impl fmt::Display for Contract {
729 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
730 let Contract {
731 name,
732 fields,
733 body,
734 pub_qual,
735 } = self;
736
737 if pub_qual.is_some() {
738 write!(f, "pub ")?;
739 }
740 write!(f, "contract {} {{", name.kind)?;
741
742 if !fields.is_empty() {
743 for field in fields {
744 writeln!(f)?;
745 write!(indented(f), "{}", field.kind)?;
746 }
747 writeln!(f)?;
748 }
749 if !body.is_empty() {
750 writeln!(f)?;
751 write!(indented(f), "{}", double_line_joined(body))?;
752 writeln!(f)?;
753 }
754 write!(f, "}}")
755 }
756}
757
758impl fmt::Display for Struct {
759 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
760 let Struct {
761 name,
762 fields,
763 functions,
764 pub_qual,
765 } = self;
766
767 if pub_qual.is_some() {
768 write!(f, "pub ")?;
769 }
770 write!(f, "struct {} ", name.kind)?;
771 write!(f, "{{")?;
772 write_nodes_line_wrapped(&mut indented(f), fields)?;
773
774 if !self.fields.is_empty() && !functions.is_empty() {
775 writeln!(f)?;
776 }
777 if !functions.is_empty() {
778 writeln!(indented(f), "{}", double_line_joined(functions))?;
779 }
780 write!(f, "}}")
781 }
782}
783
784impl fmt::Display for Enum {
785 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
786 let Enum {
787 name,
788 variants,
789 functions,
790 pub_qual,
791 } = self;
792
793 if pub_qual.is_some() {
794 write!(f, "pub ")?;
795 }
796
797 write!(f, "enum {} ", name.kind)?;
798 write!(f, "{{")?;
799 write_nodes_line_wrapped(&mut indented(f), variants)?;
800
801 if !functions.is_empty() {
802 writeln!(indented(f), "{}", double_line_joined(functions))?;
803 }
804 write!(f, "}}")
805 }
806}
807
808impl fmt::Display for TypeDesc {
809 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
810 match self {
811 TypeDesc::Unit => write!(f, "()"),
812 TypeDesc::Base { base } => write!(f, "{base}"),
813 TypeDesc::Path(path) => write!(f, "{path}"),
814 TypeDesc::Tuple { items } => {
815 if items.len() == 1 {
816 write!(f, "({},)", items[0].kind)
817 } else {
818 write!(f, "({})", node_comma_joined(items))
819 }
820 }
821 TypeDesc::Generic { base, args } => {
822 write!(f, "{}<{}>", base.kind, comma_joined(args.kind.iter()))
823 }
824 TypeDesc::SelfType => write!(f, "Self"),
825 }
826 }
827}
828
829impl fmt::Display for GenericParameter {
830 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
831 match self {
832 GenericParameter::Unbounded(name) => write!(f, "{}", name.kind),
833 GenericParameter::Bounded { name, bound } => write!(f, "{}: {}", name.kind, bound.kind),
834 }
835 }
836}
837
838impl fmt::Display for GenericArg {
839 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
840 match self {
841 GenericArg::TypeDesc(node) => write!(f, "{}", node.kind),
842 GenericArg::Int(node) => write!(f, "{}", node.kind),
843 GenericArg::ConstExpr(node) => write!(f, "{{ {} }}", node.kind),
844 }
845 }
846}
847
848impl fmt::Display for Field {
849 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
850 if self.is_pub {
851 write!(f, "pub ")?;
852 }
853 if self.is_const {
854 write!(f, "const ")?;
855 }
856 write!(f, "{}: {}", self.name.kind, self.typ.kind)
857 }
858}
859
860impl fmt::Display for Variant {
861 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
862 write!(f, "{}", self.name.kind)?;
863 match &self.kind {
864 VariantKind::Unit => Ok(()),
865 VariantKind::Tuple(elts) => {
866 write!(f, "({})", node_comma_joined(elts))
867 }
868 }
869 }
870}
871
872impl fmt::Display for ContractStmt {
873 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
874 match self {
875 ContractStmt::Function(node) => write!(f, "{}", node.kind),
876 }
877 }
878}
879
880impl fmt::Display for Node<Function> {
881 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
882 self.kind.fmt(f)
883 }
884}
885
886impl fmt::Display for Function {
887 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
888 let FunctionSignature {
889 pub_,
890 unsafe_,
891 name,
892 generic_params,
893 args,
894 return_type,
895 } = &self.sig.kind;
896
897 if pub_.is_some() {
898 write!(f, "pub ")?;
899 }
900 if unsafe_.is_some() {
901 write!(f, "unsafe ")?;
902 }
903 write!(f, "fn {}", name.kind)?;
904 if !generic_params.kind.is_empty() {
905 write!(f, "<{}>", comma_joined(generic_params.kind.iter()))?;
906 }
907 write!(f, "({})", node_comma_joined(args))?;
908
909 if let Some(return_type) = return_type.as_ref() {
910 write!(f, " -> {}", return_type.kind)?;
911 }
912 write!(f, " {{")?;
913 write_nodes_line_wrapped(&mut indented(f), &self.body)?;
914 write!(f, "}}")
915 }
916}
917
918impl fmt::Display for FunctionArg {
919 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
920 match self {
921 FunctionArg::Regular {
922 mut_,
923 label,
924 name,
925 typ,
926 } => {
927 if mut_.is_some() {
928 write!(f, "mut ")?
929 }
930 if let Some(label) = label {
931 write!(f, "{} ", label.kind)?
932 }
933
934 write!(f, "{}: {}", name.kind, typ.kind)
935 }
936 FunctionArg::Self_ { mut_ } => {
937 if mut_.is_some() {
938 write!(f, "mut ")?;
939 }
940 write!(f, "self")
941 }
942 }
943 }
944}
945
946impl fmt::Display for FuncStmt {
947 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
948 match self {
949 FuncStmt::Return { value } => {
950 if let Some(value) = value {
951 write!(f, "return {}", value.kind)
952 } else {
953 write!(f, "return")
954 }
955 }
956 FuncStmt::VarDecl {
957 mut_,
958 target,
959 typ,
960 value,
961 } => {
962 let mut_ = if mut_.is_some() { "mut " } else { "" };
963 if let Some(value) = value {
964 write!(
965 f,
966 "let {}{}: {} = {}",
967 mut_, target.kind, typ.kind, value.kind
968 )
969 } else {
970 write!(f, "let {}{}: {}", mut_, target.kind, typ.kind)
971 }
972 }
973 FuncStmt::ConstantDecl { name, typ, value } => {
974 write!(f, "const {}: {} = {}", name.kind, typ.kind, value.kind)
975 }
976 FuncStmt::Assign { target, value } => write!(f, "{} = {}", target.kind, value.kind),
977 FuncStmt::AugAssign { target, op, value } => {
978 write!(f, "{} {}= {}", target.kind, op.kind, value.kind)
979 }
980 FuncStmt::For { target, iter, body } => {
981 write!(f, "for {} in {} {{", target.kind, iter.kind)?;
982 write_nodes_line_wrapped(&mut indented(f), body)?;
983 write!(f, "}}")
984 }
985 FuncStmt::While { test, body } => {
986 write!(f, "while {} {{", test.kind)?;
987 write_nodes_line_wrapped(&mut indented(f), body)?;
988 write!(f, "}}")
989 }
990 FuncStmt::If {
991 test,
992 body,
993 or_else,
994 } => {
995 write!(f, "if {} {{", test.kind)?;
996 write_nodes_line_wrapped(&mut indented(f), body)?;
997
998 if or_else.is_empty() {
999 write!(f, "}}")
1000 } else {
1001 if body.is_empty() {
1002 writeln!(f)?;
1003 }
1004
1005 if matches!(
1006 &or_else[..],
1007 &[Node {
1008 kind: FuncStmt::If { .. },
1009 ..
1010 }]
1011 ) {
1012 write!(f, "}} else ")?;
1013 write!(f, "{}", or_else[0].kind)
1014 } else {
1015 write!(f, "}} else {{")?;
1016 write_nodes_line_wrapped(&mut indented(f), or_else)?;
1017 write!(f, "}}")
1018 }
1019 }
1020 }
1021 FuncStmt::Match { expr, arms } => {
1022 write!(f, "match {} {{", expr.kind)?;
1023 write_nodes_line_wrapped(&mut indented(f), arms)?;
1024 write!(f, "}}")
1025 }
1026 FuncStmt::Assert { test, msg } => {
1027 if let Some(msg) = msg {
1028 write!(f, "assert {}, {}", test.kind, msg.kind)
1029 } else {
1030 write!(f, "assert {}", test.kind)
1031 }
1032 }
1033 FuncStmt::Expr { value } => write!(f, "{}", value.kind),
1034 FuncStmt::Break => write!(f, "break"),
1035 FuncStmt::Continue => write!(f, "continue"),
1036 FuncStmt::Revert { error } => {
1037 if let Some(error) = error {
1038 write!(f, "revert {}", error.kind)
1039 } else {
1040 write!(f, "revert")
1041 }
1042 }
1043 FuncStmt::Unsafe(body) => {
1044 write!(f, "unsafe {{")?;
1045 write_nodes_line_wrapped(&mut indented(f), body)?;
1046 write!(f, "}}")
1047 }
1048 }
1049 }
1050}
1051
1052impl fmt::Display for VarDeclTarget {
1053 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1054 match self {
1055 VarDeclTarget::Name(name) => write!(f, "{name}"),
1056 VarDeclTarget::Tuple(elts) => {
1057 if elts.len() == 1 {
1058 write!(f, "({},)", elts[0].kind)
1059 } else {
1060 write!(f, "({})", node_comma_joined(elts))
1061 }
1062 }
1063 }
1064 }
1065}
1066
1067impl fmt::Display for Expr {
1068 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1069 match self {
1070 Expr::Ternary {
1071 if_expr,
1072 test,
1073 else_expr,
1074 } => write!(
1075 f,
1076 "{} if {} else {}",
1077 if_expr.kind, test.kind, else_expr.kind
1078 ),
1079 Expr::BoolOperation { left, op, right } => {
1080 let left = maybe_fmt_left_with_parens(&op.kind, &left.kind);
1081 let right = maybe_fmt_right_with_parens(&op.kind, &right.kind);
1082 write!(f, "{} {} {}", left, op.kind, right)
1083 }
1084 Expr::BinOperation { left, op, right } => {
1085 let left = maybe_fmt_left_with_parens(&op.kind, &left.kind);
1086 let right = maybe_fmt_right_with_parens(&op.kind, &right.kind);
1087 write!(f, "{} {} {}", left, op.kind, right)
1088 }
1089 Expr::UnaryOperation { op, operand } => {
1090 let operand = maybe_fmt_operand_with_parens(&op.kind, &operand.kind);
1091 if op.kind == UnaryOperator::Not {
1092 write!(f, "{} {}", op.kind, operand)
1093 } else {
1094 write!(f, "{}{}", op.kind, operand)
1095 }
1096 }
1097 Expr::CompOperation { left, op, right } => {
1098 let left = maybe_fmt_left_with_parens(&op.kind, &left.kind);
1099 let right = maybe_fmt_right_with_parens(&op.kind, &right.kind);
1100 write!(f, "{} {} {}", left, op.kind, right)
1101 }
1102 Expr::Attribute { value, attr } => write!(f, "{}.{}", value.kind, attr.kind),
1103 Expr::Subscript { value, index } => write!(f, "{}[{}]", value.kind, index.kind),
1104 Expr::Call {
1105 func,
1106 generic_args,
1107 args,
1108 } => {
1109 write!(f, "{}", func.kind)?;
1110 if let Some(generic_args) = generic_args {
1111 write!(f, "<{}>", comma_joined(generic_args.kind.iter()))?;
1112 }
1113 write!(f, "({})", node_comma_joined(&args.kind))
1114 }
1115 Expr::List { elts } => write!(f, "[{}]", node_comma_joined(elts)),
1116 Expr::Repeat { value: elt, len } => write!(f, "[{}; {}]", elt.kind, len.kind),
1117 Expr::Tuple { elts } => {
1118 if elts.len() == 1 {
1119 write!(f, "({},)", elts[0].kind)
1120 } else {
1121 write!(f, "({})", node_comma_joined(elts))
1122 }
1123 }
1124 Expr::Bool(bool) => write!(f, "{bool}"),
1125 Expr::Name(name) => write!(f, "{name}"),
1126 Expr::Path(path) => write!(f, "{path}"),
1127 Expr::Num(num) => write!(f, "{num}"),
1128 Expr::Str(str) => write!(f, "\"{str}\""),
1129 Expr::Unit => write!(f, "()"),
1130 }
1131 }
1132}
1133
1134impl fmt::Display for CallArg {
1135 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1136 if let Some(label) = &self.label {
1137 if let Expr::Name(var_name) = &self.value.kind {
1138 if var_name == &label.kind {
1139 return write!(f, "{var_name}");
1140 }
1141 }
1142 write!(f, "{}: {}", label.kind, self.value.kind)
1143 } else {
1144 write!(f, "{}", self.value.kind)
1145 }
1146 }
1147}
1148
1149impl fmt::Display for BoolOperator {
1150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1151 use BoolOperator::*;
1152 match self {
1153 And => write!(f, "and"),
1154 Or => write!(f, "or"),
1155 }
1156 }
1157}
1158
1159impl fmt::Display for BinOperator {
1160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1161 use BinOperator::*;
1162 match self {
1163 Add => write!(f, "+"),
1164 Sub => write!(f, "-"),
1165 Mult => write!(f, "*"),
1166 Div => write!(f, "/"),
1167 Mod => write!(f, "%"),
1168 Pow => write!(f, "**"),
1169 LShift => write!(f, "<<"),
1170 RShift => write!(f, ">>"),
1171 BitOr => write!(f, "|"),
1172 BitXor => write!(f, "^"),
1173 BitAnd => write!(f, "&"),
1174 }
1175 }
1176}
1177
1178impl fmt::Display for UnaryOperator {
1179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1180 use UnaryOperator::*;
1181 match self {
1182 Invert => write!(f, "~"),
1183 Not => write!(f, "not"),
1184 USub => write!(f, "-"),
1185 }
1186 }
1187}
1188
1189impl fmt::Display for CompOperator {
1190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191 use CompOperator::*;
1192 match self {
1193 Eq => write!(f, "=="),
1194 NotEq => write!(f, "!="),
1195 Lt => write!(f, "<"),
1196 LtE => write!(f, "<="),
1197 Gt => write!(f, ">"),
1198 GtE => write!(f, ">="),
1199 }
1200 }
1201}
1202
1203impl fmt::Display for MatchArm {
1204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1205 write!(f, "{} => {{", self.pat.kind)?;
1206 write_nodes_line_wrapped(&mut indented(f), &self.body)?;
1207 write!(f, "}}")
1208 }
1209}
1210
1211impl fmt::Display for Pattern {
1212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1213 match self {
1214 Self::WildCard => write!(f, "_"),
1215 Self::Rest => write!(f, ".."),
1216 Self::Literal(pat) => write!(f, "{}", pat.kind),
1217 Self::Path(path) => write!(f, "{}", path.kind),
1218 Self::PathTuple(path, elts) => {
1219 write!(f, "{}", path.kind)?;
1220 write!(f, "({})", node_comma_joined(elts))
1221 }
1222 Self::Tuple(elts) => {
1223 write!(f, "({})", node_comma_joined(elts))
1224 }
1225 Self::PathStruct {
1226 path,
1227 fields,
1228 has_rest: is_rest,
1229 } => {
1230 write!(f, "{}", path.kind)?;
1231 let fields = fields
1232 .iter()
1233 .map(|(name, pat)| format!("{}: {}", name.kind, pat.kind));
1234 let fields = comma_joined(fields);
1235 if *is_rest {
1236 write!(f, "{{{fields}, ..}}")
1237 } else {
1238 write!(f, "{{{fields}}}")
1239 }
1240 }
1241 Self::Or(pats) => {
1242 write!(f, "{}", node_delim_joined(pats, "| "))
1243 }
1244 }
1245 }
1246}
1247
1248impl fmt::Display for LiteralPattern {
1249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1250 match self {
1251 Self::Bool(b) => write!(f, "{b}"),
1252 }
1253 }
1254}
1255
1256fn node_comma_joined(nodes: &[Node<impl fmt::Display>]) -> String {
1257 node_delim_joined(nodes, ", ")
1258}
1259
1260fn node_delim_joined(nodes: &[Node<impl fmt::Display>], delim: &str) -> String {
1261 delim_joined(nodes.iter().map(|node| &node.kind), delim)
1262}
1263
1264fn comma_joined<T>(items: impl Iterator<Item = T>) -> String
1265where
1266 T: fmt::Display,
1267{
1268 delim_joined(items, ", ")
1269}
1270
1271fn delim_joined<T>(items: impl Iterator<Item = T>, delim: &str) -> String
1272where
1273 T: fmt::Display,
1274{
1275 items
1276 .map(|item| format!("{item}"))
1277 .collect::<Vec<_>>()
1278 .join(delim)
1279}
1280
1281fn write_nodes_line_wrapped(f: &mut impl Write, nodes: &[Node<impl fmt::Display>]) -> fmt::Result {
1282 if !nodes.is_empty() {
1283 writeln!(f)?;
1284 }
1285 for n in nodes {
1286 writeln!(f, "{}", n.kind)?;
1287 }
1288 Ok(())
1289}
1290
1291fn double_line_joined(items: &[impl fmt::Display]) -> String {
1292 items
1293 .iter()
1294 .map(|item| format!("{item}"))
1295 .collect::<Vec<_>>()
1296 .join("\n\n")
1297}
1298
1299trait InfixBindingPower {
1300 fn infix_binding_power(&self) -> (u8, u8);
1301}
1302
1303trait PrefixBindingPower {
1304 fn prefix_binding_power(&self) -> u8;
1305}
1306
1307impl InfixBindingPower for BoolOperator {
1308 fn infix_binding_power(&self) -> (u8, u8) {
1309 use BoolOperator::*;
1310
1311 match self {
1312 Or => (50, 51),
1313 And => (60, 61),
1314 }
1315 }
1316}
1317
1318impl InfixBindingPower for BinOperator {
1319 fn infix_binding_power(&self) -> (u8, u8) {
1320 use BinOperator::*;
1321
1322 match self {
1323 Add | Sub => (120, 121),
1324 Mult | Div | Mod => (130, 131),
1325 Pow => (141, 140),
1326 LShift | RShift => (110, 111),
1327 BitOr => (80, 81),
1328 BitXor => (90, 91),
1329 BitAnd => (100, 101),
1330 }
1331 }
1332}
1333
1334impl InfixBindingPower for CompOperator {
1335 fn infix_binding_power(&self) -> (u8, u8) {
1336 (70, 71)
1337 }
1338}
1339
1340impl PrefixBindingPower for UnaryOperator {
1341 fn prefix_binding_power(&self) -> u8 {
1342 use UnaryOperator::*;
1343
1344 match self {
1345 Not => 65,
1346 Invert | USub => 135,
1347 }
1348 }
1349}
1350
1351fn maybe_fmt_left_with_parens(op: &impl InfixBindingPower, expr: &Expr) -> String {
1352 if expr_right_binding_power(expr) < op.infix_binding_power().0 {
1353 format!("({expr})")
1354 } else {
1355 format!("{expr}")
1356 }
1357}
1358
1359fn maybe_fmt_right_with_parens(op: &impl InfixBindingPower, expr: &Expr) -> String {
1360 if op.infix_binding_power().1 > expr_left_binding_power(expr) {
1361 format!("({expr})")
1362 } else {
1363 format!("{expr}")
1364 }
1365}
1366
1367fn maybe_fmt_operand_with_parens(op: &impl PrefixBindingPower, expr: &Expr) -> String {
1368 if op.prefix_binding_power() > expr_left_binding_power(expr) {
1369 format!("({expr})")
1370 } else {
1371 format!("{expr}")
1372 }
1373}
1374
1375fn expr_left_binding_power(expr: &Expr) -> u8 {
1376 let max_power = u8::MAX;
1377
1378 match expr {
1379 Expr::Ternary { .. } => max_power,
1380 Expr::BoolOperation { op, .. } => op.kind.infix_binding_power().0,
1381 Expr::BinOperation { op, .. } => op.kind.infix_binding_power().0,
1382 Expr::UnaryOperation { op, .. } => op.kind.prefix_binding_power(),
1383 Expr::CompOperation { op, .. } => op.kind.infix_binding_power().0,
1384 Expr::Attribute { .. } => max_power,
1385 Expr::Subscript { .. } => max_power,
1386 Expr::Call { .. } => max_power,
1387 Expr::List { .. } => max_power,
1388 Expr::Repeat { .. } => max_power,
1389 Expr::Tuple { .. } => max_power,
1390 Expr::Bool(_) => max_power,
1391 Expr::Name(_) => max_power,
1392 Expr::Path(_) => max_power,
1393 Expr::Num(_) => max_power,
1394 Expr::Str(_) => max_power,
1395 Expr::Unit => max_power,
1396 }
1397}
1398
1399fn expr_right_binding_power(expr: &Expr) -> u8 {
1400 let max_power = u8::MAX;
1401
1402 match expr {
1403 Expr::Ternary { .. } => max_power,
1404 Expr::BoolOperation { op, .. } => op.kind.infix_binding_power().1,
1405 Expr::BinOperation { op, .. } => op.kind.infix_binding_power().1,
1406 Expr::UnaryOperation { op, .. } => op.kind.prefix_binding_power(),
1407 Expr::CompOperation { op, .. } => op.kind.infix_binding_power().1,
1408 Expr::Attribute { .. } => max_power,
1409 Expr::Subscript { .. } => max_power,
1410 Expr::Call { .. } => max_power,
1411 Expr::List { .. } => max_power,
1412 Expr::Repeat { .. } => max_power,
1413 Expr::Tuple { .. } => max_power,
1414 Expr::Bool(_) => max_power,
1415 Expr::Name(_) => max_power,
1416 Expr::Path(_) => max_power,
1417 Expr::Num(_) => max_power,
1418 Expr::Str(_) => max_power,
1419 Expr::Unit => max_power,
1420 }
1421}