1mod annotation;
18pub use annotation::*;
19
20mod intrinsic;
21pub use intrinsic::*;
22
23mod variant;
24pub use variant::*;
25
26mod input;
27pub use input::*;
28
29mod output;
30pub use output::*;
31
32mod mode;
33pub use mode::*;
34
35use crate::{Block, ConstParameter, FunctionStub, Identifier, Indent, Node, NodeID, TupleType, TypeKind};
36use leo_span::{Span, Symbol};
37
38use itertools::Itertools as _;
39use serde::Serialize;
40use std::fmt;
41
42#[derive(Clone, Default, Serialize)]
44pub struct Function {
45 pub is_exported: Option<bool>,
50 pub annotations: Vec<Annotation>,
52 pub variant: Variant,
54 pub identifier: Identifier,
56 pub const_parameters: Vec<ConstParameter>,
58 pub input: Vec<Input>,
60 pub output: Vec<Output>,
62 pub output_type: TypeKind,
64 pub block: Block,
66 pub span: Span,
68 pub id: NodeID,
70}
71
72impl PartialEq for Function {
73 fn eq(&self, other: &Self) -> bool {
74 self.identifier == other.identifier
75 }
76}
77
78impl Eq for Function {}
79
80impl Function {
81 #[allow(clippy::too_many_arguments)]
83 pub fn new(
84 is_exported: Option<bool>,
85 annotations: Vec<Annotation>,
86 variant: Variant,
87 identifier: Identifier,
88 const_parameters: Vec<ConstParameter>,
89 input: Vec<Input>,
90 output: Vec<Output>,
91 block: Block,
92 span: Span,
93 id: NodeID,
94 ) -> Self {
95 let output_type = match output.len() {
96 0 => TypeKind::Unit,
97 1 => output[0].type_.kind().clone(),
98 _ => TypeKind::Tuple(TupleType::new(output.iter().map(|o| o.type_.kind().clone()).collect())),
99 };
100
101 Function {
102 is_exported,
103 annotations,
104 variant,
105 identifier,
106 const_parameters,
107 input,
108 output,
109 output_type,
110 block,
111 span,
112 id,
113 }
114 }
115
116 pub fn name(&self) -> Symbol {
118 self.identifier.name
119 }
120
121 pub fn has_final_output(&self) -> bool {
123 self.output.iter().any(|o| matches!(o.type_.kind(), TypeKind::Future(_)))
124 }
125
126 pub fn is_test(&self) -> bool {
128 self.annotations.iter().any(|a| a.identifier.name == leo_span::sym::test)
129 }
130}
131
132impl From<FunctionStub> for Function {
133 fn from(function: FunctionStub) -> Self {
134 Self {
135 is_exported: None,
136 annotations: function.annotations,
137 variant: function.variant,
138 identifier: function.identifier,
139 const_parameters: vec![],
140 input: function.input,
141 output: function.output,
142 output_type: function.output_type,
143 block: Block::default(),
144 span: function.span,
145 id: function.id,
146 }
147 }
148}
149
150impl fmt::Debug for Function {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 write!(f, "{self}")
153 }
154}
155
156impl fmt::Display for Function {
157 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158 for annotation in &self.annotations {
159 writeln!(f, "{annotation}")?;
160 }
161
162 if self.is_exported == Some(true) {
163 write!(f, "export ")?;
164 }
165
166 match self.variant {
167 Variant::FinalFn => write!(f, "final fn ")?,
168 Variant::Fn => write!(f, "fn ")?,
169 Variant::Finalize => write!(f, "finalize ")?,
170 Variant::EntryPoint => write!(f, "fn ")?,
171 Variant::View => write!(f, "view fn ")?,
172 }
173
174 write!(f, "{}", self.identifier)?;
175 if !self.const_parameters.is_empty() {
176 write!(f, "::[{}]", self.const_parameters.iter().format(", "))?;
177 }
178 write!(f, "({})", self.input.iter().format(", "))?;
179
180 match self.output.len() {
181 0 => {}
182 1 => {
183 if !matches!(self.output[0].type_.kind(), TypeKind::Unit) {
184 write!(f, " -> {}", self.output[0])?;
185 }
186 }
187 _ => {
188 write!(f, " -> ({})", self.output.iter().format(", "))?;
189 }
190 }
191
192 writeln!(f, " {{")?;
193 for stmt in self.block.statements.iter() {
194 writeln!(f, "{}{}", Indent(stmt), stmt.semicolon())?;
195 }
196 write!(f, "}}")
197 }
198}
199
200crate::simple_node_impl!(Function);