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 : : #include "rust-desugar-for-loops.h"
20 : : #include "rust-ast-visitor.h"
21 : : #include "rust-ast.h"
22 : : #include "rust-hir-map.h"
23 : : #include "rust-path.h"
24 : : #include "rust-pattern.h"
25 : : #include "rust-stmt.h"
26 : : #include "rust-expr.h"
27 : : #include "rust-ast-builder.h"
28 : :
29 : : namespace Rust {
30 : : namespace AST {
31 : :
32 : 4939 : DesugarForLoops::DesugarForLoops () {}
33 : :
34 : : void
35 : 4939 : DesugarForLoops::go (AST::Crate &crate)
36 : : {
37 : 4939 : DefaultASTVisitor::visit (crate);
38 : 4939 : }
39 : :
40 : : static void
41 : 18 : replace_for_loop (std::unique_ptr<Expr> &for_loop,
42 : : std::unique_ptr<Expr> &&expanded)
43 : : {
44 : 0 : for_loop = std::move (expanded);
45 : 0 : }
46 : :
47 : : MatchArm
48 : 36 : DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr<Pattern> &&path)
49 : : {
50 : 36 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
51 : 36 : patterns.emplace_back (std::move (path));
52 : :
53 : 36 : return MatchArm (std::move (patterns), loc);
54 : 36 : }
55 : :
56 : : MatchCase
57 : 18 : DesugarForLoops::DesugarCtx::make_break_arm ()
58 : : {
59 : 18 : auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression (
60 : 18 : builder.path_in_expression (LangItem::Kind::OPTION_NONE))));
61 : :
62 : 18 : auto break_expr
63 : 18 : = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc));
64 : :
65 : 18 : return MatchCase (std::move (arm), std::move (break_expr));
66 : 18 : }
67 : :
68 : : MatchCase
69 : 18 : DesugarForLoops::DesugarCtx::make_continue_arm ()
70 : : {
71 : 18 : auto val = builder.identifier_pattern (DesugarCtx::continue_pattern_id);
72 : :
73 : 18 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
74 : 18 : patterns.emplace_back (std::move (val));
75 : :
76 : 18 : auto pattern_item = std::unique_ptr<TupleStructItems> (
77 : 18 : new TupleStructItemsNoRange (std::move (patterns)));
78 : 18 : auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
79 : 36 : builder.path_in_expression (LangItem::Kind::OPTION_SOME),
80 : 18 : std::move (pattern_item)));
81 : :
82 : 18 : auto val_arm = make_match_arm (std::move (pattern));
83 : :
84 : 18 : auto next = builder.identifier (DesugarCtx::next_value_id);
85 : :
86 : 18 : auto assignment = std::unique_ptr<Expr> (
87 : : new AssignmentExpr (std::move (next),
88 : 36 : builder.identifier (DesugarCtx::continue_pattern_id),
89 : 54 : {}, loc));
90 : :
91 : 18 : return MatchCase (std::move (val_arm), std::move (assignment));
92 : 18 : }
93 : :
94 : : std::unique_ptr<Stmt>
95 : 36 : DesugarForLoops::DesugarCtx::statementify (std::unique_ptr<Expr> &&expr)
96 : : {
97 : 36 : return std::unique_ptr<Stmt> (new ExprStmt (std::move (expr), loc, true));
98 : : }
99 : :
100 : : std::unique_ptr<Expr>
101 : 18 : DesugarForLoops::desugar (AST::ForLoopExpr &expr)
102 : : {
103 : 18 : auto ctx = DesugarCtx (expr.get_locus ());
104 : :
105 : 18 : auto into_iter = std::make_unique<PathInExpression> (
106 : 18 : ctx.builder.path_in_expression (LangItem::Kind::INTOITER_INTOITER));
107 : 18 : auto next = std::make_unique<PathInExpression> (
108 : 18 : ctx.builder.path_in_expression (LangItem::Kind::ITERATOR_NEXT));
109 : :
110 : : // IntoIterator::into_iter(<head>)
111 : 18 : auto into_iter_call
112 : 18 : = ctx.builder.call (std::move (into_iter),
113 : 54 : expr.get_iterator_expr ().clone_expr ());
114 : :
115 : : // Iterator::next(iter)
116 : 18 : auto next_call = ctx.builder.call (
117 : 18 : std::move (next),
118 : 54 : ctx.builder.ref (ctx.builder.identifier (DesugarCtx::iter_id), true));
119 : :
120 : : // None => break,
121 : 18 : auto break_arm = ctx.make_break_arm ();
122 : : // Some(val) => __next = val; },
123 : 18 : auto continue_arm = ctx.make_continue_arm ();
124 : :
125 : : // match <next_call> {
126 : : // <continue_arm>
127 : : // <break_arm>
128 : : // }
129 : 18 : auto match_next
130 : 72 : = ctx.builder.match (std::move (next_call),
131 : 18 : {std::move (continue_arm), std::move (break_arm)});
132 : :
133 : : // let mut __next;
134 : 36 : auto let_next = ctx.builder.let (
135 : 18 : ctx.builder.identifier_pattern (DesugarCtx::next_value_id, true));
136 : : // let <pattern> = __next;
137 : 18 : auto let_pat
138 : 36 : = ctx.builder.let (expr.get_pattern ().clone_pattern (), nullptr,
139 : 54 : ctx.builder.identifier (DesugarCtx::next_value_id));
140 : :
141 : 18 : auto loop_stmts = std::vector<std::unique_ptr<Stmt>> ();
142 : 18 : loop_stmts.emplace_back (std::move (let_next));
143 : 18 : loop_stmts.emplace_back (ctx.statementify (std::move (match_next)));
144 : 18 : loop_stmts.emplace_back (std::move (let_pat));
145 : 18 : loop_stmts.emplace_back (
146 : 36 : ctx.statementify (expr.get_loop_block ().clone_expr ()));
147 : :
148 : : // loop {
149 : : // <let_next>;
150 : : // <match_next>;
151 : : // <let_pat>;
152 : : //
153 : : // <body>;
154 : : // }
155 : 18 : auto loop = ctx.builder.loop (std::move (loop_stmts));
156 : :
157 : 18 : auto mut_iter_pattern
158 : 18 : = ctx.builder.identifier_pattern (DesugarCtx::iter_id, true);
159 : 18 : auto match_iter
160 : 54 : = ctx.builder.match (std::move (into_iter_call),
161 : : {ctx.builder.match_case (std::move (mut_iter_pattern),
162 : 18 : std::move (loop))});
163 : :
164 : 18 : auto let_result
165 : 36 : = ctx.builder.let (ctx.builder.identifier_pattern (DesugarCtx::result_id),
166 : 54 : nullptr, std::move (match_iter));
167 : 18 : auto result_return = ctx.builder.identifier (DesugarCtx::result_id);
168 : :
169 : 18 : return ctx.builder.block (std::move (let_result), std::move (result_return));
170 : 54 : }
171 : :
172 : : void
173 : 21144 : DesugarForLoops::maybe_desugar_expr (std::unique_ptr<Expr> &expr)
174 : : {
175 : 21144 : if (expr->get_expr_kind () == AST::Expr::Kind::Loop)
176 : : {
177 : 168 : auto &loop = static_cast<AST::BaseLoopExpr &> (*expr);
178 : :
179 : 168 : if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For)
180 : : {
181 : 18 : auto &for_loop = static_cast<AST::ForLoopExpr &> (loop);
182 : :
183 : 18 : auto desugared = desugar (for_loop);
184 : :
185 : 18 : replace_for_loop (expr, std::move (desugared));
186 : 18 : }
187 : : }
188 : 21144 : }
189 : :
190 : : void
191 : 19775 : DesugarForLoops::visit (AST::BlockExpr &block)
192 : : {
193 : 40985 : for (auto &stmt : block.get_statements ())
194 : 21210 : if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr)
195 : 7762 : maybe_desugar_expr (static_cast<AST::ExprStmt &> (*stmt).get_expr_ptr ());
196 : :
197 : 19775 : if (block.has_tail_expr ())
198 : 13382 : maybe_desugar_expr (block.get_tail_expr_ptr ());
199 : :
200 : 19775 : DefaultASTVisitor::visit (block);
201 : 19775 : }
202 : :
203 : : } // namespace AST
204 : : } // namespace Rust
|