leo_ast/statement/
mod.rs

1// Copyright (C) 2019-2025 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::{Deserialize, Serialize};
49use std::fmt;
50
51/// Program statement that defines some action (or expression) to be carried out.
52#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, 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    pub fn is_empty(self: &Statement) -> bool {
87        match self {
88            Statement::Block(block) => block.statements.is_empty(),
89            Statement::Return(return_) => matches!(return_.expression, Expression::Unit(_)),
90            _ => false,
91        }
92    }
93}
94
95impl fmt::Display for Statement {
96    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97        match self {
98            Statement::Assert(x) => x.fmt(f),
99            Statement::Assign(x) => x.fmt(f),
100            Statement::Block(x) => x.fmt(f),
101            Statement::Conditional(x) => x.fmt(f),
102            Statement::Const(x) => x.fmt(f),
103            Statement::Definition(x) => x.fmt(f),
104            Statement::Expression(x) => x.fmt(f),
105            Statement::Iteration(x) => x.fmt(f),
106            Statement::Return(x) => x.fmt(f),
107        }
108    }
109}
110
111impl Node for Statement {
112    fn span(&self) -> Span {
113        use Statement::*;
114        match self {
115            Assert(n) => n.span(),
116            Assign(n) => n.span(),
117            Block(n) => n.span(),
118            Conditional(n) => n.span(),
119            Const(n) => n.span(),
120            Definition(n) => n.span(),
121            Expression(n) => n.span(),
122            Iteration(n) => n.span(),
123            Return(n) => n.span(),
124        }
125    }
126
127    fn set_span(&mut self, span: Span) {
128        use Statement::*;
129        match self {
130            Assert(n) => n.set_span(span),
131            Assign(n) => n.set_span(span),
132            Block(n) => n.set_span(span),
133            Conditional(n) => n.set_span(span),
134            Const(n) => n.set_span(span),
135            Definition(n) => n.set_span(span),
136            Expression(n) => n.set_span(span),
137            Iteration(n) => n.set_span(span),
138            Return(n) => n.set_span(span),
139        }
140    }
141
142    fn id(&self) -> NodeID {
143        use Statement::*;
144        match self {
145            Assert(n) => n.id(),
146            Assign(n) => n.id(),
147            Block(n) => n.id(),
148            Conditional(n) => n.id(),
149            Const(n) => n.id(),
150            Definition(n) => n.id(),
151            Expression(n) => n.id(),
152            Iteration(n) => n.id(),
153            Return(n) => n.id(),
154        }
155    }
156
157    fn set_id(&mut self, id: NodeID) {
158        use Statement::*;
159        match self {
160            Assert(n) => n.set_id(id),
161            Assign(n) => n.set_id(id),
162            Block(n) => n.set_id(id),
163            Conditional(n) => n.set_id(id),
164            Const(n) => n.set_id(id),
165            Definition(n) => n.set_id(id),
166            Expression(n) => n.set_id(id),
167            Iteration(n) => n.set_id(id),
168            Return(n) => n.set_id(id),
169        }
170    }
171}