1 /**
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "boxedTypeLowering.h"
17
18 #include "checker/ETSchecker.h"
19 #include "compiler/lowering/util.h"
20 #include "generated/signatures.h"
21
22 namespace ark::es2panda::compiler {
23
Name() const24 std::string_view BoxedTypeLowering::Name() const
25 {
26 return "BoxedTypeLowering";
27 }
28
BoxNumberLiteralArguments(ir::CallExpression * callExpr,PhaseManager * phaseManager,checker::ETSChecker * checker,parser::ETSParser * parser)29 void BoxNumberLiteralArguments(ir::CallExpression *callExpr, PhaseManager *phaseManager, checker::ETSChecker *checker,
30 parser::ETSParser *parser)
31 {
32 const static std::unordered_map<ir::BoxingUnboxingFlags, util::StringView> BOXTO({
33 {ir::BoxingUnboxingFlags::BOX_TO_BOOLEAN, compiler::Signatures::BUILTIN_BOOLEAN_CLASS},
34 {ir::BoxingUnboxingFlags::BOX_TO_BYTE, compiler::Signatures::BUILTIN_BYTE_CLASS},
35 {ir::BoxingUnboxingFlags::BOX_TO_SHORT, compiler::Signatures::BUILTIN_SHORT_CLASS},
36 {ir::BoxingUnboxingFlags::BOX_TO_CHAR, compiler::Signatures::BUILTIN_CHAR_CLASS},
37 {ir::BoxingUnboxingFlags::BOX_TO_INT, compiler::Signatures::BUILTIN_INT_CLASS},
38 {ir::BoxingUnboxingFlags::BOX_TO_LONG, compiler::Signatures::BUILTIN_LONG_CLASS},
39 {ir::BoxingUnboxingFlags::BOX_TO_FLOAT, compiler::Signatures::BUILTIN_FLOAT_CLASS},
40 {ir::BoxingUnboxingFlags::BOX_TO_DOUBLE, compiler::Signatures::BUILTIN_DOUBLE_CLASS},
41 });
42
43 for (size_t i = 0; i < callExpr->Arguments().size(); ++i) {
44 auto arg = callExpr->Arguments()[i];
45 if (arg->IsNumberLiteral()) {
46 const auto boxingFlag = arg->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG;
47 auto it = BOXTO.find(static_cast<ir::BoxingUnboxingFlags>(boxingFlag));
48 if (it == BOXTO.end()) {
49 continue;
50 }
51
52 auto res = parser->CreateFormattedExpression("@@I1.valueOf(@@E2)", it->second, arg);
53 res->SetParent(callExpr);
54 res->SetRange(arg->Range());
55 arg->RemoveBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOXING_FLAG);
56 callExpr->Arguments()[i] = res;
57
58 Recheck(phaseManager, checker->VarBinder()->AsETSBinder(), checker, res);
59 }
60 }
61 }
62
Perform(public_lib::Context * const ctx,parser::Program * const program)63 bool BoxedTypeLowering::Perform(public_lib::Context *const ctx, parser::Program *const program)
64 {
65 for (const auto &[_, extPrograms] : program->ExternalSources()) {
66 (void)_;
67 for (auto *const extProg : extPrograms) {
68 if (extProg->GetFlag(parser::ProgramFlags::AST_BOXED_TYPE_LOWERED)) {
69 continue;
70 }
71 Perform(ctx, extProg);
72 extProg->SetFlag(parser::ProgramFlags::AST_BOXED_TYPE_LOWERED);
73 }
74 }
75
76 auto checker = ctx->checker->AsETSChecker();
77 auto parser = ctx->parser->AsETSParser();
78 auto phaseManager = ctx->phaseManager;
79 program->Ast()->TransformChildrenRecursively(
80 // CC-OFFNXT(G.FMT.14-CPP) project code style
81 [phaseManager, checker, parser](checker::AstNodePtr ast) -> checker::AstNodePtr {
82 if (!ast->IsCallExpression()) {
83 return ast;
84 }
85
86 auto callExpr = ast->AsCallExpression();
87 if (callExpr->Signature() == nullptr ||
88 // Skip lambda expressions because lambda parameters are treated a special way as ETSObjectType.
89 callExpr->Callee()->TsType()->IsETSObjectType()) {
90 return ast;
91 }
92
93 BoxNumberLiteralArguments(callExpr, phaseManager, checker, parser);
94
95 return ast;
96 },
97 Name());
98
99 return true;
100 }
101
102 } // namespace ark::es2panda::compiler
103