1mod annotation;
18pub use annotation::*;
19
20mod core_function;
21pub use core_function::*;
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
104impl From<FunctionStub> for Function {
105 fn from(function: FunctionStub) -> Self {
106 Self {
107 annotations: function.annotations,
108 variant: function.variant,
109 identifier: function.identifier,
110 const_parameters: vec![],
111 input: function.input,
112 output: function.output,
113 output_type: function.output_type,
114 block: Block::default(),
115 span: function.span,
116 id: function.id,
117 }
118 }
119}
120
121impl fmt::Debug for Function {
122 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123 write!(f, "{self}")
124 }
125}
126
127impl fmt::Display for Function {
128 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129 for annotation in &self.annotations {
130 writeln!(f, "{annotation}")?;
131 }
132
133 match self.variant {
134 Variant::Inline => write!(f, "inline ")?,
135 Variant::Function => write!(f, "function ")?,
136 Variant::AsyncFunction => write!(f, "async function ")?,
137 Variant::Transition => write!(f, "transition ")?,
138 Variant::AsyncTransition => write!(f, "async transition ")?,
139 Variant::Script => write!(f, "script ")?,
140 }
141
142 write!(f, "{}", self.identifier)?;
143 if !self.const_parameters.is_empty() {
144 write!(f, "::[{}]", self.const_parameters.iter().format(", "))?;
145 }
146 write!(f, "({})", self.input.iter().format(", "))?;
147
148 match self.output.len() {
149 0 => {}
150 1 => {
151 if !matches!(self.output[0].type_, Type::Unit) {
152 write!(f, " -> {}", self.output[0])?;
153 }
154 }
155 _ => {
156 write!(f, " -> ({})", self.output.iter().format(", "))?;
157 }
158 }
159
160 writeln!(f, " {{")?;
161 for stmt in self.block.statements.iter() {
162 writeln!(f, "{}{}", Indent(stmt), stmt.semicolon())?;
163 }
164 write!(f, "}}")
165 }
166}
167
168crate::simple_node_impl!(Function);