Skip to main content

leo_ast/statement/
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
17mod assert;
18pub use assert::*;
19
20mod assign;
21pub use assign::*;
22
23mod block;
24pub use block::*;
25
26mod conditional;
27pub use conditional::*;
28
29mod const_;
30pub use const_::*;
31
32mod definition;
33pub use definition::*;
34
35mod expression;
36pub use expression::*;
37
38mod iteration;
39pub use iteration::*;
40
41mod return_;
42pub use return_::*;
43
44use crate::{Expression, Node, NodeID};
45
46use leo_span::Span;
47
48use serde::Serialize;
49use std::fmt;
50
51/// Program statement that defines some action (or expression) to be carried out.
52#[derive(Clone, PartialEq, Eq, Hash, Serialize, Debug)]
53pub enum Statement {
54    /// An assert statement.
55    Assert(AssertStatement),
56    /// An assignment statement.
57    Assign(Box<AssignStatement>),
58    /// A block statement.
59    Block(Block),
60    /// An `if` statement.
61    Conditional(ConditionalStatement),
62    /// A binding from identifier to constant value.
63    Const(ConstDeclaration),
64    /// A binding or set of bindings / variables to declare.
65    Definition(DefinitionStatement),
66    /// An expression statement
67    Expression(ExpressionStatement),
68    /// A `for` statement.
69    Iteration(Box<IterationStatement>),
70    /// A return statement `return expr;`.
71    Return(ReturnStatement),
72}
73
74impl Statement {
75    /// Returns a dummy statement made from an empty block `{}`.
76    pub fn dummy() -> Self {
77        Block { statements: Vec::new(), span: Default::default(), id: Default::default() }.into()
78    }
79
80    pub(crate) fn semicolon(&self) -> &'static str {
81        use Statement::*;
82
83        if matches!(self, Block(..) | Conditional(..) | Iteration(..)) { "" } else { ";" }
84    }
85
86    /// Returns `true` if the statement produces no instructions
87    pub fn is_empty(self: &Statement) -> bool {
88        match self {
89            Statement::Block(block) => block.statements.is_empty(),
90            Statement::Return(return_) => matches!(return_.expression, Expression::Unit(_)),
91            _ => false,
92        }
93    }
94
95    /// Returns `true` if the statement can be removed from a block without changing behavior.
96    pub fn is_removable(self: &Statement) -> bool {
97        self.is_empty() && !matches!(self, Statement::Return(_))
98    }
99}
100
101impl fmt::Display for Statement {
102    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103        match self {
104            Statement::Assert(x) => x.fmt(f),
105            Statement::Assign(x) => x.fmt(f),
106            Statement::Block(x) => x.fmt(f),
107            Statement::Conditional(x) => x.fmt(f),
108            Statement::Const(x) => x.fmt(f),
109            Statement::Definition(x) => x.fmt(f),
110            Statement::Expression(x) => x.fmt(f),
111            Statement::Iteration(x) => x.fmt(f),
112            Statement::Return(x) => x.fmt(f),
113        }
114    }
115}
116
117impl Node for Statement {
118    fn span(&self) -> Span {
119        use Statement::*;
120        match self {
121            Assert(n) => n.span(),
122            Assign(n) => n.span(),
123            Block(n) => n.span(),
124            Conditional(n) => n.span(),
125            Const(n) => n.span(),
126            Definition(n) => n.span(),
127            Expression(n) => n.span(),
128            Iteration(n) => n.span(),
129            Return(n) => n.span(),
130        }
131    }
132
133    fn set_span(&mut self, span: Span) {
134        use Statement::*;
135        match self {
136            Assert(n) => n.set_span(span),
137            Assign(n) => n.set_span(span),
138            Block(n) => n.set_span(span),
139            Conditional(n) => n.set_span(span),
140            Const(n) => n.set_span(span),
141            Definition(n) => n.set_span(span),
142            Expression(n) => n.set_span(span),
143            Iteration(n) => n.set_span(span),
144            Return(n) => n.set_span(span),
145        }
146    }
147
148    fn id(&self) -> NodeID {
149        use Statement::*;
150        match self {
151            Assert(n) => n.id(),
152            Assign(n) => n.id(),
153            Block(n) => n.id(),
154            Conditional(n) => n.id(),
155            Const(n) => n.id(),
156            Definition(n) => n.id(),
157            Expression(n) => n.id(),
158            Iteration(n) => n.id(),
159            Return(n) => n.id(),
160        }
161    }
162
163    fn set_id(&mut self, id: NodeID) {
164        use Statement::*;
165        match self {
166            Assert(n) => n.set_id(id),
167            Assign(n) => n.set_id(id),
168            Block(n) => n.set_id(id),
169            Conditional(n) => n.set_id(id),
170            Const(n) => n.set_id(id),
171            Definition(n) => n.set_id(id),
172            Expression(n) => n.set_id(id),
173            Iteration(n) => n.set_id(id),
174            Return(n) => n.set_id(id),
175        }
176    }
177}