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#[derive(Clone, Default, Serialize, Deserialize)]
37pub struct FunctionPrototype {
38    /// Annotations on the function.
39    pub annotations: Vec<Annotation>,
40    /// The function identifier, e.g., `foo` in `function foo(...) { ... }`.
41    pub identifier: Identifier,
42    /// The function's const parameters.
43    pub const_parameters: Vec<ConstParameter>,
44    /// The function's input parameters.
45    pub input: Vec<Input>,
46    /// The function's output declarations.
47    pub output: Vec<Output>,
48    /// The function's output type.
49    pub output_type: Type,
50    /// The entire span of the function definition.
51    pub span: Span,
52    /// The ID of the node.
53    pub id: NodeID,
54}
55
56impl FunctionPrototype {
57    #[allow(clippy::too_many_arguments)]
58    pub fn new(
59        annotations: Vec<Annotation>,
60        identifier: Identifier,
61        const_parameters: Vec<ConstParameter>,
62        input: Vec<Input>,
63        output: Vec<Output>,
64        span: Span,
65        id: NodeID,
66    ) -> Self {
67        let output_type = match output.len() {
68            0 => Type::Unit,
69            1 => output[0].type_.clone(),
70            _ => Type::Tuple(TupleType::new(output.iter().map(|o| o.type_.clone()).collect())),
71        };
72
73        Self { annotations, identifier, const_parameters, input, output, output_type, span, id }
74    }
75}
76
77impl PartialEq for FunctionPrototype {
78    fn eq(&self, other: &Self) -> bool {
79        self.identifier == other.identifier
80    }
81}
82
83impl Eq for FunctionPrototype {}
84
85impl fmt::Debug for FunctionPrototype {
86    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87        write!(f, "{self}")
88    }
89}
90
91impl fmt::Display for FunctionPrototype {
92    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93        for annotation in &self.annotations {
94            writeln!(f, "{annotation}")?;
95        }
96        write!(f, "fn {}", self.identifier)?;
97        if !self.const_parameters.is_empty() {
98            write!(f, "::[{}]", self.const_parameters.iter().format(", "))?;
99        }
100        write!(f, "({})", self.input.iter().format(", "))?;
101        match self.output.len() {
102            0 => {}
103            1 => {
104                if !matches!(self.output[0].type_, Type::Unit) {
105                    write!(f, " -> {}", self.output[0])?;
106                }
107            }
108            _ => {
109                write!(f, " -> ({})", self.output.iter().format(", "))?;
110            }
111        }
112        write!(f, ";")
113    }
114}
115
116crate::simple_node_impl!(FunctionPrototype);
117
118#[derive(Clone, Default, Serialize, Deserialize)]
119pub struct RecordPrototype {
120    /// The record identifier
121    pub identifier: Identifier,
122    /// The fields of this record prototype, if any.
123    pub members: Vec<Member>,
124    /// The entire span of the composite definition.
125    pub span: Span,
126    /// The ID of the node.
127    pub id: NodeID,
128}
129
130impl PartialEq for RecordPrototype {
131    fn eq(&self, other: &Self) -> bool {
132        self.identifier == other.identifier
133    }
134}
135
136impl Eq for RecordPrototype {}
137
138impl fmt::Debug for RecordPrototype {
139    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140        write!(f, "{self}")
141    }
142}
143
144impl fmt::Display for RecordPrototype {
145    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146        writeln!(f, " record {} {{", self.identifier)?;
147
148        for field in self.members.iter() {
149            writeln!(f, "{},", Indent(field))?;
150        }
151        write!(f, "}}")
152    }
153}
154
155crate::simple_node_impl!(RecordPrototype);