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::{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        matches!(self, Statement::Block(block) if block.statements.is_empty())
88    }
89}
90
91impl fmt::Display for Statement {
92    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93        match self {
94            Statement::Assert(x) => x.fmt(f),
95            Statement::Assign(x) => x.fmt(f),
96            Statement::Block(x) => x.fmt(f),
97            Statement::Conditional(x) => x.fmt(f),
98            Statement::Const(x) => x.fmt(f),
99            Statement::Definition(x) => x.fmt(f),
100            Statement::Expression(x) => x.fmt(f),
101            Statement::Iteration(x) => x.fmt(f),
102            Statement::Return(x) => x.fmt(f),
103        }
104    }
105}
106
107impl Node for Statement {
108    fn span(&self) -> Span {
109        use Statement::*;
110        match self {
111            Assert(n) => n.span(),
112            Assign(n) => n.span(),
113            Block(n) => n.span(),
114            Conditional(n) => n.span(),
115            Const(n) => n.span(),
116            Definition(n) => n.span(),
117            Expression(n) => n.span(),
118            Iteration(n) => n.span(),
119            Return(n) => n.span(),
120        }
121    }
122
123    fn set_span(&mut self, span: Span) {
124        use Statement::*;
125        match self {
126            Assert(n) => n.set_span(span),
127            Assign(n) => n.set_span(span),
128            Block(n) => n.set_span(span),
129            Conditional(n) => n.set_span(span),
130            Const(n) => n.set_span(span),
131            Definition(n) => n.set_span(span),
132            Expression(n) => n.set_span(span),
133            Iteration(n) => n.set_span(span),
134            Return(n) => n.set_span(span),
135        }
136    }
137
138    fn id(&self) -> NodeID {
139        use Statement::*;
140        match self {
141            Assert(n) => n.id(),
142            Assign(n) => n.id(),
143            Block(n) => n.id(),
144            Conditional(n) => n.id(),
145            Const(n) => n.id(),
146            Definition(n) => n.id(),
147            Expression(n) => n.id(),
148            Iteration(n) => n.id(),
149            Return(n) => n.id(),
150        }
151    }
152
153    fn set_id(&mut self, id: NodeID) {
154        use Statement::*;
155        match self {
156            Assert(n) => n.set_id(id),
157            Assign(n) => n.set_id(id),
158            Block(n) => n.set_id(id),
159            Conditional(n) => n.set_id(id),
160            Const(n) => n.set_id(id),
161            Definition(n) => n.set_id(id),
162            Expression(n) => n.set_id(id),
163            Iteration(n) => n.set_id(id),
164            Return(n) => n.set_id(id),
165        }
166    }
167}