]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/ast/rust-stmt.h
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / ast / rust-stmt.h
CommitLineData
83ffe9cd 1// Copyright (C) 2020-2023 Free Software Foundation, Inc.
d588754c
JP
2
3// This file is part of GCC.
4
5// GCC is free software; you can redistribute it and/or modify it under
6// the terms of the GNU General Public License as published by the Free
7// Software Foundation; either version 3, or (at your option) any later
8// version.
9
10// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13// for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with GCC; see the file COPYING3. If not see
17// <http://www.gnu.org/licenses/>.
18
19#ifndef RUST_AST_STATEMENT_H
20#define RUST_AST_STATEMENT_H
21
22#include "rust-ast.h"
23#include "rust-path.h"
24#include "rust-expr.h"
25
26namespace Rust {
27namespace AST {
28// Just a semi-colon, which apparently is a statement.
29class EmptyStmt : public Stmt
30{
31 Location locus;
32
33 // TODO: find another way to store this to save memory?
34 bool marked_for_strip = false;
35
36public:
37 std::string as_string () const override { return std::string (1, ';'); }
38
39 EmptyStmt (Location locus) : locus (locus) {}
40
41 Location get_locus () const override final { return locus; }
42
43 void accept_vis (ASTVisitor &vis) override;
44
45 // Can't think of any invalid invariants, so store boolean.
46 void mark_for_strip () override { marked_for_strip = true; }
47 bool is_marked_for_strip () const override { return marked_for_strip; }
48
49 bool is_item () const override final { return false; }
50
51protected:
52 /* Use covariance to implement clone function as returning this object rather
53 * than base */
54 EmptyStmt *clone_stmt_impl () const override { return new EmptyStmt (*this); }
55};
56
57/* Variable assignment let statement - type of "declaration statement" as it
58 * introduces new name into scope */
59class LetStmt : public Stmt
60{
61 // bool has_outer_attrs;
62 std::vector<Attribute> outer_attrs;
63
64 std::unique_ptr<Pattern> variables_pattern;
65
66 // bool has_type;
67 std::unique_ptr<Type> type;
68
69 // bool has_init_expr;
70 std::unique_ptr<Expr> init_expr;
71
72 Location locus;
73
74public:
75 Type *inferedType;
76
77 // Returns whether let statement has outer attributes.
78 bool has_outer_attrs () const { return !outer_attrs.empty (); }
79
80 // Returns whether let statement has a given return type.
81 bool has_type () const { return type != nullptr; }
82
83 // Returns whether let statement has an initialisation expression.
84 bool has_init_expr () const { return init_expr != nullptr; }
85
86 std::string as_string () const override;
87
88 LetStmt (std::unique_ptr<Pattern> variables_pattern,
89 std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
90 std::vector<Attribute> outer_attrs, Location locus)
91 : outer_attrs (std::move (outer_attrs)),
92 variables_pattern (std::move (variables_pattern)),
93 type (std::move (type)), init_expr (std::move (init_expr)), locus (locus)
94 {}
95
96 // Copy constructor with clone
97 LetStmt (LetStmt const &other)
98 : outer_attrs (other.outer_attrs), locus (other.locus)
99 {
100 // guard to prevent null dereference (only required if error state)
101 if (other.variables_pattern != nullptr)
102 variables_pattern = other.variables_pattern->clone_pattern ();
103
104 // guard to prevent null dereference (always required)
105 if (other.init_expr != nullptr)
106 init_expr = other.init_expr->clone_expr ();
107 if (other.type != nullptr)
108 type = other.type->clone_type ();
109 }
110
111 // Overloaded assignment operator to clone
112 LetStmt &operator= (LetStmt const &other)
113 {
114 outer_attrs = other.outer_attrs;
115 locus = other.locus;
116
117 // guard to prevent null dereference (only required if error state)
118 if (other.variables_pattern != nullptr)
119 variables_pattern = other.variables_pattern->clone_pattern ();
120 else
121 variables_pattern = nullptr;
122
123 // guard to prevent null dereference (always required)
124 if (other.init_expr != nullptr)
125 init_expr = other.init_expr->clone_expr ();
126 else
127 init_expr = nullptr;
128 if (other.type != nullptr)
129 type = other.type->clone_type ();
130 else
131 type = nullptr;
132
133 return *this;
134 }
135
136 // move constructors
137 LetStmt (LetStmt &&other) = default;
138 LetStmt &operator= (LetStmt &&other) = default;
139
140 Location get_locus () const override final { return locus; }
141
142 void accept_vis (ASTVisitor &vis) override;
143
144 // Invalid if pattern is null, so base stripping on that.
145 void mark_for_strip () override { variables_pattern = nullptr; }
146 bool is_marked_for_strip () const override
147 {
148 return variables_pattern == nullptr;
149 }
150
151 // TODO: this mutable getter seems really dodgy. Think up better way.
152 std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
153 const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
154
155 // TODO: is this better? Or is a "vis_block" better?
156 std::unique_ptr<Expr> &get_init_expr ()
157 {
158 rust_assert (has_init_expr ());
159 return init_expr;
160 }
161
162 std::unique_ptr<Pattern> &get_pattern ()
163 {
164 rust_assert (variables_pattern != nullptr);
165 return variables_pattern;
166 }
167
168 std::unique_ptr<Type> &get_type ()
169 {
170 rust_assert (has_type ());
171 return type;
172 }
173
174 bool is_item () const override final { return false; }
175
176protected:
177 /* Use covariance to implement clone function as returning this object rather
178 * than base */
179 LetStmt *clone_stmt_impl () const override { return new LetStmt (*this); }
180};
181
182/* Abstract base class for expression statements (statements containing an
183 * expression) */
184class ExprStmt : public Stmt
185{
186public:
187 enum ExprStmtType
188 {
189 WITH_BLOCK,
190 WITHOUT_BLOCK
191 };
192
193protected:
194 Location locus;
195
196public:
197 Location get_locus () const override final { return locus; }
198
199 bool is_item () const override final { return false; }
200
201 virtual ExprStmtType get_type () const = 0;
202
203protected:
204 ExprStmt (Location locus) : locus (locus) {}
205};
206
207/* Statement containing an expression without a block (or, due to technical
208 * difficulties, can only be guaranteed to hold an expression). */
209class ExprStmtWithoutBlock : public ExprStmt
210{
211 // TODO: ensure that this works
212 std::unique_ptr<ExprWithoutBlock> expr;
213 /* HACK: cannot ensure type safety of ExprWithoutBlock due to Pratt parsing,
214 * so have to store more general type of Expr. FIXME: fix this issue somehow
215 * or redesign AST. */
216 // std::unique_ptr<Expr> expr;
217
218public:
219 std::string as_string () const override;
220
221 ExprStmtWithoutBlock (std::unique_ptr<ExprWithoutBlock> expr, Location locus)
222 : ExprStmt (locus), expr (std::move (expr->to_stmt ()))
223 {}
224
225 /*ExprStmtWithoutBlock (std::unique_ptr<Expr> expr, Location locus)
226 : ExprStmt (locus), expr (std::move (expr))
227 {}*/
228
229 // Copy constructor with clone
230 ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) : ExprStmt (other)
231 {
232 // guard to prevent null dereference (only required if error state)
233 if (other.expr != nullptr)
234 expr = other.expr->clone_expr_without_block ();
235 }
236 /*ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other)
237 : ExprStmt (other), expr (other.expr->clone_expr ())
238 {}*/
239
240 // Overloaded assignment operator to clone
241 ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other)
242 {
243 ExprStmt::operator= (other);
244 // expr = other.expr->clone_expr ();
245
246 // guard to prevent null dereference (only required if error state)
247 if (other.expr != nullptr)
248 expr = other.expr->clone_expr_without_block ();
249 else
250 expr = nullptr;
251
252 return *this;
253 }
254
255 // move constructors
256 ExprStmtWithoutBlock (ExprStmtWithoutBlock &&other) = default;
257 ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock &&other) = default;
258
259 void accept_vis (ASTVisitor &vis) override;
260
261 // Invalid if expr is null, so base stripping on that.
262 void mark_for_strip () override { expr = nullptr; }
263 bool is_marked_for_strip () const override { return expr == nullptr; }
264
265 // TODO: is this better? Or is a "vis_block" better?
266 std::unique_ptr<ExprWithoutBlock> &get_expr ()
267 {
268 rust_assert (expr != nullptr);
269 return expr;
270 }
271
272 ExprStmtType get_type () const override
273 {
274 return ExprStmtType::WITHOUT_BLOCK;
275 };
276
277protected:
278 /* Use covariance to implement clone function as returning this object rather
279 * than base */
280 ExprStmtWithoutBlock *clone_stmt_impl () const override
281 {
282 return new ExprStmtWithoutBlock (*this);
283 }
284};
285
286// Statement containing an expression with a block
287class ExprStmtWithBlock : public ExprStmt
288{
289 std::unique_ptr<ExprWithBlock> expr;
290 bool semicolon_followed;
291
292public:
293 std::string as_string () const override;
294
295 std::vector<LetStmt *> locals;
296
297 ExprStmtWithBlock (std::unique_ptr<ExprWithBlock> expr, Location locus,
298 bool semicolon_followed)
299 : ExprStmt (locus), expr (std::move (expr)),
300 semicolon_followed (semicolon_followed)
301 {}
302
303 // Copy constructor with clone
304 ExprStmtWithBlock (ExprStmtWithBlock const &other) : ExprStmt (other)
305 {
306 // guard to prevent null dereference (only required if error state)
307 if (other.expr != nullptr)
308 expr = other.expr->clone_expr_with_block ();
309 }
310
311 // Overloaded assignment operator to clone
312 ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other)
313 {
314 ExprStmt::operator= (other);
315
316 // guard to prevent null dereference (only required if error state)
317 if (other.expr != nullptr)
318 expr = other.expr->clone_expr_with_block ();
319 else
320 expr = nullptr;
321
322 return *this;
323 }
324
325 // move constructors
326 ExprStmtWithBlock (ExprStmtWithBlock &&other) = default;
327 ExprStmtWithBlock &operator= (ExprStmtWithBlock &&other) = default;
328
329 void accept_vis (ASTVisitor &vis) override;
330
331 // Invalid if expr is null, so base stripping on that.
332 void mark_for_strip () override { expr = nullptr; }
333 bool is_marked_for_strip () const override { return expr == nullptr; }
334
335 // TODO: is this better? Or is a "vis_block" better?
336 std::unique_ptr<ExprWithBlock> &get_expr ()
337 {
338 rust_assert (expr != nullptr);
339 return expr;
340 }
341
342 bool is_semicolon_followed () const { return semicolon_followed; }
343
344 ExprStmtType get_type () const override { return ExprStmtType::WITH_BLOCK; };
345
346protected:
347 /* Use covariance to implement clone function as returning this object rather
348 * than base */
349 ExprStmtWithBlock *clone_stmt_impl () const override
350 {
351 return new ExprStmtWithBlock (*this);
352 }
353};
354
355} // namespace AST
356} // namespace Rust
357
358#endif