13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "bigintLowering.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include "compiler/lowering/scopesInit/scopesInitPhase.h"
193af6ab5fSopenharmony_ci#include "compiler/lowering/util.h"
203af6ab5fSopenharmony_ci
213af6ab5fSopenharmony_cinamespace ark::es2panda::compiler {
223af6ab5fSopenharmony_ci
233af6ab5fSopenharmony_cistd::string_view BigIntLowering::Name() const
243af6ab5fSopenharmony_ci{
253af6ab5fSopenharmony_ci    return "BigIntLowering";
263af6ab5fSopenharmony_ci}
273af6ab5fSopenharmony_ci
283af6ab5fSopenharmony_ciir::Expression *CreateBigInt(public_lib::Context *ctx, ir::BigIntLiteral *literal)
293af6ab5fSopenharmony_ci{
303af6ab5fSopenharmony_ci    auto parser = ctx->parser->AsETSParser();
313af6ab5fSopenharmony_ci    auto checker = ctx->checker->AsETSChecker();
323af6ab5fSopenharmony_ci
333af6ab5fSopenharmony_ci    // This will change the bigint literal node into the new class instance expression:
343af6ab5fSopenharmony_ci    // 123456n => new BigInt("123456")
353af6ab5fSopenharmony_ci    std::string src {"new "};
363af6ab5fSopenharmony_ci    src += Signatures::BUILTIN_BIGINT_CLASS;
373af6ab5fSopenharmony_ci    src += "(\"";
383af6ab5fSopenharmony_ci    src += literal->Str().Utf8();
393af6ab5fSopenharmony_ci    src += "\")";
403af6ab5fSopenharmony_ci
413af6ab5fSopenharmony_ci    auto loweringResult = parser->CreateExpression(src);
423af6ab5fSopenharmony_ci    loweringResult->SetParent(literal->Parent());
433af6ab5fSopenharmony_ci
443af6ab5fSopenharmony_ci    InitScopesPhaseETS::RunExternalNode(loweringResult, checker->VarBinder());
453af6ab5fSopenharmony_ci    checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(loweringResult, NearestScope(loweringResult));
463af6ab5fSopenharmony_ci    loweringResult->Check(checker);
473af6ab5fSopenharmony_ci
483af6ab5fSopenharmony_ci    return loweringResult;
493af6ab5fSopenharmony_ci}
503af6ab5fSopenharmony_ci
513af6ab5fSopenharmony_cibool ReplaceStrictEqualByNormalEqual(ir::BinaryExpression *expr)
523af6ab5fSopenharmony_ci{
533af6ab5fSopenharmony_ci    auto left = expr->Left()->TsType();
543af6ab5fSopenharmony_ci    auto isBigintLeft = (left != nullptr && left->IsETSBigIntType()) || expr->Left()->IsBigIntLiteral();
553af6ab5fSopenharmony_ci    auto right = expr->Right()->TsType();
563af6ab5fSopenharmony_ci    auto isBigintRight = (right != nullptr && right->IsETSBigIntType()) || expr->Right()->IsBigIntLiteral();
573af6ab5fSopenharmony_ci    if (!isBigintLeft && !isBigintRight) {
583af6ab5fSopenharmony_ci        return false;
593af6ab5fSopenharmony_ci    }
603af6ab5fSopenharmony_ci
613af6ab5fSopenharmony_ci    if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_STRICT_EQUAL) {
623af6ab5fSopenharmony_ci        expr->SetOperator(lexer::TokenType::PUNCTUATOR_EQUAL);
633af6ab5fSopenharmony_ci    } else if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL) {
643af6ab5fSopenharmony_ci        expr->SetOperator(lexer::TokenType::PUNCTUATOR_NOT_EQUAL);
653af6ab5fSopenharmony_ci    } else {
663af6ab5fSopenharmony_ci        return false;
673af6ab5fSopenharmony_ci    }
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci    return true;
703af6ab5fSopenharmony_ci}
713af6ab5fSopenharmony_ci
723af6ab5fSopenharmony_ci// Currently there are no compile time operations for bigint.
733af6ab5fSopenharmony_cibool RemoveConst(ir::BinaryExpression *expr)
743af6ab5fSopenharmony_ci{
753af6ab5fSopenharmony_ci    bool isRemoved = false;
763af6ab5fSopenharmony_ci    auto left = expr->Left()->TsType();
773af6ab5fSopenharmony_ci    if (left != nullptr && left->IsETSBigIntType()) {
783af6ab5fSopenharmony_ci        left->RemoveTypeFlag(checker::TypeFlag::CONSTANT);
793af6ab5fSopenharmony_ci        isRemoved = true;
803af6ab5fSopenharmony_ci    }
813af6ab5fSopenharmony_ci
823af6ab5fSopenharmony_ci    auto right = expr->Right()->TsType();
833af6ab5fSopenharmony_ci    if (right != nullptr && right->IsETSBigIntType()) {
843af6ab5fSopenharmony_ci        right->RemoveTypeFlag(checker::TypeFlag::CONSTANT);
853af6ab5fSopenharmony_ci        isRemoved = true;
863af6ab5fSopenharmony_ci    }
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_ci    return isRemoved;
893af6ab5fSopenharmony_ci}
903af6ab5fSopenharmony_ci
913af6ab5fSopenharmony_cibool BigIntLowering::Perform(public_lib::Context *const ctx, parser::Program *const program)
923af6ab5fSopenharmony_ci{
933af6ab5fSopenharmony_ci    for (const auto &[_, ext_programs] : program->ExternalSources()) {
943af6ab5fSopenharmony_ci        (void)_;
953af6ab5fSopenharmony_ci        for (auto *const extProg : ext_programs) {
963af6ab5fSopenharmony_ci            Perform(ctx, extProg);
973af6ab5fSopenharmony_ci        }
983af6ab5fSopenharmony_ci    }
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_ci    auto checker = ctx->checker->AsETSChecker();
1013af6ab5fSopenharmony_ci
1023af6ab5fSopenharmony_ci    program->Ast()->TransformChildrenRecursively(
1033af6ab5fSopenharmony_ci        [ctx, checker](ir::AstNode *ast) -> ir::AstNode * {
1043af6ab5fSopenharmony_ci            if (ast->IsBigIntLiteral() && ast->Parent() != nullptr && ast->Parent()->IsClassProperty()) {
1053af6ab5fSopenharmony_ci                return CreateBigInt(ctx, ast->AsBigIntLiteral());
1063af6ab5fSopenharmony_ci            }
1073af6ab5fSopenharmony_ci
1083af6ab5fSopenharmony_ci            if (ast->IsBinaryExpression()) {
1093af6ab5fSopenharmony_ci                auto expr = ast->AsBinaryExpression();
1103af6ab5fSopenharmony_ci                bool doCheck = ReplaceStrictEqualByNormalEqual(expr);
1113af6ab5fSopenharmony_ci                doCheck |= RemoveConst(expr);
1123af6ab5fSopenharmony_ci                if (doCheck) {
1133af6ab5fSopenharmony_ci                    expr->Check(checker);
1143af6ab5fSopenharmony_ci                }
1153af6ab5fSopenharmony_ci            }
1163af6ab5fSopenharmony_ci
1173af6ab5fSopenharmony_ci            return ast;
1183af6ab5fSopenharmony_ci        },
1193af6ab5fSopenharmony_ci        Name());
1203af6ab5fSopenharmony_ci
1213af6ab5fSopenharmony_ci    return true;
1223af6ab5fSopenharmony_ci}
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci}  // namespace ark::es2panda::compiler
125