From 5ad3cacc3a812c3f1aec1a9d4ebe33d70b34af2e Mon Sep 17 00:00:00 2001 From: aakmaev Date: Mon, 22 Jan 2024 03:57:02 +0300 Subject: [PATCH] Implement literal types in unions Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I8XU3L?from=project-issue Signed-off-by: Akmaev Alexey --- ets2panda/checker/ets/typeCreation.cpp | 13 +- ets2panda/checker/types/ets/etsStringType.cpp | 12 +- ets2panda/checker/types/ets/etsUnionType.cpp | 76 +++++++----- ets2panda/checker/types/ets/etsUnionType.h | 4 +- ets2panda/checker/types/ets/intType.cpp | 3 +- ets2panda/checker/types/type.cpp | 5 + ets2panda/checker/types/type.h | 7 ++ .../compiler/lowering/ets/unionLowering.cpp | 115 +++++++++++++----- ets2panda/ir/expressions/literal.h | 6 +- .../ir/expressions/literals/numberLiteral.cpp | 5 + .../ir/expressions/literals/numberLiteral.h | 1 + .../ir/expressions/literals/stringLiteral.cpp | 5 + .../ir/expressions/literals/stringLiteral.h | 1 + ets2panda/parser/ETSparser.cpp | 8 ++ 14 files changed, 186 insertions(+), 75 deletions(-) diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index bf8867a24d..a2ac1d04f2 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -14,7 +14,6 @@ */ #include "checker/ETSchecker.h" -#include "checker/ets/boxingConverter.h" #include "checker/types/ets/byteType.h" #include "checker/types/ets/charType.h" #include "checker/types/ets/etsDynamicFunctionType.h" @@ -130,17 +129,13 @@ Type *ETSChecker::CreateETSUnionType(ArenaVector &&constituentTypes) return nullptr; } - ArenaVector newConstituentTypes(Allocator()->Adapter()); - - for (auto *it : constituentTypes) { - newConstituentTypes.push_back( - it->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) ? BoxingConverter::ETSTypeFromSource(this, it) : it); + ETSUnionType::NormalizeTypes(Relation(), constituentTypes); + if (constituentTypes.size() == 1) { + return constituentTypes[0]; } + ArenaVector newConstituentTypes = ETSUnionType::BoxTypes(Relation(), constituentTypes); ETSUnionType::NormalizeTypes(Relation(), newConstituentTypes); - if (newConstituentTypes.size() == 1) { - return newConstituentTypes[0]; - } return Allocator()->New(this, std::move(newConstituentTypes)); } diff --git a/ets2panda/checker/types/ets/etsStringType.cpp b/ets2panda/checker/types/ets/etsStringType.cpp index d9c46fbe52..0f2707c2a2 100644 --- a/ets2panda/checker/types/ets/etsStringType.cpp +++ b/ets2panda/checker/types/ets/etsStringType.cpp @@ -20,20 +20,26 @@ namespace panda::es2panda::checker { void ETSStringType::Identical(TypeRelation *relation, Type *other) { - if (other->IsETSStringType()) { + bool bothConstants = HasTypeFlag(TypeFlag::CONSTANT) && other->HasTypeFlag(TypeFlag::CONSTANT); + if (other->IsETSStringType() && + ((bothConstants && value_ == other->AsETSStringType()->GetValue()) || !bothConstants)) { relation->Result(true); } } bool ETSStringType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) { - relation->Result(target->IsETSStringType()); + bool bothConstants = HasTypeFlag(TypeFlag::CONSTANT) && target->HasTypeFlag(TypeFlag::CONSTANT); + relation->Result(target->IsETSStringType() && + ((bothConstants && value_ == target->AsETSStringType()->GetValue()) || !bothConstants)); return relation->IsTrue(); } void ETSStringType::AssignmentTarget([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *source) { - if (source->IsETSStringType()) { + bool bothConstants = HasTypeFlag(TypeFlag::CONSTANT) && source->HasTypeFlag(TypeFlag::CONSTANT); + if (source->IsETSStringType() && + ((bothConstants && value_ == source->AsETSStringType()->GetValue()) || !bothConstants)) { relation->Result(true); } } diff --git a/ets2panda/checker/types/ets/etsUnionType.cpp b/ets2panda/checker/types/ets/etsUnionType.cpp index 6ff849b9bf..d80c4e6424 100644 --- a/ets2panda/checker/types/ets/etsUnionType.cpp +++ b/ets2panda/checker/types/ets/etsUnionType.cpp @@ -16,6 +16,7 @@ #include #include "etsUnionType.h" +#include "checker/ets/boxingConverter.h" #include "checker/ets/conversion.h" #include "checker/types/globalTypesHolder.h" #include "checker/ETSchecker.h" @@ -65,7 +66,7 @@ Type *ETSUnionType::ComputeLUB(ETSChecker *checker) const { auto lub = constituentTypes_.front(); for (auto *t : constituentTypes_) { - if (!checker->IsReferenceType(t)) { + if (!ETSChecker::IsReferenceType(t)) { return checker->GetGlobalTypesHolder()->GlobalETSObjectType(); } if (t->IsETSObjectType() && t->AsETSObjectType()->SuperType() == nullptr) { @@ -103,33 +104,31 @@ bool ETSUnionType::AssignmentSource(TypeRelation *relation, Type *target) void ETSUnionType::AssignmentTarget(TypeRelation *relation, Type *source) { auto *const checker = relation->GetChecker()->AsETSChecker(); - auto *const refSource = - source->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) ? checker->PrimitiveTypeAsETSBuiltinType(source) : source; - auto exactType = std::find_if( - constituentTypes_.begin(), constituentTypes_.end(), [checker, relation, source, refSource](Type *ct) { - if (ct == refSource && source->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) && ct->IsETSObjectType() && - ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE)) { - relation->GetNode()->SetBoxingUnboxingFlags(checker->GetBoxingFlag(ct)); - return relation->IsAssignableTo(refSource, ct); - } - return false; - }); + auto *refSource = source->IsETSPrimitiveType() && !source->IsConstantType() + ? checker->PrimitiveTypeAsETSBuiltinType(source) + : source; + auto exactType = std::find_if(constituentTypes_.begin(), constituentTypes_.end(), + [checker, relation, source, refSource](Type *ct) { + if (ct == refSource && source->IsETSPrimitiveType() && ct->IsETSUnboxableType()) { + relation->GetNode()->SetBoxingUnboxingFlags(checker->GetBoxingFlag(ct)); + return relation->IsAssignableTo(refSource, ct); + } + return false; + }); if (exactType != constituentTypes_.end()) { return; } size_t assignableCount = 0; for (auto *it : constituentTypes_) { - if (relation->IsAssignableTo(refSource, it)) { - if (refSource != source) { - relation->IsAssignableTo(source, it); - ASSERT(relation->IsTrue()); + if (relation->IsAssignableTo(source, it)) { + if (source->IsETSPrimitiveType()) { + relation->GetNode()->SetBoxingUnboxingFlags( + checker->GetBoxingFlag(checker->PrimitiveTypeAsETSBuiltinType(it))); } ++assignableCount; continue; } - bool assignPrimitive = it->IsETSObjectType() && - it->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE) && - source->HasTypeFlag(TypeFlag::ETS_PRIMITIVE); + bool assignPrimitive = it->IsETSUnboxableType() && source->IsETSPrimitiveType(); if (assignPrimitive && relation->IsAssignableTo(source, checker->ETSBuiltinTypeAsPrimitiveType(it))) { Type *unboxedIt = checker->ETSBuiltinTypeAsPrimitiveType(it); if (unboxedIt != source) { @@ -196,11 +195,11 @@ void ETSUnionType::NormalizeTypes(TypeRelation *relation, ArenaVector &c while (cmpIt != constituentTypes.end()) { auto newEnd = std::remove_if( constituentTypes.begin(), constituentTypes.end(), [relation, checker, cmpIt, numberFound](Type *ct) { + bool both_constants = (*cmpIt)->HasTypeFlag(TypeFlag::CONSTANT) && ct->HasTypeFlag(TypeFlag::CONSTANT); relation->Result(false); (*cmpIt)->IsSupertypeOf(relation, ct); - bool removeSubtype = ct != *cmpIt && relation->IsTrue(); - bool removeNumeric = numberFound && ct->IsETSObjectType() && - ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE) && + bool removeSubtype = ct != *cmpIt && !both_constants && relation->IsTrue(); + bool removeNumeric = numberFound && ct->IsETSUnboxableType() && !ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE) && !ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN); bool removeNever = ct == checker->GetGlobalTypesHolder()->GlobalBuiltinNeverType(); @@ -215,20 +214,33 @@ void ETSUnionType::NormalizeTypes(TypeRelation *relation, ArenaVector &c } } +ArenaVector ETSUnionType::BoxTypes(TypeRelation *relation, ArenaVector &constituentTypes) +{ + auto *const checker = relation->GetChecker()->AsETSChecker(); + ArenaVector boxedConstituentTypes(checker->Allocator()->Adapter()); + for (auto *it : constituentTypes) { + boxedConstituentTypes.push_back(it->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && !it->IsConstantType() + ? BoxingConverter::ETSTypeFromSource(checker, it) + : it); + } + return boxedConstituentTypes; +} + Type *ETSUnionType::Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) { ArenaVector copiedConstituents(allocator->Adapter()); + ETSUnionType::NormalizeTypes(relation, copiedConstituents); + if (copiedConstituents.size() == 1) { + return copiedConstituents[0]; + } + for (auto *it : constituentTypes_) { copiedConstituents.push_back(it->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) ? relation->GetChecker()->AsETSChecker()->PrimitiveTypeAsETSBuiltinType(it) : it->Instantiate(allocator, relation, globalTypes)); } - ETSUnionType::NormalizeTypes(relation, copiedConstituents); - if (copiedConstituents.size() == 1) { - return copiedConstituents[0]; - } return allocator->New(relation->GetChecker()->AsETSChecker(), std::move(copiedConstituents)); } @@ -246,8 +258,9 @@ Type *ETSUnionType::Substitute(TypeRelation *relation, const Substitution *subst void ETSUnionType::Cast(TypeRelation *relation, Type *target) { auto *const checker = relation->GetChecker()->AsETSChecker(); - auto *const refTarget = - target->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) ? checker->PrimitiveTypeAsETSBuiltinType(target) : target; + auto *const refTarget = target->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) && !target->IsConstantType() + ? checker->PrimitiveTypeAsETSBuiltinType(target) + : target; auto exactType = std::find_if(constituentTypes_.begin(), constituentTypes_.end(), [this, relation, refTarget](Type *src) { if (src == refTarget && relation->IsCastableTo(src, refTarget)) { @@ -261,6 +274,13 @@ void ETSUnionType::Cast(TypeRelation *relation, Type *target) return; } for (auto *source : constituentTypes_) { + if (source->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) && target->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT)) { + auto *const unboxedTarget = checker->ETSBuiltinTypeAsPrimitiveType(target); + if (relation->IsCastableTo(source, unboxedTarget)) { + GetLeastUpperBoundType()->Cast(relation, target); + return; + } + } if (relation->IsCastableTo(source, refTarget)) { GetLeastUpperBoundType()->Cast(relation, refTarget); ASSERT(relation->IsTrue()); diff --git a/ets2panda/checker/types/ets/etsUnionType.h b/ets2panda/checker/types/ets/etsUnionType.h index 6fc427aa9c..d76bdcf0d7 100644 --- a/ets2panda/checker/types/ets/etsUnionType.h +++ b/ets2panda/checker/types/ets/etsUnionType.h @@ -24,7 +24,7 @@ class GlobalTypesHolder; class ETSUnionType : public Type { public: - // constituentTypes must be normalized + // constituentTypes must be normalized and boxed explicit ETSUnionType(ETSChecker *checker, ArenaVector &&constituentTypes); const ArenaVector &ConstituentTypes() const @@ -59,6 +59,8 @@ public: static void NormalizeTypes(TypeRelation *relation, ArenaVector &constituentTypes); + static ArenaVector BoxTypes(TypeRelation *relation, ArenaVector &constituentTypes); + std::tuple ResolveConditionExpr() const override { for (auto const &tp : ConstituentTypes()) { diff --git a/ets2panda/checker/types/ets/intType.cpp b/ets2panda/checker/types/ets/intType.cpp index 4c8871d842..e0524cf24f 100644 --- a/ets2panda/checker/types/ets/intType.cpp +++ b/ets2panda/checker/types/ets/intType.cpp @@ -21,7 +21,8 @@ namespace panda::es2panda::checker { void IntType::Identical(TypeRelation *relation, Type *other) { - if (other->IsIntType()) { + bool bothConstants = HasTypeFlag(TypeFlag::CONSTANT) && other->HasTypeFlag(TypeFlag::CONSTANT); + if (other->IsIntType() && ((bothConstants && value_ == other->AsIntType()->GetValue()) || !bothConstants)) { relation->Result(true); } } diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index 0e3b315c12..26cec219b3 100644 --- a/ets2panda/checker/types/type.cpp +++ b/ets2panda/checker/types/type.cpp @@ -61,6 +61,11 @@ bool Type::IsETSStringType() const return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::STRING); } +bool Type::IsETSUnboxableType() const +{ + return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE); +} + bool Type::IsETSAsyncFuncReturnType() const { return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::ASYNC_FUNC_RETURN_TYPE); diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 047346f00b..aa353ae0bd 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -161,6 +161,13 @@ public: return HasTypeFlag(checker::TypeFlag::CONSTANT); } + bool IsETSPrimitiveType() const + { + return HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE); + } + + bool IsETSUnboxableType() const; + TypeFlag TypeFlags() const { return typeFlags_; diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index 930c61a3a9..4ef8631f0b 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -152,10 +152,10 @@ ir::TSAsExpression *HandleUnionCastToPrimitive(checker::ETSChecker *checker, ir: expr->TsType()); } if (sourceType != nullptr && expr->Expr()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { - if (expr->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + if (expr->TsType()->IsETSPrimitiveType()) { auto *const boxedExprType = checker::BoxingConverter::ETSTypeFromSource(checker, expr->TsType()); auto *const asExpr = GenAsExpression(checker, boxedExprType, expr->Expr(), expr); - asExpr->SetBoxingUnboxingFlags(expr->Expr()->GetBoxingUnboxingFlags()); + asExpr->SetBoxingUnboxingFlags(checker->GetUnboxingFlag(expr->TsType())); expr->Expr()->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); expr->SetExpr(asExpr); } @@ -173,12 +173,10 @@ ir::BinaryExpression *GenInstanceofExpr(checker::ETSChecker *checker, ir::Expres auto *const lhsExpr = unionNode->Clone(checker->Allocator())->AsExpression(); lhsExpr->Check(checker); lhsExpr->SetBoxingUnboxingFlags(unionNode->GetBoxingUnboxingFlags()); - auto *rhsType = constituentType; - if (!constituentType->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT)) { - checker->Relation()->SetNode(unionNode); - rhsType = checker::conversion::Boxing(checker->Relation(), constituentType); - checker->Relation()->SetNode(nullptr); - } + auto *rhsType = constituentType->IsETSPrimitiveType() + ? checker::BoxingConverter::ETSTypeFromSource(checker, constituentType) + : constituentType; + rhsType = rhsType->IsETSStringType() ? checker->GlobalBuiltinETSStringType() : rhsType; auto *const rhsExpr = checker->Allocator()->New(rhsType->AsETSObjectType()->Name(), checker->Allocator()); auto *const instanceofExpr = @@ -205,6 +203,7 @@ ir::VariableDeclaration *GenVariableDeclForBinaryExpr(checker::ETSChecker *check varId->SetVariable(var); varId->SetTsType(var->TsType()); + // NOTE(aakmaev): init false for default auto declarator = checker->AllocNode(ir::VariableDeclaratorFlag::LET, varId); ArenaVector declarators(checker->Allocator()->Adapter()); declarators.push_back(declarator); @@ -240,47 +239,100 @@ ir::BlockStatement *GenBlockStmtForAssignmentBinary(checker::ETSChecker *checker return localBlockStmt; } -ir::Expression *SetBoxFlagOrGenAsExpression(checker::ETSChecker *checker, checker::Type *constituentType, - ir::Expression *otherNode) +ir::Expression *ProcessUnionOperand(checker::ETSChecker *checker, checker::Type *constituentType, + ir::Expression *unionNode, checker::Type *otherNodeType) { - if (constituentType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::UNBOXABLE_TYPE) && - !otherNode->IsETSUnionType() && otherNode->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - auto *unboxedConstituentType = checker->ETSBuiltinTypeAsPrimitiveType(constituentType); - if (unboxedConstituentType != otherNode->TsType()) { - auto *const primAsExpression = - GenAsExpression(checker, unboxedConstituentType, otherNode, otherNode->Parent()); - primAsExpression->SetBoxingUnboxingFlags(checker->GetBoxingFlag(constituentType)); - return primAsExpression; - } - return otherNode; + bool isAnyOpIsC = (!constituentType->IsETSPrimitiveType() && !constituentType->IsETSUnboxableType()) || + (!otherNodeType->IsETSPrimitiveType() && !otherNodeType->IsETSUnboxableType()); + if (isAnyOpIsC) { + return GenAsExpression(checker, + constituentType->IsETSPrimitiveType() + ? checker->PrimitiveTypeAsETSBuiltinType(constituentType) + : constituentType, + unionNode, unionNode->Parent()); } - if (otherNode->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - otherNode->SetBoxingUnboxingFlags( - checker->GetBoxingFlag(checker::BoxingConverter::ETSTypeFromSource(checker, otherNode->TsType()))); + return UnionCastToPrimitive(checker, checker->PrimitiveTypeAsETSBuiltinType(constituentType)->AsETSObjectType(), + checker->ETSBuiltinTypeAsPrimitiveType(constituentType), unionNode); +} + +ir::Expression *ProcessOtherOperand(checker::ETSChecker *checker, checker::Type *constituentType, + ir::Expression *otherNode, checker::Type *otherNodeType) +{ + bool isConstituentIsC = !constituentType->IsETSPrimitiveType() && !constituentType->IsETSUnboxableType(); + bool isOtherIsC = !otherNodeType->IsETSPrimitiveType() && !otherNodeType->IsETSUnboxableType(); + if (otherNodeType->IsETSPrimitiveType() && isConstituentIsC) { + return GenAsExpression(checker, checker->PrimitiveTypeAsETSBuiltinType(otherNodeType), otherNode, + otherNode->Parent()); + } + if (!isOtherIsC && otherNodeType->IsETSUnboxableType()) { + auto *const unboxedOtherType = checker->ETSBuiltinTypeAsPrimitiveType(otherNodeType); + otherNode->SetBoxingUnboxingFlags(checker->GetUnboxingFlag(unboxedOtherType)); + return GenAsExpression(checker, unboxedOtherType, otherNode, otherNode->Parent()); } return otherNode; } +/* There are 8 cases to process operands: + * ┌----------------------------------------------┐ + * | cType | other | modification | + * |----------------------------------------------| + * | p | p | union as p; None | + * | p | b | union as p; unbox | + * | b | p | union as p; None | + * | b | b | union as p; unbox | + * | p | C | union as box(p); None | + * | b | C | union as b; None | + * | C | p | union as C; box(p) | + * | C | b | union as C; None | + * └----------------------------------------------┘ + * where cType = constituentType; p = primitive; b = boxed; C = some non-unboxable object. + */ ir::Expression *ProcessOperandsInBinaryExpr(checker::ETSChecker *checker, ir::BinaryExpression *expr, checker::Type *constituentType) { ASSERT(expr->OperatorType() == lexer::TokenType::PUNCTUATOR_EQUAL || expr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_EQUAL); bool isLhsUnion = expr->Left()->TsType()->IsETSUnionType(); - ir::Expression *unionNode = isLhsUnion ? expr->Left() : expr->Right(); - auto *const asExpression = GenAsExpression(checker, constituentType, unionNode, expr); + auto *const unionNode = isLhsUnion ? expr->Left() : expr->Right(); + auto *const otherNode = isLhsUnion ? expr->Right() : expr->Left(); + auto *const unionAsExpr = ProcessUnionOperand(checker, constituentType, unionNode, otherNode->TsType()); + auto *const otherAsExpr = ProcessOtherOperand(checker, constituentType, otherNode, otherNode->TsType()); if (isLhsUnion) { - expr->SetLeft(asExpression); - expr->SetRight(SetBoxFlagOrGenAsExpression(checker, constituentType, expr->Right())); + expr->SetLeft(unionAsExpr); + expr->SetRight(otherAsExpr); + } else { + expr->SetRight(unionAsExpr); + expr->SetLeft(otherAsExpr); + } + if (expr->Left()->TsType()->IsETSPrimitiveType() && expr->Right()->TsType()->IsETSPrimitiveType()) { + expr->SetOperationType(unionAsExpr->TsType()); } else { - expr->SetRight(asExpression); - expr->SetLeft(SetBoxFlagOrGenAsExpression(checker, constituentType, expr->Left())); + expr->SetOperationType(checker->GlobalETSObjectType()); } - expr->SetOperationType(checker->GlobalETSObjectType()); expr->SetTsType(checker->GlobalETSBooleanType()); return expr; } +bool IsIdenticalInstanceofBranch(ir::IfStatement *instanceofBranch, ir::BinaryExpression *test) +{ + ASSERT(test->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF); + if (instanceofBranch == nullptr) { + return false; + } + auto *const newBranchType = test->Right()->TsType(); + while (instanceofBranch != nullptr) { + auto *const currBranchType = instanceofBranch->Test()->AsBinaryExpression()->Right()->TsType(); + if (currBranchType == newBranchType) { + return true; + } + if (instanceofBranch->Alternate() == nullptr) { + return false; + } + instanceofBranch = instanceofBranch->Alternate()->AsIfStatement(); + } + return false; +} + ir::Statement *FindStatementFromNode(ir::Expression *expr) { ir::AstNode *node = expr; @@ -316,6 +368,9 @@ ir::BlockStatement *ReplaceBinaryExprInStmt(checker::ETSChecker *checker, ir::Ex ir::IfStatement *instanceofTree = nullptr; for (auto *uType : unionNode->TsType()->AsETSUnionType()->ConstituentTypes()) { auto *const test = GenInstanceofExpr(checker, unionNode, uType); + if (IsIdenticalInstanceofBranch(instanceofTree, test)) { + continue; + } auto *clonedBinary = expr->Clone(checker->Allocator(), expr->Parent())->AsBinaryExpression(); clonedBinary->Check(checker); auto *const consequent = GenBlockStmtForAssignmentBinary( diff --git a/ets2panda/ir/expressions/literal.h b/ets2panda/ir/expressions/literal.h index 80954603a3..d88fdbe8e5 100644 --- a/ets2panda/ir/expressions/literal.h +++ b/ets2panda/ir/expressions/literal.h @@ -16,10 +16,10 @@ #ifndef ES2PANDA_IR_EXPRESSION_LITERAL_H #define ES2PANDA_IR_EXPRESSION_LITERAL_H -#include "ir/expression.h" +#include "ir/typeNode.h" namespace panda::es2panda::ir { -class Literal : public Expression { +class Literal : public TypeNode { public: Literal() = delete; ~Literal() override = default; @@ -33,7 +33,7 @@ public: } protected: - explicit Literal(AstNodeType const type) : Expression(type) {} + explicit Literal(AstNodeType const type) : TypeNode(type) {} }; } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/literals/numberLiteral.cpp b/ets2panda/ir/expressions/literals/numberLiteral.cpp index dc7e40501b..4c045b5553 100644 --- a/ets2panda/ir/expressions/literals/numberLiteral.cpp +++ b/ets2panda/ir/expressions/literals/numberLiteral.cpp @@ -74,6 +74,11 @@ checker::Type *NumberLiteral::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } +checker::Type *NumberLiteral::GetType(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); +} + // NOLINTNEXTLINE(google-default-arguments) NumberLiteral *NumberLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { diff --git a/ets2panda/ir/expressions/literals/numberLiteral.h b/ets2panda/ir/expressions/literals/numberLiteral.h index 0abcbbce6d..c3c4a0276c 100644 --- a/ets2panda/ir/expressions/literals/numberLiteral.h +++ b/ets2panda/ir/expressions/literals/numberLiteral.h @@ -60,6 +60,7 @@ public: void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check(checker::TSChecker *checker) override; checker::Type *Check(checker::ETSChecker *checker) override; + checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/expressions/literals/stringLiteral.cpp b/ets2panda/ir/expressions/literals/stringLiteral.cpp index 11bc091825..41f449d42a 100644 --- a/ets2panda/ir/expressions/literals/stringLiteral.cpp +++ b/ets2panda/ir/expressions/literals/stringLiteral.cpp @@ -87,6 +87,11 @@ checker::Type *StringLiteral::Check(checker::ETSChecker *checker) return checker->GetAnalyzer()->Check(this); } +checker::Type *StringLiteral::GetType(checker::ETSChecker *checker) +{ + return checker->GetAnalyzer()->Check(this); +} + // NOLINTNEXTLINE(google-default-arguments) StringLiteral *StringLiteral::Clone(ArenaAllocator *const allocator, AstNode *const parent) { diff --git a/ets2panda/ir/expressions/literals/stringLiteral.h b/ets2panda/ir/expressions/literals/stringLiteral.h index 081eed374f..c5ff3a460f 100644 --- a/ets2panda/ir/expressions/literals/stringLiteral.h +++ b/ets2panda/ir/expressions/literals/stringLiteral.h @@ -52,6 +52,7 @@ public: void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check(checker::TSChecker *checker) override; checker::Type *Check(checker::ETSChecker *checker) override; + checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 5db2c3fd05..78cfd1c7f4 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -2836,6 +2836,14 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota typeAnnotation = ParseThisType(options); break; } + case lexer::TokenType::LITERAL_NUMBER: { + typeAnnotation = ParseNumberLiteral(); + break; + } + case lexer::TokenType::LITERAL_STRING: { + typeAnnotation = ParseStringLiteral(); + break; + } default: { break; } -- Gitee