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