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, Type};
36use leo_span::{Span, Symbol};
37
38use itertools::Itertools as _;
39use serde::{Deserialize, Serialize};
40use std::fmt;
41
42#[derive(Clone, Default, Serialize, Deserialize)]
44pub struct Function {
45 pub annotations: Vec<Annotation>,
47 pub variant: Variant,
49 pub identifier: Identifier,
51 pub const_parameters: Vec<ConstParameter>,
53 pub input: Vec<Input>,
55 pub output: Vec<Output>,
57 pub output_type: Type,
59 pub block: Block,
61 pub span: Span,
63 pub id: NodeID,
65}
66
67impl PartialEq for Function {
68 fn eq(&self, other: &Self) -> bool {
69 self.identifier == other.identifier
70 }
71}
72
73impl Eq for Function {}
74
75impl Function {
76 #[allow(clippy::too_many_arguments)]
78 pub fn new(
79 annotations: Vec<Annotation>,
80 variant: Variant,
81 identifier: Identifier,
82 const_parameters: Vec<ConstParameter>,
83 input: Vec<Input>,
84 output: Vec<Output>,
85 block: Block,
86 span: Span,
87 id: NodeID,
88 ) -> Self {
89 let output_type = match output.len() {
90 0 => Type::Unit,
91 1 => output[0].type_.clone(),
92 _ => Type::Tuple(TupleType::new(output.iter().map(|o| o.type_.clone()).collect())),
93 };
94
95 Function { annotations, variant, identifier, const_parameters, input, output, output_type, block, span, id }
96 }
97
98 pub fn name(&self) -> Symbol {
100 self.identifier.name
101 }
102
103 pub fn has_final_output(&self) -> bool {
105 self.output.iter().any(|o| matches!(o.type_, Type::Future(_)))
106 }
107}
108
109impl From<FunctionStub> for Function {
110 fn from(function: FunctionStub) -> Self {
111 Self {
112 annotations: function.annotations,
113 variant: function.variant,
114 identifier: function.identifier,
115 const_parameters: vec![],
116 input: function.input,
117 output: function.output,
118 output_type: function.output_type,
119 block: Block::default(),
120 span: function.span,
121 id: function.id,
122 }
123 }
124}
125
126impl fmt::Debug for Function {
127 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128 write!(f, "{self}")
129 }
130}
131
132impl fmt::Display for Function {
133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 for annotation in &self.annotations {
135 writeln!(f, "{annotation}")?;
136 }
137
138 match self.variant {
139 Variant::FinalFn => write!(f, "final fn ")?,
140 Variant::Fn => write!(f, "fn ")?,
141 Variant::Finalize => write!(f, "finalize ")?,
142 Variant::EntryPoint => write!(f, "fn ")?,
143 }
144
145 write!(f, "{}", self.identifier)?;
146 if !self.const_parameters.is_empty() {
147 write!(f, "::[{}]", self.const_parameters.iter().format(", "))?;
148 }
149 write!(f, "({})", self.input.iter().format(", "))?;
150
151 match self.output.len() {
152 0 => {}
153 1 => {
154 if !matches!(self.output[0].type_, Type::Unit) {
155 write!(f, " -> {}", self.output[0])?;
156 }
157 }
158 _ => {
159 write!(f, " -> ({})", self.output.iter().format(", "))?;
160 }
161 }
162
163 writeln!(f, " {{")?;
164 for stmt in self.block.statements.iter() {
165 writeln!(f, "{}{}", Indent(stmt), stmt.semicolon())?;
166 }
167 write!(f, "}}")
168 }
169}
170
171crate::simple_node_impl!(Function);