Skip to main content

leo_ast/interface/
prototypes.rs

1// Copyright (C) 2019-2026 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use std::fmt;
18
19use crate::{
20    Annotation,
21    ConstParameter,
22    Identifier,
23    Input,
24    Member,
25    Node,
26    NodeID,
27    Output,
28    TupleType,
29    Type,
30    indent_display::Indent,
31};
32use itertools::Itertools;
33use leo_span::Span;
34use serde::{Deserialize, Serialize};
35
36/// A mapping prototype in an interface, e.g. `mapping balances: address => u128;`.
37#[derive(Clone, Default, Debug, Serialize, Deserialize)]
38pub struct MappingPrototype {
39    /// The name of the mapping.
40    pub identifier: Identifier,
41    /// The type of the key.
42    pub key_type: Type,
43    /// The type of the value.
44    pub value_type: Type,
45    /// The entire span of the mapping prototype.
46    pub span: Span,
47    /// The ID of the node.
48    pub id: NodeID,
49}
50
51impl PartialEq for MappingPrototype {
52    fn eq(&self, other: &Self) -> bool {
53        self.identifier == other.identifier
54    }
55}
56
57impl Eq for MappingPrototype {}
58
59impl fmt::Display for MappingPrototype {
60    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61        write!(f, "mapping {}: {} => {};", self.identifier, self.key_type, self.value_type)
62    }
63}
64
65crate::simple_node_impl!(MappingPrototype);
66
67/// A storage variable prototype in an interface, e.g. `storage counter: u32;`.
68#[derive(Clone, Default, Debug, Serialize, Deserialize)]
69pub struct StorageVariablePrototype {
70    /// The name of the storage variable.
71    pub identifier: Identifier,
72    /// The type of the variable.
73    pub type_: Type,
74    /// The entire span of the storage variable prototype.
75    pub span: Span,
76    /// The ID of the node.
77    pub id: NodeID,
78}
79
80impl PartialEq for StorageVariablePrototype {
81    fn eq(&self, other: &Self) -> bool {
82        self.identifier == other.identifier
83    }
84}
85
86impl Eq for StorageVariablePrototype {}
87
88impl fmt::Display for StorageVariablePrototype {
89    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90        write!(f, "storage {}: {};", self.identifier, self.type_)
91    }
92}
93
94crate::simple_node_impl!(StorageVariablePrototype);
95
96#[derive(Clone, Default, Serialize, Deserialize)]
97pub struct FunctionPrototype {
98    /// Annotations on the function.
99    pub annotations: Vec<Annotation>,
100    /// The function identifier, e.g., `foo` in `function foo(...) { ... }`.
101    pub identifier: Identifier,
102    /// The function's const parameters.
103    pub const_parameters: Vec<ConstParameter>,
104    /// The function's input parameters.
105    pub input: Vec<Input>,
106    /// The function's output declarations.
107    pub output: Vec<Output>,
108    /// The function's output type.
109    pub output_type: Type,
110    /// The entire span of the function definition.
111    pub span: Span,
112    /// The ID of the node.
113    pub id: NodeID,
114}
115
116impl FunctionPrototype {
117    #[allow(clippy::too_many_arguments)]
118    pub fn new(
119        annotations: Vec<Annotation>,
120        identifier: Identifier,
121        const_parameters: Vec<ConstParameter>,
122        input: Vec<Input>,
123        output: Vec<Output>,
124        span: Span,
125        id: NodeID,
126    ) -> Self {
127        let output_type = match output.len() {
128            0 => Type::Unit,
129            1 => output[0].type_.clone(),
130            _ => Type::Tuple(TupleType::new(output.iter().map(|o| o.type_.clone()).collect())),
131        };
132
133        Self { annotations, identifier, const_parameters, input, output, output_type, span, id }
134    }
135}
136
137impl PartialEq for FunctionPrototype {
138    fn eq(&self, other: &Self) -> bool {
139        self.identifier == other.identifier
140    }
141}
142
143impl Eq for FunctionPrototype {}
144
145impl fmt::Debug for FunctionPrototype {
146    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147        write!(f, "{self}")
148    }
149}
150
151impl fmt::Display for FunctionPrototype {
152    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
153        for annotation in &self.annotations {
154            writeln!(f, "{annotation}")?;
155        }
156        write!(f, "fn {}", self.identifier)?;
157        if !self.const_parameters.is_empty() {
158            write!(f, "::[{}]", self.const_parameters.iter().format(", "))?;
159        }
160        write!(f, "({})", self.input.iter().format(", "))?;
161        match self.output.len() {
162            0 => {}
163            1 => {
164                if !matches!(self.output[0].type_, Type::Unit) {
165                    write!(f, " -> {}", self.output[0])?;
166                }
167            }
168            _ => {
169                write!(f, " -> ({})", self.output.iter().format(", "))?;
170            }
171        }
172        write!(f, ";")
173    }
174}
175
176crate::simple_node_impl!(FunctionPrototype);
177
178#[derive(Clone, Default, Serialize, Deserialize)]
179pub struct RecordPrototype {
180    /// The record identifier
181    pub identifier: Identifier,
182    /// The fields of this record prototype, if any.
183    pub members: Vec<Member>,
184    /// The entire span of the composite definition.
185    pub span: Span,
186    /// The ID of the node.
187    pub id: NodeID,
188}
189
190impl PartialEq for RecordPrototype {
191    fn eq(&self, other: &Self) -> bool {
192        self.identifier == other.identifier
193    }
194}
195
196impl Eq for RecordPrototype {}
197
198impl fmt::Debug for RecordPrototype {
199    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200        write!(f, "{self}")
201    }
202}
203
204impl fmt::Display for RecordPrototype {
205    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
206        writeln!(f, " record {} {{", self.identifier)?;
207
208        for field in self.members.iter() {
209            writeln!(f, "{},", Indent(field))?;
210        }
211        write!(f, "}}")
212    }
213}
214
215crate::simple_node_impl!(RecordPrototype);