libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / rust / ast / rust-stmt.h
blob51c59182ba65521cec64e33381500eaefd93cfa5
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
8 // version.
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.
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
22 #include "rust-ast.h"
23 #include "rust-path.h"
24 #include "rust-expr.h"
25 #include <memory>
27 namespace Rust {
28 namespace AST {
29 // Just a semi-colon, which apparently is a statement.
30 class EmptyStmt : public Stmt
32 location_t locus;
34 // TODO: find another way to store this to save memory?
35 bool marked_for_strip = false;
37 public:
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; }
54 protected:
55 /* Use covariance to implement clone function as returning this object rather
56 * than base */
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;
69 // bool has_type;
70 std::unique_ptr<Type> type;
72 // bool has_init_expr;
73 std::unique_ptr<Expr> init_expr;
75 location_t locus;
77 public:
78 Type *inferedType;
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;
118 locus = other.locus;
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;
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;
136 return *this;
139 // move constructors
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 ());
162 return *init_expr;
165 std::unique_ptr<Expr> &get_init_expr_ptr ()
167 rust_assert (has_init_expr ());
168 return init_expr;
171 Pattern &get_pattern ()
173 rust_assert (variables_pattern != nullptr);
174 return *variables_pattern;
177 Type &get_type ()
179 rust_assert (has_type ());
180 return *type;
183 std::unique_ptr<Type> &get_type_ptr ()
185 rust_assert (has_type ());
186 return type;
189 bool is_item () const override final { return false; }
190 Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Let; }
192 protected:
193 /* Use covariance to implement clone function as returning this object rather
194 * than base */
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;
202 location_t locus;
203 bool semicolon_followed;
205 public:
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
213 // semicolon.
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 ();
245 else
246 expr = nullptr;
248 locus = other.locus;
249 semicolon_followed = other.semicolon_followed;
251 return *this;
254 // move constructors
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?
265 Expr &get_expr ()
267 rust_assert (expr != nullptr);
268 return *expr;
271 std::unique_ptr<Expr> &get_expr_ptr ()
273 rust_assert (expr != nullptr);
274 return expr;
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; }
285 protected:
286 /* Use covariance to implement clone function as returning this object rather
287 * than base */
288 ExprStmt *clone_stmt_impl () const override { return new ExprStmt (*this); }
291 } // namespace AST
292 } // namespace Rust
294 #endif