• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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