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