Branch data Line data Source code
1 : : // Copyright (C) 2025 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_DESUGAR_FOR_LOOPS_H
20 : : #define RUST_DESUGAR_FOR_LOOPS_H
21 : :
22 : : #include "rust-ast-builder.h"
23 : : #include "rust-ast-visitor.h"
24 : : #include "rust-expr.h"
25 : :
26 : : namespace Rust {
27 : : namespace AST {
28 : :
29 : : // Desugar for-loops into a set of other AST nodes. The desugar is of the
30 : : // following form:
31 : : //
32 : : // ```
33 : : // for <pat> in <head> <body>
34 : : // ```
35 : : //
36 : : // becomes:
37 : : //
38 : : // ```
39 : : // {
40 : : // let result = match ::std::iter::IntoIterator::into_iter(<head>) {
41 : : // mut iter => {
42 : : // loop {
43 : : // let mut __next;
44 : : // match ::std::iter::Iterator::next(&mut iter) {
45 : : // ::std::option::Option::Some(val) => __next = val,
46 : : // ::std::option::Option::None => break
47 : : // };
48 : : // let <pat> = __next;
49 : : //
50 : : // <body>;
51 : : // }
52 : : // }
53 : : // };
54 : : // result
55 : : // }
56 : : // ```
57 : : //
58 : : // NOTE: In a perfect world, this would be an immutable visitor which would take
59 : : // ownership of the AST node and return a new one, instead of mutating this one
60 : : // in place. Nevertheless, this isn't Rust, and doing immutable visitors in C++
61 : : // sucks, and the world isn't perfect, so we are impure and sad.
62 : : //
63 : : // NOTE: This class could eventually be removed in favor of
64 : : // an HIR desugar. This would avoid mutating the AST and would be cleaner.
65 : : // However, it requires multiple changes in the way we do typechecking and name
66 : : // resolution, as this desugar creates new bindings. Because of this, these new
67 : : // bindings need to be inserted into the name-resolution context outside of the
68 : : // name resolution pass, which is difficult. Those bindings are needed because
69 : : // of the way the typechecker is currently structured, where it will fetch name
70 : : // resolution information in order to typecheck paths - which technically isn't
71 : : // necessary.
72 : : class DesugarForLoops : public DefaultASTVisitor
73 : : {
74 : : using DefaultASTVisitor::visit;
75 : :
76 : : public:
77 : : DesugarForLoops ();
78 : : void go (AST::Crate &);
79 : :
80 : : private:
81 : : struct DesugarCtx
82 : : {
83 : 18 : DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
84 : :
85 : : Builder builder;
86 : : location_t loc;
87 : :
88 : : MatchArm make_match_arm (std::unique_ptr<Pattern> &&pattern);
89 : : MatchCase make_break_arm ();
90 : : MatchCase make_continue_arm ();
91 : : std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&expr);
92 : :
93 : : constexpr static const char *continue_pattern_id = "#val";
94 : : constexpr static const char *next_value_id = "#__next";
95 : : constexpr static const char *iter_id = "#iter";
96 : : constexpr static const char *result_id = "#result";
97 : : };
98 : :
99 : : std::unique_ptr<Expr> desugar (AST::ForLoopExpr &expr);
100 : : void maybe_desugar_expr (std::unique_ptr<Expr> &expr);
101 : :
102 : : void visit (AST::BlockExpr &) override;
103 : : };
104 : :
105 : : } // namespace AST
106 : : } // namespace Rust
107 : :
108 : : #endif // ! RUST_DESUGAR_FOR_LOOPS_H
|