Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 Free Software Foundation, Inc.
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 : : #include <memory>
26 : :
27 : : namespace Rust {
28 : : namespace AST {
29 : : // Just a semi-colon, which apparently is a statement.
30 : 140 : class EmptyStmt : public Stmt
31 : : {
32 : : location_t locus;
33 : :
34 : : // TODO: find another way to store this to save memory?
35 : : bool marked_for_strip = false;
36 : :
37 : : public:
38 : 0 : std::string as_string () const override { return std::string (1, ';'); }
39 : :
40 : 47 : EmptyStmt (location_t locus) : locus (locus) {}
41 : :
42 : 45 : location_t get_locus () const override final { return locus; }
43 : :
44 : : void accept_vis (ASTVisitor &vis) override;
45 : :
46 : : // Can't think of any invalid invariants, so store boolean.
47 : 0 : void mark_for_strip () override { marked_for_strip = true; }
48 : 160 : bool is_marked_for_strip () const override { return marked_for_strip; }
49 : :
50 : 90 : bool is_item () const override final { return false; }
51 : :
52 : 132 : Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Empty; }
53 : :
54 : : protected:
55 : : /* Use covariance to implement clone function as returning this object rather
56 : : * than base */
57 : 140 : EmptyStmt *clone_stmt_impl () const override { return new EmptyStmt (*this); }
58 : : };
59 : :
60 : : /* Variable assignment let statement - type of "declaration statement" as it
61 : : * introduces new name into scope */
62 : : class LetStmt : public Stmt
63 : : {
64 : : // bool has_outer_attrs;
65 : : std::vector<Attribute> outer_attrs;
66 : :
67 : : std::unique_ptr<Pattern> variables_pattern;
68 : :
69 : : // bool has_type;
70 : : std::unique_ptr<Type> type;
71 : :
72 : : // bool has_init_expr;
73 : : std::unique_ptr<Expr> init_expr;
74 : :
75 : : location_t locus;
76 : :
77 : : public:
78 : : Type *inferedType;
79 : :
80 : : // Returns whether let statement has outer attributes.
81 : : bool has_outer_attrs () const { return !outer_attrs.empty (); }
82 : :
83 : : // Returns whether let statement has a given return type.
84 : 113926 : bool has_type () const { return type != nullptr; }
85 : :
86 : : // Returns whether let statement has an initialisation expression.
87 : 113926 : bool has_init_expr () const { return init_expr != nullptr; }
88 : :
89 : : std::string as_string () const override;
90 : :
91 : 10401 : LetStmt (std::unique_ptr<Pattern> variables_pattern,
92 : : std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
93 : : std::vector<Attribute> outer_attrs, location_t locus)
94 : 20802 : : outer_attrs (std::move (outer_attrs)),
95 : 10401 : variables_pattern (std::move (variables_pattern)),
96 : 10401 : type (std::move (type)), init_expr (std::move (init_expr)), locus (locus)
97 : 10401 : {}
98 : :
99 : : // Copy constructor with clone
100 : 679 : LetStmt (LetStmt const &other)
101 : 679 : : outer_attrs (other.outer_attrs), locus (other.locus)
102 : : {
103 : : // guard to prevent null dereference (only required if error state)
104 : 679 : if (other.variables_pattern != nullptr)
105 : 679 : variables_pattern = other.variables_pattern->clone_pattern ();
106 : :
107 : : // guard to prevent null dereference (always required)
108 : 679 : if (other.init_expr != nullptr)
109 : 673 : init_expr = other.init_expr->clone_expr ();
110 : 679 : if (other.type != nullptr)
111 : 6 : type = other.type->clone_type ();
112 : 679 : }
113 : :
114 : : // Overloaded assignment operator to clone
115 : : LetStmt &operator= (LetStmt const &other)
116 : : {
117 : : outer_attrs = other.outer_attrs;
118 : : locus = other.locus;
119 : :
120 : : // guard to prevent null dereference (only required if error state)
121 : : if (other.variables_pattern != nullptr)
122 : : variables_pattern = other.variables_pattern->clone_pattern ();
123 : : else
124 : : variables_pattern = nullptr;
125 : :
126 : : // guard to prevent null dereference (always required)
127 : : if (other.init_expr != nullptr)
128 : : init_expr = other.init_expr->clone_expr ();
129 : : else
130 : : init_expr = nullptr;
131 : : if (other.type != nullptr)
132 : : type = other.type->clone_type ();
133 : : else
134 : : type = nullptr;
135 : :
136 : : return *this;
137 : : }
138 : :
139 : : // move constructors
140 : : LetStmt (LetStmt &&other) = default;
141 : : LetStmt &operator= (LetStmt &&other) = default;
142 : :
143 : 11080 : location_t get_locus () const override final { return locus; }
144 : :
145 : : void accept_vis (ASTVisitor &vis) override;
146 : :
147 : : // Invalid if pattern is null, so base stripping on that.
148 : 0 : void mark_for_strip () override { variables_pattern = nullptr; }
149 : 25050 : bool is_marked_for_strip () const override
150 : : {
151 : 25050 : return variables_pattern == nullptr;
152 : : }
153 : :
154 : : // TODO: this mutable getter seems really dodgy. Think up better way.
155 : 91608 : std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
156 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
157 : :
158 : : // TODO: is this better? Or is a "vis_block" better?
159 : 93780 : Expr &get_init_expr ()
160 : : {
161 : 93780 : rust_assert (has_init_expr ());
162 : 93780 : return *init_expr;
163 : : }
164 : :
165 : 10114 : std::unique_ptr<Expr> &get_init_expr_ptr ()
166 : : {
167 : 10114 : rust_assert (has_init_expr ());
168 : 10114 : return init_expr;
169 : : }
170 : :
171 : 113926 : Pattern &get_pattern ()
172 : : {
173 : 113926 : rust_assert (variables_pattern != nullptr);
174 : 113926 : return *variables_pattern;
175 : : }
176 : :
177 : 14706 : Type &get_type ()
178 : : {
179 : 14706 : rust_assert (has_type ());
180 : 14706 : return *type;
181 : : }
182 : :
183 : 1769 : std::unique_ptr<Type> &get_type_ptr ()
184 : : {
185 : 1769 : rust_assert (has_type ());
186 : 1769 : return type;
187 : : }
188 : :
189 : 19908 : bool is_item () const override final { return false; }
190 : 18768 : Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Let; }
191 : :
192 : : protected:
193 : : /* Use covariance to implement clone function as returning this object rather
194 : : * than base */
195 : 679 : LetStmt *clone_stmt_impl () const override { return new LetStmt (*this); }
196 : : };
197 : :
198 : : // Expression statements (statements containing an expression)
199 : : class ExprStmt : public Stmt
200 : : {
201 : : std::unique_ptr<Expr> expr;
202 : : location_t locus;
203 : : bool semicolon_followed;
204 : :
205 : : public:
206 : 5885 : location_t get_locus () const override final { return locus; }
207 : :
208 : 11738 : bool is_item () const override final { return false; }
209 : :
210 : 5854 : bool is_expr () const override final { return true; }
211 : :
212 : : // Used for the last statement for statement macros with a trailing
213 : : // semicolon.
214 : 167 : void add_semicolon () override final { semicolon_followed = true; }
215 : :
216 : : std::string as_string () const override;
217 : :
218 : 10868 : Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Expr; }
219 : :
220 : : std::vector<LetStmt *> locals;
221 : :
222 : 5999 : ExprStmt (std::unique_ptr<Expr> &&expr, location_t locus,
223 : : bool semicolon_followed)
224 : 11998 : : expr (std::move (expr)), locus (locus),
225 : 5999 : semicolon_followed (semicolon_followed)
226 : : {}
227 : :
228 : : // Copy constructor with clone
229 : 986 : ExprStmt (ExprStmt const &other)
230 : 986 : : locus (other.locus), semicolon_followed (other.semicolon_followed)
231 : : {
232 : : // guard to prevent null dereference (only required if error state)
233 : 986 : if (other.expr != nullptr)
234 : 986 : expr = other.expr->clone_expr ();
235 : 986 : }
236 : :
237 : : // Overloaded assignment operator to clone
238 : : ExprStmt &operator= (ExprStmt const &other)
239 : : {
240 : : Stmt::operator= (other);
241 : :
242 : : // guard to prevent null dereference (only required if error state)
243 : : if (other.expr != nullptr)
244 : : expr = other.expr->clone_expr ();
245 : : else
246 : : expr = nullptr;
247 : :
248 : : locus = other.locus;
249 : : semicolon_followed = other.semicolon_followed;
250 : :
251 : : return *this;
252 : : }
253 : :
254 : : // move constructors
255 : : ExprStmt (ExprStmt &&other) = default;
256 : : ExprStmt &operator= (ExprStmt &&other) = default;
257 : :
258 : : void accept_vis (ASTVisitor &vis) override;
259 : :
260 : : // Invalid if expr is null, so base stripping on that.
261 : 17 : void mark_for_strip () override { expr = nullptr; }
262 : 34514 : bool is_marked_for_strip () const override { return expr == nullptr; }
263 : :
264 : : // TODO: is this better? Or is a "vis_block" better?
265 : 63406 : Expr &get_expr ()
266 : : {
267 : 63406 : rust_assert (expr != nullptr);
268 : 63406 : return *expr;
269 : : }
270 : :
271 : 6844 : std::unique_ptr<Expr> &get_expr_ptr ()
272 : : {
273 : 6844 : rust_assert (expr != nullptr);
274 : 6844 : return expr;
275 : : }
276 : :
277 : 17 : std::unique_ptr<Expr> take_expr ()
278 : : {
279 : 17 : rust_assert (expr != nullptr);
280 : 17 : return std::move (expr);
281 : : }
282 : :
283 : 12376 : bool is_semicolon_followed () const { return semicolon_followed; }
284 : :
285 : : protected:
286 : : /* Use covariance to implement clone function as returning this object rather
287 : : * than base */
288 : 986 : ExprStmt *clone_stmt_impl () const override { return new ExprStmt (*this); }
289 : : };
290 : :
291 : : } // namespace AST
292 : : } // namespace Rust
293 : :
294 : : #endif
|