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-question-mark.h"
20 : : #include "rust-ast-builder.h"
21 : : #include "rust-ast-visitor.h"
22 : :
23 : : namespace Rust {
24 : : namespace AST {
25 : :
26 : 4939 : DesugarQuestionMark::DesugarQuestionMark () {}
27 : :
28 : : void
29 : 4939 : DesugarQuestionMark::go (AST::Crate &crate)
30 : : {
31 : 4939 : DesugarQuestionMark::visit (crate);
32 : 4939 : }
33 : :
34 : : void
35 : 7762 : DesugarQuestionMark::visit (ExprStmt &stmt)
36 : : {
37 : 7762 : if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
38 : 0 : desugar_and_replace (stmt.get_expr_ptr ());
39 : :
40 : 7762 : DefaultASTVisitor::visit (stmt);
41 : 7762 : }
42 : :
43 : : void
44 : 10238 : DesugarQuestionMark::visit (CallExpr &call)
45 : : {
46 : 10238 : if (call.get_function_expr ().get_expr_kind ()
47 : : == Expr::Kind::ErrorPropagation)
48 : 0 : desugar_and_replace (call.get_function_expr_ptr ());
49 : :
50 : 22284 : for (auto &arg : call.get_params ())
51 : 12046 : if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation)
52 : 0 : desugar_and_replace (arg);
53 : :
54 : 10238 : DefaultASTVisitor::visit (call);
55 : 10238 : }
56 : :
57 : : void
58 : 12810 : DesugarQuestionMark::visit (LetStmt &stmt)
59 : : {
60 : 12810 : if (stmt.has_init_expr ()
61 : 12810 : && stmt.get_init_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
62 : 2 : desugar_and_replace (stmt.get_init_expr_ptr ());
63 : :
64 : 12810 : DefaultASTVisitor::visit (stmt);
65 : 12810 : }
66 : :
67 : : MatchArm
68 : 4 : make_match_arm (std::unique_ptr<Pattern> &&pattern)
69 : : {
70 : 4 : auto loc = pattern->get_locus ();
71 : :
72 : 4 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
73 : 4 : patterns.emplace_back (std::move (pattern));
74 : :
75 : 4 : return MatchArm (std::move (patterns), loc);
76 : 4 : }
77 : :
78 : : MatchCase
79 : 2 : ok_case (Builder &builder)
80 : : {
81 : 2 : auto val = builder.identifier_pattern ("val");
82 : :
83 : 2 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
84 : 2 : patterns.emplace_back (std::move (val));
85 : :
86 : 2 : auto pattern_item = std::unique_ptr<TupleStructItems> (
87 : 2 : new TupleStructItemsNoRange (std::move (patterns)));
88 : 2 : auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
89 : 4 : builder.path_in_expression (LangItem::Kind::RESULT_OK),
90 : 2 : std::move (pattern_item)));
91 : :
92 : 2 : auto arm = make_match_arm (std::move (pattern));
93 : :
94 : 2 : auto ret_val = builder.identifier ("val");
95 : :
96 : 2 : return MatchCase (std::move (arm), std::move (ret_val));
97 : 2 : }
98 : :
99 : : MatchCase
100 : 2 : err_case (Builder &builder)
101 : : {
102 : 2 : auto val = builder.identifier_pattern ("err");
103 : :
104 : 2 : auto patterns = std::vector<std::unique_ptr<Pattern>> ();
105 : 2 : patterns.emplace_back (std::move (val));
106 : :
107 : 2 : auto pattern_item = std::unique_ptr<TupleStructItems> (
108 : 2 : new TupleStructItemsNoRange (std::move (patterns)));
109 : 2 : auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern (
110 : 4 : builder.path_in_expression (LangItem::Kind::RESULT_ERR),
111 : 2 : std::move (pattern_item)));
112 : :
113 : 2 : auto arm = make_match_arm (std::move (pattern));
114 : :
115 : 2 : auto try_from_err = std::make_unique<PathInExpression> (
116 : 2 : builder.path_in_expression (LangItem::Kind::TRY_FROM_ERROR));
117 : 2 : auto from_from = std::make_unique<PathInExpression> (
118 : 2 : builder.path_in_expression (LangItem::Kind::FROM_FROM));
119 : :
120 : 2 : auto early_return = builder.return_expr (
121 : 4 : builder.call (std::move (try_from_err),
122 : 4 : builder.call (std::move (from_from),
123 : 6 : builder.identifier ("err"))));
124 : :
125 : 2 : return MatchCase (std::move (arm), std::move (early_return));
126 : 2 : }
127 : :
128 : : std::unique_ptr<Expr>
129 : 2 : DesugarQuestionMark::desugar (ErrorPropagationExpr &expr)
130 : : {
131 : 2 : auto builder = Builder (expr.get_locus ());
132 : :
133 : : // Try::into_result(<expr>)
134 : 2 : auto try_into = std::make_unique<PathInExpression> (
135 : 2 : builder.path_in_expression (LangItem::Kind::TRY_INTO_RESULT));
136 : 2 : auto call = builder.call (std::move (try_into),
137 : 6 : expr.get_propagating_expr ().clone_expr ());
138 : :
139 : : // Ok(val) => val,
140 : 2 : auto ok_match_case = ok_case (builder);
141 : : // Err(err) => return Try::from_error(From::from(err)),
142 : 2 : auto err_match_case = err_case (builder);
143 : :
144 : 2 : auto cases = std::vector<MatchCase> ();
145 : 2 : cases.emplace_back (ok_match_case);
146 : 2 : cases.emplace_back (err_match_case);
147 : :
148 : : // match <call> {
149 : : // <ok_arm>
150 : : // <err_arm>
151 : : // }
152 : 2 : return std::unique_ptr<MatchExpr> (new MatchExpr (std::move (call),
153 : : std::move (cases), {}, {},
154 : 2 : expr.get_locus ()));
155 : 6 : }
156 : :
157 : : void
158 : 2 : DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr)
159 : : {
160 : 2 : auto original = static_cast<ErrorPropagationExpr &> (*ptr);
161 : 2 : auto desugared = desugar (original);
162 : :
163 : 2 : ptr = std::move (desugared);
164 : 2 : }
165 : :
166 : : } // namespace AST
167 : : } // namespace Rust
|