1 /**
2 * Copyright (c) 2023-2024 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 "bigintLowering.h"
17
18 #include "compiler/lowering/scopesInit/scopesInitPhase.h"
19 #include "compiler/lowering/util.h"
20
21 namespace ark::es2panda::compiler {
22
Name() const23 std::string_view BigIntLowering::Name() const
24 {
25 return "BigIntLowering";
26 }
27
CreateBigInt(public_lib::Context * ctx,ir::BigIntLiteral * literal)28 ir::Expression *CreateBigInt(public_lib::Context *ctx, ir::BigIntLiteral *literal)
29 {
30 auto parser = ctx->parser->AsETSParser();
31 auto checker = ctx->checker->AsETSChecker();
32
33 // This will change the bigint literal node into the new class instance expression:
34 // 123456n => new BigInt("123456")
35 std::string src {"new "};
36 src += Signatures::BUILTIN_BIGINT_CLASS;
37 src += "(\"";
38 src += literal->Str().Utf8();
39 src += "\")";
40
41 auto loweringResult = parser->CreateExpression(src);
42 loweringResult->SetParent(literal->Parent());
43
44 InitScopesPhaseETS::RunExternalNode(loweringResult, checker->VarBinder());
45 checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(loweringResult, NearestScope(loweringResult));
46 loweringResult->Check(checker);
47
48 return loweringResult;
49 }
50
ReplaceStrictEqualByNormalEqual(ir::BinaryExpression * expr)51 bool ReplaceStrictEqualByNormalEqual(ir::BinaryExpression *expr)
52 {
53 auto left = expr->Left()->TsType();
54 auto isBigintLeft = (left != nullptr && left->IsETSBigIntType()) || expr->Left()->IsBigIntLiteral();
55 auto right = expr->Right()->TsType();
56 auto isBigintRight = (right != nullptr && right->IsETSBigIntType()) || expr->Right()->IsBigIntLiteral();
57 if (!isBigintLeft && !isBigintRight) {
58 return false;
59 }
60
61 if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_STRICT_EQUAL) {
62 expr->SetOperator(lexer::TokenType::PUNCTUATOR_EQUAL);
63 } else if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL) {
64 expr->SetOperator(lexer::TokenType::PUNCTUATOR_NOT_EQUAL);
65 } else {
66 return false;
67 }
68
69 return true;
70 }
71
72 // Currently there are no compile time operations for bigint.
RemoveConst(ir::BinaryExpression * expr)73 bool RemoveConst(ir::BinaryExpression *expr)
74 {
75 bool isRemoved = false;
76 auto left = expr->Left()->TsType();
77 if (left != nullptr && left->IsETSBigIntType()) {
78 left->RemoveTypeFlag(checker::TypeFlag::CONSTANT);
79 isRemoved = true;
80 }
81
82 auto right = expr->Right()->TsType();
83 if (right != nullptr && right->IsETSBigIntType()) {
84 right->RemoveTypeFlag(checker::TypeFlag::CONSTANT);
85 isRemoved = true;
86 }
87
88 return isRemoved;
89 }
90
PerformForModule(public_lib::Context * const ctx,parser::Program * const program)91 bool BigIntLowering::PerformForModule(public_lib::Context *const ctx, parser::Program *const program)
92 {
93 auto checker = ctx->checker->AsETSChecker();
94
95 program->Ast()->TransformChildrenRecursively(
96 // CC-OFFNXT(G.FMT.14-CPP) project code style
97 [ctx, checker](ir::AstNode *ast) -> ir::AstNode * {
98 if (ast->IsBigIntLiteral() && ast->Parent() != nullptr && ast->Parent()->IsClassProperty()) {
99 return CreateBigInt(ctx, ast->AsBigIntLiteral());
100 }
101
102 if (ast->IsBinaryExpression()) {
103 auto expr = ast->AsBinaryExpression();
104 bool doCheck = ReplaceStrictEqualByNormalEqual(expr);
105 doCheck |= RemoveConst(expr);
106 if (doCheck) {
107 expr->Check(checker);
108 }
109 }
110
111 return ast;
112 },
113 Name());
114
115 return true;
116 }
117
118 } // namespace ark::es2panda::compiler
119