1mod annotation;
18pub use annotation::*;
19
20mod const_parameter;
21pub use const_parameter::*;
22
23mod core_function;
24pub use core_function::*;
25
26mod variant;
27pub use variant::*;
28
29mod input;
30pub use input::*;
31
32mod output;
33pub use output::*;
34
35mod mode;
36pub use mode::*;
37
38use crate::{Block, FunctionStub, Identifier, Indent, Node, NodeID, TupleType, Type};
39use leo_span::{Span, Symbol};
40
41use itertools::Itertools as _;
42use serde::{Deserialize, Serialize};
43use std::fmt;
44
45#[derive(Clone, Default, Serialize, Deserialize)]
47pub struct Function {
48 pub annotations: Vec<Annotation>,
50 pub variant: Variant,
52 pub identifier: Identifier,
54 pub const_parameters: Vec<ConstParameter>,
56 pub input: Vec<Input>,
58 pub output: Vec<Output>,
60 pub output_type: Type,
62 pub block: Block,
64 pub span: Span,
66 pub id: NodeID,
68}
69
70impl PartialEq for Function {
71 fn eq(&self, other: &Self) -> bool {
72 self.identifier == other.identifier
73 }
74}
75
76impl Eq for Function {}
77
78impl Function {
79 #[allow(clippy::too_many_arguments)]
81 pub fn new(
82 annotations: Vec<Annotation>,
83 variant: Variant,
84 identifier: Identifier,
85 const_parameters: Vec<ConstParameter>,
86 input: Vec<Input>,
87 output: Vec<Output>,
88 block: Block,
89 span: Span,
90 id: NodeID,
91 ) -> Self {
92 let output_type = match output.len() {
93 0 => Type::Unit,
94 1 => output[0].type_.clone(),
95 _ => Type::Tuple(TupleType::new(output.iter().map(|o| o.type_.clone()).collect())),
96 };
97
98 Function { annotations, variant, identifier, const_parameters, input, output, output_type, block, span, id }
99 }
100
101 pub fn name(&self) -> Symbol {
103 self.identifier.name
104 }
105}
106
107impl From<FunctionStub> for Function {
108 fn from(function: FunctionStub) -> Self {
109 Self {
110 annotations: function.annotations,
111 variant: function.variant,
112 identifier: function.identifier,
113 const_parameters: vec![],
114 input: function.input,
115 output: function.output,
116 output_type: function.output_type,
117 block: Block::default(),
118 span: function.span,
119 id: function.id,
120 }
121 }
122}
123
124impl fmt::Debug for Function {
125 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126 write!(f, "{}", self)
127 }
128}
129
130impl fmt::Display for Function {
131 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132 match self.variant {
133 Variant::Inline => write!(f, "inline ")?,
134 Variant::Function => write!(f, "function ")?,
135 Variant::AsyncFunction => write!(f, "async function ")?,
136 Variant::Transition => write!(f, "transition ")?,
137 Variant::AsyncTransition => write!(f, "async transition ")?,
138 Variant::Script => write!(f, "script ")?,
139 }
140
141 write!(f, "{}", self.identifier)?;
142 if !self.const_parameters.is_empty() {
143 write!(f, "::[{}]", self.const_parameters.iter().format(", "))?;
144 }
145 write!(f, "({})", self.input.iter().format(", "))?;
146
147 match self.output.len() {
148 0 => {}
149 1 => {
150 if !matches!(self.output[0].type_, Type::Unit) {
151 write!(f, " -> {}", self.output[0])?;
152 }
153 }
154 _ => {
155 write!(f, " -> ({})", self.output.iter().format(", "))?;
156 }
157 }
158
159 writeln!(f, " {{")?;
160 for stmt in self.block.statements.iter() {
161 writeln!(f, "{}{}", Indent(stmt), stmt.semicolon())?;
162 }
163 write!(f, "}}")
164 }
165}
166
167crate::simple_node_impl!(Function);