Skip to main content

leo_ast/stub/
mod.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
17//! A stub contains function templates as well as definitions for mappings, composites, records, and constants.
18
19pub mod function_stub;
20pub use function_stub::*;
21
22use crate::{Composite, ConstDeclaration, Identifier, Indent, Library, Mapping, NodeID, Program, ProgramId};
23use indexmap::IndexSet;
24use leo_span::{Span, Symbol};
25use serde::{Deserialize, Serialize};
26use std::fmt;
27
28#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
29pub enum Stub {
30    /// A dependency that is a Leo program.
31    FromLeo {
32        program: Program,
33        parents: IndexSet<Symbol>, // These are the names of all the programs that import this dependency.
34    },
35    /// A dependency that is an Aleo program.
36    FromAleo {
37        program: AleoProgram,
38        parents: IndexSet<Symbol>, // These are the names of all the programs that import this dependency.
39    },
40    /// A dependency that is a Leo library.
41    FromLibrary {
42        library: Library,
43        parents: IndexSet<Symbol>, // These are the names of all the programs that import this dependency.
44    },
45}
46
47impl Stub {
48    /// Returns the programs that this stub imports using explicit `import`s. Note that library
49    /// imports are implicit so they do not show up in this returned iterator.
50    pub fn explicit_imports(&self) -> Box<dyn Iterator<Item = (Symbol, Span)> + '_> {
51        match self {
52            Stub::FromLeo { program, .. } => Box::new(program.imports.iter().map(|(sym, id)| (*sym, id.span()))),
53            Stub::FromAleo { program, .. } => {
54                Box::new(program.imports.iter().map(|id| (id.as_symbol(), Span::default())))
55            }
56            Stub::FromLibrary { .. } => Box::new(std::iter::empty()),
57        }
58    }
59
60    /// Returns the set of parent symbols for this stub.
61    pub fn parents(&self) -> &IndexSet<Symbol> {
62        match self {
63            Stub::FromLeo { parents, .. } => parents,
64            Stub::FromAleo { parents, .. } => parents,
65            Stub::FromLibrary { parents, .. } => parents,
66        }
67    }
68
69    /// Inserts the given program name as a parent for this stub, implying that the stub is
70    /// imported by this parent.
71    pub fn add_parent(&mut self, parent: Symbol) {
72        match self {
73            Stub::FromLeo { parents, .. } | Stub::FromAleo { parents, .. } | Stub::FromLibrary { parents, .. } => {
74                parents.insert(parent);
75            }
76        }
77    }
78
79    /// Does this `Stub` represent a Leo program?
80    pub fn is_leo_program(&self) -> bool {
81        matches!(self, Self::FromLeo { .. })
82    }
83
84    /// Does this `Stub` represent an Aleo program?
85    pub fn is_aleo_program(&self) -> bool {
86        matches!(self, Self::FromAleo { .. })
87    }
88
89    /// Does this `Stub` represent a library?
90    pub fn is_library(&self) -> bool {
91        matches!(self, Self::FromLibrary { .. })
92    }
93}
94
95impl fmt::Display for Stub {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        match self {
98            Stub::FromLeo { program, .. } => write!(f, "{program}"),
99            Stub::FromAleo { program, .. } => write!(f, "{program}"),
100            Stub::FromLibrary { library, .. } => write!(f, "{library}"),
101        }
102    }
103}
104
105impl From<Program> for Stub {
106    fn from(program: Program) -> Self {
107        Stub::FromLeo { program, parents: IndexSet::new() }
108    }
109}
110
111impl From<AleoProgram> for Stub {
112    fn from(program: AleoProgram) -> Self {
113        Stub::FromAleo { program, parents: IndexSet::new() }
114    }
115}
116
117impl From<Library> for Stub {
118    fn from(library: Library) -> Self {
119        Stub::FromLibrary { library, parents: IndexSet::new() }
120    }
121}
122
123/// Stores the Leo stub abstract syntax tree.
124#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
125pub struct AleoProgram {
126    /// A vector of imported programs.
127    pub imports: Vec<ProgramId>,
128    /// The stub id
129    pub stub_id: ProgramId,
130    /// A vector of const definitions.
131    pub consts: Vec<(Symbol, ConstDeclaration)>,
132    /// A vector of composite definitions.
133    pub composites: Vec<(Symbol, Composite)>,
134    /// A vector of mapping definitions.
135    pub mappings: Vec<(Symbol, Mapping)>,
136    /// A vector of function stub definitions.
137    pub functions: Vec<(Symbol, FunctionStub)>,
138    /// The span associated with the stub.
139    pub span: Span,
140}
141
142impl Default for AleoProgram {
143    /// Constructs an empty program stub
144    fn default() -> Self {
145        Self {
146            imports: Vec::new(),
147            stub_id: ProgramId {
148                name: Identifier::new(Symbol::intern(""), NodeID::default()),
149                network: Identifier::new(Symbol::intern(""), NodeID::default()),
150            },
151            consts: Vec::new(),
152            composites: Vec::new(),
153            mappings: Vec::new(),
154            functions: Vec::new(),
155            span: Span::default(),
156        }
157    }
158}
159
160impl fmt::Display for AleoProgram {
161    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162        writeln!(f, "stub {} {{", self.stub_id)?;
163        for import in self.imports.iter() {
164            writeln!(f, "    import {import};")?;
165        }
166        for (_, mapping) in self.mappings.iter() {
167            writeln!(f, "{};", Indent(mapping))?;
168        }
169        for (_, composite) in self.composites.iter() {
170            writeln!(f, "{}", Indent(composite))?;
171        }
172        for (_, function) in self.functions.iter() {
173            writeln!(f, "{}", Indent(function))?;
174        }
175        write!(f, "}}")
176    }
177}