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
Perform(public_lib::Context *const ctx, parser::Program *const program)91 bool BigIntLowering::Perform(public_lib::Context *const ctx, parser::Program *const program)
92 {
93 for (const auto &[_, ext_programs] : program->ExternalSources()) {
94 (void)_;
95 for (auto *const extProg : ext_programs) {
96 Perform(ctx, extProg);
97 }
98 }
99
100 auto checker = ctx->checker->AsETSChecker();
101
102 program->Ast()->TransformChildrenRecursively(
103 [ctx, checker](ir::AstNode *ast) -> ir::AstNode * {
104 if (ast->IsBigIntLiteral() && ast->Parent() != nullptr && ast->Parent()->IsClassProperty()) {
105 return CreateBigInt(ctx, ast->AsBigIntLiteral());
106 }
107
108 if (ast->IsBinaryExpression()) {
109 auto expr = ast->AsBinaryExpression();
110 bool doCheck = ReplaceStrictEqualByNormalEqual(expr);
111 doCheck |= RemoveConst(expr);
112 if (doCheck) {
113 expr->Check(checker);
114 }
115 }
116
117 return ast;
118 },
119 Name());
120
121 return true;
122 }
123
124 } // namespace ark::es2panda::compiler
125