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 21namespace ark::es2panda::compiler { 22 23std::string_view BigIntLowering::Name() const 24{ 25 return "BigIntLowering"; 26} 27 28ir::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 51bool 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. 73bool 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 91bool 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