Line data Source code
1 : // Copyright (C) 2025-2026 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.h"
21 : #include "rust-hir-map.h"
22 : #include "rust-path.h"
23 : #include "rust-pattern.h"
24 : #include "rust-stmt.h"
25 : #include "rust-expr.h"
26 : #include "rust-ast-builder.h"
27 :
28 : namespace Rust {
29 : namespace AST {
30 :
31 119 : DesugarForLoops::DesugarForLoops () {}
32 :
33 : MatchCase
34 119 : DesugarForLoops::DesugarCtx::make_break_arm ()
35 : {
36 119 : auto arm = builder.match_arm (std::unique_ptr<Pattern> (new PathInExpression (
37 119 : builder.path_in_expression (LangItem::Kind::OPTION_NONE))));
38 :
39 119 : auto break_expr
40 119 : = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, tl::nullopt, {}, loc));
41 :
42 119 : return MatchCase (std::move (arm), std::move (break_expr));
43 119 : }
44 :
45 : MatchCase
46 119 : DesugarForLoops::DesugarCtx::make_continue_arm ()
47 : {
48 119 : auto val = builder.identifier_pattern (DesugarCtx::continue_pattern_id);
49 :
50 119 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
51 119 : patterns.emplace_back (std::move (val));
52 :
53 119 : auto pattern_item = std::unique_ptr<TupleStructItems> (
54 119 : new TupleStructItemsNoRest (std::move (patterns)));
55 119 : auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
56 238 : builder.path_in_expression (LangItem::Kind::OPTION_SOME),
57 119 : std::move (pattern_item)));
58 :
59 119 : auto val_arm = builder.match_arm (std::move (pattern));
60 :
61 119 : auto next = builder.identifier (DesugarCtx::next_value_id);
62 :
63 119 : auto assignment = std::unique_ptr<Expr> (
64 : new AssignmentExpr (std::move (next),
65 238 : builder.identifier (DesugarCtx::continue_pattern_id),
66 357 : {}, loc));
67 :
68 119 : return MatchCase (std::move (val_arm), std::move (assignment));
69 119 : }
70 :
71 : std::unique_ptr<Expr>
72 119 : DesugarForLoops::desugar (ForLoopExpr &expr, Builder::Source node_source)
73 : {
74 119 : auto ctx = DesugarCtx (expr.get_locus (), node_source);
75 :
76 119 : auto into_iter = std::make_unique<PathInExpression> (
77 119 : ctx.builder.path_in_expression (LangItem::Kind::INTOITER_INTOITER));
78 119 : auto next = std::make_unique<PathInExpression> (
79 119 : ctx.builder.path_in_expression (LangItem::Kind::ITERATOR_NEXT));
80 :
81 : // IntoIterator::into_iter(<head>)
82 119 : auto into_iter_call
83 119 : = ctx.builder.call (std::move (into_iter),
84 357 : expr.get_iterator_expr ().clone_expr ());
85 :
86 : // Iterator::next(iter)
87 119 : auto next_call = ctx.builder.call (
88 119 : std::move (next),
89 357 : ctx.builder.ref (ctx.builder.identifier (DesugarCtx::iter_id), true));
90 :
91 : // None => break,
92 119 : auto break_arm = ctx.make_break_arm ();
93 : // Some(val) => __next = val; },
94 119 : auto continue_arm = ctx.make_continue_arm ();
95 :
96 : // match <next_call> {
97 : // <continue_arm>
98 : // <break_arm>
99 : // }
100 119 : auto match_next
101 476 : = ctx.builder.match (std::move (next_call),
102 119 : {std::move (continue_arm), std::move (break_arm)});
103 :
104 : // let mut __next;
105 119 : auto let_next = ctx.builder.let (
106 119 : ctx.builder.identifier_pattern (DesugarCtx::next_value_id, true));
107 : // let <pattern> = __next;
108 119 : auto let_pat
109 238 : = ctx.builder.let (expr.get_pattern ().clone_pattern (), nullptr,
110 357 : ctx.builder.identifier (DesugarCtx::next_value_id));
111 :
112 119 : auto loop_stmts = std::vector<std::unique_ptr<Stmt>> ();
113 119 : loop_stmts.emplace_back (std::move (let_next));
114 119 : loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_next)));
115 119 : loop_stmts.emplace_back (std::move (let_pat));
116 119 : loop_stmts.emplace_back (
117 238 : ctx.builder.statementify (expr.get_loop_block ().clone_expr ()));
118 :
119 : // loop {
120 : // <let_next>;
121 : // <match_next>;
122 : // <let_pat>;
123 : //
124 : // <body>;
125 : // }
126 119 : auto loop = ctx.builder.loop (std::move (loop_stmts));
127 :
128 119 : auto mut_iter_pattern
129 119 : = ctx.builder.identifier_pattern (DesugarCtx::iter_id, true);
130 119 : auto match_iter
131 357 : = ctx.builder.match (std::move (into_iter_call),
132 : {ctx.builder.match_case (std::move (mut_iter_pattern),
133 119 : std::move (loop))});
134 :
135 119 : auto let_result
136 238 : = ctx.builder.let (ctx.builder.identifier_pattern (DesugarCtx::result_id),
137 357 : nullptr, std::move (match_iter));
138 119 : auto result_return = ctx.builder.identifier (DesugarCtx::result_id);
139 :
140 119 : return ctx.builder.block (std::move (let_result), std::move (result_return));
141 357 : }
142 :
143 : void
144 119 : DesugarForLoops::go (std::unique_ptr<Expr> &ptr, Builder::Source node_source)
145 : {
146 119 : rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop);
147 :
148 119 : auto &loop = static_cast<BaseLoopExpr &> (*ptr);
149 :
150 119 : rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::For);
151 :
152 119 : auto &for_loop = static_cast<ForLoopExpr &> (loop);
153 119 : auto desugared = DesugarForLoops ().desugar (for_loop, node_source);
154 :
155 119 : ptr = std::move (desugared);
156 119 : }
157 :
158 : } // namespace AST
159 : } // namespace Rust
|