1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
19 #ifndef RUST_AST_STATEMENT_H
20 #define RUST_AST_STATEMENT_H
23 #include "rust-path.h"
24 #include "rust-expr.h"
29 // Just a semi-colon, which apparently is a statement.
30 class EmptyStmt
: public Stmt
34 // TODO: find another way to store this to save memory?
35 bool marked_for_strip
= false;
38 std::string
as_string () const override
{ return std::string (1, ';'); }
40 EmptyStmt (location_t locus
) : locus (locus
) {}
42 location_t
get_locus () const override final
{ return locus
; }
44 void accept_vis (ASTVisitor
&vis
) override
;
46 // Can't think of any invalid invariants, so store boolean.
47 void mark_for_strip () override
{ marked_for_strip
= true; }
48 bool is_marked_for_strip () const override
{ return marked_for_strip
; }
50 bool is_item () const override final
{ return false; }
52 Stmt::Kind
get_stmt_kind () final
{ return Stmt::Kind::Empty
; }
55 /* Use covariance to implement clone function as returning this object rather
57 EmptyStmt
*clone_stmt_impl () const override
{ return new EmptyStmt (*this); }
60 /* Variable assignment let statement - type of "declaration statement" as it
61 * introduces new name into scope */
62 class LetStmt
: public Stmt
64 // bool has_outer_attrs;
65 std::vector
<Attribute
> outer_attrs
;
67 std::unique_ptr
<Pattern
> variables_pattern
;
70 std::unique_ptr
<Type
> type
;
72 // bool has_init_expr;
73 std::unique_ptr
<Expr
> init_expr
;
80 // Returns whether let statement has outer attributes.
81 bool has_outer_attrs () const { return !outer_attrs
.empty (); }
83 // Returns whether let statement has a given return type.
84 bool has_type () const { return type
!= nullptr; }
86 // Returns whether let statement has an initialisation expression.
87 bool has_init_expr () const { return init_expr
!= nullptr; }
89 std::string
as_string () const override
;
91 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 : outer_attrs (std::move (outer_attrs
)),
95 variables_pattern (std::move (variables_pattern
)),
96 type (std::move (type
)), init_expr (std::move (init_expr
)), locus (locus
)
99 // Copy constructor with clone
100 LetStmt (LetStmt
const &other
)
101 : outer_attrs (other
.outer_attrs
), locus (other
.locus
)
103 // guard to prevent null dereference (only required if error state)
104 if (other
.variables_pattern
!= nullptr)
105 variables_pattern
= other
.variables_pattern
->clone_pattern ();
107 // guard to prevent null dereference (always required)
108 if (other
.init_expr
!= nullptr)
109 init_expr
= other
.init_expr
->clone_expr ();
110 if (other
.type
!= nullptr)
111 type
= other
.type
->clone_type ();
114 // Overloaded assignment operator to clone
115 LetStmt
&operator= (LetStmt
const &other
)
117 outer_attrs
= other
.outer_attrs
;
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 ();
124 variables_pattern
= nullptr;
126 // guard to prevent null dereference (always required)
127 if (other
.init_expr
!= nullptr)
128 init_expr
= other
.init_expr
->clone_expr ();
131 if (other
.type
!= nullptr)
132 type
= other
.type
->clone_type ();
140 LetStmt (LetStmt
&&other
) = default;
141 LetStmt
&operator= (LetStmt
&&other
) = default;
143 location_t
get_locus () const override final
{ return locus
; }
145 void accept_vis (ASTVisitor
&vis
) override
;
147 // Invalid if pattern is null, so base stripping on that.
148 void mark_for_strip () override
{ variables_pattern
= nullptr; }
149 bool is_marked_for_strip () const override
151 return variables_pattern
== nullptr;
154 // TODO: this mutable getter seems really dodgy. Think up better way.
155 std::vector
<Attribute
> &get_outer_attrs () { return outer_attrs
; }
156 const std::vector
<Attribute
> &get_outer_attrs () const { return outer_attrs
; }
158 // TODO: is this better? Or is a "vis_block" better?
159 Expr
&get_init_expr ()
161 rust_assert (has_init_expr ());
165 std::unique_ptr
<Expr
> &get_init_expr_ptr ()
167 rust_assert (has_init_expr ());
171 Pattern
&get_pattern ()
173 rust_assert (variables_pattern
!= nullptr);
174 return *variables_pattern
;
179 rust_assert (has_type ());
183 std::unique_ptr
<Type
> &get_type_ptr ()
185 rust_assert (has_type ());
189 bool is_item () const override final
{ return false; }
190 Stmt::Kind
get_stmt_kind () final
{ return Stmt::Kind::Let
; }
193 /* Use covariance to implement clone function as returning this object rather
195 LetStmt
*clone_stmt_impl () const override
{ return new LetStmt (*this); }
198 // Expression statements (statements containing an expression)
199 class ExprStmt
: public Stmt
201 std::unique_ptr
<Expr
> expr
;
203 bool semicolon_followed
;
206 location_t
get_locus () const override final
{ return locus
; }
208 bool is_item () const override final
{ return false; }
210 bool is_expr () const override final
{ return true; }
212 // Used for the last statement for statement macros with a trailing
214 void add_semicolon () override final
{ semicolon_followed
= true; }
216 std::string
as_string () const override
;
218 Stmt::Kind
get_stmt_kind () final
{ return Stmt::Kind::Expr
; }
220 std::vector
<LetStmt
*> locals
;
222 ExprStmt (std::unique_ptr
<Expr
> &&expr
, location_t locus
,
223 bool semicolon_followed
)
224 : expr (std::move (expr
)), locus (locus
),
225 semicolon_followed (semicolon_followed
)
228 // Copy constructor with clone
229 ExprStmt (ExprStmt
const &other
)
230 : locus (other
.locus
), semicolon_followed (other
.semicolon_followed
)
232 // guard to prevent null dereference (only required if error state)
233 if (other
.expr
!= nullptr)
234 expr
= other
.expr
->clone_expr ();
237 // Overloaded assignment operator to clone
238 ExprStmt
&operator= (ExprStmt
const &other
)
240 Stmt::operator= (other
);
242 // guard to prevent null dereference (only required if error state)
243 if (other
.expr
!= nullptr)
244 expr
= other
.expr
->clone_expr ();
249 semicolon_followed
= other
.semicolon_followed
;
255 ExprStmt (ExprStmt
&&other
) = default;
256 ExprStmt
&operator= (ExprStmt
&&other
) = default;
258 void accept_vis (ASTVisitor
&vis
) override
;
260 // Invalid if expr is null, so base stripping on that.
261 void mark_for_strip () override
{ expr
= nullptr; }
262 bool is_marked_for_strip () const override
{ return expr
== nullptr; }
264 // TODO: is this better? Or is a "vis_block" better?
267 rust_assert (expr
!= nullptr);
271 std::unique_ptr
<Expr
> &get_expr_ptr ()
273 rust_assert (expr
!= nullptr);
277 std::unique_ptr
<Expr
> take_expr ()
279 rust_assert (expr
!= nullptr);
280 return std::move (expr
);
283 bool is_semicolon_followed () const { return semicolon_followed
; }
286 /* Use covariance to implement clone function as returning this object rather
288 ExprStmt
*clone_stmt_impl () const override
{ return new ExprStmt (*this); }