fe_parser/
ast.rs

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    // TODO: replace with `Name(SmolStr)`, or eliminate in favor of `Path`?
127    Base {
128        base: SmolStr,
129    },
130    Path(Path),
131    Tuple {
132        items: Vec1<Node<TypeDesc>>,
133    },
134    Generic {
135        // TODO: when we support user-defined generic types,
136        // this will have to be a `Path`
137        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/// struct or contract field, with optional 'pub' and 'const' qualifiers
192#[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/// Enum variant definition.
203#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
204pub struct Variant {
205    pub name: Node<SmolStr>,
206    pub kind: VariantKind,
207}
208
209/// Enum variant kind.
210#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
211pub enum VariantKind {
212    /// Unit variant.
213    /// E.g., `Bar` in
214    ///
215    /// ```fe
216    /// enum Foo {
217    ///     Bar
218    ///     Baz(u32, i32)
219    /// }
220    /// ```
221    Unit,
222
223    /// Tuple variant.
224    /// E.g., `Baz(u32, i32)` in
225    ///
226    /// ```fe
227    /// enum Foo {
228    ///     Bar
229    ///     Baz(u32, i32)
230    /// }
231    /// ```
232    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    // qualifier order: `pub unsafe fn`
244    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    /// Represents a wildcard pattern `_`.
361    WildCard,
362    /// Rest pattern. e.g., `..`
363    Rest,
364    /// Represents a literal pattern. e.g., `true`.
365    Literal(Node<LiteralPattern>),
366    /// Represents tuple destructuring pattern. e.g., `(x, y, z)`.
367    Tuple(Vec<Node<Pattern>>),
368    /// Represents unit variant pattern. e.g., `Enum::Unit`.
369    Path(Node<Path>),
370    /// Represents tuple variant pattern. e.g., `Enum::Tuple(x, y, z)`.
371    PathTuple(Node<Path>, Vec<Node<Pattern>>),
372    /// Represents struct or struct variant destructuring pattern. e.g.,
373    /// `MyStruct {x: pat1, y: pat2}}`.
374    PathStruct {
375        path: Node<Path>,
376        fields: Vec<(Node<SmolStr>, Node<Pattern>)>,
377        has_rest: bool,
378    },
379    /// Represents or pattern. e.g., `EnumUnit | EnumTuple(_, _, _)`
380    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        // TODO pub use
643        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}