diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 30bba267c94ff308429d0214a574b896b7375555..0e6805a900f5296f3ed4a5a5b2e929b22e72f793 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -65,6 +65,7 @@ libes2panda_sources = [ "checker/types/ets/doubleType.cpp", "checker/types/ets/etsArrayType.cpp", "checker/types/ets/etsAsyncFuncReturnType.cpp", + "checker/types/ets/etsBigIntType.cpp", "checker/types/ets/etsBooleanType.cpp", "checker/types/ets/etsDynamicType.cpp", "checker/types/ets/etsEnumType.cpp", @@ -162,6 +163,7 @@ libes2panda_sources = [ "compiler/lowering/ets/objectIndexAccess.cpp", "compiler/lowering/ets/opAssignment.cpp", "compiler/lowering/ets/promiseVoid.cpp", + "compiler/lowering/ets/structLowering.cpp", "compiler/lowering/ets/tupleLowering.cpp", "compiler/lowering/ets/unionLowering.cpp", "compiler/lowering/phase.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index a5c6d1294c773d13722d86634da752272cad572b..1313e981c04ee4927cfd107025edd8d86b11febf 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -159,6 +159,7 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/unionLowering.cpp compiler/lowering/ets/expandBrackets.cpp compiler/lowering/ets/promiseVoid.cpp + compiler/lowering/ets/structLowering.cpp ir/astDump.cpp ir/srcDump.cpp ir/astNode.cpp @@ -395,6 +396,7 @@ set(ES2PANDA_LIB_SRC checker/types/ets/etsFunctionType.cpp checker/types/ets/etsObjectType.cpp checker/types/ets/etsStringType.cpp + checker/types/ets/etsBigIntType.cpp checker/types/ets/etsTupleType.cpp checker/types/ets/etsTypeParameter.cpp checker/types/ets/etsUnionType.cpp diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 1099d4f2f060797095db897940a2ac1a6dcca4f9..5b7ac5a9edcd8c4dd082b90fc6ec8e129c50668f 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -21,6 +21,8 @@ #include "checker/ets/typeRelationContext.h" #include "util/helpers.h" +#include + namespace panda::es2panda::checker { ETSChecker *ETSAnalyzer::GetETSChecker() const @@ -968,9 +970,41 @@ checker::Type *ETSAnalyzer::Check(ir::BlockExpression *st) const UNREACHABLE(); } -ArenaVector &ChooseSignatures(checker::Type *calleeType, bool isConstructorCall, - bool isFunctionalInterface) +ArenaVector GetUnionTypeSignatures(ETSChecker *checker, checker::ETSUnionType *etsUnionType) +{ + ArenaVector callSignatures(checker->Allocator()->Adapter()); + + for (auto *constituentType : etsUnionType->ConstituentTypes()) { + if (constituentType->IsETSObjectType()) { + ArenaVector tmpCallSignatures(checker->Allocator()->Adapter()); + tmpCallSignatures = constituentType->AsETSObjectType() + ->GetOwnProperty("invoke") + ->TsType() + ->AsETSFunctionType() + ->CallSignatures(); + callSignatures.insert(callSignatures.end(), tmpCallSignatures.begin(), tmpCallSignatures.end()); + } + if (constituentType->IsETSFunctionType()) { + ArenaVector tmpCallSignatures(checker->Allocator()->Adapter()); + tmpCallSignatures = constituentType->AsETSFunctionType()->CallSignatures(); + callSignatures.insert(callSignatures.end(), tmpCallSignatures.begin(), tmpCallSignatures.end()); + } + if (constituentType->IsETSUnionType()) { + ArenaVector tmpCallSignatures(checker->Allocator()->Adapter()); + tmpCallSignatures = GetUnionTypeSignatures(checker, constituentType->AsETSUnionType()); + callSignatures.insert(callSignatures.end(), tmpCallSignatures.begin(), tmpCallSignatures.end()); + } + } + + return callSignatures; +} + +ArenaVector &ChooseSignatures(ETSChecker *checker, checker::Type *calleeType, + bool isConstructorCall, bool isFunctionalInterface, + bool isUnionTypeWithFunctionalInterface) { + static ArenaVector unionSignatures(checker->Allocator()->Adapter()); + unionSignatures.clear(); if (isConstructorCall) { return calleeType->AsETSObjectType()->ConstructSignatures(); } @@ -981,6 +1015,10 @@ ArenaVector &ChooseSignatures(checker::Type *calleeType, bool isCon ->AsETSFunctionType() ->CallSignatures(); } + if (isUnionTypeWithFunctionalInterface) { + unionSignatures = GetUnionTypeSignatures(checker, calleeType->AsETSUnionType()); + return unionSignatures; + } return calleeType->AsETSFunctionType()->CallSignatures(); } @@ -998,7 +1036,8 @@ checker::ETSObjectType *ChooseCalleeObj(ETSChecker *checker, ir::CallExpression } checker::Signature *ResolveSignature(ETSChecker *checker, ir::CallExpression *expr, checker::Type *calleeType, - bool isConstructorCall, bool isFunctionalInterface) + bool isConstructorCall, bool isFunctionalInterface, + bool isUnionTypeWithFunctionalInterface) { bool extensionFunctionType = expr->Callee()->IsMemberExpression() && checker->ExtensionETSFunctionType(calleeType); @@ -1008,7 +1047,8 @@ checker::Signature *ResolveSignature(ETSChecker *checker, ir::CallExpression *ex if (extensionFunctionType) { return ResolveCallExtensionFunction(calleeType->AsETSFunctionType(), checker, expr); } - auto &signatures = ChooseSignatures(calleeType, isConstructorCall, isFunctionalInterface); + auto &signatures = ChooseSignatures(checker, calleeType, isConstructorCall, isFunctionalInterface, + isUnionTypeWithFunctionalInterface); checker::Signature *signature = checker->ResolveCallExpressionAndTrailingLambda(signatures, expr, expr->Start()); if (signature->Function()->IsExtensionMethod()) { checker->ThrowTypeError({"No matching call signature"}, expr->Start()); @@ -1020,6 +1060,9 @@ checker::Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, checker::Typ { ETSChecker *checker = GetETSChecker(); bool isConstructorCall = expr->IsETSConstructorCall(); + bool isUnionTypeWithFunctionalInterface = + calleeType->IsETSUnionType() && + calleeType->AsETSUnionType()->HasObjectType(checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); bool isFunctionalInterface = calleeType->IsETSObjectType() && calleeType->AsETSObjectType()->HasObjectFlag( checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); bool etsExtensionFuncHelperType = calleeType->IsETSExtensionFuncHelperType(); @@ -1030,12 +1073,12 @@ checker::Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, checker::Typ } if (!isFunctionalInterface && !calleeType->IsETSFunctionType() && !isConstructorCall && - !etsExtensionFuncHelperType) { + !etsExtensionFuncHelperType && !isUnionTypeWithFunctionalInterface) { checker->ThrowTypeError("This expression is not callable.", expr->Start()); } - checker::Signature *signature = - ResolveSignature(checker, expr, calleeType, isConstructorCall, isFunctionalInterface); + checker::Signature *signature = ResolveSignature(checker, expr, calleeType, isConstructorCall, + isFunctionalInterface, isUnionTypeWithFunctionalInterface); checker->CheckObjectLiteralArguments(signature, expr->Arguments()); checker->AddUndefinedParamsForDefaultParams(signature, expr->Arguments(), checker); @@ -1107,7 +1150,7 @@ checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const // NOTE(vpukhov): #14902 substituted signature is not updated } expr->SetOptionalType(returnType); - if (expr->IsOptional() && calleeType->IsNullishOrNullLike()) { + if (expr->IsOptional() && checker->MayHaveNulllikeValue(expr->Callee()->Check(checker))) { checker->Relation()->SetNode(expr); returnType = checker->CreateOptionalResultType(returnType); checker->Relation()->SetNode(nullptr); @@ -1179,7 +1222,7 @@ checker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const builtinAlternateType = alternateType; } - expr->SetTsType(checker->FindLeastUpperBound(builtinConseqType, builtinAlternateType)); + expr->SetTsType(checker->CreateETSUnionType(builtinConseqType, builtinAlternateType)); } } @@ -1492,6 +1535,37 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const auto unboxedOperandType = isCondExpr ? checker->ETSBuiltinTypeAsConditionalType(argType) : checker->ETSBuiltinTypeAsPrimitiveType(argType); + if (argType != nullptr && argType->IsETSBigIntType() && argType->HasTypeFlag(checker::TypeFlag::BIGINT_LITERAL)) { + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_MINUS: { + checker::Type *type = checker->CreateETSBigIntLiteralType(argType->AsETSBigIntType()->GetValue()); + + // We do not need this const anymore as we are negating the bigint object in runtime + type->RemoveTypeFlag(checker::TypeFlag::CONSTANT); + expr->argument_->SetTsType(type); + expr->SetTsType(type); + return expr->TsType(); + } + default: + // Handled below + // NOTE(kkonsw): handle other unary operators for bigint literals + break; + } + } + + if (argType != nullptr && argType->IsETSBigIntType()) { + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_MINUS: + case lexer::TokenType::PUNCTUATOR_PLUS: + case lexer::TokenType::PUNCTUATOR_TILDE: { + expr->SetTsType(argType); + return expr->TsType(); + } + default: + break; + } + } + switch (expr->OperatorType()) { case lexer::TokenType::PUNCTUATOR_MINUS: case lexer::TokenType::PUNCTUATOR_PLUS: { @@ -1510,17 +1584,17 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const break; } case lexer::TokenType::PUNCTUATOR_TILDE: { - if (operandType == nullptr || !operandType->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL)) { - checker->ThrowTypeError("Bad operand type, the type of the operand must be integral type.", + if (operandType == nullptr || !operandType->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + checker->ThrowTypeError("Bad operand type, the type of the operand must be numeric type.", expr->Argument()->Start()); } if (operandType->HasTypeFlag(checker::TypeFlag::CONSTANT)) { - expr->SetTsType(checker->BitwiseNegateIntegralType(operandType, expr)); + expr->SetTsType(checker->BitwiseNegateNumericType(operandType, expr)); break; } - expr->SetTsType(operandType); + expr->SetTsType(checker->SelectGlobalIntegerTypeForNumeric(operandType)); break; } case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { @@ -1557,7 +1631,7 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const } } - if (argType->IsETSObjectType() && (unboxedOperandType != nullptr) && + if ((argType != nullptr) && argType->IsETSObjectType() && (unboxedOperandType != nullptr) && unboxedOperandType->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { expr->Argument()->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(unboxedOperandType)); } @@ -1587,6 +1661,11 @@ checker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const } } + if (operandType->IsETSBigIntType()) { + expr->SetTsType(operandType); + return expr->TsType(); + } + auto unboxedType = checker->ETSBuiltinTypeAsPrimitiveType(operandType); if (unboxedType == nullptr || !unboxedType->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { checker->ThrowTypeError("Bad operand type, the type of the operand must be numeric type.", @@ -1609,7 +1688,9 @@ checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::YieldExpression *expr) co // compile methods for LITERAL EXPRESSIONS in alphabetical order checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::BigIntLiteral *expr) const { - UNREACHABLE(); + ETSChecker *checker = GetETSChecker(); + expr->SetTsType(checker->CreateETSBigIntLiteralType(expr->Str())); + return expr->TsType(); } checker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const @@ -2660,6 +2741,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const { ETSChecker *checker = GetETSChecker(); if (st->TypeParams() != nullptr) { + st->SetTypeParameterTypes(checker->CreateTypeForTypeParameters(st->TypeParams())); for (auto *const param : st->TypeParams()->Params()) { const auto *const res = st->TypeAnnotation()->FindChild([¶m](const ir::AstNode *const node) { if (!node->IsIdentifier()) { @@ -2674,8 +2756,6 @@ checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const {"Type alias generic parameter '", param->Name()->Name(), "' is not used in type annotation"}, param->Start()); } - - checker->SetUpParameterType(param); } } diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index b1815ac6b04f86d302759e4b055a54c4ef02a213..f5422c70ab8f68809af4d75d880093d487b1a210 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -226,6 +226,11 @@ Type *ETSChecker::GlobalETSStringLiteralType() const return GetGlobalTypesHolder()->GlobalETSStringLiteralType(); } +Type *ETSChecker::GlobalETSBigIntType() const +{ + return GetGlobalTypesHolder()->GlobalETSBigIntBuiltinType(); +} + Type *ETSChecker::GlobalWildcardType() const { return GetGlobalTypesHolder()->GlobalWildcardType(); @@ -246,6 +251,11 @@ ETSObjectType *ETSChecker::GlobalBuiltinETSStringType() const return AsETSObjectType(&GlobalTypesHolder::GlobalETSStringBuiltinType); } +ETSObjectType *ETSChecker::GlobalBuiltinETSBigIntType() const +{ + return AsETSObjectType(&GlobalTypesHolder::GlobalETSBigIntBuiltinType); +} + ETSObjectType *ETSChecker::GlobalBuiltinTypeType() const { return AsETSObjectType(&GlobalTypesHolder::GlobalTypeBuiltinType); @@ -344,4 +354,19 @@ void ETSChecker::HandleUpdatedCallExpressionNode(ir::CallExpression *callExpr) VarBinder()->AsETSBinder()->HandleCustomNodes(callExpr); } +Type *ETSChecker::SelectGlobalIntegerTypeForNumeric(Type *type) +{ + switch (ETSType(type)) { + case checker::TypeFlag::FLOAT: { + return GlobalIntType(); + } + case checker::TypeFlag::DOUBLE: { + return GlobalLongType(); + } + default: { + return type; + } + } +} + } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 39e385217502cde0510d077afb36444172780e0b..abca67d8221529f73ddc615b79e8cf5979b9f8ea 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -28,8 +28,10 @@ #include "checker/types/globalTypesHolder.h" #include "ir/ts/tsTypeParameter.h" #include "ir/ts/tsTypeParameterInstantiation.h" +#include "lexer/token/tokenType.h" #include "util/enumbitops.h" #include "util/ustring.h" +#include "utils/bit_utils.h" #include "checker/resolveResult.h" #include "macros.h" @@ -38,6 +40,7 @@ #include #include #include +#include namespace panda::es2panda::varbinder { class VarBinder; @@ -98,11 +101,13 @@ public: Type *GlobalETSNullType() const; Type *GlobalETSUndefinedType() const; Type *GlobalETSStringLiteralType() const; + Type *GlobalETSBigIntType() const; Type *GlobalWildcardType() const; ETSObjectType *GlobalETSObjectType() const; ETSObjectType *GlobalETSNullishObjectType() const; ETSObjectType *GlobalBuiltinETSStringType() const; + ETSObjectType *GlobalBuiltinETSBigIntType() const; ETSObjectType *GlobalBuiltinTypeType() const; ETSObjectType *GlobalBuiltinExceptionType() const; ETSObjectType *GlobalBuiltinErrorType() const; @@ -177,9 +182,11 @@ public: Type *FindLeastUpperBound(Type *source, Type *target); static Type *GetApparentType(Type *type); static Type const *GetApparentType(Type const *type); + Type *MaybePromotedBuiltinType(Type *type) const; Type *GetCommonClass(Type *source, Type *target); ETSObjectType *GetClosestCommonAncestor(ETSObjectType *source, ETSObjectType *target); ETSObjectType *GetTypeargumentedLUB(ETSObjectType *source, ETSObjectType *target); + bool HasETSFunctionType(ir::TypeNode *typeAnnotation); // Type creation ByteType *CreateByteType(int8_t value); @@ -190,9 +197,17 @@ public: LongType *CreateLongType(int64_t value); ShortType *CreateShortType(int16_t value); CharType *CreateCharType(char16_t value); + ETSBigIntType *CreateETSBigIntLiteralType(util::StringView value); ETSStringType *CreateETSStringLiteralType(util::StringView value); ETSArrayType *CreateETSArrayType(Type *elementType); Type *CreateETSUnionType(ArenaVector &&constituentTypes); + template + Type *CreateETSUnionType(Types &&...types) + { + ArenaVector constituentTypes(Allocator()->Adapter()); + (constituentTypes.push_back(types), ...); + return CreateETSUnionType(std::move(constituentTypes)); + } ETSFunctionType *CreateETSFunctionType(Signature *signature); ETSFunctionType *CreateETSFunctionType(Signature *signature, util::StringView name); ETSFunctionType *CreateETSFunctionType(ir::ScriptFunction *func, Signature *signature, util::StringView name); @@ -215,7 +230,8 @@ public: // Arithmetic Type *NegateNumericType(Type *type, ir::Expression *node); - Type *BitwiseNegateIntegralType(Type *type, ir::Expression *node); + Type *BitwiseNegateNumericType(Type *type, ir::Expression *node); + bool CheckBinaryOperatorForBigInt(Type *left, Type *right, ir::Expression *expr, lexer::TokenType op); std::tuple CheckBinaryOperator(ir::Expression *left, ir::Expression *right, ir::Expression *expr, lexer::TokenType operationType, lexer::SourcePosition pos, bool forcePromotion = false); @@ -253,6 +269,7 @@ public: checker::Type *CheckBinaryOperatorNullishCoalescing(ir::Expression *right, lexer::SourcePosition pos, checker::Type *leftType, checker::Type *rightType); Type *HandleArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType); + Type *HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType); void FlagExpressionWithUnboxing(Type *type, Type *unboxedType, ir::Expression *typeExpression); template Type *PerformArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType); @@ -282,6 +299,7 @@ public: { return Allocator()->New>(Allocator()->Adapter()); } + ArenaVector CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration const *typeParams); [[nodiscard]] bool EnhanceSubstitutionForType(const ArenaVector &typeParams, Type *paramType, Type *argumentType, Substitution *substitution, ArenaUnorderedSet *instantiatedTypeParams); @@ -330,6 +348,7 @@ public: void CheckIdenticalOverloads(ETSFunctionType *func, ETSFunctionType *overload, const ir::MethodDefinition *currentFunc); Signature *AdjustForTypeParameters(Signature *source, Signature *target); + void ThrowOverrideError(Signature *signature, Signature *overriddenSignature, const OverrideErrorCode &errorCode); void CheckOverride(Signature *signature); bool CheckOverride(Signature *signature, ETSObjectType *site); std::tuple CheckOverride(Signature *signature, Signature *other); @@ -521,6 +540,7 @@ public: bool ExtensionETSFunctionType(checker::Type *type); void ValidateTupleMinElementSize(ir::ArrayExpression *arrayExpr, ETSTupleType *tuple); void ModifyPreferredType(ir::ArrayExpression *arrayExpr, Type *newPreferredType); + Type *SelectGlobalIntegerTypeForNumeric(Type *type); // Exception ETSObjectType *CheckExceptionOrErrorType(checker::Type *type, lexer::SourcePosition pos); @@ -637,20 +657,20 @@ private: return isConstruct ? &dynamicNewIntrinsics_ : &dynamicCallIntrinsics_; } - ArenaVector CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration *typeParams); - using Type2TypeMap = std::unordered_map; void CheckTypeParameterConstraint(ir::TSTypeParameter *param, Type2TypeMap &extends); void SetUpTypeParameterConstraint(ir::TSTypeParameter *param); + ETSObjectType *UpdateGlobalType(ETSObjectType *objType, util::StringView name); + ETSObjectType *UpdateBoxedGlobalType(ETSObjectType *objType, util::StringView name); ETSObjectType *CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags); void CheckProgram(parser::Program *program, bool runAnalysis = false); template UType HandleModulo(UType leftValue, UType rightValue); - template - UType HandleBitWiseArithmetic(UType leftValue, UType rightValue, lexer::TokenType operationType); + template + Type *HandleBitWiseArithmetic(Type *leftValue, Type *rightValue, lexer::TokenType operationType); template typename TargetType::UType GetOperand(Type *type); diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index 53122119d85e686157f4052cdf1694a9aad800e1..8016022e5196d55cc3404b674d8a72100d8c1cf1 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -134,6 +134,11 @@ public: return uncheckedCastableResults_; } + RelationHolder &SupertypeResults() + { + return supertypeResults_; + } + std::unordered_set &TypeStack() { return typeStack_; @@ -209,6 +214,7 @@ private: RelationHolder assignableResults_; RelationHolder comparableResults_; RelationHolder uncheckedCastableResults_; + RelationHolder supertypeResults_; std::unordered_set typeStack_; }; diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index e65660e1594e586328cdb7dc908ae629fa91f4ad..7e7da4307db93bae133bca5f3e55f3850c118a41 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -68,7 +68,7 @@ Type *ETSChecker::NegateNumericType(Type *type, ir::Expression *node) return result; } -Type *ETSChecker::BitwiseNegateIntegralType(Type *type, ir::Expression *node) +Type *ETSChecker::BitwiseNegateNumericType(Type *type, ir::Expression *node) { ASSERT(type->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_INTEGRAL)); @@ -97,6 +97,16 @@ Type *ETSChecker::BitwiseNegateIntegralType(Type *type, ir::Expression *node) result = CreateLongType(static_cast(~static_cast(type->AsLongType()->GetValue()))); break; } + case TypeFlag::FLOAT: { + result = CreateIntType( + ~static_cast(CastFloatToInt(type->AsFloatType()->GetValue()))); + break; + } + case TypeFlag::DOUBLE: { + result = CreateLongType( + ~static_cast(CastFloatToInt(type->AsDoubleType()->GetValue()))); + break; + } default: { UNREACHABLE(); } @@ -126,6 +136,44 @@ Type *ETSChecker::HandleRelationOperationOnTypes(Type *left, Type *right, lexer: return PerformRelationOperationOnTypes(left, right, operationType); } +bool ETSChecker::CheckBinaryOperatorForBigInt(Type *left, Type *right, ir::Expression *expr, lexer::TokenType op) +{ + if ((left == nullptr) || (right == nullptr)) { + return false; + } + + if (!left->IsETSBigIntType()) { + return false; + } + + if (!right->IsETSBigIntType()) { + return false; + } + + if (expr->IsBinaryExpression()) { + ir::BinaryExpression *be = expr->AsBinaryExpression(); + if (be->OperatorType() == lexer::TokenType::PUNCTUATOR_STRICT_EQUAL) { + // Handle strict comparison as normal comparison for bigint objects + be->SetOperator(lexer::TokenType::PUNCTUATOR_EQUAL); + } + } + + switch (op) { + case lexer::TokenType::PUNCTUATOR_EQUAL: + case lexer::TokenType::KEYW_INSTANCEOF: + // This is handled in the main CheckBinaryOperator function + return false; + default: + break; + } + + // Remove const flag - currently there are no compile time operations for bigint + left->RemoveTypeFlag(TypeFlag::CONSTANT); + right->RemoveTypeFlag(TypeFlag::CONSTANT); + + return true; +} + checker::Type *ETSChecker::CheckBinaryOperatorMulDivMod(ir::Expression *left, ir::Expression *right, lexer::TokenType operationType, lexer::SourcePosition pos, bool isEqualOp, checker::Type *const leftType, @@ -164,6 +212,11 @@ checker::Type *ETSChecker::CheckBinaryOperatorPlus(ir::Expression *left, ir::Exp } if (leftType->IsETSStringType() || rightType->IsETSStringType()) { + if (operationType == lexer::TokenType::PUNCTUATOR_MINUS || + operationType == lexer::TokenType::PUNCTUATOR_MINUS_EQUAL) { + ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); + } + return HandleStringConcatenation(leftType, rightType); } @@ -199,13 +252,13 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift(ir::Expression *left, ir::Ex FlagExpressionWithUnboxing(leftType, unboxedL, left); FlagExpressionWithUnboxing(rightType, unboxedR, right); - if (promotedLeftType == nullptr || !promotedLeftType->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL) || - promotedRightType == nullptr || !promotedRightType->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL)) { - ThrowTypeError("Bad operand type, the types of the operands must be integral type.", pos); + if (promotedLeftType == nullptr || !promotedLeftType->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC) || + promotedRightType == nullptr || !promotedRightType->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); } if (promotedLeftType->HasTypeFlag(TypeFlag::CONSTANT) && promotedRightType->HasTypeFlag(TypeFlag::CONSTANT)) { - return HandleArithmeticOperationOnTypes(promotedLeftType, promotedRightType, operationType); + return HandleBitwiseOperationOnTypes(promotedLeftType, promotedRightType, operationType); } switch (ETSType(promotedLeftType)) { @@ -218,10 +271,12 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift(ir::Expression *left, ir::Ex case TypeFlag::CHAR: { return GlobalCharType(); } - case TypeFlag::INT: { + case TypeFlag::INT: + case TypeFlag::FLOAT: { return GlobalIntType(); } - case TypeFlag::LONG: { + case TypeFlag::LONG: + case TypeFlag::DOUBLE: { return GlobalLongType(); } default: { @@ -248,20 +303,20 @@ checker::Type *ETSChecker::CheckBinaryOperatorBitwise(ir::Expression *left, ir:: } auto [promotedType, bothConst] = - ApplyBinaryOperatorPromotion(unboxedL, unboxedR, TypeFlag::ETS_INTEGRAL, !isEqualOp); + ApplyBinaryOperatorPromotion(unboxedL, unboxedR, TypeFlag::ETS_NUMERIC, !isEqualOp); FlagExpressionWithUnboxing(leftType, unboxedL, left); FlagExpressionWithUnboxing(rightType, unboxedR, right); if (promotedType == nullptr && !bothConst) { - ThrowTypeError("Bad operand type, the types of the operands must be integral type.", pos); + ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); } if (bothConst) { - return HandleArithmeticOperationOnTypes(leftType, rightType, operationType); + return HandleBitwiseOperationOnTypes(leftType, rightType, operationType); } - return promotedType; + return SelectGlobalIntegerTypeForNumeric(promotedType); } checker::Type *ETSChecker::CheckBinaryOperatorLogical(ir::Expression *left, ir::Expression *right, ir::Expression *expr, @@ -475,83 +530,87 @@ Type *ETSChecker::CheckBinaryOperatorNullishCoalescing(ir::Expression *right, le return FindLeastUpperBound(nonNullishLeftType, rightType); } -// NOLINTNEXTLINE(readability-function-size) -std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, ir::Expression *right, - ir::Expression *expr, lexer::TokenType operationType, - lexer::SourcePosition pos, bool forcePromotion) +using CheckBinaryFunction = std::function; + +std::map &GetCheckMap() { - checker::Type *const leftType = left->Check(this); - checker::Type *const rightType = right->Check(this); - const bool isLogicalExtendedOperator = (operationType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) || - (operationType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); - Type *unboxedL = - isLogicalExtendedOperator ? ETSBuiltinTypeAsConditionalType(leftType) : ETSBuiltinTypeAsPrimitiveType(leftType); - Type *unboxedR = isLogicalExtendedOperator ? ETSBuiltinTypeAsConditionalType(rightType) - : ETSBuiltinTypeAsPrimitiveType(rightType); + static std::map checkMap = { + {lexer::TokenType::PUNCTUATOR_MULTIPLY, &ETSChecker::CheckBinaryOperatorMulDivMod}, + {lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL, &ETSChecker::CheckBinaryOperatorMulDivMod}, + {lexer::TokenType::PUNCTUATOR_DIVIDE, &ETSChecker::CheckBinaryOperatorMulDivMod}, + {lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL, &ETSChecker::CheckBinaryOperatorMulDivMod}, + {lexer::TokenType::PUNCTUATOR_MOD, &ETSChecker::CheckBinaryOperatorMulDivMod}, + {lexer::TokenType::PUNCTUATOR_MOD_EQUAL, &ETSChecker::CheckBinaryOperatorMulDivMod}, + + {lexer::TokenType::PUNCTUATOR_MINUS, &ETSChecker::CheckBinaryOperatorPlus}, + {lexer::TokenType::PUNCTUATOR_MINUS_EQUAL, &ETSChecker::CheckBinaryOperatorPlus}, + {lexer::TokenType::PUNCTUATOR_PLUS, &ETSChecker::CheckBinaryOperatorPlus}, + {lexer::TokenType::PUNCTUATOR_PLUS_EQUAL, &ETSChecker::CheckBinaryOperatorPlus}, + + {lexer::TokenType::PUNCTUATOR_LEFT_SHIFT, &ETSChecker::CheckBinaryOperatorShift}, + {lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL, &ETSChecker::CheckBinaryOperatorShift}, + {lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT, &ETSChecker::CheckBinaryOperatorShift}, + {lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL, &ETSChecker::CheckBinaryOperatorShift}, + {lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT, &ETSChecker::CheckBinaryOperatorShift}, + {lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL, &ETSChecker::CheckBinaryOperatorShift}, + + {lexer::TokenType::PUNCTUATOR_BITWISE_OR, &ETSChecker::CheckBinaryOperatorBitwise}, + {lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL, &ETSChecker::CheckBinaryOperatorBitwise}, + {lexer::TokenType::PUNCTUATOR_BITWISE_AND, &ETSChecker::CheckBinaryOperatorBitwise}, + {lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL, &ETSChecker::CheckBinaryOperatorBitwise}, + {lexer::TokenType::PUNCTUATOR_BITWISE_XOR, &ETSChecker::CheckBinaryOperatorBitwise}, + {lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL, &ETSChecker::CheckBinaryOperatorBitwise}, + }; + + return checkMap; +} +struct BinaryOperatorParams { + ir::Expression *left; + ir::Expression *right; + ir::Expression *expr; + lexer::TokenType operationType; + lexer::SourcePosition pos; + bool isEqualOp; +}; + +struct TypeParams { + checker::Type *leftType; + checker::Type *rightType; + Type *unboxedL; + Type *unboxedR; +}; + +static std::tuple CheckBinaryOperatorHelper(ETSChecker *checker, + const BinaryOperatorParams &binaryParams, + const TypeParams &typeParams) +{ + ir::Expression *left = binaryParams.left; + ir::Expression *right = binaryParams.right; + lexer::SourcePosition pos = binaryParams.pos; + checker::Type *const leftType = typeParams.leftType; + checker::Type *const rightType = typeParams.rightType; + Type *unboxedL = typeParams.unboxedL; + Type *unboxedR = typeParams.unboxedR; checker::Type *tsType {}; - bool isEqualOp = (operationType > lexer::TokenType::PUNCTUATOR_SUBSTITUTION && - operationType < lexer::TokenType::PUNCTUATOR_ARROW) && - !forcePromotion; - - switch (operationType) { - case lexer::TokenType::PUNCTUATOR_MULTIPLY: - case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: - case lexer::TokenType::PUNCTUATOR_DIVIDE: - case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: - case lexer::TokenType::PUNCTUATOR_MOD: - case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: { - tsType = CheckBinaryOperatorMulDivMod(left, right, operationType, pos, isEqualOp, leftType, rightType, - unboxedL, unboxedR); - break; - } - case lexer::TokenType::PUNCTUATOR_MINUS: - case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: { - if (leftType->IsETSStringType() || rightType->IsETSStringType()) { - ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); - } - - [[fallthrough]]; - } - case lexer::TokenType::PUNCTUATOR_PLUS: - case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { - tsType = CheckBinaryOperatorPlus(left, right, operationType, pos, isEqualOp, leftType, rightType, unboxedL, - unboxedR); - break; - } - case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: - case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: - case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: - case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: - case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: - case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: { - tsType = CheckBinaryOperatorShift(left, right, operationType, pos, isEqualOp, leftType, rightType, unboxedL, - unboxedR); - break; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: - case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: - case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { - tsType = CheckBinaryOperatorBitwise(left, right, operationType, pos, isEqualOp, leftType, rightType, - unboxedL, unboxedR); - break; - } + switch (binaryParams.operationType) { case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { - tsType = CheckBinaryOperatorLogical(left, right, expr, pos, leftType, rightType, unboxedL, unboxedR); + tsType = checker->CheckBinaryOperatorLogical(left, right, binaryParams.expr, pos, leftType, rightType, + unboxedL, unboxedR); break; } case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { - return CheckBinaryOperatorStrictEqual(left, pos, leftType, rightType); + return checker->CheckBinaryOperatorStrictEqual(left, pos, leftType, rightType); } case lexer::TokenType::PUNCTUATOR_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - std::tuple res = - CheckBinaryOperatorEqual(left, right, operationType, pos, leftType, rightType, unboxedL, unboxedR); + std::tuple res = checker->CheckBinaryOperatorEqual( + left, right, binaryParams.operationType, pos, leftType, rightType, unboxedL, unboxedR); if (!(std::get<0>(res) == nullptr && std::get<1>(res) == nullptr)) { return res; } @@ -561,18 +620,18 @@ std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: case lexer::TokenType::PUNCTUATOR_GREATER_THAN: case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: { - return CheckBinaryOperatorLessGreater(left, right, operationType, pos, isEqualOp, leftType, rightType, - unboxedL, unboxedR); + return checker->CheckBinaryOperatorLessGreater(left, right, binaryParams.operationType, pos, + binaryParams.isEqualOp, leftType, rightType, unboxedL, + unboxedR); } case lexer::TokenType::KEYW_INSTANCEOF: { - return CheckBinaryOperatorInstanceOf(pos, leftType, rightType); + return checker->CheckBinaryOperatorInstanceOf(pos, leftType, rightType); } case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: { - tsType = CheckBinaryOperatorNullishCoalescing(right, pos, leftType, rightType); + tsType = checker->CheckBinaryOperatorNullishCoalescing(right, pos, leftType, rightType); break; } default: { - // NOTE UNREACHABLE(); break; } @@ -581,6 +640,51 @@ std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, return {tsType, tsType}; } +std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, ir::Expression *right, + ir::Expression *expr, lexer::TokenType op, + lexer::SourcePosition pos, bool forcePromotion) +{ + checker::Type *const leftType = left->Check(this); + checker::Type *const rightType = right->Check(this); + if ((leftType == nullptr) || (rightType == nullptr)) { + ThrowTypeError("Unexpected type error in binary expression", pos); + } + + const bool isLogicalExtendedOperator = + (op == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) || (op == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + Type *unboxedL = + isLogicalExtendedOperator ? ETSBuiltinTypeAsConditionalType(leftType) : ETSBuiltinTypeAsPrimitiveType(leftType); + Type *unboxedR = isLogicalExtendedOperator ? ETSBuiltinTypeAsConditionalType(rightType) + : ETSBuiltinTypeAsPrimitiveType(rightType); + + checker::Type *tsType {}; + bool isEqualOp = + (op > lexer::TokenType::PUNCTUATOR_SUBSTITUTION && op < lexer::TokenType::PUNCTUATOR_ARROW) && !forcePromotion; + + if (CheckBinaryOperatorForBigInt(leftType, rightType, expr, op)) { + switch (op) { + case lexer::TokenType::PUNCTUATOR_GREATER_THAN: + case lexer::TokenType::PUNCTUATOR_LESS_THAN: + case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: + case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: + return {GlobalETSBooleanType(), GlobalETSBooleanType()}; + default: + return {leftType, rightType}; + } + }; + + auto checkMap = GetCheckMap(); + if (checkMap.find(op) != checkMap.end()) { + auto check = checkMap[op]; + tsType = check(this, left, right, op, pos, isEqualOp, leftType, rightType, unboxedL, unboxedR); + return {tsType, tsType}; + } + + BinaryOperatorParams binaryParams {left, right, expr, op, pos, isEqualOp}; + TypeParams typeParams {leftType, rightType, unboxedL, unboxedR}; + return CheckBinaryOperatorHelper(this, binaryParams, typeParams); +} + Type *ETSChecker::HandleArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType) { ASSERT(left->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC) && @@ -601,6 +705,26 @@ Type *ETSChecker::HandleArithmeticOperationOnTypes(Type *left, Type *right, lexe return PerformArithmeticOperationOnTypes(left, right, operationType); } +Type *ETSChecker::HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType) +{ + ASSERT(left->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC) && + right->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC)); + + if (left->IsDoubleType() || right->IsDoubleType()) { + return HandleBitWiseArithmetic(left, right, operationType); + } + + if (left->IsFloatType() || right->IsFloatType()) { + return HandleBitWiseArithmetic(left, right, operationType); + } + + if (left->IsLongType() || right->IsLongType()) { + return HandleBitWiseArithmetic(left, right, operationType); + } + + return HandleBitWiseArithmetic(left, right, operationType); +} + void ETSChecker::FlagExpressionWithUnboxing(Type *type, Type *unboxedType, ir::Expression *typeExpression) { if (type->IsETSObjectType() && (unboxedType != nullptr)) { diff --git a/ets2panda/checker/ets/arithmetic.h b/ets2panda/checker/ets/arithmetic.h index 928e9b6daf42b5d7c2224ca7837f7c49d9a12029..258d93134b30fdb80e52705d51aa7c04b20bb1d9 100644 --- a/ets2panda/checker/ets/arithmetic.h +++ b/ets2panda/checker/ets/arithmetic.h @@ -17,7 +17,6 @@ #define ES2PANDA_COMPILER_CHECKER_ETS_ARITHMETIC_H #include "checker/ETSchecker.h" -#include "checker/types/ets/etsBooleanType.h" namespace panda::es2panda::checker { @@ -137,7 +136,7 @@ Type *ETSChecker::PerformArithmeticOperationOnTypes(Type *left, Type *right, lex break; } default: { - result = HandleBitWiseArithmetic(leftValue, rightValue, operationType); + UNREACHABLE(); } } @@ -174,63 +173,69 @@ inline DoubleType::UType panda::es2panda::checker::ETSChecker::HandleModulo -UType ETSChecker::HandleBitWiseArithmetic(UType leftValue, UType rightValue, lexer::TokenType operationType) +template +inline IntegerUType CastIfFloat(FloatOrIntegerUType num) +{ + if constexpr (std::is_floating_point_v) { + return CastFloatToInt(num); + } else { + return num; + } +} + +template +Type *ETSChecker::HandleBitWiseArithmetic(Type *left, Type *right, lexer::TokenType operationType) { - using UnsignedType = std::make_unsigned_t; - auto unsignedLeftValue = static_cast(leftValue); - auto unsignedRightValue = static_cast(rightValue); - size_t mask = std::numeric_limits::digits - 1U; - size_t shift = static_cast(unsignedRightValue) & mask; + using IntegerUType = typename IntegerType::UType; + using UnsignedUType = std::make_unsigned_t; + + UnsignedUType result = 0; + UnsignedUType unsignedLeftValue = CastIfFloat(GetOperand(left)); + UnsignedUType unsignedRightValue = CastIfFloat(GetOperand(right)); + + auto mask = std::numeric_limits::digits - 1U; + auto shift = unsignedRightValue & mask; switch (operationType) { case lexer::TokenType::PUNCTUATOR_BITWISE_AND: case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: { - return unsignedLeftValue & unsignedRightValue; + result = unsignedLeftValue & unsignedRightValue; + break; } case lexer::TokenType::PUNCTUATOR_BITWISE_OR: case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: { - return unsignedLeftValue | unsignedRightValue; + result = unsignedLeftValue | unsignedRightValue; + break; } case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: { - return unsignedLeftValue ^ unsignedRightValue; + result = unsignedLeftValue ^ unsignedRightValue; + break; } case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: { - static_assert(sizeof(UType) == 4 || sizeof(UType) == 8); - return unsignedLeftValue << shift; + static_assert(sizeof(UnsignedUType) == 4 || sizeof(UnsignedUType) == 8); + result = unsignedLeftValue << shift; + break; } case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: { - static_assert(sizeof(UType) == 4 || sizeof(UType) == 8); - return leftValue >> shift; // NOLINT(hicpp-signed-bitwise) + static_assert(sizeof(IntegerUType) == 4 || sizeof(IntegerUType) == 8); + result = static_cast(unsignedLeftValue) >> shift; // NOLINT(hicpp-signed-bitwise) + break; } case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: { - static_assert(sizeof(UType) == 4 || sizeof(UType) == 8); - return unsignedLeftValue >> shift; + static_assert(sizeof(UnsignedUType) == 4 || sizeof(UnsignedUType) == 8); + result = unsignedLeftValue >> shift; + break; } default: { UNREACHABLE(); } } -} - -template <> -inline FloatType::UType ETSChecker::HandleBitWiseArithmetic( - [[maybe_unused]] FloatType::UType leftValue, [[maybe_unused]] FloatType::UType rightValue, - [[maybe_unused]] lexer::TokenType operationType) -{ - return 0.0; -} -template <> -inline DoubleType::UType ETSChecker::HandleBitWiseArithmetic( - [[maybe_unused]] DoubleType::UType leftValue, [[maybe_unused]] DoubleType::UType rightValue, - [[maybe_unused]] lexer::TokenType operationType) -{ - return 0.0; + return Allocator()->New(result); } } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/ets/conversion.cpp b/ets2panda/checker/ets/conversion.cpp index a37d8ca39cc433803417ba910a4847b40936fb46..e1ff98642e31f0cf7f1c0c38e6af2117d6836345 100644 --- a/ets2panda/checker/ets/conversion.cpp +++ b/ets2panda/checker/ets/conversion.cpp @@ -52,20 +52,17 @@ void WideningNarrowingPrimitive(TypeRelation *const relation, ByteType *const so void WideningReference(TypeRelation *const relation, ETSObjectType *const source, ETSObjectType *const target) { - relation->Result(false); - target->IsSupertypeOf(relation, source); + relation->IsSupertypeOf(target, source); } void WideningReference(TypeRelation *const relation, ETSArrayType *const source, ETSObjectType *const target) { - relation->Result(false); - target->IsSupertypeOf(relation, source); + relation->IsSupertypeOf(target, source); } void WideningReference(TypeRelation *const relation, ETSArrayType *const source, ETSArrayType *const target) { - relation->Result(false); - target->IsSupertypeOf(relation, source); + relation->IsSupertypeOf(target, source); } namespace { @@ -80,7 +77,7 @@ bool IsAllowedNarrowingReferenceConversion(TypeRelation *const relation, Type *c // - S is not a subtype of T relation->Result(false); - if (target->IsSupertypeOf(relation, source), relation->IsTrue()) { + if (relation->IsSupertypeOf(target, source)) { return false; } @@ -97,8 +94,7 @@ bool IsAllowedNarrowingReferenceConversion(TypeRelation *const relation, Type *c // 1. S and T are class types, and either |S| <: |T| or |T| <: |S|. // NOTE: use type erased S and T relation->Result(false); - if ((t->IsSupertypeOf(relation, s), relation->IsTrue()) || - (s->IsSupertypeOf(relation, t), relation->IsTrue())) { + if (relation->IsSupertypeOf(t, s) || relation->IsSupertypeOf(s, t)) { return true; } @@ -116,7 +112,7 @@ bool IsAllowedNarrowingReferenceConversion(TypeRelation *const relation, Type *c // 4. S is a class type, T is an interface type, and S names a class that is marked as final and that // implements the interface named by T. if (s->HasObjectFlag(ETSObjectFlags::CLASS) && t->HasObjectFlag(ETSObjectFlags::INTERFACE) && - s->GetDeclNode()->IsFinal() && (s->IsSupertypeOf(relation, t), relation->IsTrue())) { + s->GetDeclNode()->IsFinal() && relation->IsSupertypeOf(s, t)) { return true; } @@ -130,7 +126,7 @@ bool IsAllowedNarrowingReferenceConversion(TypeRelation *const relation, Type *c // implements the interface named by S. relation->Result(false); if (s->HasObjectFlag(ETSObjectFlags::INTERFACE) && t->HasObjectFlag(ETSObjectFlags::CLASS) && - t->GetDeclNode()->IsFinal() && (t->IsSupertypeOf(relation, s), relation->IsTrue())) { + t->GetDeclNode()->IsFinal() && relation->IsSupertypeOf(t, s)) { return true; } } diff --git a/ets2panda/checker/ets/enum.cpp b/ets2panda/checker/ets/enum.cpp index ac4af44d689e414454069aac6660a46445869f01..a61f4137c88b8c8cf5f543dbfdcb13b6a7853f12 100644 --- a/ets2panda/checker/ets/enum.cpp +++ b/ets2panda/checker/ets/enum.cpp @@ -139,7 +139,7 @@ template varbinder::FunctionParamScope *const paramScope, ArenaVector &¶ms, ArenaVector &&body, - ir::TypeNode *const returnTypeAnnotation) + ir::TypeNode *const returnTypeAnnotation, bool isDeclare) { auto *const functionScope = varbinder->Allocator()->New(checker->Allocator(), paramScope); functionScope->BindParamScope(paramScope); @@ -148,9 +148,15 @@ template auto *const bodyBlock = checker->Allocator()->New(checker->Allocator(), std::move(body)); bodyBlock->SetScope(functionScope); + auto flags = ir::ModifierFlags::PUBLIC; + + if (isDeclare) { + flags |= ir::ModifierFlags::DECLARE; + } + auto *const function = checker->Allocator()->New( ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), bodyBlock, - ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::PUBLIC, false, Language(Language::Id::ETS)); + ir::ScriptFunctionFlags::METHOD, flags, isDeclare, Language(Language::Id::ETS)); function->SetScope(functionScope); varbinder->AsETSBinder()->BuildInternalName(function); @@ -335,7 +341,7 @@ ETSEnumType::Method ETSChecker::CreateEnumFromIntMethod(ir::Identifier *const na auto *const enumTypeAnnotation = MakeTypeReference(Allocator(), enumType->GetName()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), - std::move(body), enumTypeAnnotation); + std::move(body), enumTypeAnnotation, enumType->GetDecl()->IsDeclare()); function->AddFlag(ir::ScriptFunctionFlags::THROWS); auto *const ident = MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::FROM_INT_METHOD_NAME); @@ -371,7 +377,7 @@ ETSEnumType::Method ETSChecker::CreateEnumToStringMethod(ir::Identifier *const s auto *const stringTypeAnnotation = MakeTypeReference(Allocator(), GlobalBuiltinETSStringType()->Name()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), - std::move(body), stringTypeAnnotation); + std::move(body), stringTypeAnnotation, enumType->GetDecl()->IsDeclare()); auto *const functionIdent = MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::TO_STRING_METHOD_NAME); @@ -409,7 +415,7 @@ ETSEnumType::Method ETSChecker::CreateEnumGetValueMethod(ir::Identifier *const v auto *const intTypeAnnotation = Allocator()->New(ir::PrimitiveType::INT); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), - std::move(body), intTypeAnnotation); + std::move(body), intTypeAnnotation, enumType->GetDecl()->IsDeclare()); auto *const functionIdent = MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::GET_VALUE_METHOD_NAME); @@ -447,7 +453,7 @@ ETSEnumType::Method ETSChecker::CreateEnumGetNameMethod(ir::Identifier *const na auto *const stringTypeAnnotation = MakeTypeReference(Allocator(), GlobalBuiltinETSStringType()->Name()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), - std::move(body), stringTypeAnnotation); + std::move(body), stringTypeAnnotation, enumType->GetDecl()->IsDeclare()); auto *const functionIdent = MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::GET_NAME_METHOD_NAME); @@ -571,7 +577,7 @@ ETSEnumType::Method ETSChecker::CreateEnumValueOfMethod(ir::Identifier *const na auto *const enumTypeAnnotation = MakeTypeReference(Allocator(), enumType->GetName()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), - std::move(body), enumTypeAnnotation); + std::move(body), enumTypeAnnotation, enumType->GetDecl()->IsDeclare()); function->AddFlag(ir::ScriptFunctionFlags::THROWS); auto *const functionIdent = @@ -603,7 +609,7 @@ ETSEnumType::Method ETSChecker::CreateEnumValuesMethod(ir::Identifier *const ite Allocator()->New(MakeTypeReference(Allocator(), enumType->GetName())); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), paramScope, std::move(params), - std::move(body), enumArrayTypeAnnotation); + std::move(body), enumArrayTypeAnnotation, enumType->GetDecl()->IsDeclare()); auto *const functionIdent = MakeQualifiedIdentifier(Allocator(), enumType->GetDecl(), ETSEnumType::VALUES_METHOD_NAME); diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 6b8c568fe516ec58115efe6d0226dfe7e46e69fa..8bb6da708bf5ae2914081f411c271b5dc94f2e08 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -67,6 +67,7 @@ namespace panda::es2panda::checker { +// NOTE: #14993 merge with InstantiationContext::ValidateTypeArg bool ETSChecker::IsCompatibleTypeArgument(ETSTypeParameter *typeParam, Type *typeArgument, const Substitution *substitution) { @@ -76,21 +77,8 @@ bool ETSChecker::IsCompatibleTypeArgument(ETSTypeParameter *typeParam, Type *typ if (!typeArgument->IsETSTypeParameter() && !IsReferenceType(typeArgument)) { return false; } - if (typeArgument->IsETSUnionType()) { - auto const &constitutent = typeArgument->AsETSUnionType()->ConstituentTypes(); - return std::all_of(constitutent.begin(), constitutent.end(), [this, typeParam, substitution](Type *typeArg) { - return IsCompatibleTypeArgument(typeParam->AsETSTypeParameter(), typeArg, substitution); - }); - } - - if (auto *constraint = typeParam->GetConstraintType(); constraint != nullptr) { - constraint = constraint->Substitute(Relation(), substitution); - constraint->IsSupertypeOf(Relation(), typeArgument); - if (!Relation()->IsTrue()) { - return false; - } - } - return true; + auto *constraint = typeParam->GetConstraintType()->Substitute(Relation(), substitution); + return Relation()->IsSupertypeOf(constraint, typeArgument); } /* A very rough and imprecise partial type inference */ @@ -256,6 +244,11 @@ Signature *ETSChecker::ValidateSignature(Signature *signature, const ir::TSTypeP return nullptr; } + if (argument->IsArrayExpression()) { + argument->AsArrayExpression()->GetPrefferedTypeFromFuncParam( + this, substitutedSig->Function()->Params()[index], flags); + } + auto *const argumentType = argument->Check(this); if (auto const invocationCtx = checker::InvocationContext( @@ -1047,9 +1040,9 @@ bool ETSChecker::IsOverridableIn(Signature *signature) return false; } - if (signature->HasSignatureFlag(SignatureFlags::PUBLIC)) { - return FindAncestorGivenByType(signature->Function(), ir::AstNodeType::TS_INTERFACE_DECLARATION) == nullptr || - signature->HasSignatureFlag(SignatureFlags::STATIC); + // NOTE: #15095 workaround, separate internal visibility check + if (signature->HasSignatureFlag(SignatureFlags::PUBLIC | SignatureFlags::INTERNAL)) { + return true; } return signature->HasSignatureFlag(SignatureFlags::PROTECTED); @@ -1071,7 +1064,6 @@ bool ETSChecker::IsMethodOverridesOther(Signature *target, Signature *source) if (Relation()->IsTrue()) { CheckThrowMarkers(source, target); - CheckStaticHide(target, source); if (source->HasSignatureFlag(SignatureFlags::STATIC)) { return false; } @@ -1158,6 +1150,38 @@ Signature *ETSChecker::AdjustForTypeParameters(Signature *source, Signature *tar return target->Substitute(Relation(), substitution); } +void ETSChecker::ThrowOverrideError(Signature *signature, Signature *overriddenSignature, + const OverrideErrorCode &errorCode) +{ + const char *reason {}; + switch (errorCode) { + case OverrideErrorCode::OVERRIDDEN_STATIC: { + reason = "overridden method is static."; + break; + } + case OverrideErrorCode::OVERRIDDEN_FINAL: { + reason = "overridden method is final."; + break; + } + case OverrideErrorCode::INCOMPATIBLE_RETURN: { + reason = "overriding return type is not compatible with the other return type."; + break; + } + case OverrideErrorCode::OVERRIDDEN_WEAKER: { + reason = "overridden method has weaker access privilege."; + break; + } + default: { + UNREACHABLE(); + } + } + + ThrowTypeError({signature->Function()->Id()->Name(), signature, " in ", signature->Owner(), " cannot override ", + overriddenSignature->Function()->Id()->Name(), overriddenSignature, " in ", + overriddenSignature->Owner(), " because ", reason}, + signature->Function()->Start()); +} + bool ETSChecker::CheckOverride(Signature *signature, ETSObjectType *site) { auto *target = site->GetProperty(signature->Function()->Id()->Name(), PropertySearchFlags::SEARCH_METHOD); @@ -1189,40 +1213,15 @@ bool ETSChecker::CheckOverride(Signature *signature, ETSObjectType *site) (itSubst->Function()->IsGetter() && !signature->Function()->IsGetter())) { continue; } - } else if (!IsMethodOverridesOther(itSubst, signature)) { + } + if (!IsMethodOverridesOther(itSubst, signature)) { continue; } auto [success, errorCode] = CheckOverride(signature, itSubst); if (!success) { - const char *reason {}; - switch (errorCode) { - case OverrideErrorCode::OVERRIDDEN_STATIC: { - reason = "overridden method is static."; - break; - } - case OverrideErrorCode::OVERRIDDEN_FINAL: { - reason = "overridden method is final."; - break; - } - case OverrideErrorCode::INCOMPATIBLE_RETURN: { - reason = "overriding return type is not compatible with the other return type."; - break; - } - case OverrideErrorCode::OVERRIDDEN_WEAKER: { - reason = "overridden method has weaker access privilege."; - break; - } - default: { - UNREACHABLE(); - } - } - - ThrowTypeError({signature->Function()->Id()->Name(), signature, " in ", signature->Owner(), - " cannot override ", it->Function()->Id()->Name(), it, " in ", it->Owner(), " because ", - reason}, - signature->Function()->Start()); + ThrowOverrideError(signature, it, errorCode); } isOverridingAnySignature = true; @@ -2590,8 +2589,7 @@ bool ETSChecker::IsReturnTypeSubstitutable(Signature *const s1, Signature *const // - If R1 is a reference type then R1, adapted to the type parameters of d2 (link to generic methods), is a // subtype of R2. ASSERT(r1->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT) || r1->IsETSTypeParameter()); - r2->IsSupertypeOf(Relation(), r1); - return Relation()->IsTrue(); + return Relation()->IsSupertypeOf(r2, r1); } std::string ETSChecker::GetAsyncImplName(const util::StringView &name) diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 371f3a7aec3e21e833d4882f429432d8704d9474..cb5032a5301b5ef2e4a337a19ee6b1c4996186d6 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -169,37 +169,43 @@ Type *ETSChecker::CreateOptionalResultType(Type *type) return CreateNullishType(type, checker::TypeFlag::UNDEFINED, Allocator(), Relation(), GetGlobalTypesHolder()); } -bool ETSChecker::MayHaveNullValue(const Type *type) const +// NOTE(vpukhov): #14595 could be implemented with relation +template +static bool MatchConstitutentOrConstraint(P const &pred, const Type *type) { - if (type->ContainsNull() || type->IsETSNullType()) { + if (pred(type)) { return true; } + if (type->IsETSUnionType()) { + for (auto const &ctype : type->AsETSUnionType()->ConstituentTypes()) { + if (MatchConstitutentOrConstraint(pred, ctype)) { + return true; + } + } + return false; + } if (type->IsETSTypeParameter()) { - return MayHaveNullValue(type->AsETSTypeParameter()->EffectiveConstraint(this)); + return MatchConstitutentOrConstraint(pred, type->AsETSTypeParameter()->GetConstraintType()); } return false; } +bool ETSChecker::MayHaveNullValue(const Type *type) const +{ + const auto pred = [](const Type *t) { return t->ContainsNull() || t->IsETSNullType(); }; + return MatchConstitutentOrConstraint(pred, type); +} + bool ETSChecker::MayHaveUndefinedValue(const Type *type) const { - if (type->ContainsUndefined() || type->IsETSUndefinedType()) { - return true; - } - if (type->IsETSTypeParameter()) { - return MayHaveUndefinedValue(type->AsETSTypeParameter()->EffectiveConstraint(this)); - } - return false; + const auto pred = [](const Type *t) { return t->ContainsUndefined() || t->IsETSUndefinedType(); }; + return MatchConstitutentOrConstraint(pred, type); } bool ETSChecker::MayHaveNulllikeValue(const Type *type) const { - if (type->IsNullishOrNullLike()) { - return true; - } - if (type->IsETSTypeParameter()) { - return MayHaveNulllikeValue(type->AsETSTypeParameter()->EffectiveConstraint(this)); - } - return false; + const auto pred = [](const Type *t) { return t->IsNullishOrNullLike(); }; + return MatchConstitutentOrConstraint(pred, type); } bool ETSChecker::IsConstantExpression(ir::Expression *expr, Type *type) @@ -354,7 +360,7 @@ Type *ETSChecker::GuaranteedTypeForUncheckedCast(Type *base, Type *substituted) if (!base->IsETSTypeParameter()) { return nullptr; } - auto *constr = base->AsETSTypeParameter()->EffectiveConstraint(this); + auto *constr = base->AsETSTypeParameter()->GetConstraintType(); // Constraint is supertype of TypeArg AND TypeArg is supertype of Constraint return Relation()->IsIdenticalTo(substituted, constr) ? nullptr : constr; } @@ -774,6 +780,10 @@ std::tuple ETSChecker::ApplyBinaryOperatorPromotion(Type *left, Ty return {GlobalLongType(), bothConst}; } + if (unboxedL->IsCharType() && unboxedR->IsCharType()) { + return {GlobalCharType(), bothConst}; + } + return {GlobalIntType(), bothConst}; } @@ -1558,7 +1568,7 @@ bool ETSChecker::IsFunctionContainsSignature(ETSFunctionType *funcType, Signatur void ETSChecker::CheckFunctionContainsClashingSignature(const ETSFunctionType *funcType, Signature *signature) { for (auto *it : funcType->CallSignatures()) { - SavedTypeRelationFlagsContext strfCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK); + SavedTypeRelationFlagsContext strfCtx(Relation(), TypeRelationFlag::NONE); Relation()->IsIdenticalTo(it, signature); if (Relation()->IsTrue() && it->Function()->Id()->Name() == signature->Function()->Id()->Name()) { std::stringstream ss; @@ -1662,7 +1672,7 @@ bool ETSChecker::IsTypeBuiltinType(const Type *type) const bool ETSChecker::IsReferenceType(const Type *type) { return type->HasTypeFlag(checker::TypeFlag::ETS_ARRAY_OR_OBJECT) || type->IsETSNullLike() || - type->IsETSStringType() || type->IsETSTypeParameter() || type->IsETSUnionType(); + type->IsETSStringType() || type->IsETSTypeParameter() || type->IsETSUnionType() || type->IsETSBigIntType(); } const ir::AstNode *ETSChecker::FindJumpTarget(ir::AstNodeType nodeType, const ir::AstNode *node, @@ -2609,6 +2619,19 @@ void ETSChecker::ModifyPreferredType(ir::ArrayExpression *const arrayExpr, Type } } +std::string GenerateImplicitInstantiateArg(varbinder::LocalVariable *instantiateMethod, const std::string &className) +{ + auto callSignatures = instantiateMethod->TsType()->AsETSFunctionType()->CallSignatures(); + ASSERT(!callSignatures.empty()); + auto methodOwner = std::string(callSignatures[0]->Owner()->Name()); + std::string implicitInstantiateArgument = "()=>{return new " + className + "()"; + if (methodOwner != className) { + implicitInstantiateArgument.append(" as " + methodOwner); + } + implicitInstantiateArgument.append("}"); + return implicitInstantiateArgument; +} + bool ETSChecker::TryTransformingToStaticInvoke(ir::Identifier *const ident, const Type *resolvedType) { ASSERT(ident->Parent()->IsCallExpression()); @@ -2654,13 +2677,14 @@ bool ETSChecker::TryTransformingToStaticInvoke(ir::Identifier *const ident, cons callExpr->SetCallee(transformedCallee); if (instantiateMethod != nullptr) { - std::string implicitInstantiateArgument = "()=>{return new " + std::string(className) + "()}"; + std::string implicitInstantiateArgument = + GenerateImplicitInstantiateArg(instantiateMethod, std::string(className)); parser::Program program(Allocator(), VarBinder()); es2panda::CompilerOptions options; auto parser = parser::ETSParser(&program, options, parser::ParserStatus::NO_OPTS); auto *argExpr = parser.CreateExpression(implicitInstantiateArgument); - compiler::ScopesInitPhaseETS::RunExternalNode(argExpr, &program); + compiler::InitScopesPhaseETS::RunExternalNode(argExpr, &program); argExpr->SetParent(callExpr); argExpr->SetRange(ident->Range()); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 22debb2259c959489a1b9a670a37bb85493d3a1d..c82c2961cb09762ce6930c51a53f7b9ab5be6b3a 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "boxingConverter.h" #include "varbinder/variableFlags.h" #include "checker/ets/castingContext.h" #include "checker/types/ets/etsObjectType.h" @@ -55,6 +56,7 @@ #include "checker/types/ets/etsDynamicType.h" #include "checker/types/ets/types.h" #include "checker/ets/typeRelationContext.h" +#include "ir/ets/etsUnionType.h" namespace panda::es2panda::checker { ETSObjectType *ETSChecker::GetSuperType(ETSObjectType *type) @@ -165,7 +167,7 @@ ArenaVector ETSChecker::GetInterfaces(ETSObjectType *type) return type->Interfaces(); } -ArenaVector ETSChecker::CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration *typeParams) +ArenaVector ETSChecker::CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration const *typeParams) { ArenaVector result {Allocator()->Adapter()}; checker::ScopeContext scopeCtx(this, typeParams->Scope()); @@ -247,12 +249,14 @@ void ETSChecker::SetUpTypeParameterConstraint(ir::TSTypeParameter *const param) ThrowTypeError("Extends constraint must be an object", param->Constraint()->Start()); } paramType->SetConstraintType(constraint); + } else { + paramType->SetConstraintType(GlobalETSNullishObjectType()); } + if (param->DefaultType() != nullptr) { traverseReferenced(param->DefaultType()); - auto *const dflt = param->DefaultType()->GetType(this); // NOTE: #14993 ensure default matches constraint - paramType->SetDefaultType(dflt); + paramType->SetDefaultType(MaybePromotedBuiltinType(param->DefaultType()->GetType(this))); } } @@ -263,6 +267,8 @@ ETSTypeParameter *ETSChecker::SetUpParameterType(ir::TSTypeParameter *const para paramType->AddTypeFlag(TypeFlag::GENERIC); paramType->SetDeclNode(param); paramType->SetVariable(param->Variable()); + // NOTE: #15026 recursive type parameter workaround + paramType->SetConstraintType(GlobalETSNullishObjectType()); param->Name()->Variable()->SetTsType(paramType); return paramType; @@ -405,6 +411,12 @@ void ETSChecker::ResolveDeclaredMembersOfObject(ETSObjectType *type) if (classProp->TypeAnnotation() != nullptr && classProp->TypeAnnotation()->IsETSFunctionType()) { type->AddProperty(it->AsLocalVariable()); it->AddFlag(varbinder::VariableFlags::METHOD_REFERENCE); + } else if (classProp->TypeAnnotation() != nullptr && classProp->TypeAnnotation()->IsETSTypeReference()) { + bool hasFunctionType = HasETSFunctionType(classProp->TypeAnnotation()); + if (hasFunctionType) { + type->AddProperty(it->AsLocalVariable()); + it->AddFlag(varbinder::VariableFlags::METHOD_REFERENCE); + } } } @@ -418,6 +430,12 @@ void ETSChecker::ResolveDeclaredMembersOfObject(ETSObjectType *type) if (classProp->TypeAnnotation() != nullptr && classProp->TypeAnnotation()->IsETSFunctionType()) { type->AddProperty(it->AsLocalVariable()); it->AddFlag(varbinder::VariableFlags::METHOD_REFERENCE); + } else if (classProp->TypeAnnotation() != nullptr && classProp->TypeAnnotation()->IsETSTypeReference()) { + bool hasFunctionType = HasETSFunctionType(classProp->TypeAnnotation()); + if (hasFunctionType) { + type->AddProperty(it->AsLocalVariable()); + it->AddFlag(varbinder::VariableFlags::METHOD_REFERENCE); + } } } @@ -473,6 +491,39 @@ void ETSChecker::ResolveDeclaredMembersOfObject(ETSObjectType *type) type->AddObjectFlag(ETSObjectFlags::RESOLVED_MEMBERS); } +bool ETSChecker::HasETSFunctionType(ir::TypeNode *typeAnnotation) +{ + if (typeAnnotation->IsETSFunctionType()) { + return true; + } + std::unordered_set childrenSet; + + if (typeAnnotation->IsETSTypeReference()) { + auto *typeDecl = + typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Variable()->Declaration(); + if (typeDecl != nullptr && typeDecl->IsTypeAliasDecl()) { + typeAnnotation = typeDecl->Node()->AsTSTypeAliasDeclaration()->TypeAnnotation(); + if (typeAnnotation->IsETSUnionType()) { + for (auto *type : typeAnnotation->AsETSUnionType()->Types()) { + if (type->IsETSTypeReference()) { + childrenSet.insert(type); + } + } + } else { + childrenSet.insert(typeAnnotation); + } + } + + for (auto *child : childrenSet) { + if (HasETSFunctionType(child)) { + return true; + } + } + } + + return false; +} + std::vector ETSChecker::CollectAbstractSignaturesFromObject(const ETSObjectType *objType) { std::vector abstracts; @@ -1477,22 +1528,25 @@ Type *ETSChecker::FindLeastUpperBound(Type *source, Type *target) Type *ETSChecker::GetApparentType(Type *type) { - if (type->IsETSTypeParameter()) { - auto *const param = type->AsETSTypeParameter(); - return param->HasConstraint() ? param->GetConstraintType() : param; + while (type->IsETSTypeParameter()) { + type = type->AsETSTypeParameter()->GetConstraintType(); } return type; } Type const *ETSChecker::GetApparentType(Type const *type) { - if (type->IsETSTypeParameter()) { - auto *const param = type->AsETSTypeParameter(); - return param->HasConstraint() ? param->GetConstraintType() : param; + while (type->IsETSTypeParameter()) { + type = type->AsETSTypeParameter()->GetConstraintType(); } return type; } +Type *ETSChecker::MaybePromotedBuiltinType(Type *type) const +{ + return type->HasTypeFlag(TypeFlag::ETS_PRIMITIVE) ? checker::BoxingConverter::ETSTypeFromSource(this, type) : type; +} + Type *ETSChecker::GetCommonClass(Type *source, Type *target) { SavedTypeRelationFlagsContext checkerCtx(this->Relation(), TypeRelationFlag::IGNORE_TYPE_PARAMETERS); @@ -1501,13 +1555,11 @@ Type *ETSChecker::GetCommonClass(Type *source, Type *target) return source; } - target->IsSupertypeOf(Relation(), source); - if (Relation()->IsTrue()) { + if (Relation()->IsSupertypeOf(target, source)) { return target; } - source->IsSupertypeOf(Relation(), target); - if (Relation()->IsTrue()) { + if (Relation()->IsSupertypeOf(source, target)) { return source; } @@ -1540,8 +1592,7 @@ ETSObjectType *ETSChecker::GetClosestCommonAncestor(ETSObjectType *source, ETSOb auto *sourceBase = GetOriginalBaseType(source); auto *sourceType = sourceBase == nullptr ? source : sourceBase; - targetType->IsSupertypeOf(Relation(), sourceType); - if (Relation()->IsTrue()) { + if (Relation()->IsSupertypeOf(targetType, sourceType)) { // NOTE: TorokG. Extending the search to find intersection types return targetType; } diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index bf8867a24d72fa9cb9091953f44e90483fa30063..4551e1169aab7c8d5790ea7680eaf52620cb403a 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #include "checker/ETSchecker.h" #include "checker/ets/boxingConverter.h" #include "checker/types/ets/byteType.h" @@ -34,6 +35,7 @@ #include "varbinder/ETSBinder.h" #include "parser/program/program.h" #include "util/helpers.h" +#include "checker/types/ts/bigintType.h" namespace panda::es2panda::checker { ByteType *ETSChecker::CreateByteType(int8_t value) @@ -102,6 +104,11 @@ CharType *ETSChecker::CreateCharType(char16_t value) return Allocator()->New(value); } +ETSBigIntType *ETSChecker::CreateETSBigIntLiteralType(util::StringView value) +{ + return Allocator()->New(Allocator(), GlobalBuiltinETSBigIntType(), value); +} + ETSStringType *ETSChecker::CreateETSStringLiteralType(util::StringView value) { return Allocator()->New(Allocator(), GlobalBuiltinETSStringType(), value); @@ -206,9 +213,126 @@ ETSExtensionFuncHelperType *ETSChecker::CreateETSExtensionFuncHelperType(ETSFunc return Allocator()->New(classMethodType, extensionFunctionType); } +std::map &GetNameToTypeIdMap() +{ + static std::map nameToTypeId = { + {compiler::Signatures::BUILTIN_BIGINT_CLASS, GlobalTypeId::ETS_BIG_INT_BUILTIN}, + {compiler::Signatures::BUILTIN_STRING_CLASS, GlobalTypeId::ETS_STRING_BUILTIN}, + {compiler::Signatures::BUILTIN_OBJECT_CLASS, GlobalTypeId::ETS_OBJECT_BUILTIN}, + {compiler::Signatures::BUILTIN_EXCEPTION_CLASS, GlobalTypeId::ETS_EXCEPTION_BUILTIN}, + {compiler::Signatures::BUILTIN_ERROR_CLASS, GlobalTypeId::ETS_ERROR_BUILTIN}, + {compiler::Signatures::BUILTIN_TYPE_CLASS, GlobalTypeId::ETS_TYPE_BUILTIN}, + {compiler::Signatures::BUILTIN_PROMISE_CLASS, GlobalTypeId::ETS_PROMISE_BUILTIN}, + {compiler::Signatures::BUILTIN_BOX_CLASS, GlobalTypeId::ETS_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_BOOLEAN_BOX_CLASS, GlobalTypeId::ETS_BOOLEAN_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_BYTE_BOX_CLASS, GlobalTypeId::ETS_BYTE_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_CHAR_BOX_CLASS, GlobalTypeId::ETS_CHAR_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_SHORT_BOX_CLASS, GlobalTypeId::ETS_SHORT_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_INT_BOX_CLASS, GlobalTypeId::ETS_INT_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_LONG_BOX_CLASS, GlobalTypeId::ETS_LONG_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_FLOAT_BOX_CLASS, GlobalTypeId::ETS_FLOAT_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_DOUBLE_BOX_CLASS, GlobalTypeId::ETS_DOUBLE_BOX_BUILTIN}, + {compiler::Signatures::BUILTIN_VOID_CLASS, GlobalTypeId::ETS_VOID_BUILTIN}, + }; + + return nameToTypeId; +} + +std::map> &GetNameToGlobalTypeMap() +{ + static std::map> nameToGlobalType = { + {compiler::Signatures::BUILTIN_BIGINT_CLASS, &ETSChecker::GlobalBuiltinETSBigIntType}, + {compiler::Signatures::BUILTIN_STRING_CLASS, &ETSChecker::GlobalBuiltinETSStringType}, + {compiler::Signatures::BUILTIN_OBJECT_CLASS, &ETSChecker::GlobalETSObjectType}, + {compiler::Signatures::BUILTIN_EXCEPTION_CLASS, &ETSChecker::GlobalBuiltinExceptionType}, + {compiler::Signatures::BUILTIN_ERROR_CLASS, &ETSChecker::GlobalBuiltinErrorType}, + {compiler::Signatures::BUILTIN_TYPE_CLASS, &ETSChecker::GlobalBuiltinTypeType}, + {compiler::Signatures::BUILTIN_PROMISE_CLASS, &ETSChecker::GlobalBuiltinPromiseType}, + {compiler::Signatures::BUILTIN_VOID_CLASS, &ETSChecker::GlobalBuiltinVoidType}, + }; + + return nameToGlobalType; +} + +std::map> &GetNameToGlobalBoxTypeMap() +{ + static std::map> nameToGlobalBoxType = { + {compiler::Signatures::BUILTIN_BOX_CLASS, &ETSChecker::GlobalETSObjectType}, + {compiler::Signatures::BUILTIN_BOOLEAN_BOX_CLASS, &ETSChecker::GlobalETSBooleanType}, + {compiler::Signatures::BUILTIN_BYTE_BOX_CLASS, &ETSChecker::GlobalByteType}, + {compiler::Signatures::BUILTIN_CHAR_BOX_CLASS, &ETSChecker::GlobalCharType}, + {compiler::Signatures::BUILTIN_SHORT_BOX_CLASS, &ETSChecker::GlobalShortType}, + {compiler::Signatures::BUILTIN_INT_BOX_CLASS, &ETSChecker::GlobalIntType}, + {compiler::Signatures::BUILTIN_LONG_BOX_CLASS, &ETSChecker::GlobalLongType}, + {compiler::Signatures::BUILTIN_FLOAT_BOX_CLASS, &ETSChecker::GlobalFloatType}, + {compiler::Signatures::BUILTIN_DOUBLE_BOX_CLASS, &ETSChecker::GlobalDoubleType}, + }; + + return nameToGlobalBoxType; +} + +ETSObjectType *ETSChecker::UpdateBoxedGlobalType(ETSObjectType *objType, util::StringView name) +{ + auto nameToGlobalBoxType = GetNameToGlobalBoxTypeMap(); + auto nameToTypeId = GetNameToTypeIdMap(); + + if (nameToGlobalBoxType.find(name) != nameToGlobalBoxType.end()) { + std::function globalType = nameToGlobalBoxType[name]; + if (GlobalBuiltinBoxType(globalType(this)) != nullptr) { + return GlobalBuiltinBoxType(globalType(this)); + } + + auto id = nameToTypeId.find(name); + if (id != nameToTypeId.end()) { + GetGlobalTypesHolder()->GlobalTypes()[static_cast(id->second)] = objType; + } + } + + return objType; +} + +ETSObjectType *ETSChecker::UpdateGlobalType(ETSObjectType *objType, util::StringView name) +{ + auto nameToGlobalType = GetNameToGlobalTypeMap(); + auto nameToTypeId = GetNameToTypeIdMap(); + + if (nameToGlobalType.find(name) != nameToGlobalType.end()) { + std::function globalType = nameToGlobalType[name]; + if (globalType(this) != nullptr) { + return globalType(this); + } + + auto id = nameToTypeId.find(name); + if (id != nameToTypeId.end()) { + GetGlobalTypesHolder()->GlobalTypes()[static_cast(id->second)] = objType; + } + + if (name == compiler::Signatures::BUILTIN_OBJECT_CLASS) { + auto *nullish = + CreateNullishType(objType, checker::TypeFlag::NULLISH, Allocator(), Relation(), GetGlobalTypesHolder()); + GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_NULLISH_OBJECT)] = nullish; + } + } + + return objType; +} + ETSObjectType *ETSChecker::CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags) { + if (name == compiler::Signatures::BUILTIN_BIGINT_CLASS) { + if (GlobalBuiltinETSBigIntType() != nullptr) { + return GlobalBuiltinETSBigIntType(); + } + + GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BIG_INT_BUILTIN)] = + CreateNewETSObjectType(name, declNode, flags | ETSObjectFlags::BUILTIN_BIGINT); + GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BIG_INT)] = + Allocator()->New(Allocator(), GlobalBuiltinETSBigIntType()); + + return GlobalBuiltinETSBigIntType(); + } + if (name == compiler::Signatures::BUILTIN_STRING_CLASS) { if (GlobalBuiltinETSStringType() != nullptr) { return GlobalBuiltinETSStringType(); @@ -222,93 +346,12 @@ ETSObjectType *ETSChecker::CreateETSObjectTypeCheckBuiltins(util::StringView nam } auto *objType = CreateNewETSObjectType(name, declNode, flags); - - if (name == compiler::Signatures::BUILTIN_OBJECT_CLASS) { - if (GlobalETSObjectType() != nullptr) { - return GlobalETSObjectType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_OBJECT_BUILTIN)] = objType; - auto *nullish = - CreateNullishType(objType, checker::TypeFlag::NULLISH, Allocator(), Relation(), GetGlobalTypesHolder()); - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_NULLISH_OBJECT)] = nullish; - } else if (name == compiler::Signatures::BUILTIN_EXCEPTION_CLASS) { - if (GlobalBuiltinExceptionType() != nullptr) { - return GlobalBuiltinExceptionType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_EXCEPTION_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_ERROR_CLASS) { - if (GlobalBuiltinErrorType() != nullptr) { - return GlobalBuiltinErrorType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_ERROR_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_TYPE_CLASS) { - if (GlobalBuiltinTypeType() != nullptr) { - return GlobalBuiltinTypeType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_TYPE_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_PROMISE_CLASS) { - if (GlobalBuiltinPromiseType() != nullptr) { - return GlobalBuiltinPromiseType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_PROMISE_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalETSObjectType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalETSObjectType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_BOOLEAN_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalETSBooleanType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalETSBooleanType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BOOLEAN_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_BYTE_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalByteType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalByteType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BYTE_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_CHAR_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalCharType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalCharType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_CHAR_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_SHORT_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalShortType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalShortType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_SHORT_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_INT_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalIntType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalIntType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_INT_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_LONG_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalLongType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalLongType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_LONG_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_FLOAT_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalFloatType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalFloatType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_FLOAT_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_FLOAT_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalFloatType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalFloatType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_FLOAT_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_DOUBLE_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalDoubleType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalDoubleType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_DOUBLE_BOX_BUILTIN)] = objType; - } else if (name == compiler::Signatures::BUILTIN_VOID_CLASS) { - if (GlobalBuiltinVoidType() != nullptr) { - return GlobalBuiltinVoidType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_VOID_BUILTIN)] = objType; + auto nameToGlobalBoxType = GetNameToGlobalBoxTypeMap(); + if (nameToGlobalBoxType.find(name) != nameToGlobalBoxType.end()) { + return UpdateBoxedGlobalType(objType, name); } - return objType; + return UpdateGlobalType(objType, name); } ETSObjectType *ETSChecker::CreateETSObjectType(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags) @@ -441,8 +484,9 @@ ETSObjectType *ETSChecker::CreateNewETSObjectType(util::StringView name, ir::Ast if (containingObjType != nullptr) { prefix = containingObjType->AssemblerName(); - } else if (declNode->GetTopStatement()->Type() != - ir::AstNodeType::BLOCK_STATEMENT) { // NOTE: should not occur, fix for TS_INTERFACE_DECLARATION + } else if (const auto *topStatement = declNode->GetTopStatement(); + topStatement->Type() != + ir::AstNodeType::ETS_SCRIPT) { // NOTE: should not occur, fix for TS_INTERFACE_DECLARATION ASSERT(declNode->IsTSInterfaceDeclaration()); assemblerName = declNode->AsTSInterfaceDeclaration()->InternalName(); } else { diff --git a/ets2panda/checker/ets/typeRelationContext.cpp b/ets2panda/checker/ets/typeRelationContext.cpp index 22f1a5f1f81a3a21a7cc1db4ad6afb6eaef906f9..1cad83ce426738e4a6580b90f0201c88854f00cf 100644 --- a/ets2panda/checker/ets/typeRelationContext.cpp +++ b/ets2panda/checker/ets/typeRelationContext.cpp @@ -14,6 +14,7 @@ */ #include "typeRelationContext.h" +#include "boxingConverter.h" #include "varbinder/scope.h" #include "varbinder/variable.h" #include "varbinder/declaration.h" @@ -60,12 +61,13 @@ bool InstantiationContext::ValidateTypeArguments(ETSObjectType *type, ir::TSType extends "Comparable", we will get an error here. */ - auto const getTypes = [this, &typeArgs, type](size_t idx) -> std::pair { + auto const isDefaulted = [typeArgs](size_t idx) { return typeArgs == nullptr || idx >= typeArgs->Params().size(); }; + + auto const getTypes = [this, &typeArgs, type, isDefaulted](size_t idx) -> std::pair { auto *typeParam = type->TypeArguments().at(idx)->AsETSTypeParameter(); - if (typeArgs != nullptr && idx < typeArgs->Params().size()) { - return {typeParam, typeArgs->Params().at(idx)->GetType(checker_)}; - } - return {typeParam, typeParam->GetDefaultType()}; + return {typeParam, isDefaulted(idx) + ? typeParam->GetDefaultType() + : checker_->MaybePromotedBuiltinType(typeArgs->Params().at(idx)->GetType(checker_))}; }; auto *const substitution = checker_->NewSubstitution(); @@ -87,7 +89,7 @@ bool InstantiationContext::ValidateTypeArguments(ETSObjectType *type, ir::TSType if (!ValidateTypeArg(constraint, typeArg) && typeArgs != nullptr && !checker_->Relation()->NoThrowGenericTypeAlias()) { checker_->ThrowTypeError({"Type '", typeArg, "' is not assignable to constraint type '", constraint, "'."}, - typeArgs->Params().at(idx)->Start()); + isDefaulted(idx) ? pos : typeArgs->Params().at(idx)->Start()); } } @@ -96,16 +98,10 @@ bool InstantiationContext::ValidateTypeArguments(ETSObjectType *type, ir::TSType bool InstantiationContext::ValidateTypeArg(Type *constraintType, Type *typeArg) { - if (!ETSChecker::IsReferenceType(typeArg)) { - return false; - } - - if (typeArg->IsETSUnionType()) { - auto const &constituentTypes = typeArg->AsETSUnionType()->ConstituentTypes(); - return std::all_of(constituentTypes.begin(), constituentTypes.end(), - [this, constraintType](Type *cType) { return ValidateTypeArg(constraintType, cType); }); + // NOTE: #14993 enforce ETSChecker::IsReferenceType + if (typeArg->IsWildcardType()) { + return true; } - return checker_->Relation()->IsAssignableTo(typeArg, constraintType); } diff --git a/ets2panda/checker/ets/typeRelationContext.h b/ets2panda/checker/ets/typeRelationContext.h index d990099248e2270f010bc29ba65bb90357e4bec6..92b8a8a602f6eaac682a0c093bd7370be37bab49 100644 --- a/ets2panda/checker/ets/typeRelationContext.h +++ b/ets2panda/checker/ets/typeRelationContext.h @@ -69,7 +69,7 @@ public: relation->SetNode(nullptr); relation->SetFlags(TypeRelationFlag::NONE); - assignable_ = true; + assignable_ = relation->IsTrue(); } bool IsAssignable() const diff --git a/ets2panda/checker/types/ets/etsBigIntType.cpp b/ets2panda/checker/types/ets/etsBigIntType.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c617a86e926d2108442e8202aa95a695222dc4f --- /dev/null +++ b/ets2panda/checker/types/ets/etsBigIntType.cpp @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "etsBigIntType.h" + +namespace panda::es2panda::checker { +void ETSBigIntType::Identical(TypeRelation *relation, Type *other) +{ + if (other->IsETSBigIntType()) { + relation->Result(true); + return; + } + + relation->Result(false); +} + +void ETSBigIntType::AssignmentTarget([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *source) +{ + if (source->IsETSBigIntType()) { + relation->Result(true); + return; + } + + relation->Result(false); +} + +Type *ETSBigIntType::Instantiate([[maybe_unused]] ArenaAllocator *allocator, [[maybe_unused]] TypeRelation *relation, + [[maybe_unused]] GlobalTypesHolder *globalTypes) +{ + return this; +} +} // namespace panda::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsBigIntType.h b/ets2panda/checker/types/ets/etsBigIntType.h new file mode 100644 index 0000000000000000000000000000000000000000..22e196e98bf5ffc76c12279c4253d66a3ef25e0c --- /dev/null +++ b/ets2panda/checker/types/ets/etsBigIntType.h @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_BIGINT_TYPE_H +#define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_BIGINT_TYPE_H + +#include "checker/types/ets/etsObjectType.h" + +namespace panda::es2panda::checker { +class ETSBigIntType : public ETSObjectType { +public: + explicit ETSBigIntType(ArenaAllocator *allocator, [[maybe_unused]] ETSObjectType *super) + : ETSObjectType(allocator, + ETSObjectFlags::CLASS | ETSObjectFlags::BUILTIN_BIGINT | ETSObjectFlags::RESOLVED_SUPER) + { + SetSuperType(super); + } + + explicit ETSBigIntType(ArenaAllocator *allocator, ETSObjectType *super, util::StringView value) + : ETSObjectType(allocator, + ETSObjectFlags::CLASS | ETSObjectFlags::BUILTIN_BIGINT | ETSObjectFlags::RESOLVED_SUPER), + value_(value) + { + SetSuperType(super); + AddTypeFlag(TypeFlag::CONSTANT); + AddTypeFlag(TypeFlag::BIGINT_LITERAL); + variable_ = super->Variable(); + } + + void Identical(TypeRelation *relation, Type *other) override; + void AssignmentTarget(TypeRelation *relation, Type *source) override; + Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; + + void ToString(std::stringstream &ss) const override + { + ss << lexer::TokenToString(lexer::TokenType::KEYW_BIGINT); + } + + void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const override + { + ss << compiler::Signatures::BUILTIN_BIGINT; + } + + util::StringView GetValue() const + { + return value_; + } + +private: + util::StringView value_ {}; +}; +} // namespace panda::es2panda::checker + +#endif diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index bbac84f8f67652c980a338fd86e6254dda0ff64c..a62da9a70c74628aecce1ca2a49e887fd689e8a3 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -436,7 +436,7 @@ void ETSObjectType::AssignmentTarget(TypeRelation *const relation, Type *source) return; } - IsSupertypeOf(relation, source); + relation->IsSupertypeOf(this, source); } bool ETSObjectType::CastWideningNarrowing(TypeRelation *const relation, Type *const target, TypeFlag unboxFlags, @@ -570,7 +570,7 @@ void ETSObjectType::Cast(TypeRelation *const relation, Type *const target) } if (this->IsETSNullLike()) { - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { + if (target->HasTypeFlag(TypeFlag::ETS_ARRAY_OR_OBJECT)) { relation->GetNode()->SetTsType(target); relation->Result(true); return; @@ -609,6 +609,17 @@ void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) relation->Result(false); auto *const etsChecker = relation->GetChecker()->AsETSChecker(); + if (source->IsETSUnionType()) { + bool res = std::all_of(source->AsETSUnionType()->ConstituentTypes().begin(), + source->AsETSUnionType()->ConstituentTypes().end(), [this, relation](Type *ct) { + relation->Result(false); + IsSupertypeOf(relation, ct); + return relation->IsTrue(); + }); + relation->Result(res); + return; + } + // 3.8.3 Subtyping among Array Types auto const *const base = GetConstOriginalBaseType(); if (base == etsChecker->GlobalETSObjectType() && source->IsETSArrayType()) { @@ -616,11 +627,6 @@ void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) return; } - if (source->IsETSTypeParameter()) { - source->AsETSTypeParameter()->ConstraintIsSubtypeOf(relation, this); - return; - } - if (!source->IsETSObjectType() || !source->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::CLASS | ETSObjectFlags::INTERFACE | ETSObjectFlags::NULL_TYPE)) { @@ -631,7 +637,7 @@ void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) return; } // All classes and interfaces are subtypes of Object - if (base == etsChecker->GlobalETSObjectType()) { + if (base == etsChecker->GlobalETSObjectType() || base == etsChecker->GlobalETSNullishObjectType()) { relation->Result(true); return; } @@ -643,16 +649,14 @@ void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) ETSObjectType *sourceObj = source->AsETSObjectType(); if (auto *sourceSuper = sourceObj->SuperType(); sourceSuper != nullptr) { - IsSupertypeOf(relation, sourceSuper); - if (relation->IsTrue()) { + if (relation->IsSupertypeOf(this, sourceSuper)) { return; } } if (HasObjectFlag(ETSObjectFlags::INTERFACE)) { for (auto *itf : sourceObj->Interfaces()) { - IsSupertypeOf(relation, itf); - if (relation->IsTrue()) { + if (relation->IsSupertypeOf(this, itf)) { return; } } diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index f84bd93eec417e74217340c47b8f5468dbccb03e..99fb0e6db086e73bd42be95ac3db1b9a84f1482d 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -48,6 +48,7 @@ enum class ETSObjectFlags : uint32_t { CHECKED_INVOKE_LEGITIMACY = 1U << 18U, UNDEFINED_TYPE = 1U << 19U, + BUILTIN_BIGINT = 1U << 22U, BUILTIN_STRING = 1U << 23U, BUILTIN_BOOLEAN = 1U << 24U, BUILTIN_BYTE = 1U << 25U, @@ -60,7 +61,7 @@ enum class ETSObjectFlags : uint32_t { UNBOXABLE_TYPE = BUILTIN_BOOLEAN | BUILTIN_BYTE | BUILTIN_CHAR | BUILTIN_SHORT | BUILTIN_INT | BUILTIN_LONG | BUILTIN_FLOAT | BUILTIN_DOUBLE, - BUILTIN_TYPE = BUILTIN_STRING | UNBOXABLE_TYPE, + BUILTIN_TYPE = BUILTIN_STRING | BUILTIN_BIGINT | UNBOXABLE_TYPE, VALID_SWITCH_TYPE = BUILTIN_BYTE | BUILTIN_CHAR | BUILTIN_SHORT | BUILTIN_INT | BUILTIN_LONG | BUILTIN_STRING | ENUM, GLOBAL_CLASS = CLASS | GLOBAL, diff --git a/ets2panda/checker/types/ets/etsTypeParameter.cpp b/ets2panda/checker/types/ets/etsTypeParameter.cpp index 8f5631304a20b34df0f66c6afe4e66ecfcd85e33..5f00ef4a3c4ccd040e8c945a0a02efc01d7dd571 100644 --- a/ets2panda/checker/types/ets/etsTypeParameter.cpp +++ b/ets2panda/checker/types/ets/etsTypeParameter.cpp @@ -70,14 +70,13 @@ void ETSTypeParameter::AssignmentTarget([[maybe_unused]] TypeRelation *relation, return; } - IsSupertypeOf(relation, source); + relation->IsSupertypeOf(this, source); } void ETSTypeParameter::Cast(TypeRelation *relation, Type *target) { - if (target->IsSupertypeOf(relation, this), relation->IsTrue()) { + if (relation->IsSupertypeOf(target, this)) { relation->RemoveFlags(TypeRelationFlag::UNCHECKED_CAST); - relation->Result(true); return; } @@ -90,9 +89,8 @@ void ETSTypeParameter::Cast(TypeRelation *relation, Type *target) void ETSTypeParameter::CastTarget(TypeRelation *relation, Type *source) { - if (IsSupertypeOf(relation, source), relation->IsTrue()) { + if (relation->IsSupertypeOf(this, source)) { relation->RemoveFlags(TypeRelationFlag::UNCHECKED_CAST); - relation->Result(true); return; } @@ -101,12 +99,12 @@ void ETSTypeParameter::CastTarget(TypeRelation *relation, Type *source) void ETSTypeParameter::IsSupertypeOf([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *source) { - if (Identical(relation, source), relation->IsTrue()) { - return; - } + relation->Result(false); +} - if (source->IsETSTypeParameter()) { - source->AsETSTypeParameter()->ConstraintIsSubtypeOf(relation, this); +void ETSTypeParameter::IsSubtypeOf([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) +{ + if (relation->IsSupertypeOf(target, GetConstraintType())) { return; } @@ -144,8 +142,7 @@ Type *ETSTypeParameter::Substitute(TypeRelation *relation, const Substitution *s if (this != original && ((ContainsNull() && !replType->ContainsNull()) || (ContainsUndefined() && !replType->ContainsUndefined()))) { // this type is explicitly marked as nullish - ASSERT(replType->IsETSObjectType() || replType->IsETSArrayType() || replType->IsETSFunctionType() || - replType->IsETSTypeParameter()); + ASSERT(ETSChecker::IsReferenceType(replType)); auto nullishFlags = TypeFlag(TypeFlags() & TypeFlag::NULLISH); auto *newReplType = checker->CreateNullishType(replType, nullishFlags, checker->Allocator(), relation, checker->GetGlobalTypesHolder()); @@ -157,27 +154,14 @@ Type *ETSTypeParameter::Substitute(TypeRelation *relation, const Substitution *s return this; } -Type *ETSTypeParameter::EffectiveConstraint(ETSChecker const *checker) const -{ - return HasConstraint() ? GetConstraintType() : checker->GlobalETSNullishObjectType(); -} - void ETSTypeParameter::ToAssemblerType(std::stringstream &ss) const { - if (HasConstraint()) { - GetConstraintType()->ToAssemblerType(ss); - } else { - ss << compiler::Signatures::BUILTIN_OBJECT; - } + GetConstraintType()->ToAssemblerType(ss); } void ETSTypeParameter::ToDebugInfoType(std::stringstream &ss) const { - if (HasConstraint()) { - GetConstraintType()->ToDebugInfoType(ss); - } else { - ETSObjectType::DebugInfoTypeFromName(ss, compiler::Signatures::BUILTIN_OBJECT); - } + GetConstraintType()->ToDebugInfoType(ss); } ETSTypeParameter *ETSTypeParameter::GetOriginal() const diff --git a/ets2panda/checker/types/ets/etsTypeParameter.h b/ets2panda/checker/types/ets/etsTypeParameter.h index 842e4a69c24a08490ba51bc604f2d6453497d456..c47ece8b30f27d24a45e8c7de3e75c26da1c19b3 100644 --- a/ets2panda/checker/types/ets/etsTypeParameter.h +++ b/ets2panda/checker/types/ets/etsTypeParameter.h @@ -57,16 +57,10 @@ public: Type *GetConstraintType() const { + ASSERT(constraint_ != nullptr); return constraint_; } - bool HasConstraint() const - { - return GetConstraintType() != nullptr; - } - - Type *EffectiveConstraint(ETSChecker const *checker) const; - void ToString(std::stringstream &ss) const override; void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; @@ -74,19 +68,10 @@ public: void Cast(TypeRelation *relation, Type *target) override; void CastTarget(TypeRelation *relation, Type *source) override; void IsSupertypeOf(TypeRelation *relation, Type *source) override; + void IsSubtypeOf(TypeRelation *relation, Type *target) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; Type *Substitute(TypeRelation *relation, const Substitution *substitution) override; - bool ConstraintIsSubtypeOf(TypeRelation *relation, Type *target) - { - if (HasConstraint()) { - target->IsSupertypeOf(relation, GetConstraintType()); - } else { - relation->Result(false); - } - return relation->IsTrue(); - } - void ToAssemblerType(std::stringstream &ss) const override; void ToDebugInfoType(std::stringstream &ss) const override; diff --git a/ets2panda/checker/types/ets/etsUnionType.cpp b/ets2panda/checker/types/ets/etsUnionType.cpp index 6ff849b9bf52a5273d630491371f834ae10e8794..9967c7d93654c7e4d600948ce4de5495f0b91de0 100644 --- a/ets2panda/checker/types/ets/etsUnionType.cpp +++ b/ets2panda/checker/types/ets/etsUnionType.cpp @@ -161,12 +161,24 @@ void ETSUnionType::LinearizeAndEraseIdentical(TypeRelation *relation, ArenaVecto } } constituentTypes = copiedConstituents; + // Removing subtypes should be in the next iteration, especially needed for proper literals removal + auto checkSubtyping = [relation](Type *lhs, Type *rhs) { + if (lhs == rhs) { + return false; + } + relation->Result(false); + lhs->IsSupertypeOf(relation, rhs); + bool inheritanceRelation = relation->IsTrue(); + rhs->IsSupertypeOf(relation, lhs); + inheritanceRelation = inheritanceRelation || relation->IsTrue(); + return inheritanceRelation; + }; // Secondly, remove identical types auto cmpIt = constituentTypes.begin(); while (cmpIt != constituentTypes.end()) { auto it = std::next(cmpIt); while (it != constituentTypes.end()) { - if (relation->IsIdenticalTo(*it, *cmpIt)) { + if (relation->IsIdenticalTo(*it, *cmpIt) && !checkSubtyping(*it, *cmpIt)) { it = constituentTypes.erase(it); } else { ++it; @@ -196,9 +208,9 @@ 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) { - relation->Result(false); - (*cmpIt)->IsSupertypeOf(relation, ct); - bool removeSubtype = ct != *cmpIt && relation->IsTrue(); + bool bothConstants = (*cmpIt)->HasTypeFlag(TypeFlag::CONSTANT) && ct->HasTypeFlag(TypeFlag::CONSTANT); + relation->IsSupertypeOf((*cmpIt), ct); + bool removeSubtype = ct != *cmpIt && !bothConstants && relation->IsTrue(); bool removeNumeric = numberFound && ct->IsETSObjectType() && ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::UNBOXABLE_TYPE) && !ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE) && @@ -285,27 +297,20 @@ void ETSUnionType::Cast(TypeRelation *relation, Type *target) void ETSUnionType::IsSupertypeOf(TypeRelation *relation, Type *source) { - relation->Result(false); - - if (source->IsETSUnionType()) { - for (auto const &sourceCtype : source->AsETSUnionType()->ConstituentTypes()) { - if (IsSupertypeOf(relation, sourceCtype), !relation->IsTrue()) { - return; - } + for (auto const &ctype : ConstituentTypes()) { + if (relation->IsSupertypeOf(ctype, source)) { + return; } - return; } +} +void ETSUnionType::IsSubtypeOf(TypeRelation *relation, Type *target) +{ for (auto const &ctype : ConstituentTypes()) { - if (ctype->IsSupertypeOf(relation, source), relation->IsTrue()) { + if (!relation->IsSupertypeOf(target, ctype)) { return; } } - - if (source->IsETSTypeParameter()) { - source->AsETSTypeParameter()->ConstraintIsSubtypeOf(relation, this); - return; - } } void ETSUnionType::CastTarget(TypeRelation *relation, Type *source) diff --git a/ets2panda/checker/types/ets/etsUnionType.h b/ets2panda/checker/types/ets/etsUnionType.h index 6fc427aa9c1012dfc3ce85e26246f4ffed512cdd..6d5be98143770c1e8b244e8d336485b1ab3eb746 100644 --- a/ets2panda/checker/types/ets/etsUnionType.h +++ b/ets2panda/checker/types/ets/etsUnionType.h @@ -43,6 +43,7 @@ public: void Cast(TypeRelation *relation, Type *target) override; void CastTarget(TypeRelation *relation, Type *source) override; void IsSupertypeOf(TypeRelation *relation, Type *source) override; + void IsSubtypeOf(TypeRelation *relation, Type *target) override; Type *FindTypeIsCastableToThis(ir::Expression *node, TypeRelation *relation, Type *source) const; Type *FindTypeIsCastableToSomeType(ir::Expression *node, TypeRelation *relation, Type *target) const; Type *FindUnboxableType() const; diff --git a/ets2panda/checker/types/ets/types.h b/ets2panda/checker/types/ets/types.h index 1f798ee532f0073398218b8c14b9eb951315b8fc..ceb2e87ade93af2b767661af558191fb1f727512 100644 --- a/ets2panda/checker/types/ets/types.h +++ b/ets2panda/checker/types/ets/types.h @@ -30,6 +30,7 @@ #include "etsUnionType.h" #include "etsVoidType.h" #include "etsStringType.h" +#include "etsBigIntType.h" #include "etsObjectType.h" #include "etsDynamicType.h" #include "etsArrayType.h" diff --git a/ets2panda/checker/types/globalTypesHolder.cpp b/ets2panda/checker/types/globalTypesHolder.cpp index 4b3071f855d3fc49135d1c833725c874c0ff5d07..c91292f5126e888d444eba88a09bb4514281cd93 100644 --- a/ets2panda/checker/types/globalTypesHolder.cpp +++ b/ets2panda/checker/types/globalTypesHolder.cpp @@ -42,6 +42,7 @@ #include "checker/types/ets/shortType.h" #include "checker/types/ets/etsBooleanType.h" #include "checker/types/ets/etsStringType.h" +#include "checker/types/ets/etsBigIntType.h" #include "checker/types/ets/etsVoidType.h" #include "checker/types/ets/etsObjectType.h" #include "checker/types/ets/wildcardType.h" @@ -126,6 +127,7 @@ GlobalTypesHolder::GlobalTypesHolder(ArenaAllocator *allocator) : builtinNameMap builtinNameMappings_.emplace("ClassNotFoundException", GlobalTypeId::ETS_CLASS_NOT_FOUND_EXCEPTION_BUILTIN); builtinNameMappings_.emplace("ClassCastException", GlobalTypeId::ETS_CLASS_CAST_EXCEPTION_BUILTIN); builtinNameMappings_.emplace("String", GlobalTypeId::ETS_STRING_BUILTIN); + builtinNameMappings_.emplace("BigInt", GlobalTypeId::ETS_BIG_INT_BUILTIN); builtinNameMappings_.emplace("StringBuilder", GlobalTypeId::ETS_STRING_BUILDER_BUILTIN); builtinNameMappings_.emplace("Type", GlobalTypeId::ETS_TYPE_BUILTIN); builtinNameMappings_.emplace("Types", GlobalTypeId::ETS_TYPES_BUILTIN); @@ -511,6 +513,16 @@ Type *GlobalTypesHolder::GlobalETSStringBuiltinType() return globalTypes_.at(static_cast(GlobalTypeId::ETS_STRING_BUILTIN)); } +Type *GlobalTypesHolder::GlobalETSBigIntBuiltinType() +{ + return globalTypes_.at(static_cast(GlobalTypeId::ETS_BIG_INT_BUILTIN)); +} + +Type *GlobalTypesHolder::GlobalETSBigIntLiteralType() +{ + return globalTypes_.at(static_cast(GlobalTypeId::ETS_BIG_INT)); +} + Type *GlobalTypesHolder::GlobalStringBuilderBuiltinType() { return globalTypes_.at(static_cast(GlobalTypeId::ETS_STRING_BUILDER_BUILTIN)); diff --git a/ets2panda/checker/types/globalTypesHolder.h b/ets2panda/checker/types/globalTypesHolder.h index 32813e9a263b62b98b8f5535642baea078106135..22c188dbf0b41e56860c5bd98675f43073554319 100644 --- a/ets2panda/checker/types/globalTypesHolder.h +++ b/ets2panda/checker/types/globalTypesHolder.h @@ -109,6 +109,8 @@ enum class GlobalTypeId { ETS_FLOAT_BOX_BUILTIN, ETS_DOUBLE_BOX_BUILTIN, ETS_NEVER_BUILTIN, + ETS_BIG_INT_BUILTIN, + ETS_BIG_INT, COUNT, }; @@ -185,6 +187,8 @@ public: Type *GlobalClassNotFoundExceptionBuiltinType(); [[nodiscard]] Type *GlobalClassCastExceptionBuiltinType() const noexcept; Type *GlobalETSStringBuiltinType(); + Type *GlobalETSBigIntBuiltinType(); + Type *GlobalETSBigIntLiteralType(); Type *GlobalStringBuilderBuiltinType(); Type *GlobalTypeBuiltinType(); Type *GlobalTypesBuiltinType(); diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index 0e3b315c12c79d1c3af0f33d5f7f8f20d31874b6..38f37ea0e407642571e7ac44abd4fa2d2429b5ad 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::IsETSBigIntType() const +{ + return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_BIGINT); +} + bool Type::IsETSAsyncFuncReturnType() const { return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::ASYNC_FUNC_RETURN_TYPE); @@ -115,6 +120,11 @@ void Type::IsSupertypeOf(TypeRelation *const relation, [[maybe_unused]] Type *so relation->Result(false); } +void Type::IsSubtypeOf(TypeRelation *const relation, [[maybe_unused]] Type *target) +{ + relation->Result(false); +} + Type *Type::AsSuper([[maybe_unused]] Checker *checker, [[maybe_unused]] varbinder::Variable *sourceVar) { return nullptr; diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 047346f00b86768880260e59630e4cd43ae26536..288ec03b9e9490e2ff4811dcf2793b6c6c40aefd 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -43,6 +43,7 @@ class ETSTypeParameter; TYPE_MAPPING(DECLARE_TYPENAMES) #undef DECLARE_TYPENAMES class ETSStringType; +class ETSBigIntType; using Substitution = ArenaMap; @@ -84,6 +85,7 @@ public: #undef TYPE_AS_CASTS bool IsETSStringType() const; + bool IsETSBigIntType() const; bool IsETSNullType() const; bool IsETSUndefinedType() const; bool IsETSNullLike() const; @@ -105,6 +107,12 @@ public: return reinterpret_cast(this); } + const ETSBigIntType *AsETSBigIntType() const + { + ASSERT(IsETSObjectType()); + return reinterpret_cast(this); + } + bool IsETSDynamicType() const { return IsETSObjectType() && HasTypeFlag(TypeFlag::ETS_DYNAMIC_FLAG); @@ -243,6 +251,7 @@ public: virtual void Cast(TypeRelation *relation, Type *target); virtual void CastTarget(TypeRelation *relation, Type *source); virtual void IsSupertypeOf(TypeRelation *relation, Type *source); + virtual void IsSubtypeOf(TypeRelation *relation, Type *target); virtual Type *AsSuper(Checker *checker, varbinder::Variable *sourceVar); virtual Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes); diff --git a/ets2panda/checker/types/typeRelation.cpp b/ets2panda/checker/types/typeRelation.cpp index f3eaa9fdbd7947cdd32cc9fb084486ac029e3e86..a0582ab359bb20047b907492d7ef0eb231f7a75d 100644 --- a/ets2panda/checker/types/typeRelation.cpp +++ b/ets2panda/checker/types/typeRelation.cpp @@ -173,6 +173,28 @@ bool TypeRelation::IsCastableTo(Type *const source, Type *const target) return result_ == RelationResult::TRUE; } +bool TypeRelation::IsSupertypeOf(Type *super, Type *sub) +{ + result_ = CacheLookup(super, sub, checker_->SupertypeResults(), RelationType::SUPERTYPE); + if (result_ == RelationResult::CACHE_MISS) { + if (IsIdenticalTo(super, sub)) { + return true; + } + + result_ = RelationResult::FALSE; + + if (super->IsSupertypeOf(this, sub), !IsTrue()) { + sub->IsSubtypeOf(this, super); + } + + if (flags_ == TypeRelationFlag::NONE) { + checker_->SupertypeResults().cached.insert({{super->Id(), sub->Id()}, {result_, RelationType::SUPERTYPE}}); + } + } + + return result_ == RelationResult::TRUE; +} + void TypeRelation::RaiseError(const std::string &errMsg, const lexer::SourcePosition &loc) const { checker_->ThrowTypeError(errMsg, loc); diff --git a/ets2panda/checker/types/typeRelation.h b/ets2panda/checker/types/typeRelation.h index 0da58eadc0e716bb7668ad96a6174fe180813346..53f1642d1b0e655d9974869e7982618449009563 100644 --- a/ets2panda/checker/types/typeRelation.h +++ b/ets2panda/checker/types/typeRelation.h @@ -69,7 +69,7 @@ enum class TypeRelationFlag : uint32_t { enum class RelationResult { TRUE, FALSE, UNKNOWN, MAYBE, CACHE_MISS, ERROR }; -enum class RelationType { COMPARABLE, ASSIGNABLE, IDENTICAL, UNCHECKED_CASTABLE }; +enum class RelationType { COMPARABLE, ASSIGNABLE, IDENTICAL, UNCHECKED_CASTABLE, SUPERTYPE }; DEFINE_BITOPS(TypeRelationFlag) @@ -265,6 +265,7 @@ public: bool IsAssignableTo(Type *source, Type *target); bool IsComparableTo(Type *source, Type *target); bool IsCastableTo(Type *source, Type *target); + bool IsSupertypeOf(Type *super, Type *sub); void RaiseError(const std::string &errMsg, const lexer::SourcePosition &loc) const; void RaiseError(std::initializer_list list, const lexer::SourcePosition &loc) const; diff --git a/ets2panda/compiler/base/condition.cpp b/ets2panda/compiler/base/condition.cpp index a3d5504886523be856f64043f8837650cea4a34e..718d8eca3bba153e64310591882aafd6da296cd6 100644 --- a/ets2panda/compiler/base/condition.cpp +++ b/ets2panda/compiler/base/condition.cpp @@ -187,8 +187,60 @@ void Condition::CompileLogicalAndExpr(ETSGen *etsg, const ir::BinaryExpression * etsg->SetLabel(binExpr, returnRightTrueLabel); } +bool Condition::CompileBinaryExprForBigInt(ETSGen *etsg, const ir::BinaryExpression *expr, Label *falseLabel) +{ + if ((expr->Left()->TsType() == nullptr) || (expr->Right()->TsType() == nullptr)) { + return false; + } + + if (!expr->Left()->TsType()->IsETSBigIntType()) { + return false; + } + + if (!expr->Right()->TsType()->IsETSBigIntType()) { + return false; + } + + std::string_view signature = compiler::Signatures::ANY; + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_LESS_THAN: + signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN; + break; + case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: + signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN_EQUAL; + break; + case lexer::TokenType::PUNCTUATOR_GREATER_THAN: + signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN; + break; + case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: + signature = compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN_EQUAL; + break; + default: + // Other operations are handled in the CompileBinaryExpr function + return false; + } + + auto ttctx = TargetTypeContext(etsg, expr->OperationType()); + RegScope rs(etsg); + VReg lhs = etsg->AllocReg(); + expr->Left()->Compile(etsg); + etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType()); + expr->Right()->Compile(etsg); + etsg->ApplyConversion(expr->Right(), expr->OperationType()); + compiler::VReg rhs = etsg->AllocReg(); + etsg->StoreAccumulator(expr, rhs); + etsg->CallBigIntBinaryComparison(expr, lhs, rhs, signature); + etsg->BranchIfFalse(expr, falseLabel); + + return true; +} + bool Condition::CompileBinaryExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel) { + if (CompileBinaryExprForBigInt(etsg, binExpr, falseLabel)) { + return true; + } + switch (binExpr->OperatorType()) { case lexer::TokenType::PUNCTUATOR_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: diff --git a/ets2panda/compiler/base/condition.h b/ets2panda/compiler/base/condition.h index 25387bc99d4f525a9efb74355c472d1b1a625128..48e26d2b449068838588f4148359b406ab1ba8d7 100644 --- a/ets2panda/compiler/base/condition.h +++ b/ets2panda/compiler/base/condition.h @@ -42,6 +42,7 @@ private: static bool CompileBinaryExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel); static void CompileLogicalAndExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel); static void CompileLogicalOrExpr(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel); + static bool CompileBinaryExprForBigInt(ETSGen *etsg, const ir::BinaryExpression *binExpr, Label *falseLabel); }; } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/core/ASTVerifier.cpp b/ets2panda/compiler/core/ASTVerifier.cpp index 7af3d4e1866503dcff9f19e1b45a308230a1735f..e0e1eab1676f090865ea7b6f1e813076cf5e8b76 100644 --- a/ets2panda/compiler/core/ASTVerifier.cpp +++ b/ets2panda/compiler/core/ASTVerifier.cpp @@ -23,57 +23,33 @@ #include "ir/base/classStaticBlock.h" #include "ir/base/methodDefinition.h" #include "ir/base/scriptFunction.h" -#include "ir/ets/etsFunctionType.h" #include "ir/ets/etsNewClassInstanceExpression.h" -#include "ir/ets/etsParameterExpression.h" -#include "ir/ets/etsTypeReference.h" -#include "ir/ets/etsTypeReferencePart.h" -#include "ir/ets/etsImportDeclaration.h" #include "ir/ets/etsScript.h" +#include "ir/ets/etsImportDeclaration.h" +#include "ir/expressions/sequenceExpression.h" #include "ir/module/importSpecifier.h" #include "ir/module/importNamespaceSpecifier.h" #include "ir/module/importDefaultSpecifier.h" #include "ir/expressions/callExpression.h" #include "ir/expressions/binaryExpression.h" -#include "ir/expressions/functionExpression.h" #include "ir/expressions/identifier.h" -#include "ir/expressions/literals/numberLiteral.h" -#include "ir/expressions/literals/stringLiteral.h" #include "ir/expressions/memberExpression.h" -#include "ir/statements/blockStatement.h" #include "ir/statements/forInStatement.h" #include "ir/statements/forOfStatement.h" #include "ir/statements/forUpdateStatement.h" -#include "ir/statements/variableDeclaration.h" #include "ir/statements/variableDeclarator.h" -#include "ir/statements/classDeclaration.h" #include "ir/statements/expressionStatement.h" #include "ir/statements/throwStatement.h" -#include "ir/statements/tryStatement.h" -#include "ir/ts/tsClassImplements.h" #include "ir/ts/tsTypeParameter.h" -#include "ir/ts/tsTypeParameterDeclaration.h" -#include "ir/ts/tsTypeParameterInstantiation.h" #include "lexer/token/tokenType.h" #include "util/ustring.h" #include "utils/arena_containers.h" #include "varbinder/scope.h" -#include -#include +constexpr auto RECURSIVE_SUFFIX = "ForAll"; namespace panda::es2panda::compiler { -template -ASTVerifier::CheckFunction RecursiveCheck(const Func &func) -{ - return [func](const ir::AstNode *ast) -> bool { - bool hasParent = func(ast); - ast->IterateRecursively([func, &hasParent](ir::AstNode *child) { hasParent &= func(child); }); - return hasParent; - }; -} - static bool IsNumericType(const ir::AstNode *ast) { if (ast == nullptr) { @@ -115,7 +91,7 @@ static bool IsStringType(const ir::AstNode *ast) } template -bool IsContainedIn(const T *child, const T *parent) +static bool IsContainedIn(const T *child, const T *parent) { if (child == nullptr || parent == nullptr) { return false; @@ -148,7 +124,8 @@ bool IsVisibleInternalNode(const ir::AstNode *ast, const ir::AstNode *objTypeDec return currentTopStatement == objectTopStatement || (packageNameCurrent == packageNameObject && !packageNameCurrent.Empty()); } -bool ValidateVariableAccess(const varbinder::LocalVariable *propVar, const ir::MemberExpression *ast) + +static bool ValidateVariableAccess(const varbinder::LocalVariable *propVar, const ir::MemberExpression *ast) { const auto *propVarDecl = propVar->Declaration(); if (propVarDecl == nullptr) { @@ -189,7 +166,7 @@ bool ValidateVariableAccess(const varbinder::LocalVariable *propVar, const ir::M return false; } -bool ValidateMethodAccess(const ir::MemberExpression *memberExpression, const ir::CallExpression *ast) +static bool ValidateMethodAccess(const ir::MemberExpression *memberExpression, const ir::CallExpression *ast) { auto *memberObjType = memberExpression->ObjType(); if (memberObjType == nullptr) { @@ -236,691 +213,568 @@ bool ValidateMethodAccess(const ir::MemberExpression *memberExpression, const ir return false; } -bool ValidateExport(const varbinder::Variable *var) -{ - const auto *decl = var->Declaration(); - if (decl == nullptr) { - return false; - } - const auto *node = decl->Node(); - if (node == nullptr) { - return false; - } - return node->IsExported(); -} +class NodeHasParent { +public: + explicit NodeHasParent([[maybe_unused]] ArenaAllocator &allocator) {} -std::string ToStringHelper(const varbinder::ScopeType type) -{ - switch (type) { - case varbinder::ScopeType::CATCH: { - return "CATCH"; - } - case varbinder::ScopeType::CATCH_PARAM: { - return "CATCH_PARAM"; + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + const auto isEtsScript = ast->IsETSScript(); + const auto hasParent = ast->Parent() != nullptr; + if (!isEtsScript && !hasParent) { + ctx.AddInvariantError("NodeHasParent", "NULL_PARENT", *ast); + return ASTVerifier::CheckResult::FAILED; } - case varbinder::ScopeType::CLASS: { - return "CLASS"; - } - case varbinder::ScopeType::FUNCTION: { - return "FUNCTION"; - } - case varbinder::ScopeType::FUNCTION_PARAM: { - return "FUNCTION_PARAM"; - } - case varbinder::ScopeType::GLOBAL: { - return "GLOBAL"; - } - case varbinder::ScopeType::LOCAL: { - return "LOCAL"; - } - case varbinder::ScopeType::LOOP: { - return "LOOP"; - } - case varbinder::ScopeType::LOOP_DECL: { - return "LOOP_DECL"; - } - case varbinder::ScopeType::MODULE: { - return "MODULE"; - } - case varbinder::ScopeType::PARAM: { - return "PARAM"; - } - default: { - return "MUST BE UNREACHABLE"; + if (ast->IsProgram()) { + return ASTVerifier::CheckResult::SUCCESS; } + return ASTVerifier::CheckResult::SUCCESS; } -} +}; -std::string ToStringHelper(const util::StringView &name) -{ - return name == nullptr ? "" : name.Mutf8(); -} - -std::string ToStringHelper(const varbinder::Scope *scope) -{ - if (scope == nullptr) { - return ""; - } +class IdentifierHasVariable { +public: + explicit IdentifierHasVariable([[maybe_unused]] ArenaAllocator &allocator) {} - switch (scope->Type()) { - case varbinder::ScopeType::FUNCTION: { - return "FUNC_SCOPE " + ToStringHelper(scope->AsFunctionScope()->Name()); + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + if (!ast->IsIdentifier()) { + return ASTVerifier::CheckResult::SUCCESS; } - case varbinder::ScopeType::LOCAL: { - return "LOCAL_SCOPE "; + if (ast->AsIdentifier()->Variable() != nullptr) { + return ASTVerifier::CheckResult::SUCCESS; } - case varbinder::ScopeType::CATCH: { - return "CATCH_SCOPE "; - } - default: { - return "MUST BE UNREACHABLE"; - } - } -} -std::string ToStringHelper(const varbinder::Variable *var) -{ - if (var == nullptr) { - return ""; + const auto *id = ast->AsIdentifier(); + ctx.AddInvariantError("IdentifierHasVariable", "NULL_VARIABLE", *id); + return ASTVerifier::CheckResult::FAILED; } - switch (var->Type()) { - case varbinder::VariableType::LOCAL: { - return "LOCAL_VAR " + ToStringHelper(var->Name()); - } - case varbinder::VariableType::MODULE: { - return "MODULE_VAR " + ToStringHelper(var->Name()); - } - case varbinder::VariableType::GLOBAL: { - return "GLOBAL_VAR " + ToStringHelper(var->Name()); - } - case varbinder::VariableType::ENUM: { - return "ENUM_VAR " + ToStringHelper(var->Name()); - } - default: { - return "MUST BE UNREACHABLE"; - } - } -} +private: +}; -template -std::string ToStringParamsHelper(const ir::AstNode *parent, const ArenaVector ¶ms) -{ - std::string name; - if (parent != nullptr) { - name = ToStringHelper(parent) + " "; - } +class NodeHasType { +public: + explicit NodeHasType([[maybe_unused]] ArenaAllocator &allocator) {} - name += "("; - for (auto const *param : params) { - name += ToStringHelper(param); + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + if (ast->IsTyped()) { + if (ast->IsClassDefinition() && ast->AsClassDefinition()->Ident()->Name() == "ETSGLOBAL") { + return ASTVerifier::CheckResult::SKIP_SUBTREE; + } + const auto *typed = static_cast(ast); + if (typed->TsType() == nullptr) { + ctx.AddInvariantError("NodeHasType", "NULL_TS_TYPE", *ast); + return ASTVerifier::CheckResult::FAILED; + } + } + return ASTVerifier::CheckResult::SUCCESS; } - return name + ")"; -} - -template -std::string ToStringParamsHelper(const ArenaVector ¶ms) -{ - std::string name = "("; +private: +}; - for (auto const *param : params) { - name += ToStringHelper(param); - } +class VariableHasScope { +public: + explicit VariableHasScope(ArenaAllocator &allocator) : allocator_ {allocator} {} - return name + ")"; -} + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + if (!ast->IsIdentifier()) { + return ASTVerifier::CheckResult::SUCCESS; // we will check invariant of Identifier only + } -std::string ToStringHelper(const ir::AstNode *ast) -{ - if (ast == nullptr) { - return ""; + // we will check invariant for only local variables of identifiers + if (const auto maybeVar = GetLocalScopeVariable(allocator_, ctx, ast); maybeVar.has_value()) { + const auto var = *maybeVar; + const auto scope = var->GetScope(); + if (scope == nullptr) { + ctx.AddInvariantError("VariableHasScope", "NULL_SCOPE_LOCAL_VAR", *ast); + return ASTVerifier::CheckResult::FAILED; + } + return ScopeEncloseVariable(ctx, var) ? ASTVerifier::CheckResult::SUCCESS + : ASTVerifier::CheckResult::FAILED; + } + return ASTVerifier::CheckResult::SUCCESS; } - switch (ast->Type()) { - case ir::AstNodeType::IDENTIFIER: { - return "ID " + ToStringHelper(ast->AsIdentifier()->Name()); - } - case ir::AstNodeType::CLASS_DEFINITION: { - return "CLS_DEF " + ToStringHelper(ast->AsClassDefinition()->Ident()); + static std::optional GetLocalScopeVariable(ArenaAllocator &allocator, + ASTVerifier::ErrorContext &ctx, + const ir::AstNode *ast) + { + if (!ast->IsIdentifier()) { + return std::nullopt; } - case ir::AstNodeType::CLASS_DECLARATION: { - return "CLS_DECL " + ToStringHelper(ast->AsClassDeclaration()->Definition()); - } - case ir::AstNodeType::BLOCK_STATEMENT: { - return "BLOCK " + ToStringHelper(ast->AsBlockStatement()->Scope()); - } - case ir::AstNodeType::SCRIPT_FUNCTION: { - auto const *sf = ast->AsScriptFunction(); - return "SCRIPT_FUN " + ToStringHelper(sf->Scope()) + "::" + ToStringHelper(sf->Id()); - } - case ir::AstNodeType::FUNCTION_EXPRESSION: { - return "FUN_EXPR " + ToStringHelper(ast->AsFunctionExpression()->Function()); - } - case ir::AstNodeType::METHOD_DEFINITION: { - return "METHOD_DEF " + ToStringHelper(ast->AsMethodDefinition()->Value()); - } - case ir::AstNodeType::ETS_TYPE_REFERENCE_PART: { - return "TYPE_REF_PART " + ToStringHelper(ast->AsETSTypeReferencePart()->Name()); - } - case ir::AstNodeType::ETS_TYPE_REFERENCE: { - return "TYPE_REF " + ToStringHelper(ast->AsETSTypeReference()->Part()); - } - case ir::AstNodeType::VARIABLE_DECLARATOR: { - return "VAR_DECLARATOR " + ToStringHelper(ast->AsVariableDeclarator()->Id()); - } - case ir::AstNodeType::VARIABLE_DECLARATION: { - if (ast->AsVariableDeclaration()->Declarators().empty()) { - return "VAR_DECLARATION "; + + auto invariantHasVariable = IdentifierHasVariable {allocator}; + const auto variable = ast->AsIdentifier()->Variable(); + if ((invariantHasVariable(ctx, ast) == ASTVerifier::CheckResult::SUCCESS) && variable->IsLocalVariable()) { + const auto localVar = variable->AsLocalVariable(); + if (localVar->HasFlag(varbinder::VariableFlags::LOCAL)) { + return localVar; } - return "VAR_DECLARATION " + ToStringHelper(ast->AsVariableDeclaration()->Declarators().at(0)); - } - case ir::AstNodeType::CALL_EXPRESSION: { - return "CALL_EXPR " + ToStringHelper(ast->AsCallExpression()->Callee()) + "(...)"; - } - case ir::AstNodeType::EXPRESSION_STATEMENT: { - return "EXPR_STMT " + ToStringHelper(ast->AsExpressionStatement()->GetExpression()); - } - case ir::AstNodeType::MEMBER_EXPRESSION: { - auto const *me = ast->AsMemberExpression(); - return "MEMBER_EXPR " + ToStringHelper(me->Object()) + "." + ToStringHelper(me->Property()); - } - case ir::AstNodeType::CLASS_STATIC_BLOCK: { - return "CLS_STATIC_BLOCK " + ToStringHelper(ast->AsClassStaticBlock()->Function()); - } - case ir::AstNodeType::ETS_PACKAGE_DECLARATION: { - return "PKG_DECL "; - } - case ir::AstNodeType::TS_TYPE_PARAMETER_DECLARATION: { - auto params = ast->AsTSTypeParameterDeclaration()->Params(); - return "PARAM_DECL " + ToStringParamsHelper(ast->Parent(), params); - } - case ir::AstNodeType::TS_TYPE_PARAMETER: { - return "TYPE_PARAM " + ToStringHelper(ast->AsTSTypeParameter()->Name()); } - case ir::AstNodeType::TS_TYPE_PARAMETER_INSTANTIATION: { - return "PARAM_INSTANTIATION " + - ToStringParamsHelper(ast->Parent(), ast->AsTSTypeParameterInstantiation()->Params()); - } - case ir::AstNodeType::THROW_STATEMENT: { - return "THROW_STMT " + ToStringHelper(ast->AsThrowStatement()->Argument()); - } - case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: { - return "NEW_CLS_INSTANCE " + ToStringHelper(ast->AsETSNewClassInstanceExpression()->GetTypeRef()); - } - case ir::AstNodeType::STRING_LITERAL: { - return "STR_LITERAL " + ToStringHelper(ast->AsStringLiteral()->Str()); - } - case ir::AstNodeType::TRY_STATEMENT: { - return "TRY_STMT " + ToStringHelper(ast->AsTryStatement()->Block()); - } - case ir::AstNodeType::CATCH_CLAUSE: { - return "CATCH_CLAUSE "; - } - case ir::AstNodeType::NUMBER_LITERAL: { - return "NUMBER_LITERAL " + ToStringHelper(ast->AsNumberLiteral()->Str()); - } - case ir::AstNodeType::ETS_PARAMETER_EXPRESSION: { - return "ETS_PARAM_EXPR " + ToStringHelper(ast->AsETSParameterExpression()->Ident()); - } - case ir::AstNodeType::TS_INTERFACE_DECLARATION: { - return "TS_INTERFACE_DECL " + ToStringHelper(ast->AsTSInterfaceDeclaration()->Id()); + return std::nullopt; + } + + bool ScopeEncloseVariable(ASTVerifier::ErrorContext &ctx, const varbinder::LocalVariable *var) + { + ASSERT(var); + + const auto scope = var->GetScope(); + if (scope == nullptr || var->Declaration() == nullptr) { + return true; } - case ir::AstNodeType::TS_INTERFACE_BODY: { - return "TS_INTERFACE_BODY "; + const auto node = var->Declaration()->Node(); + if (node == nullptr) { + return true; } - case ir::AstNodeType::ETS_FUNCTION_TYPE: { - return "ETS_FUNC_TYPE " + ToStringParamsHelper(ast->AsETSFunctionType()->Params()); + const auto name = "VariableHasScope"; + bool isOk = true; + if (scope->Bindings().count(var->Name()) == 0) { + ctx.AddInvariantError(name, "SCOPE_DO_NOT_ENCLOSE_LOCAL_VAR", *node); + isOk = false; } - case ir::AstNodeType::TS_CLASS_IMPLEMENTS: { - return "TS_CLASS_IMPL " + ToStringHelper(ast->AsTSClassImplements()->Expr()); + const auto scopeNode = scope->Node(); + auto varNode = node; + if (!IsContainedIn(varNode, scopeNode) || scopeNode == nullptr) { + ctx.AddInvariantError(name, "SCOPE_NODE_DONT_DOMINATE_VAR_NODE", *node); + isOk = false; } - default: { - return "MUST BE UNREACHABLE"; + const auto &decls = scope->Decls(); + const auto declDominate = std::count(decls.begin(), decls.end(), var->Declaration()); + if (declDominate == 0) { + ctx.AddInvariantError(name, "SCOPE_DECL_DONT_DOMINATE_VAR_DECL", *node); + isOk = false; } + return isOk; } -} -// NOLINTBEGIN(cppcoreguidelines-macro-usage) -#define ADD_CHECK(Name) \ - { \ - const auto check = [this](const ir::AstNode *ast) -> bool { return this->Name(ast); }; \ - checks_.emplace_back(NamedCheck {#Name, check}); \ - allChecks_.insert(#Name); \ - checks_.emplace_back(NamedCheck {#Name "Recursive", RecursiveCheck(check)}); \ - allChecks_.insert(#Name "Recursive"); \ - } -// NOLINTEND(cppcoreguidelines-macro-usage) +private: + ArenaAllocator &allocator_; +}; -bool ASTVerifier::HasParent(const ir::AstNode *ast) -{ - if (ast != nullptr && !ast->IsETSScript() && ast->Parent() == nullptr) { - AddError("NULL_PARENT: " + ToStringHelper(ast), ast->Start()); - return false; - } - - return true; -} - -bool ASTVerifier::HasType(const ir::AstNode *ast) -{ - if (ast->IsTyped() && static_cast(ast)->TsType() == nullptr) { - AddError("NULL_TS_TYPE: " + ToStringHelper(ast), ast->Start()); - return false; - } - return true; -} +class EveryChildHasValidParent { +public: + explicit EveryChildHasValidParent([[maybe_unused]] ArenaAllocator &allocator) {} -bool ASTVerifier::HasVariable(const ir::AstNode *ast) -{ - if (!ast->IsIdentifier() || ast->AsIdentifier()->Variable() != nullptr) { - return true; + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + auto result = ASTVerifier::CheckResult::SUCCESS; + if (ast->IsETSScript()) { + return result; + } + ast->Iterate([&](const ir::AstNode *node) { + if (ast != node->Parent()) { + ctx.AddInvariantError("EveryChildHasValidParent", "INCORRECT_PARENT_REF", *node); + result = ASTVerifier::CheckResult::FAILED; + } + }); + return result; } - const auto *id = ast->AsIdentifier(); - AddError("NULL_VARIABLE: " + ToStringHelper(id), id->Start()); - return false; -} +private: +}; -bool ASTVerifier::HasScope(const ir::AstNode *ast) -{ - if (!ast->IsIdentifier()) { - return true; // we will check only Identifier - } +class VariableHasEnclosingScope { +public: + explicit VariableHasEnclosingScope(ArenaAllocator &allocator) : allocator_ {allocator} {} - // we will check only local variables of identifiers - if (const auto maybeVar = GetLocalScopeVariable(ast)) { + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + const auto maybeVar = VariableHasScope::GetLocalScopeVariable(allocator_, ctx, ast); + if (!maybeVar) { + return ASTVerifier::CheckResult::SUCCESS; + } const auto var = *maybeVar; const auto scope = var->GetScope(); + const auto name = "VariableHasEnclosingScope"; if (scope == nullptr) { - AddError("NULL_SCOPE_LOCAL_VAR: " + ToStringHelper(ast), ast->Start()); - return false; + // already checked + return ASTVerifier::CheckResult::SUCCESS; + } + const auto encloseScope = scope->EnclosingVariableScope(); + if (encloseScope == nullptr) { + ctx.AddInvariantError(name, "NO_ENCLOSING_VAR_SCOPE", *ast); + return ASTVerifier::CheckResult::FAILED; } - return ScopeEncloseVariable(var); + const auto node = scope->Node(); + auto result = ASTVerifier::CheckResult::SUCCESS; + if (!IsContainedIn(ast, node)) { + result = ASTVerifier::CheckResult::FAILED; + ctx.AddInvariantError(name, "VARIABLE_NOT_ENCLOSE_SCOPE", *ast); + } + if (!IsContainedIn(scope, encloseScope)) { + result = ASTVerifier::CheckResult::FAILED; + ctx.AddInvariantError(name, "VARIABLE_NOT_ENCLOSE_SCOPE", *ast); + } + return result; } - return true; -} -std::optional ASTVerifier::GetLocalScopeVariable(const ir::AstNode *ast) -{ - if (!ast->IsIdentifier()) { - return std::nullopt; - } +private: + ArenaAllocator &allocator_; +}; + +class SequenceExpressionHasLastType { +public: + explicit SequenceExpressionHasLastType([[maybe_unused]] ArenaAllocator &allocator) {} - const auto variable = ast->AsIdentifier()->Variable(); - if (HasVariable(ast) && variable->IsLocalVariable()) { - const auto localVar = variable->AsLocalVariable(); - if (localVar->HasFlag(varbinder::VariableFlags::LOCAL)) { - return localVar; + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + if (!ast->IsSequenceExpression()) { + return ASTVerifier::CheckResult::SUCCESS; } + const auto *expr = ast->AsSequenceExpression(); + const auto *last = expr->Sequence().back(); + const auto name = "SequenceExpressionHasLastType"; + if (expr->TsType() == nullptr) { + ctx.AddInvariantError(name, "Sequence expression type is null", *expr); + return ASTVerifier::CheckResult::FAILED; + } + if (last->TsType() == nullptr) { + ctx.AddInvariantError(name, "Sequence expression last type is null", *last); + return ASTVerifier::CheckResult::FAILED; + } + if (expr->TsType() != last->TsType()) { + ctx.AddInvariantError(name, "Sequence expression type and last expression type are not the same", *expr); + return ASTVerifier::CheckResult::FAILED; + } + return ASTVerifier::CheckResult::SUCCESS; } - return std::nullopt; -} -bool ASTVerifier::VerifyChildNode(const ir::AstNode *ast) -{ - ASSERT(ast); - bool isOk = true; - ast->Iterate([&](const auto node) { - if (ast != node->Parent()) { - AddError("INCORRECT_PARENT_REF: " + ToStringHelper(node), node->Start()); - isOk = false; - } - }); - return isOk; -} +private: +}; -bool ASTVerifier::VerifyScopeNode(const ir::AstNode *ast) -{ - ASSERT(ast); - const auto maybeVar = GetLocalScopeVariable(ast); - if (!maybeVar) { - return true; - } - const auto var = *maybeVar; - const auto scope = var->GetScope(); - if (scope == nullptr) { - // already checked - return false; - } - const auto encloseScope = scope->EnclosingVariableScope(); - if (encloseScope == nullptr) { - AddError("NO_ENCLOSING_VAR_SCOPE: " + ToStringHelper(ast), ast->Start()); - return false; - } - const auto node = scope->Node(); - bool isOk = true; - if (!IsContainedIn(ast, node)) { - isOk = false; - AddError("VARIABLE_NOT_ENCLOSE_SCOPE: " + ToStringHelper(ast), ast->Start()); - } - if (!IsContainedIn(scope, encloseScope)) { - isOk = false; - AddError("VARIABLE_NOT_ENCLOSE_SCOPE: " + ToStringHelper(ast), ast->Start()); - } - return isOk; -} +class ForLoopCorrectlyInitialized { +public: + explicit ForLoopCorrectlyInitialized([[maybe_unused]] ArenaAllocator &allocator) {} -bool ASTVerifier::ScopeEncloseVariable(const varbinder::LocalVariable *var) -{ - ASSERT(var); + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + const auto name = "ForLoopCorrectlyInitialized"; + if (ast->IsForInStatement()) { + auto const *left = ast->AsForInStatement()->Left(); + if (left == nullptr) { + ctx.AddInvariantError(name, "NULL FOR-IN-LEFT", *ast); + return ASTVerifier::CheckResult::FAILED; + } - const auto scope = var->GetScope(); - if (scope == nullptr || var->Declaration() == nullptr) { - return true; - } - const auto node = var->Declaration()->Node(); - if (node == nullptr) { - return true; - } - const auto varStart = node->Start(); - bool isOk = true; - if (scope->Bindings().count(var->Name()) == 0) { - AddError("SCOPE_DO_NOT_ENCLOSE_LOCAL_VAR: " + ToStringHelper(node), varStart); - isOk = false; - } - const auto scopeNode = scope->Node(); - auto varNode = node; - if (!IsContainedIn(varNode, scopeNode) || scopeNode == nullptr) { - AddError("SCOPE_NODE_DONT_DOMINATE_VAR_NODE: " + ToStringHelper(node), varStart); - isOk = false; - } - const auto &decls = scope->Decls(); - const auto declDominate = std::count(decls.begin(), decls.end(), var->Declaration()); - if (declDominate == 0) { - AddError("SCOPE_DECL_DONT_DOMINATE_VAR_DECL: " + ToStringHelper(node), varStart); - isOk = false; - } - return isOk; -} + if (!left->IsIdentifier() && !left->IsVariableDeclaration()) { + ctx.AddInvariantError(name, "INCORRECT FOR-IN-LEFT", *ast); + return ASTVerifier::CheckResult::FAILED; + } + } -bool ASTVerifier::CheckArithmeticExpression(const ir::AstNode *ast) -{ - if (ast == nullptr) { - return false; - } + if (ast->IsForOfStatement()) { + auto const *left = ast->AsForOfStatement()->Left(); + if (left == nullptr) { + ctx.AddInvariantError(name, "NULL FOR-OF-LEFT", *ast); + return ASTVerifier::CheckResult::FAILED; + } - if (ast->IsBinaryExpression() && ast->AsBinaryExpression()->IsArithmetic()) { - if (ast->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS && - IsStringType(ast->AsBinaryExpression()->Left()) && IsStringType(ast->AsBinaryExpression()->Right())) { - return true; + if (!left->IsIdentifier() && !left->IsVariableDeclaration()) { + ctx.AddInvariantError(name, "INCORRECT FOR-OF-LEFT", *ast); + return ASTVerifier::CheckResult::FAILED; + } } - bool isCorrect = true; - ast->Iterate([&isCorrect](ir::AstNode *child) { isCorrect &= (IsNumericType(child)); }); - return isCorrect; - } - return true; -} + if (ast->IsForUpdateStatement()) { + // The most important part of for-loop is the test. + // But it also can be null. Then there must be break;(return) in the body. + auto const *test = ast->AsForUpdateStatement()->Test(); + if (test == nullptr) { + auto const *body = ast->AsForUpdateStatement()->Body(); + if (body == nullptr) { + ctx.AddInvariantError(name, "NULL FOR-TEST AND FOR-BODY", *ast); + return ASTVerifier::CheckResult::FAILED; + } + bool hasExit = body->IsBreakStatement() || body->IsReturnStatement(); + body->IterateRecursively([&hasExit](ir::AstNode *child) { + hasExit |= child->IsBreakStatement() || child->IsReturnStatement(); + }); + if (!hasExit) { + // an infinite loop + ctx.AddInvariantError(name, "WARNING: NULL FOR-TEST AND FOR-BODY doesn't exit", *ast); + } + return ASTVerifier::CheckResult::SUCCESS; + } -bool ASTVerifier::IsForLoopCorrectInitialized(const ir::AstNode *ast) -{ - if (ast == nullptr) { - return false; + if (!test->IsExpression()) { + ctx.AddInvariantError(name, "NULL FOR VAR", *ast); + return ASTVerifier::CheckResult::FAILED; + } + } + return ASTVerifier::CheckResult::SUCCESS; } - if (ast->IsForInStatement()) { - auto const *left = ast->AsForInStatement()->Left(); - if (left == nullptr) { - AddError("NULL FOR-IN-LEFT: " + ToStringHelper(ast), ast->Start()); - return false; - } +private: +}; - if (!left->IsIdentifier() && !left->IsVariableDeclaration()) { - AddError("INCORRECT FOR-IN-LEFT: " + ToStringHelper(ast), ast->Start()); - return false; +class ModifierAccessValid { +public: + explicit ModifierAccessValid([[maybe_unused]] ArenaAllocator &allocator) {} + + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + const auto name = "ModifierAccessValid"; + if (ast->IsMemberExpression()) { + const auto *propVar = ast->AsMemberExpression()->PropVar(); + if (propVar != nullptr && propVar->HasFlag(varbinder::VariableFlags::PROPERTY) && + !ValidateVariableAccess(propVar, ast->AsMemberExpression())) { + ctx.AddInvariantError(name, "PROPERTY_NOT_VISIBLE_HERE", *ast); + return ASTVerifier::CheckResult::FAILED; + } + } + if (ast->IsCallExpression()) { + const auto *callExpr = ast->AsCallExpression(); + const auto *callee = callExpr->Callee(); + if (callee != nullptr && callee->IsMemberExpression()) { + const auto *calleeMember = callee->AsMemberExpression(); + const auto *propVarCallee = calleeMember->PropVar(); + if (propVarCallee != nullptr && propVarCallee->HasFlag(varbinder::VariableFlags::METHOD) && + !ValidateMethodAccess(calleeMember, ast->AsCallExpression())) { + ctx.AddInvariantError(name, "PROPERTY_NOT_VISIBLE_HERE", *callee); + return ASTVerifier::CheckResult::FAILED; + } + } } + return ASTVerifier::CheckResult::SUCCESS; + } + +private: +}; + +class ImportExportAccessValid { +public: + explicit ImportExportAccessValid([[maybe_unused]] ArenaAllocator &allocator) {} + + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + ASTVerifier::InvariantSet importedVariables {}; + if (ast->IsETSImportDeclaration()) { + const auto importDecl = ast->AsETSImportDeclaration()->Specifiers(); + const auto name = [](ir::AstNode *const specifier) { + if (specifier->IsImportNamespaceSpecifier()) { + return specifier->AsImportNamespaceSpecifier()->Local()->Name(); + } + if (specifier->IsImportSpecifier()) { + return specifier->AsImportSpecifier()->Local()->Name(); + } + return specifier->AsImportDefaultSpecifier()->Local()->Name(); + }; + for (const auto import : importDecl) { + importedVariables.emplace(name(import)); + } + } + const auto name = "ImportExportAccessValid"; + if (ast->IsCallExpression()) { + const auto *callExpr = ast->AsCallExpression(); + const auto *callee = callExpr->Callee(); + if (callee != nullptr && callee->IsIdentifier() && + !HandleImportExportIdentifier(importedVariables, callee->AsIdentifier(), callExpr)) { + ctx.AddInvariantError(name, "PROPERTY_NOT_VISIBLE_HERE(NOT_EXPORTED)", *callee); + return ASTVerifier::CheckResult::FAILED; + } + } + if (ast->IsIdentifier() && !HandleImportExportIdentifier(importedVariables, ast->AsIdentifier(), nullptr)) { + ctx.AddInvariantError(name, "PROPERTY_NOT_VISIBLE_HERE(NOT_EXPORTED)", *ast); + return ASTVerifier::CheckResult::FAILED; + } + return ASTVerifier::CheckResult::SUCCESS; } - if (ast->IsForOfStatement()) { - auto const *left = ast->AsForOfStatement()->Left(); - if (left == nullptr) { - AddError("NULL FOR-OF-LEFT: " + ToStringHelper(ast), ast->Start()); +private: + bool ValidateExport(const varbinder::Variable *var) + { + const auto *decl = var->Declaration(); + if (decl == nullptr) { return false; } - - if (!left->IsIdentifier() && !left->IsVariableDeclaration()) { - AddError("INCORRECT FOR-OF-LEFT: " + ToStringHelper(ast), ast->Start()); + const auto *node = decl->Node(); + if (node == nullptr) { return false; } + return node->IsExported(); } - if (ast->IsForUpdateStatement()) { - // The most important part of for-loop is the test. - // But it also can be null. Then there must be break;(return) in the body. - auto const *test = ast->AsForUpdateStatement()->Test(); - if (test == nullptr) { - auto const *body = ast->AsForUpdateStatement()->Body(); - if (body == nullptr) { - AddError("NULL FOR-TEST AND FOR-BODY: " + ToStringHelper(ast), ast->Start()); - return false; - } - bool hasExit = body->IsBreakStatement() || body->IsReturnStatement(); - body->IterateRecursively( - [&hasExit](ir::AstNode *child) { hasExit |= child->IsBreakStatement() || child->IsReturnStatement(); }); - if (!hasExit) { - // an infinite loop - AddError("WARNING: NULL FOR-TEST AND FOR-BODY doesn't exit: " + ToStringHelper(ast), ast->Start()); - } + bool InvariantImportExportMethod(const ASTVerifier::InvariantSet &importedVariables, + const varbinder::Variable *varCallee, const ir::AstNode *callExpr, + util::StringView name) + { + auto *signature = callExpr->AsCallExpression()->Signature(); + if (signature->Owner() == nullptr) { + // NOTE(vpukhov): Add a synthetic owner for dynamic signatures + ASSERT(callExpr->AsCallExpression()->Callee()->TsType()->HasTypeFlag(checker::TypeFlag::ETS_DYNAMIC_FLAG)); return true; } - if (test->IsExpression()) { - AddError("NULL FOR VAR: " + ToStringHelper(ast), ast->Start()); + if (signature != nullptr && varCallee->Declaration() != nullptr && + varCallee->Declaration()->Node() != nullptr && + !IsContainedIn(varCallee->Declaration()->Node(), signature->Owner()->GetDeclNode()) && + varCallee->Declaration()->Node() != signature->Owner()->GetDeclNode()) { + if (importedVariables.find(name.Mutf8()) != importedVariables.end() || + importedVariables.find("") != importedVariables.end()) { + return ValidateExport(varCallee); + } return false; } + return true; } - return true; -} - -bool ASTVerifier::AreForLoopsCorrectInitialized(const ir::AstNode *ast) -{ - if (ast == nullptr) { - return false; - } - - bool isForInitialized = IsForLoopCorrectInitialized(ast); - ast->IterateRecursively( - [this, &isForInitialized](ir::AstNode *child) { isForInitialized &= IsForLoopCorrectInitialized(child); }); - return isForInitialized; -} -bool ASTVerifier::VerifyModifierAccess(const ir::AstNode *ast) -{ - if (ast == nullptr) { - return false; - } - if (ast->IsMemberExpression()) { - const auto *propVar = ast->AsMemberExpression()->PropVar(); - if (propVar == nullptr || (propVar->HasFlag(varbinder::VariableFlags::PROPERTY) && - !ValidateVariableAccess(propVar, ast->AsMemberExpression()))) { - AddError("PROPERTY_NOT_VISIBLE_HERE: " + ToStringHelper(ast), ast->Start()); - return false; - } - } - if (ast->IsCallExpression()) { - const auto *callExpr = ast->AsCallExpression(); - const auto *callee = callExpr->Callee(); - if (callee == nullptr) { - return false; - } - if (callee->IsMemberExpression()) { - const auto *calleeMember = callee->AsMemberExpression(); - const auto *propVarCallee = calleeMember->PropVar(); - if (propVarCallee == nullptr || (propVarCallee->HasFlag(varbinder::VariableFlags::METHOD) && - !ValidateMethodAccess(calleeMember, ast->AsCallExpression()))) { - AddError("PROPERTY_NOT_VISIBLE_HERE: " + ToStringHelper(callee), callee->Start()); + bool InvariantImportExportVariable(const ASTVerifier::InvariantSet &importedVariables, + const varbinder::Variable *var, const ir::Identifier *ident, + util::StringView name) + { + if (!var->HasFlag(varbinder::VariableFlags::LOCAL) && !var->HasFlag(varbinder::VariableFlags::VAR) && + var->HasFlag(varbinder::VariableFlags::INITIALIZED) && var->Declaration() != nullptr && + var->Declaration()->Node() != nullptr && !var->Declaration()->Node()->IsMethodDefinition() && + !var->Declaration()->Node()->IsClassProperty()) { + auto varParent = var->Declaration()->Node()->Parent(); + if (varParent != nullptr && !IsContainedIn(ident->Parent(), varParent) && ident->Parent() != varParent) { + if (var->GetScope() != nullptr && var->GetScope()->Parent() != nullptr && + var->GetScope()->Parent()->IsGlobalScope() && + ident->GetTopStatement() == varParent->GetTopStatement()) { + return true; + } + if (importedVariables.find(name.Mutf8()) != importedVariables.end() || + importedVariables.find("") != importedVariables.end()) { + return ValidateExport(var); + } return false; } } + return true; } - return true; -} -bool ASTVerifier::VerifyExportAccess(const ir::AstNode *ast) -{ - if (ast == nullptr) { - return false; - } - if (ast->IsETSImportDeclaration()) { - const auto importDecl = ast->AsETSImportDeclaration()->Specifiers(); - const auto name = [](ir::AstNode *const specifier) { - if (specifier->IsImportNamespaceSpecifier()) { - return specifier->AsImportNamespaceSpecifier()->Local()->Name(); - } - if (specifier->IsImportSpecifier()) { - return specifier->AsImportSpecifier()->Local()->Name(); + bool HandleImportExportIdentifier(ASTVerifier::InvariantSet &importedVariables, const ir::Identifier *ident, + const ir::AstNode *callExpr) + { + if (ident->IsReference()) { + const auto *var = ident->Variable(); + if (var != nullptr) { + if (var->HasFlag(varbinder::VariableFlags::METHOD) && callExpr != nullptr) { + return InvariantImportExportMethod(importedVariables, var, callExpr, ident->Name()); + } + return InvariantImportExportVariable(importedVariables, var, ident, ident->Name()); } - return specifier->AsImportDefaultSpecifier()->Local()->Name(); - }; - for (const auto import : importDecl) { - importedVariables_.emplace(name(import)); } - } - if (ast->IsCallExpression()) { - const auto *callExpr = ast->AsCallExpression(); - const auto *callee = callExpr->Callee(); - if (callee != nullptr && callee->IsIdentifier() && - !HandleImportExportIdentifier(callee->AsIdentifier(), callExpr)) { - AddError("PROPERTY_NOT_VISIBLE_HERE(NOT_EXPORTED): " + ToStringHelper(callee), callee->Start()); - return false; - } - } - if (ast->IsIdentifier() && !HandleImportExportIdentifier(ast->AsIdentifier())) { - AddError("PROPERTY_NOT_VISIBLE_HERE(NOT_EXPORTED): " + ToStringHelper(ast), ast->Start()); - return false; - } - return true; -} - -bool ASTVerifier::CheckImportExportMethod(const varbinder::Variable *varCallee, const ir::AstNode *callExpr, - util::StringView name) -{ - auto *signature = callExpr->AsCallExpression()->Signature(); - if (signature->Owner() == nullptr) { - // NOTE(vpukhov): Add a synthetic owner for dynamic signatures - ASSERT(callExpr->AsCallExpression()->Callee()->TsType()->HasTypeFlag(checker::TypeFlag::ETS_DYNAMIC_FLAG)); return true; } +}; + +class ArithmeticOperationValid { +public: + explicit ArithmeticOperationValid([[maybe_unused]] ArenaAllocator &allocator) {} - if (signature != nullptr && varCallee->Declaration() != nullptr && varCallee->Declaration()->Node() != nullptr && - !IsContainedIn(varCallee->Declaration()->Node(), signature->Owner()->GetDeclNode()) && - varCallee->Declaration()->Node() != signature->Owner()->GetDeclNode()) { - if (importedVariables_.find(name) != importedVariables_.end() || - importedVariables_.find(util::StringView("")) != importedVariables_.end()) { - return ValidateExport(varCallee); + ASTVerifier::CheckResult operator()([[maybe_unused]] ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + if (ast->IsBinaryExpression() && ast->AsBinaryExpression()->IsArithmetic()) { + if (ast->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS && + IsStringType(ast->AsBinaryExpression()->Left()) && IsStringType(ast->AsBinaryExpression()->Right())) { + return ASTVerifier::CheckResult::SUCCESS; + } + auto result = ASTVerifier::CheckResult::SUCCESS; + ast->Iterate([&result](ir::AstNode *child) { + if (!IsNumericType(child)) { + result = ASTVerifier::CheckResult::FAILED; + } + }); + return result; } - return false; + + return ASTVerifier::CheckResult::SUCCESS; } - return true; -} -bool ASTVerifier::CheckImportExportVariable(const varbinder::Variable *var, const ir::Identifier *ident, - util::StringView name) -{ - if (!var->HasFlag(varbinder::VariableFlags::LOCAL) && !var->HasFlag(varbinder::VariableFlags::VAR) && - var->HasFlag(varbinder::VariableFlags::INITIALIZED) && var->Declaration() != nullptr && - var->Declaration()->Node() != nullptr && !var->Declaration()->Node()->IsMethodDefinition() && - !var->Declaration()->Node()->IsClassProperty()) { - auto varParent = var->Declaration()->Node()->Parent(); - if (varParent != nullptr && !IsContainedIn(ident->Parent(), varParent) && ident->Parent() != varParent) { - if (var->GetScope() != nullptr && var->GetScope()->Parent() != nullptr && - var->GetScope()->Parent()->IsGlobalScope() && - ident->GetTopStatement() == varParent->GetTopStatement()) { - return true; +private: +}; + +template +static ASTVerifier::InvariantCheck RecursiveInvariant(const Func &func) +{ + return [func](ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) -> ASTVerifier::CheckResult { + std::function aux; + auto result = ASTVerifier::CheckResult::SUCCESS; + aux = [&ctx, &func, &aux, &result](const ir::AstNode *child) -> void { + if (result == ASTVerifier::CheckResult::FAILED) { + return; } - if (importedVariables_.find(name) != importedVariables_.end() || - importedVariables_.find(util::StringView("")) != importedVariables_.end()) { - return ValidateExport(var); + const auto newResult = func(ctx, child); + if (newResult == ASTVerifier::CheckResult::SKIP_SUBTREE) { + return; } - return false; - } - } - return true; + result = newResult; + child->Iterate(aux); + }; + aux(ast); + return result; + }; } -bool ASTVerifier::HandleImportExportIdentifier(const ir::Identifier *ident, const ir::AstNode *callExpr) +void ASTVerifier::AddInvariant(const std::string &name, const InvariantCheck &invariant) { - if (ident->IsReference()) { - const auto *var = ident->Variable(); - if (var != nullptr) { - if (var->HasFlag(varbinder::VariableFlags::METHOD) && callExpr != nullptr) { - return CheckImportExportMethod(var, callExpr, ident->Name()); - } - return CheckImportExportVariable(var, ident, ident->Name()); - } - } - return true; + invariantsChecks_[name] = invariant; + invariantsNames_.insert(name); + invariantsChecks_[name + RECURSIVE_SUFFIX] = RecursiveInvariant(invariant); + invariantsNames_.insert(name + RECURSIVE_SUFFIX); } -ASTVerifier::ASTVerifier(ArenaAllocator *allocator, bool saveErrors, util::StringView sourceCode) - : saveErrors_(saveErrors), - allocator_ {allocator}, - namedErrors_ {allocator_->Adapter()}, - encounteredErrors_ {allocator_->Adapter()}, - checks_ {allocator_->Adapter()}, - allChecks_(allocator_->Adapter()) +ASTVerifier::ASTVerifier(ArenaAllocator *allocator) { - if (!sourceCode.Empty()) { - index_.emplace(sourceCode); - } - - ADD_CHECK(HasParent); - ADD_CHECK(HasType); - ADD_CHECK(HasVariable); - ADD_CHECK(HasScope); - ADD_CHECK(VerifyChildNode); - ADD_CHECK(VerifyScopeNode); - ADD_CHECK(IsForLoopCorrectInitialized); - ADD_CHECK(AreForLoopsCorrectInitialized); - ADD_CHECK(VerifyModifierAccess); - ADD_CHECK(VerifyExportAccess); - ADD_CHECK(CheckArithmeticExpression); + AddInvariant("NodeHasParent", *allocator->New(*allocator)); + AddInvariant("NodeHasType", *allocator->New(*allocator)); + AddInvariant("IdentifierHasVariable", *allocator->New(*allocator)); + AddInvariant("VariableHasScope", *allocator->New(*allocator)); + AddInvariant("EveryChildHasValidParent", *allocator->New(*allocator)); + AddInvariant("VariableHasEnclosingScope", *allocator->New(*allocator)); + AddInvariant("ForLoopCorrectlyInitialized", *allocator->New(*allocator)); + AddInvariant("ModifierAccessValid", *allocator->New(*allocator)); + AddInvariant("ImportExportAccessValid", *allocator->New(*allocator)); + AddInvariant("ArithmeticOperationValid", *allocator->New(*allocator)); + AddInvariant("SequenceExpressionHasLastType", *allocator->New(*allocator)); } -bool ASTVerifier::VerifyFull(const ir::AstNode *ast) +std::tuple ASTVerifier::VerifyFull( + const std::unordered_set &warnings, const std::unordered_set &asserts, + const ir::AstNode *ast) { - return Verify(ast, allChecks_); + auto recursiveChecks = InvariantSet {}; + std::copy_if(invariantsNames_.begin(), invariantsNames_.end(), + std::inserter(recursiveChecks, recursiveChecks.end()), + [](const std::string &s) { return s.find(RECURSIVE_SUFFIX) != s.npos; }); + return Verify(warnings, asserts, ast, recursiveChecks); } -bool ASTVerifier::Verify(const ir::AstNode *ast, const CheckSet &checkSet) +std::tuple ASTVerifier::Verify( + const std::unordered_set &warnings, const std::unordered_set &asserts, + const ir::AstNode *ast, const InvariantSet &invariantSet) { - bool isCorrect = true; - auto checkAndReport = [&isCorrect, this](util::StringView name, const CheckFunction &check, - const ir::AstNode *node) { - if (node == nullptr) { - return; - } + ErrorContext warningCtx {}; + AssertsContext assertCtx {}; - isCorrect &= check(node); - if (!isCorrect) { - for (const auto &error : encounteredErrors_) { - namedErrors_.emplace_back(NamedError {name, error}); + const auto containsInvariants = + std::includes(invariantsNames_.begin(), invariantsNames_.end(), invariantSet.begin(), invariantSet.end()); + if (!containsInvariants) { + auto invalidInvariants = InvariantSet {}; + for (const auto &invariant : invariantSet) { + if (invariantsNames_.find(invariant) == invariantsNames_.end()) { + invalidInvariants.insert(invariant.data()); } - encounteredErrors_.clear(); } - }; - - const auto containsChecks = std::includes(allChecks_.begin(), allChecks_.end(), checkSet.begin(), checkSet.end()); - if (!containsChecks) { - auto invalidChecks = CheckSet {allocator_->Adapter()}; - for (const auto &check : checkSet) { - if (allChecks_.find(check) == allChecks_.end()) { - invalidChecks.insert(check); - } - } - for (const auto &check : invalidChecks) { - const auto &message = check.Mutf8() + " check is not found"; - namedErrors_.emplace_back(NamedError {"Check", Error {message, lexer::SourceLocation {}}}); + for (const auto &invariant : invalidInvariants) { + assertCtx.AddError(std::string {"invariant was not found: "} + invariant); } } - for (const auto &[name, check] : checks_) { - if (checkSet.find(name) != checkSet.end()) { - checkAndReport(name, check, ast); + for (const auto &invariantName : invariantSet) { + if (warnings.count(invariantName) > 0) { + invariantsChecks_[invariantName](warningCtx, ast); + } else if (asserts.count(invariantName) > 0) { + invariantsChecks_[invariantName](assertCtx, ast); } } - return isCorrect; + + return std::make_tuple(warningCtx.GetErrors(), assertCtx.GetErrors()); } } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/core/ASTVerifier.h b/ets2panda/compiler/core/ASTVerifier.h index b92a55c897dff8af47b716989fda0b863e25b8e4..ba03e4fc8d042098e7ba4e2ceeb9ff356af35a47 100644 --- a/ets2panda/compiler/core/ASTVerifier.h +++ b/ets2panda/compiler/core/ASTVerifier.h @@ -16,106 +16,235 @@ #ifndef ES2PANDA_COMPILER_CORE_ASTVERIFIER_H #define ES2PANDA_COMPILER_CORE_ASTVERIFIER_H +#include +#include +#include +#include +#include + #include "ir/astNode.h" +#include "ir/statements/blockStatement.h" #include "lexer/token/sourceLocation.h" +#include "parser/program/program.h" #include "util/ustring.h" #include "utils/arena_containers.h" +#include "utils/json_builder.h" #include "varbinder/variable.h" namespace panda::es2panda::compiler { +/* + * ASTVerifier used for checking various invariants that should hold during AST transformation in lowerings + * For all available checks lookup the constructor + */ class ASTVerifier final { public: - struct Error { + struct InvariantError { + std::string cause; std::string message; - lexer::SourceLocation location; + size_t line; + }; + struct CheckError { + explicit CheckError(std::string name, InvariantError error) + : invariantName_ {std::move(name)}, error_ {std::move(error)} + { + } + std::function DumpJSON() const + { + return [&](JsonObjectBuilder &body) { + body.AddProperty("invariant", invariantName_); + body.AddProperty("cause", error_.cause); + body.AddProperty("message", error_.message); + body.AddProperty("line", error_.line + 1); + }; + } + const std::string &GetName() const + { + return invariantName_; + } + + private: + std::string invariantName_; + InvariantError error_; + }; + using Errors = std::vector; + + enum class CheckResult { FAILED, SUCCESS, SKIP_SUBTREE }; + class ErrorContext { + public: + explicit ErrorContext() = default; + + void AddError(const std::string &message) + { + errors_.emplace_back(CheckError {"Unnamed", ASTVerifier::InvariantError {message, "", 0}}); + } + + virtual void AddInvariantError(const std::string &name, const std::string &cause, const ir::AstNode &node) + { + errors_.emplace_back( + CheckError {name, ASTVerifier::InvariantError {cause, node.DumpJSON(), node.Start().line}}); + } + + ASTVerifier::Errors GetErrors() + { + return errors_; + } + + private: + Errors errors_; }; - struct NamedError { - util::StringView checkName; - Error error; + + class AssertsContext : public ErrorContext { + public: + void AddInvariantError(const std::string &name, const std::string &cause, const ir::AstNode &node) override + { + ASTVerifier::ErrorContext::AddInvariantError(name, cause, node); + // NOTE(tatiana): add ASSERT here + } }; - using Errors = ArenaVector; - using CheckFunction = std::function; - struct NamedCheck { - util::StringView checkName; - CheckFunction check; + class NoneContext : public ErrorContext { + public: + void AddInvariantError([[maybe_unused]] const std::string &name, [[maybe_unused]] const std::string &cause, + [[maybe_unused]] const ir::AstNode &node) override + { + } }; - using Checks = ArenaVector; + using InvariantCheck = std::function; + struct Invariant { + util::StringView invariantName; + InvariantCheck invariant; + }; + using Invariants = std::map; NO_COPY_SEMANTIC(ASTVerifier); NO_MOVE_SEMANTIC(ASTVerifier); - explicit ASTVerifier(ArenaAllocator *allocator, bool saveErrors = true, util::StringView sourceCode = ""); + explicit ASTVerifier(ArenaAllocator *allocator); ~ASTVerifier() = default; - using CheckSet = ArenaSet; + using InvariantSet = std::unordered_set; /** - * @brief Run all existing checks on some ast node (and consequently it's children) + * @brief Run all existing invariants on some ast node (and consequently it's children) * @param ast AstNode which will be analyzed - * @return bool Result of analysis + * @return Errors report of analysis */ - bool VerifyFull(const ir::AstNode *ast); + std::tuple VerifyFull(const std::unordered_set &warnings, + const std::unordered_set &asserts, + const ir::AstNode *ast); /** - * @brief Run some particular checks on some ast node - * @note Checks must be supplied as strings to check_set, additionally check - * name can be suffixed by `Recursive` string to include recursive analysis of provided node + * @brief Run some particular invariants on some ast node + * @note invariants must be supplied as strings to invariant_set, additionally invariant + * name can be suffixed by `ForAll` string to include recursive analysis of provided node + * I.e. 'HasParent' invariant can be named 'HasParentRecursive' to traverse all child nodes as well * @param ast AstNode which will be analyzed - * @param check_set Set of strings which will be used as check names - * @return bool Result of analysis + * @param invariant_set Set of strings which will be used as invariant names + * @return Errors report of analysis */ - bool Verify(const ir::AstNode *ast, const CheckSet &checkSet); + std::tuple Verify(const std::unordered_set &warnings, + const std::unordered_set &asserts, + const ir::AstNode *ast, + const InvariantSet &invariantSet); - Errors GetErrors() const +private: + void AddInvariant(const std::string &name, const InvariantCheck &invariant); + + Invariants invariantsChecks_; + InvariantSet invariantsNames_; +}; + +class ASTVerifierContext final { +public: + explicit ASTVerifierContext(ASTVerifier &verifier) : verifier_ {verifier} {} + + void IntroduceNewInvariants(util::StringView phaseName) { - return namedErrors_; + auto invariantSet = [phaseName]() -> std::optional { + (void)phaseName; + if (phaseName == "ScopesInitPhase") { + return {{ + "NodeHasParentForAll", + "EveryChildHasValidParentForAll", + "VariableHasScopeForAll", + }}; + } + if (phaseName == "CheckerPhase") { + return {{ + "NodeHasTypeForAll", + "IdentifierHasVariableForAll", + "ArithmeticOperationValidForAll", + "SequenceExpressionHasLastTypeForAll", + "ForLoopCorrectlyInitializedForAll", + "VariableHasEnclosingScopeForAll", + "ModifierAccessValidForAll", + "ImportExportAccessValid", + }}; + } + const std::set withoutAdditionalChecks = {"PromiseVoidInferencePhase", + "StructLowering", + "GenerateTsDeclarationsPhase", + "InterfacePropertyDeclarationsPhase", + "LambdaConstructionPhase", + "ObjectIndexLowering", + "OpAssignmentLowering", + "PromiseVoidInferencePhase", + "TupleLowering", + "UnionLowering", + "ExpandBracketsPhase"}; + if (withoutAdditionalChecks.count(phaseName.Mutf8()) > 0) { + return {{}}; + } + if (phaseName.Utf8().find("plugins") != std::string_view::npos) { + return {{}}; + } + return std::nullopt; + }(); + + ASSERT_PRINT(invariantSet.has_value(), + std::string {"Invariant set does not contain value for "} + phaseName.Mutf8()); + const auto &s = *invariantSet; + accumulatedChecks_.insert(s.begin(), s.end()); } -private: - bool HasParent(const ir::AstNode *ast); - bool HasType(const ir::AstNode *ast); - bool HasVariable(const ir::AstNode *ast); - bool HasScope(const ir::AstNode *ast); - bool VerifyChildNode(const ir::AstNode *ast); - bool VerifyScopeNode(const ir::AstNode *ast); - bool CheckArithmeticExpression(const ir::AstNode *ast); - bool IsForLoopCorrectInitialized(const ir::AstNode *ast); - bool AreForLoopsCorrectInitialized(const ir::AstNode *ast); - bool VerifyModifierAccess(const ir::AstNode *ast); - bool VerifyExportAccess(const ir::AstNode *ast); - - bool HandleImportExportIdentifier(const ir::Identifier *ident, const ir::AstNode *callExpr = nullptr); - bool CheckImportExportVariable(const varbinder::Variable *var, const ir::Identifier *ident, util::StringView name); - bool CheckImportExportMethod(const varbinder::Variable *varCallee, const ir::AstNode *callExpr, - util::StringView name); - - void AddError(const std::string &message, const lexer::SourcePosition &from) + bool Verify(const std::unordered_set &warnings, const std::unordered_set &errors, + const ir::AstNode *ast, util::StringView phaseName, util::StringView sourceName) { - if (saveErrors_) { - const auto loc = index_.has_value() ? index_->GetLocation(from) : lexer::SourceLocation {}; - encounteredErrors_.emplace_back(Error {message, loc}); - } + auto [warns, asserts] = verifier_.Verify(warnings, errors, ast, accumulatedChecks_); + std::for_each(warns.begin(), warns.end(), [this, &sourceName, &phaseName](ASTVerifier::CheckError &e) { + warnings_.Add([e, sourceName, phaseName](JsonObjectBuilder &err) { + err.AddProperty("from", sourceName.Utf8()); + err.AddProperty("phase", phaseName.Utf8()); + err.AddProperty("error", e.DumpJSON()); + }); + }); + std::for_each(asserts.begin(), asserts.end(), [this, &sourceName, &phaseName](ASTVerifier::CheckError &e) { + asserts_.Add([e, sourceName, phaseName](JsonObjectBuilder &err) { + err.AddProperty("from", sourceName.Utf8()); + err.AddProperty("phase", phaseName.Utf8()); + err.AddProperty("error", e.DumpJSON()); + }); + }); + return warns.empty() && asserts.empty(); } - bool ScopeEncloseVariable(const varbinder::LocalVariable *var); - std::optional GetLocalScopeVariable(const ir::AstNode *ast); + std::string DumpWarningsJSON() + { + return std::move(warnings_).Build(); + } + std::string DumpAssertsJSON() + { + return std::move(asserts_).Build(); + } private: - std::optional index_; - - bool saveErrors_; - ArenaAllocator *allocator_; - Errors namedErrors_; - ArenaVector encounteredErrors_; - Checks checks_; - CheckSet allChecks_; - std::unordered_set importedVariables_; + ASTVerifier &verifier_; + JsonArrayBuilder warnings_; + JsonArrayBuilder asserts_; + ASTVerifier::InvariantSet accumulatedChecks_ {}; }; -std::string ToStringHelper(const ir::AstNode *ast); - } // namespace panda::es2panda::compiler #endif // ES2PANDA_COMPILER_CORE_ASTVERIFIER_H diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 2efcab39a748212e7e0e23af88eae3343a80333e..23eba24fc164e62486e9a46335e4aeb13dea7ed4 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -290,6 +290,32 @@ static void CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, etsg->CallDynamic(node, objReg, qnameReg, signature, arguments); } +static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::ETSNewClassInstanceExpression *expr) +{ + if (expr->GetSignature()->RestVar() != nullptr) { + std::size_t const argumentCount = expr->GetArguments().size(); + std::size_t const parameterCount = expr->GetSignature()->MinArgCount(); + ASSERT(argumentCount >= parameterCount); + + auto &arguments = const_cast &>(expr->GetArguments()); + std::size_t i = parameterCount; + + if (i < argumentCount && expr->GetArguments()[i]->IsSpreadElement()) { + arguments[i] = expr->GetArguments()[i]->AsSpreadElement()->Argument(); + } else { + ArenaVector elements(checker->Allocator()->Adapter()); + for (; i < argumentCount; ++i) { + elements.emplace_back(expr->GetArguments()[i]); + } + auto *arrayExpression = checker->AllocNode(std::move(elements), checker->Allocator()); + arrayExpression->SetParent(const_cast(expr)); + arrayExpression->SetTsType(expr->GetSignature()->RestVar()->TsType()); + arguments.erase(expr->GetArguments().begin() + parameterCount, expr->GetArguments().end()); + arguments.emplace_back(arrayExpression); + } + } +} + void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const { ETSGen *etsg = GetETSGen(); @@ -298,6 +324,7 @@ void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const auto *name = expr->GetTypeRef()->AsETSTypeReference()->Part()->Name(); CreateDynamicObject(expr, etsg, objReg, name, expr->signature_, expr->GetArguments()); } else { + ConvertRestArguments(const_cast(etsg->Checker()->AsETSChecker()), expr); etsg->InitObject(expr, expr->signature_, expr->GetArguments()); } @@ -523,9 +550,83 @@ static void CompileLogical(compiler::ETSGen *etsg, const ir::BinaryExpression *e etsg->SetAccumulatorType(expr->TsType()); } +std::map &GetBigintSignatures() +{ + static std::map bigintSignatures = { + {lexer::TokenType::PUNCTUATOR_PLUS, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_ADD}, + {lexer::TokenType::PUNCTUATOR_MINUS, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_SUBTRACT}, + {lexer::TokenType::PUNCTUATOR_MULTIPLY, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_MULTIPLY}, + {lexer::TokenType::PUNCTUATOR_DIVIDE, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_DIVIDE}, + {lexer::TokenType::PUNCTUATOR_MOD, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_MODULE}, + {lexer::TokenType::PUNCTUATOR_BITWISE_OR, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_BITWISE_OR}, + {lexer::TokenType::PUNCTUATOR_BITWISE_AND, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_BITWISE_AND}, + {lexer::TokenType::PUNCTUATOR_BITWISE_XOR, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_BITWISE_XOR}, + {lexer::TokenType::PUNCTUATOR_LEFT_SHIFT, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LEFT_SHIFT}, + {lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_RIGHT_SHIFT}, + {lexer::TokenType::PUNCTUATOR_GREATER_THAN, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN}, + {lexer::TokenType::PUNCTUATOR_LESS_THAN, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN}, + {lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL, + compiler::Signatures::BUILTIN_BIGINT_OPERATOR_GREATER_THAN_EQUAL}, + {lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_LESS_THAN_EQUAL}, + }; + + return bigintSignatures; +} + +static bool CompileBigInt(compiler::ETSGen *etsg, const ir::BinaryExpression *expr) +{ + if ((expr->Left()->TsType() == nullptr) || (expr->Right()->TsType() == nullptr)) { + return false; + } + + if (!expr->Left()->TsType()->IsETSBigIntType()) { + return false; + } + + if (!expr->Right()->TsType()->IsETSBigIntType()) { + return false; + } + + auto map = GetBigintSignatures(); + if (map.find(expr->OperatorType()) == map.end()) { + return false; + } + + const checker::Type *operationType = expr->OperationType(); + auto ttctx = compiler::TargetTypeContext(etsg, operationType); + compiler::RegScope rs(etsg); + compiler::VReg lhs = etsg->AllocReg(); + expr->Left()->Compile(etsg); + etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, operationType); + expr->Right()->Compile(etsg); + etsg->ApplyConversion(expr->Right(), operationType); + compiler::VReg rhs = etsg->AllocReg(); + etsg->StoreAccumulator(expr, rhs); + + std::string_view signature = map.at(expr->OperatorType()); + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_GREATER_THAN: + case lexer::TokenType::PUNCTUATOR_LESS_THAN: + case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: + case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: + etsg->CallBigIntBinaryComparison(expr, lhs, rhs, signature); + break; + default: + etsg->CallBigIntBinaryOperator(expr, lhs, rhs, signature); + break; + } + + return true; +} + void ETSCompiler::Compile(const ir::BinaryExpression *expr) const { ETSGen *etsg = GetETSGen(); + + if (CompileBigInt(etsg, expr)) { + return; + } + if (etsg->TryLoadConstantExpression(expr)) { return; } @@ -551,8 +652,7 @@ void ETSCompiler::Compile(const ir::BinaryExpression *expr) const etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType()); expr->Right()->Compile(etsg); etsg->ApplyConversion(expr->Right(), expr->OperationType()); - if (expr->OperatorType() >= lexer::TokenType::PUNCTUATOR_LEFT_SHIFT && - expr->OperatorType() <= lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT) { + if (expr->OperationType()->IsIntType()) { etsg->ApplyCast(expr->Right(), expr->OperationType()); } @@ -788,7 +888,11 @@ void ETSCompiler::Compile(const ir::ConditionalExpression *expr) const expr->Alternate()->Compile(etsg); etsg->ApplyConversion(expr->Alternate()); etsg->SetLabel(expr, endLabel); - etsg->SetAccumulatorType(expr->TsType()); + if (expr->TsType()->IsETSUnionType()) { + etsg->SetAccumulatorType(expr->TsType()->AsETSUnionType()->GetLeastUpperBoundType()); + } else { + etsg->SetAccumulatorType(expr->TsType()); + } } void ETSCompiler::Compile([[maybe_unused]] const ir::DirectEvalExpression *expr) const @@ -1064,7 +1168,13 @@ void ETSCompiler::Compile(const ir::UnaryExpression *expr) const if (!etsg->TryLoadConstantExpression(expr->Argument())) { expr->Argument()->Compile(etsg); } + etsg->ApplyConversion(expr->Argument(), nullptr); + + if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_TILDE) { + etsg->ApplyCast(expr->Argument(), expr->TsType()); + } + etsg->Unary(expr, expr->OperatorType()); } @@ -1083,7 +1193,16 @@ void ETSCompiler::Compile(const ir::UpdateExpression *expr) const lref.GetValue(); expr->Argument()->SetBoxingUnboxingFlags(argumentUnboxingFlags); etsg->ApplyConversion(expr->Argument(), nullptr); - etsg->Update(expr, expr->OperatorType()); + + if (expr->Argument()->TsType()->IsETSBigIntType()) { + compiler::RegScope rs(etsg); + compiler::VReg valueReg = etsg->AllocReg(); + etsg->StoreAccumulator(expr->Argument(), valueReg); + etsg->UpdateBigInt(expr, valueReg, expr->OperatorType()); + } else { + etsg->Update(expr, expr->OperatorType()); + } + expr->Argument()->SetBoxingUnboxingFlags(argumentBoxingFlags); etsg->ApplyConversion(expr->Argument(), expr->Argument()->TsType()); lref.SetValue(); @@ -1100,7 +1219,12 @@ void ETSCompiler::Compile(const ir::UpdateExpression *expr) const expr->Argument()->SetBoxingUnboxingFlags(argumentUnboxingFlags); etsg->ApplyConversion(expr->Argument(), nullptr); - etsg->Update(expr, expr->OperatorType()); + + if (expr->Argument()->TsType()->IsETSBigIntType()) { + etsg->UpdateBigInt(expr, originalValueReg, expr->OperatorType()); + } else { + etsg->Update(expr, expr->OperatorType()); + } expr->Argument()->SetBoxingUnboxingFlags(argumentBoxingFlags); etsg->ApplyConversion(expr->Argument(), expr->Argument()->TsType()); @@ -1116,7 +1240,13 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::YieldExpression *expr) cons // compile methods for LITERAL EXPRESSIONS in alphabetical order void ETSCompiler::Compile([[maybe_unused]] const ir::BigIntLiteral *expr) const { - UNREACHABLE(); + ETSGen *etsg = GetETSGen(); + compiler::TargetTypeContext ttctx = compiler::TargetTypeContext(etsg, expr->TsType()); + compiler::RegScope rs {etsg}; + etsg->LoadAccumulatorBigInt(expr, expr->Str()); + const compiler::VReg value = etsg->AllocReg(); + etsg->StoreAccumulator(expr, value); + etsg->CreateBigIntObject(expr, value); } void ETSCompiler::Compile(const ir::BooleanLiteral *expr) const diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 9603461920f60c560ea4dc739ebc7265f423bd9a..f4718ce80bdace2ae58f7e0798ca4f626ad54025 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -611,6 +611,11 @@ void ETSGen::LoadThis(const ir::AstNode *node) LoadAccumulator(node, GetThisReg()); } +void ETSGen::CreateBigIntObject(const ir::AstNode *node, VReg arg0) +{ + Ra().Emit(node, Signatures::BUILTIN_BIGINT_CTOR, arg0, dummyReg_); +} + void ETSGen::CreateLambdaObjectFromIdentReference(const ir::AstNode *node, ir::ClassDefinition *lambdaObj) { auto *ctor = lambdaObj->TsType()->AsETSObjectType()->ConstructSignatures()[0]; @@ -836,6 +841,10 @@ void ETSGen::CheckedReferenceNarrowing(const ir::AstNode *node, const checker::T { ASSERT(target->HasTypeFlag(TYPE_FLAG_BYTECODE_REF) && !target->IsETSNullLike()); // NOTE(vpukhov): implement for nulllike and union targets + if (target == Checker()->GlobalETSNullishObjectType()) { + SetAccumulatorType(target); + return; + } Sa().Emit(node, ToAssemblerType(target)); SetAccumulatorType(target); @@ -851,6 +860,19 @@ void ETSGen::GuardUncheckedType(const ir::AstNode *node, const checker::Type *un } } +void ETSGen::LoadConstantObject(const ir::Expression *node, const checker::Type *type) +{ + if (type->HasTypeFlag(checker::TypeFlag::BIGINT_LITERAL)) { + LoadAccumulatorBigInt(node, type->AsETSObjectType()->AsETSBigIntType()->GetValue()); + const VReg value = AllocReg(); + StoreAccumulator(node, value); + CreateBigIntObject(node, value); + } else { + LoadAccumulatorString(node, type->AsETSObjectType()->AsETSStringType()->GetValue()); + SetAccumulatorType(node->TsType()); + } +} + bool ETSGen::TryLoadConstantExpression(const ir::Expression *node) { const auto *type = node->TsType(); @@ -895,8 +917,7 @@ bool ETSGen::TryLoadConstantExpression(const ir::Expression *node) break; } case checker::TypeFlag::ETS_OBJECT: { - LoadAccumulatorString(node, type->AsETSObjectType()->AsETSStringType()->GetValue()); - SetAccumulatorType(node->TsType()); + LoadConstantObject(node, type); break; } default: { @@ -1612,7 +1633,7 @@ void ETSGen::CastToArrayOrObject(const ir::AstNode *const node, const checker::T return; } - if (targetType->IsETSTypeParameter() && targetType->AsETSTypeParameter()->HasConstraint()) { + if (targetType->IsETSTypeParameter()) { CheckedReferenceNarrowing(node, targetType->AsETSTypeParameter()->GetConstraintType()); } else if (targetType->IsETSObjectType()) { CheckedReferenceNarrowing(node, targetType->AsETSObjectType()->GetConstOriginalBaseType()); @@ -2134,7 +2155,10 @@ void ETSGen::BinaryEqualityRef(const ir::AstNode *node, bool testEqual, VReg lhs StoreAccumulator(node, rhs); LoadAccumulator(node, lhs); - if (GetVRegType(lhs)->IsETSStringType()) { + + if (GetVRegType(lhs)->IsETSBigIntType()) { + CallThisStatic1(node, lhs, Signatures::BUILTIN_BIGINT_EQUALS, rhs); + } else if (GetVRegType(lhs)->IsETSStringType()) { CallThisStatic1(node, lhs, Signatures::BUILTIN_STRING_EQUALS, rhs); } else { CallThisVirtual1(node, lhs, Signatures::BUILTIN_OBJECT_EQUALS, rhs); @@ -2227,6 +2251,13 @@ void ETSGen::Unary(const ir::AstNode *node, lexer::TokenType op) void ETSGen::UnaryMinus(const ir::AstNode *node) { + if (GetAccumulatorType()->IsETSBigIntType()) { + const VReg value = AllocReg(); + StoreAccumulator(node, value); + CallThisStatic0(node, value, Signatures::BUILTIN_BIGINT_NEGATE); + return; + } + switch (checker::ETSChecker::ETSType(GetAccumulatorType())) { case checker::TypeFlag::LONG: { Sa().Emit(node); @@ -2255,6 +2286,14 @@ void ETSGen::UnaryMinus(const ir::AstNode *node) void ETSGen::UnaryTilde(const ir::AstNode *node) { + if (GetAccumulatorType()->IsETSBigIntType()) { + const VReg value = AllocReg(); + StoreAccumulator(node, value); + CallThisStatic0(node, value, Signatures::BUILTIN_BIGINT_OPERATOR_BITWISE_NOT); + SetAccumulatorType(Checker()->GlobalETSBigIntType()); + return; + } + switch (checker::ETSChecker::ETSType(GetAccumulatorType())) { case checker::TypeFlag::LONG: { Sa().Emit(node); @@ -2299,6 +2338,23 @@ void ETSGen::Update(const ir::AstNode *node, lexer::TokenType op) } } +void ETSGen::UpdateBigInt(const ir::Expression *node, VReg arg, lexer::TokenType op) +{ + switch (op) { + case lexer::TokenType::PUNCTUATOR_PLUS_PLUS: { + CallBigIntUnaryOperator(node, arg, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_INCREMENT); + break; + } + case lexer::TokenType::PUNCTUATOR_MINUS_MINUS: { + CallBigIntUnaryOperator(node, arg, compiler::Signatures::BUILTIN_BIGINT_OPERATOR_DECREMENT); + break; + } + default: { + UNREACHABLE(); + } + } +} + void ETSGen::StringBuilderAppend(const ir::AstNode *node, VReg builder) { RegScope rs(this); @@ -2390,6 +2446,28 @@ void ETSGen::BuildString(const ir::Expression *node) SetAccumulatorType(node->TsType()); } +void ETSGen::CallBigIntUnaryOperator(const ir::Expression *node, VReg arg, const util::StringView signature) +{ + LoadAccumulator(node, arg); + CallThisStatic0(node, arg, signature); + SetAccumulatorType(Checker()->GlobalETSBigIntType()); +} + +void ETSGen::CallBigIntBinaryOperator(const ir::Expression *node, VReg lhs, VReg rhs, const util::StringView signature) +{ + LoadAccumulator(node, lhs); + CallThisStatic1(node, lhs, signature, rhs); + SetAccumulatorType(Checker()->GlobalETSBigIntType()); +} + +void ETSGen::CallBigIntBinaryComparison(const ir::Expression *node, VReg lhs, VReg rhs, + const util::StringView signature) +{ + LoadAccumulator(node, lhs); + CallThisStatic1(node, lhs, signature, rhs); + SetAccumulatorType(Checker()->GlobalETSBooleanType()); +} + void ETSGen::BuildTemplateString(const ir::TemplateLiteral *node) { RegScope rs(this); diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index bc9fc3dc799ef746e280c673ea5fbe6556631fed..248607444e353b7e167a1750f8ba81d4fe8e8e51 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -96,6 +96,7 @@ public: void Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs); void Unary(const ir::AstNode *node, lexer::TokenType op); void Update(const ir::AstNode *node, lexer::TokenType op); + void UpdateBigInt(const ir::Expression *node, VReg arg, lexer::TokenType op); bool TryLoadConstantExpression(const ir::Expression *node); void Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, Label *ifFalse); @@ -385,6 +386,12 @@ public: SetAccumulatorType(Checker()->GlobalETSStringLiteralType()); } + void LoadAccumulatorBigInt(const ir::AstNode *node, util::StringView str) + { + Sa().Emit(node, str); + SetAccumulatorType(Checker()->GlobalETSBigIntType()); + } + void LoadAccumulatorNull(const ir::AstNode *node, const checker::Type *type) { Sa().Emit(node); @@ -548,6 +555,9 @@ public: void NewArray(const ir::AstNode *node, VReg arr, VReg dim, const checker::Type *arrType); void NewObject(const ir::AstNode *node, VReg ctor, util::StringView name); void BuildString(const ir::Expression *node); + void CallBigIntUnaryOperator(const ir::Expression *node, VReg arg, util::StringView signature); + void CallBigIntBinaryOperator(const ir::Expression *node, VReg lhs, VReg rhs, util::StringView signature); + void CallBigIntBinaryComparison(const ir::Expression *node, VReg lhs, VReg rhs, util::StringView signature); void BuildTemplateString(const ir::TemplateLiteral *node); void InitObject(const ir::AstNode *node, checker::Signature *signature, const ArenaVector &arguments) @@ -632,6 +642,7 @@ public: } #endif // PANDA_WITH_ETS + void CreateBigIntObject(const ir::AstNode *node, VReg arg0); void CreateLambdaObjectFromIdentReference(const ir::AstNode *node, ir::ClassDefinition *lambdaObj); void CreateLambdaObjectFromMemberReference(const ir::AstNode *node, ir::Expression *obj, ir::ClassDefinition *lambdaObj); @@ -658,6 +669,7 @@ private: void EmitUnboxedCall(const ir::AstNode *node, std::string_view signatureFlag, const checker::Type *targetType, const checker::Type *boxedType); + void LoadConstantObject(const ir::Expression *node, const checker::Type *type); void StringBuilderAppend(const ir::AstNode *node, VReg builder); void AppendString(const ir::Expression *binExpr, VReg builder); void StringBuilder(const ir::Expression *left, const ir::Expression *right, VReg builder); @@ -837,6 +849,7 @@ private: case checker::TypeFlag::ETS_BOOLEAN: case checker::TypeFlag::BYTE: case checker::TypeFlag::SHORT: + case checker::TypeFlag::CHAR: case checker::TypeFlag::INT: { Ra().Emit(node, lhs, ifFalse); break; diff --git a/ets2panda/compiler/core/ETSfunction.cpp b/ets2panda/compiler/core/ETSfunction.cpp index 485a647a7ea292bc6cf99ba620366351530b5fc4..4ec98c2858db3109db2cc88fe417cdfd5ff01dd8 100644 --- a/ets2panda/compiler/core/ETSfunction.cpp +++ b/ets2panda/compiler/core/ETSfunction.cpp @@ -146,6 +146,12 @@ void ETSFunction::CompileSourceBlock(ETSGen *etsg, const ir::BlockStatement *blo void ETSFunction::CompileFunction(ETSGen *etsg) { + const auto *decl = etsg->RootNode()->AsScriptFunction(); + + if (decl->IsDeclare()) { + return; + } + CompileSourceBlock(etsg, etsg->RootNode()->AsScriptFunction()->Body()->AsBlockStatement()); } diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 3ecab6a0b2b0e5950d3f56b54dc45c292a13b083..22236922968d9f9d8726f0b5c7a09188e09c1b01 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -15,6 +15,7 @@ #include "compilerImpl.h" +#include "compiler/core/ASTVerifier.h" #include "es2panda.h" #include "checker/ETSAnalyzer.h" #include "checker/TSAnalyzer.h" @@ -129,6 +130,9 @@ static pandasm::Program *CreateCompiler(const CompilationUnit &unit, const Phase context.SetEmitter(&emitter); context.SetParser(&parser); + auto verifier = ASTVerifier {&allocator}; + auto verificationCtx = ASTVerifierContext {verifier}; + public_lib::Context publicContext; SetupPublicContext(&publicContext, &unit.input, &allocator, compilerImpl->Queue(), &compilerImpl->Plugins(), &parser, &context); @@ -142,7 +146,37 @@ static pandasm::Program *CreateCompiler(const CompilationUnit &unit, const Phase if (!phase->Apply(&publicContext, &program)) { return nullptr; } +#ifndef NDEBUG + using NamedProgram = std::tuple; + ArenaVector toCheck {program.Allocator()->Adapter()}; + toCheck.push_back(std::make_tuple(program.SourceFilePath(), &program)); + for (const auto &externalSource : program.ExternalSources()) { + for (const auto *external : externalSource.second) { + toCheck.push_back(std::make_tuple(external->SourceFilePath(), external)); + } + } + for (const auto &it : toCheck) { + const auto &sourceName = std::get<0>(it); + const auto &linkedProgram = std::get<1>(it); + verificationCtx.Verify(context.Options()->verifierWarnings, context.Options()->verifierErrors, + linkedProgram->Ast(), phase->Name(), sourceName); + verificationCtx.IntroduceNewInvariants(phase->Name()); + } +#endif + } + +#ifndef NDEBUG + if (!context.Options()->verifierWarnings.empty()) { + if (auto errors = verificationCtx.DumpWarningsJSON(); errors != "[]") { + LOG(ERROR, ES2PANDA) << errors; + } + } + if (!context.Options()->verifierErrors.empty()) { + if (auto errors = verificationCtx.DumpAssertsJSON(); errors != "[]") { + ASSERT_PRINT(false, errors); + } } +#endif emitter.GenAnnotation(); diff --git a/ets2panda/compiler/lowering/checkerPhase.cpp b/ets2panda/compiler/lowering/checkerPhase.cpp index d807337a65e9ac7b15bd17ba064f70fb940603c7..4b0fdd14d3754493fa21b689ae3d5f4239abf72a 100644 --- a/ets2panda/compiler/lowering/checkerPhase.cpp +++ b/ets2panda/compiler/lowering/checkerPhase.cpp @@ -15,6 +15,7 @@ #include "checkerPhase.h" #include "checker/checker.h" +#include "compiler/core/ASTVerifier.h" #include "compiler/core/compilerContext.h" namespace panda::es2panda::compiler { diff --git a/ets2panda/compiler/lowering/checkerPhase.h b/ets2panda/compiler/lowering/checkerPhase.h index ef42e7004bac3154dedd78a1dd44ece3f79e51a5..cc374cbfb494204ba7b2356063f4d6cf4ab37366 100644 --- a/ets2panda/compiler/lowering/checkerPhase.h +++ b/ets2panda/compiler/lowering/checkerPhase.h @@ -22,7 +22,7 @@ namespace panda::es2panda::compiler { class CheckerPhase : public Phase { std::string_view Name() override { - return "checker"; + return "CheckerPhase"; } bool Perform(public_lib::Context *ctx, parser::Program *program) override; diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.cpp b/ets2panda/compiler/lowering/ets/expandBrackets.cpp index f36e6ea3761330da54f6927bb88d87ff5ec4879b..d4991c1646b85c87c78c7fca5ef55c1db6f81eb2 100644 --- a/ets2panda/compiler/lowering/ets/expandBrackets.cpp +++ b/ets2panda/compiler/lowering/ets/expandBrackets.cpp @@ -63,7 +63,7 @@ bool ExpandBracketsPhase::Perform(public_lib::Context *ctx, parser::Program *pro "(@@E5);", parser::DEFAULT_SOURCE_FILE, ident, dimension, exprType, ident->Clone(allocator), newExpression); sequenceExpr->SetParent(newExpression->Parent()); - ScopesInitPhaseETS::RunExternalNode(sequenceExpr, ctx->compilerContext->VarBinder()); + InitScopesPhaseETS::RunExternalNode(sequenceExpr, ctx->compilerContext->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(sequenceExpr, scope); sequenceExpr->Check(checker); diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.h b/ets2panda/compiler/lowering/ets/expandBrackets.h index 7a771f078982b73eb9509deb771eb1f6f3d69828..30d664848f92eedde96092cc1e8761cb8b45f1c7 100644 --- a/ets2panda/compiler/lowering/ets/expandBrackets.h +++ b/ets2panda/compiler/lowering/ets/expandBrackets.h @@ -24,8 +24,9 @@ class ExpandBracketsPhase : public Phase { public: std::string_view Name() override { - return "expand-brackets"; + return "ExpandBracketsPhase"; } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; }; diff --git a/ets2panda/compiler/lowering/ets/generateDeclarations.cpp b/ets2panda/compiler/lowering/ets/generateDeclarations.cpp index ef7fb21ec26d9f34b3cb64d2d6e5283f50c324f2..9bf8336ea66fc33172fcc11543ea0ac4e7d73d44 100644 --- a/ets2panda/compiler/lowering/ets/generateDeclarations.cpp +++ b/ets2panda/compiler/lowering/ets/generateDeclarations.cpp @@ -15,10 +15,12 @@ #include "generateDeclarations.h" #include "checker/checker.h" +#include "compiler/core/ASTVerifier.h" #include "compiler/core/compilerContext.h" #include "util/declgenEts2Ts.h" namespace panda::es2panda::compiler { + bool GenerateTsDeclarationsPhase::Perform(public_lib::Context *ctx, parser::Program *program) { auto *checker = ctx->checker; diff --git a/ets2panda/compiler/lowering/ets/generateDeclarations.h b/ets2panda/compiler/lowering/ets/generateDeclarations.h index 15ab3c61ef11d7d8962e305089a076684093a707..ad6b23c6000cd93e5982ca63a2c6881dc74a72e8 100644 --- a/ets2panda/compiler/lowering/ets/generateDeclarations.h +++ b/ets2panda/compiler/lowering/ets/generateDeclarations.h @@ -24,8 +24,9 @@ class GenerateTsDeclarationsPhase : public Phase { public: std::string_view Name() override { - return "generate-ts-declarations"; + return "GenerateTsDeclarationsPhase"; } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; }; diff --git a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp index e84d17cd12573862680975158299e06ab8d30b54..9c7779af86c58e2656458acd9842878048e974c0 100644 --- a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp +++ b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp @@ -17,6 +17,7 @@ #include "checker/ETSchecker.h" #include "checker/types/type.h" +#include "compiler/core/ASTVerifier.h" #include "compiler/core/compilerContext.h" #include "compiler/lowering/util.h" #include "ir/astNode.h" @@ -28,12 +29,6 @@ #include "ir/base/classProperty.h" namespace panda::es2panda::compiler { - -std::string_view InterfacePropertyDeclarationsPhase::Name() -{ - return "interface-prop-decl"; -} - static ir::MethodDefinition *GenerateGetterOrSetter(checker::ETSChecker *const checker, ir::ClassProperty *const field, bool isSetter) { diff --git a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.h b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.h index 866fc16b56593851e79cac23bbc4e4d11978ce93..ddfbce241a919a67f2c7bf024261bf090f2c7d91 100644 --- a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.h +++ b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.h @@ -22,7 +22,11 @@ namespace panda::es2panda::compiler { class InterfacePropertyDeclarationsPhase : public Phase { public: - std::string_view Name() override; + std::string_view Name() override + { + return "InterfacePropertyDeclarationsPhase"; + } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; }; diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index dc9ed7d0ac6085e2f931ea36f316bc341325fd9b..f573c8d6786a3b82c1f1df7729fbc08fcc88f226 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -15,16 +15,11 @@ #include "lambdaLowering.h" #include "checker/checker.h" +#include "compiler/core/ASTVerifier.h" #include "compiler/core/compilerContext.h" #include "util/declgenEts2Ts.h" namespace panda::es2panda::compiler { - -std::string_view LambdaLowering::Name() -{ - return "lambda-lowering"; -} - static ir::AstNode *ConvertExpression(checker::ETSChecker *const checker, ir::ArrowFunctionExpression *const arrow) { auto *const function = arrow->Function(); @@ -43,7 +38,7 @@ static ir::AstNode *ConvertExpression(checker::ETSChecker *const checker, ir::Ar return arrow; } -bool LambdaLowering::Perform(public_lib::Context *ctx, parser::Program *program) +bool LambdaConstructionPhase::Perform(public_lib::Context *ctx, parser::Program *program) { for (auto &[_, ext_programs] : program->ExternalSources()) { (void)_; @@ -66,7 +61,7 @@ bool LambdaLowering::Perform(public_lib::Context *ctx, parser::Program *program) return true; } -bool LambdaLowering::Postcondition(public_lib::Context *ctx, const parser::Program *program) +bool LambdaConstructionPhase::Postcondition(public_lib::Context *ctx, const parser::Program *program) { for (auto &[_, ext_programs] : program->ExternalSources()) { (void)_; diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.h b/ets2panda/compiler/lowering/ets/lambdaLowering.h index c06a4cd3fafc2cd822724b85910d84ea99747a0b..f30f8eb81a3bafe00fb34c075ffcc6b81719200a 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.h +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.h @@ -20,9 +20,13 @@ namespace panda::es2panda::compiler { -class LambdaLowering : public Phase { +class LambdaConstructionPhase : public Phase { public: - std::string_view Name() override; + std::string_view Name() override + { + return "LambdaConstructionPhase"; + } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; }; diff --git a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp index 085150e5c42edf5fec00b29192092ce7f0c98efa..95fbc98ad5180a62d82945191625cc558387fc5c 100644 --- a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp +++ b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp @@ -24,16 +24,10 @@ #include "objectIndexAccess.h" #include "checker/ETSchecker.h" +#include "compiler/core/ASTVerifier.h" #include "parser/ETSparser.h" namespace panda::es2panda::compiler { - -std::string_view ObjectIndexLowering::Name() -{ - static std::string const NAME = "object-index-access"; - return NAME; -} - ir::Expression *ObjectIndexLowering::ProcessIndexSetAccess(parser::ETSParser *parser, checker::ETSChecker *checker, ir::AssignmentExpression *assignmentExpression) const { diff --git a/ets2panda/compiler/lowering/ets/objectIndexAccess.h b/ets2panda/compiler/lowering/ets/objectIndexAccess.h index 13513caa7cf4c5ab60fb92d5e370b79462c9b405..63f88b1846ee8734a16d297c98b5e7e0bab4d735 100644 --- a/ets2panda/compiler/lowering/ets/objectIndexAccess.h +++ b/ets2panda/compiler/lowering/ets/objectIndexAccess.h @@ -27,7 +27,11 @@ namespace panda::es2panda::compiler { class ObjectIndexLowering : public Phase { public: - std::string_view Name() override; + std::string_view Name() override + { + return "ObjectIndexLowering"; + } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; diff --git a/ets2panda/compiler/lowering/ets/opAssignment.cpp b/ets2panda/compiler/lowering/ets/opAssignment.cpp index e15cc8fda694517475d56b8d059c79232ae38bdf..b3c20d48559d51eced9bbd686999c4f9545b9b1c 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.cpp +++ b/ets2panda/compiler/lowering/ets/opAssignment.cpp @@ -38,11 +38,6 @@ namespace panda::es2panda::compiler { -std::string_view OpAssignmentLowering::Name() -{ - return "op-assignment"; -} - struct Conversion { lexer::TokenType from; lexer::TokenType to; @@ -176,7 +171,7 @@ ir::Expression *HandleOpAssignment(public_lib::Context *ctx, checker::ETSChecker ident1->Clone(allocator), ident2 != nullptr ? ident2->Clone(allocator) : nullptr, ident1->Clone(allocator), ident2 != nullptr ? ident2->Clone(allocator) : nullptr, right, exprType); loweringResult->SetParent(assignment->Parent()); - ScopesInitPhaseETS::RunExternalNode(loweringResult, ctx->compilerContext->VarBinder()); + InitScopesPhaseETS::RunExternalNode(loweringResult, ctx->compilerContext->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(loweringResult, scope); loweringResult->Check(checker); diff --git a/ets2panda/compiler/lowering/ets/opAssignment.h b/ets2panda/compiler/lowering/ets/opAssignment.h index 407d558a2e32051fa9ed61591cee17172df188d2..7a098a0544982dc4947d95fd9f61e9204b88797a 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.h +++ b/ets2panda/compiler/lowering/ets/opAssignment.h @@ -22,7 +22,11 @@ namespace panda::es2panda::compiler { class OpAssignmentLowering : public Phase { public: - std::string_view Name() override; + std::string_view Name() override + { + return "OpAssignmentLowering"; + } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; }; diff --git a/ets2panda/compiler/lowering/ets/promiseVoid.cpp b/ets2panda/compiler/lowering/ets/promiseVoid.cpp index 53aec6ca70684d334f15a5896ce3d4a0548a5aaf..aed5157435d536cbce8888c03d11e9ab9594c95a 100644 --- a/ets2panda/compiler/lowering/ets/promiseVoid.cpp +++ b/ets2panda/compiler/lowering/ets/promiseVoid.cpp @@ -16,6 +16,7 @@ #include "promiseVoid.h" #include "checker/ETSchecker.h" #include "checker/checker.h" +#include "compiler/core/ASTVerifier.h" #include "compiler/core/compilerContext.h" #include "generated/signatures.h" #include "ir/base/scriptFunction.h" @@ -31,13 +32,6 @@ #include "util/ustring.h" namespace panda::es2panda::compiler { - -std::string_view PromiseVoidLowering::Name() -{ - static std::string const NAME = "promise-void"; - return NAME; -} - static ir::BlockStatement *HandleAsyncScriptFunctionBody(checker::ETSChecker *checker, ir::BlockStatement *body) { (void)checker; @@ -128,7 +122,16 @@ static bool CheckForPromiseVoid(const ir::TypeNode *type) return isTypePromise && isParamVoid; } -bool PromiseVoidLowering::Perform(public_lib::Context *ctx, parser::Program *program) +/* + * Transformation is basically syntactical: it adds relevant return type and return statements to methods and function + * NOTE: but not for lambdas, at least for now + * So, the code + * async function f() {} + * transforms to + * async function f(): Promise { return Void; } + * */ + +bool PromiseVoidInferencePhase::Perform(public_lib::Context *ctx, parser::Program *program) { auto *checker = ctx->checker->AsETSChecker(); @@ -181,7 +184,7 @@ bool PromiseVoidLowering::Perform(public_lib::Context *ctx, parser::Program *pro return true; } -bool PromiseVoidLowering::Postcondition(public_lib::Context *ctx, const parser::Program *program) +bool PromiseVoidInferencePhase::Postcondition(public_lib::Context *ctx, const parser::Program *program) { (void)ctx; diff --git a/ets2panda/compiler/lowering/ets/promiseVoid.h b/ets2panda/compiler/lowering/ets/promiseVoid.h index b09200838d048fd432365686ef5a19542672dd36..89bf01118b256f6372cdc0d3a8c14ec69043d3bf 100644 --- a/ets2panda/compiler/lowering/ets/promiseVoid.h +++ b/ets2panda/compiler/lowering/ets/promiseVoid.h @@ -20,9 +20,13 @@ namespace panda::es2panda::compiler { -class PromiseVoidLowering : public Phase { +class PromiseVoidInferencePhase : public Phase { public: - std::string_view Name() override; + std::string_view Name() override + { + return "PromiseVoidInferencePhase"; + } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; diff --git a/ets2panda/compiler/lowering/ets/structLowering.cpp b/ets2panda/compiler/lowering/ets/structLowering.cpp new file mode 100644 index 0000000000000000000000000000000000000000..09da124b2f8c8559db8022887ef3dcbc8d31427c --- /dev/null +++ b/ets2panda/compiler/lowering/ets/structLowering.cpp @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "structLowering.h" +#include "checker/ETSchecker.h" +#include "compiler/core/compilerContext.h" +#include "ir/base/classDefinition.h" +#include "ir/base/classProperty.h" +#include "ir/astNode.h" +#include "ir/expression.h" +#include "ir/opaqueTypeNode.h" +#include "ir/expressions/identifier.h" +#include "ir/statements/classDeclaration.h" +#include "ir/ts/tsAsExpression.h" +#include "type_helper.h" + +namespace panda::es2panda::compiler { + +const char *const STRUCT_CLASS_NAME = "CommonStruct0"; + +ir::ETSTypeReference *CreateStructTypeReference(checker::ETSChecker *checker, + ir::ETSStructDeclaration *etsStrucDeclaration) +{ + auto *allocator = checker->Allocator(); + + ArenaVector params(allocator->Adapter()); + + ir::TSTypeParameterInstantiation *typeParamSelfInst = nullptr; + + if (etsStrucDeclaration->Definition()->TypeParams() != nullptr && + !etsStrucDeclaration->Definition()->TypeParams()->Params().empty()) { + ArenaVector selfParams(allocator->Adapter()); + ir::ETSTypeReferencePart *referencePart = nullptr; + + for (const auto ¶m : etsStrucDeclaration->Definition()->TypeParams()->Params()) { + auto *identRef = checker->AllocNode(param->AsTSTypeParameter()->Name()->Name(), allocator); + identRef->AsIdentifier()->SetReference(); + + referencePart = checker->AllocNode(identRef, nullptr, nullptr); + + auto *typeReference = checker->AllocNode(referencePart); + + selfParams.push_back(typeReference); + } + + typeParamSelfInst = checker->AllocNode(std::move(selfParams)); + } + + auto *identSelfRef = + checker->AllocNode(etsStrucDeclaration->Definition()->Ident()->Name(), allocator); + identSelfRef->AsIdentifier()->SetReference(); + + auto *referenceSelfPart = checker->AllocNode(identSelfRef, typeParamSelfInst, nullptr); + + auto *selfTypeReference = checker->AllocNode(referenceSelfPart); + + params.push_back(selfTypeReference); + + auto *typeParamInst = checker->AllocNode(std::move(params)); + + auto *identRef = checker->AllocNode(util::StringView(STRUCT_CLASS_NAME), allocator); + identRef->AsIdentifier()->SetReference(); + auto *referencePart = checker->AllocNode(identRef, typeParamInst, nullptr); + + auto *typeReference = checker->AllocNode(referencePart); + + return typeReference; +} + +bool StructLowering::Perform(public_lib::Context *ctx, parser::Program *program) +{ + for (auto &[_, ext_programs] : program->ExternalSources()) { + (void)_; + for (auto *extProg : ext_programs) { + Perform(ctx, extProg); + } + } + + checker::ETSChecker *checker = ctx->checker->AsETSChecker(); + + program->Ast()->TransformChildrenRecursively([checker](ir::AstNode *ast) -> ir::AstNode * { + if (ast->IsETSStructDeclaration()) { + auto *typeRef = CreateStructTypeReference(checker, ast->AsETSStructDeclaration()); + ast->AsETSStructDeclaration()->Definition()->SetSuper(typeRef); + ast->AsETSStructDeclaration()->Definition()->AddModifier(ir::ModifierFlags::FINAL); + } + + return ast; + }); + + return true; +} + +} // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/structLowering.h b/ets2panda/compiler/lowering/ets/structLowering.h new file mode 100644 index 0000000000000000000000000000000000000000..a311ab6929f7c22fa5d2b1c59d2552181be8093a --- /dev/null +++ b/ets2panda/compiler/lowering/ets/structLowering.h @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_STRUCT_LOWERING_H +#define ES2PANDA_COMPILER_LOWERING_STRUCT_LOWERING_H + +#include "compiler/lowering/phase.h" + +namespace panda::es2panda::compiler { + +class StructLowering : public Phase { +public: + std::string_view Name() override + { + return "StructLowering"; + } + + bool Perform(public_lib::Context *ctx, parser::Program *program) override; +}; + +} // namespace panda::es2panda::compiler + +#endif // ES2PANDA_COMPILER_LOWERING_STRUCT_LOWERING_H diff --git a/ets2panda/compiler/lowering/ets/tupleLowering.cpp b/ets2panda/compiler/lowering/ets/tupleLowering.cpp index a5f3987e52238515ee73619c6faed4e30f628c3f..b0be6f7632ea35358f544e475256bb2a24a8e57c 100644 --- a/ets2panda/compiler/lowering/ets/tupleLowering.cpp +++ b/ets2panda/compiler/lowering/ets/tupleLowering.cpp @@ -18,6 +18,7 @@ #include "checker/ETSchecker.h" #include "checker/checker.h" #include "checker/types/type.h" +#include "compiler/core/ASTVerifier.h" #include "compiler/core/compilerContext.h" #include "compiler/lowering/util.h" #include "ir/astNode.h" @@ -32,12 +33,6 @@ #include "ir/ts/tsAsExpression.h" namespace panda::es2panda::compiler { - -std::string_view TupleLowering::Name() -{ - return "tuple-lowering"; -} - static ir::Expression *ConvertTupleUpdate(checker::ETSChecker *const checker, ir::UpdateExpression *const update) { // Converts `tuple[n]++` to diff --git a/ets2panda/compiler/lowering/ets/tupleLowering.h b/ets2panda/compiler/lowering/ets/tupleLowering.h index 1c5fce5b97f203cf1822152bade203bef3c168f7..65c6d8c81d92bda63eb0118b51d210ec974f5332 100644 --- a/ets2panda/compiler/lowering/ets/tupleLowering.h +++ b/ets2panda/compiler/lowering/ets/tupleLowering.h @@ -22,7 +22,11 @@ namespace panda::es2panda::compiler { class TupleLowering : public Phase { public: - std::string_view Name() override; + std::string_view Name() override + { + return "TupleLowering"; + } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; }; diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index 930c61a3a9f3a9f2f640fcdcec6457b77d016a8f..98f789177bef49c1ccf391dd60427e3b1d1b5be0 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -14,6 +14,7 @@ */ #include "unionLowering.h" +#include "compiler/core/ASTVerifier.h" #include "varbinder/variableFlags.h" #include "varbinder/ETSBinder.h" #include "checker/ETSchecker.h" @@ -26,6 +27,8 @@ #include "ir/astNode.h" #include "ir/expression.h" #include "ir/opaqueTypeNode.h" +#include "ir/expressions/literals/nullLiteral.h" +#include "ir/expressions/literals/undefinedLiteral.h" #include "ir/expressions/binaryExpression.h" #include "ir/expressions/identifier.h" #include "ir/expressions/memberExpression.h" @@ -36,12 +39,6 @@ #include "type_helper.h" namespace panda::es2panda::compiler { - -std::string_view UnionLowering::Name() -{ - return "union-property-access"; -} - ir::ClassDefinition *GetUnionFieldClass(checker::ETSChecker *checker, varbinder::VarBinder *varbinder) { // Create the name for the synthetic class node @@ -153,9 +150,9 @@ ir::TSAsExpression *HandleUnionCastToPrimitive(checker::ETSChecker *checker, ir: } if (sourceType != nullptr && expr->Expr()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { if (expr->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - auto *const boxedExprType = checker::BoxingConverter::ETSTypeFromSource(checker, expr->TsType()); - auto *const asExpr = GenAsExpression(checker, boxedExprType, expr->Expr(), expr); - asExpr->SetBoxingUnboxingFlags(expr->Expr()->GetBoxingUnboxingFlags()); + auto *const asExpr = GenAsExpression(checker, sourceType, expr->Expr(), expr); + asExpr->SetBoxingUnboxingFlags( + checker->GetUnboxingFlag(checker->ETSBuiltinTypeAsPrimitiveType(sourceType))); expr->Expr()->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); expr->SetExpr(asExpr); } @@ -179,15 +176,24 @@ ir::BinaryExpression *GenInstanceofExpr(checker::ETSChecker *checker, ir::Expres rhsType = checker::conversion::Boxing(checker->Relation(), constituentType); checker->Relation()->SetNode(nullptr); } - auto *const rhsExpr = - checker->Allocator()->New(rhsType->AsETSObjectType()->Name(), checker->Allocator()); + if (constituentType->IsETSStringType()) { + rhsType = checker->GlobalBuiltinETSStringType(); + } + ir::Expression *rhsExpr; + if (rhsType->IsETSUndefinedType()) { + rhsExpr = checker->Allocator()->New(); + } else if (rhsType->IsETSNullType()) { + rhsExpr = checker->Allocator()->New(); + } else { + rhsExpr = checker->Allocator()->New(rhsType->AsETSObjectType()->Name(), checker->Allocator()); + auto rhsVar = NearestScope(unionNode)->Find(rhsExpr->AsIdentifier()->Name()); + rhsExpr->AsIdentifier()->SetVariable(rhsVar.variable); + } auto *const instanceofExpr = - checker->Allocator()->New(lhsExpr, rhsExpr, lexer::TokenType::KEYW_INSTANCEOF); - lhsExpr->SetParent(instanceofExpr); + checker->Allocator()->New(rhsExpr, rhsExpr, lexer::TokenType::KEYW_INSTANCEOF); + rhsExpr->SetParent(instanceofExpr); rhsExpr->SetParent(instanceofExpr); - auto rhsVar = NearestScope(unionNode)->Find(rhsExpr->Name()); - rhsExpr->SetVariable(rhsVar.variable); - rhsExpr->SetTsType(rhsVar.variable->TsType()); + rhsExpr->SetTsType(rhsType); instanceofExpr->SetOperationType(checker->GlobalETSObjectType()); instanceofExpr->SetTsType(checker->GlobalETSBooleanType()); return instanceofExpr; @@ -266,9 +272,12 @@ ir::Expression *ProcessOperandsInBinaryExpr(checker::ETSChecker *checker, ir::Bi { 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); + bool isLhsUnion = false; + ir::Expression *unionNode = (isLhsUnion = expr->Left()->TsType()->IsETSUnionType()) ? expr->Left() : expr->Right(); + checker::Type *typeToCast = constituentType->IsETSNullLike() + ? unionNode->TsType()->AsETSUnionType()->GetLeastUpperBoundType() + : constituentType; + auto *const asExpression = GenAsExpression(checker, typeToCast, unionNode, expr); if (isLhsUnion) { expr->SetLeft(asExpression); expr->SetRight(SetBoxFlagOrGenAsExpression(checker, constituentType, expr->Right())); diff --git a/ets2panda/compiler/lowering/ets/unionLowering.h b/ets2panda/compiler/lowering/ets/unionLowering.h index efc0bf6bff7470fb1a3f6a99719f4a0c2c5a9b15..5d2d707d5935b111d4f0e0fbde72c9430e674fac 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.h +++ b/ets2panda/compiler/lowering/ets/unionLowering.h @@ -22,7 +22,11 @@ namespace panda::es2panda::compiler { class UnionLowering : public Phase { public: - std::string_view Name() override; + std::string_view Name() override + { + return "UnionLowering"; + } + bool Perform(public_lib::Context *ctx, parser::Program *program) override; bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; }; diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 312b3dd8dca194e282a28ea0da99d7d796dcda4e..a7ee5fbe4e8880ea175569e8315f850fa315cdff 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -29,8 +29,10 @@ #include "compiler/lowering/ets/opAssignment.h" #include "compiler/lowering/ets/tupleLowering.h" #include "compiler/lowering/ets/unionLowering.h" +#include "compiler/lowering/ets/structLowering.h" #include "public/es2panda_lib.h" #include "compiler/lowering/ets/promiseVoid.h" +#include "utils/json_builder.h" namespace panda::es2panda::compiler { @@ -45,52 +47,71 @@ std::vector GetTrivialPhaseList() static InterfacePropertyDeclarationsPhase g_interfacePropDeclPhase; static GenerateTsDeclarationsPhase g_generateTsDeclarationsPhase; -static LambdaLowering g_lambdaLowering; +static LambdaConstructionPhase g_lambdaConstructionPhase; static OpAssignmentLowering g_opAssignmentLowering; static ObjectIndexLowering g_objectIndexLowering; static TupleLowering g_tupleLowering; // Can be only applied after checking phase, and OP_ASSIGNMENT_LOWERING phase static UnionLowering g_unionLowering; static ExpandBracketsPhase g_expandBracketsPhase; -static PromiseVoidLowering g_promiseVoidLowering; +static PromiseVoidInferencePhase g_promiseVoidInferencePhase; +static StructLowering g_structLowering; static PluginPhase g_pluginsAfterParse {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse}; static PluginPhase g_pluginsAfterCheck {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}; static PluginPhase g_pluginsAfterLowerings {"plugins-after-lowering", ES2PANDA_STATE_LOWERED, &util::Plugin::AfterLowerings}; +// NOLINTBEGIN(fuchsia-statically-constructed-objects) +static InitScopesPhaseETS g_initScopesPhaseEts; +static InitScopesPhaseAS g_initScopesPhaseAs; +static InitScopesPhaseTs g_initScopesPhaseTs; +static InitScopesPhaseJs g_initScopesPhaseJs; +// NOLINTEND(fuchsia-statically-constructed-objects) + +std::vector GetETSPhaseList() +{ + return { + &g_pluginsAfterParse, &g_initScopesPhaseEts, &g_promiseVoidInferencePhase, + &g_structLowering, &g_lambdaConstructionPhase, &g_interfacePropDeclPhase, + &g_checkerPhase, &g_pluginsAfterCheck, &g_generateTsDeclarationsPhase, + &g_opAssignmentLowering, &g_objectIndexLowering, &g_tupleLowering, + &g_unionLowering, &g_expandBracketsPhase, &g_pluginsAfterLowerings, + }; +} -std::vector GetPhaseList(ScriptExtension ext) +std::vector GetASPhaseList() +{ + return { + &g_initScopesPhaseAs, + &g_checkerPhase, + }; +} + +std::vector GetTSPhaseList() +{ + return { + &g_initScopesPhaseTs, + &g_checkerPhase, + }; +} + +std::vector GetJSPhaseList() { - static ScopesInitPhaseETS scopesPhaseEts; - static ScopesInitPhaseAS scopesPhaseAs; - static ScopesInitPhaseTs scopesPhaseTs; - static ScopesInitPhaseJs scopesPhaseJs; + return { + &g_initScopesPhaseJs, + &g_checkerPhase, + }; +} +std::vector GetPhaseList(ScriptExtension ext) +{ switch (ext) { case ScriptExtension::ETS: - return { - &scopesPhaseEts, &g_pluginsAfterParse, - &g_promiseVoidLowering, &g_lambdaLowering, - &g_interfacePropDeclPhase, &g_checkerPhase, - &g_pluginsAfterCheck, &g_generateTsDeclarationsPhase, - &g_opAssignmentLowering, &g_objectIndexLowering, - &g_tupleLowering, &g_unionLowering, - &g_expandBracketsPhase, &g_pluginsAfterLowerings, - }; - + return GetETSPhaseList(); case ScriptExtension::AS: - return std::vector { - &scopesPhaseAs, - &g_checkerPhase, - }; + return GetASPhaseList(); case ScriptExtension::TS: - return std::vector { - &scopesPhaseTs, - &g_checkerPhase, - }; + return GetTSPhaseList(); case ScriptExtension::JS: - return std::vector { - &scopesPhaseJs, - &g_checkerPhase, - }; + return GetJSPhaseList(); default: UNREACHABLE(); } @@ -98,25 +119,6 @@ std::vector GetPhaseList(ScriptExtension ext) bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) { -#ifndef NDEBUG - const auto checkProgram = [](const parser::Program *p) { - ASTVerifier verifier {p->Allocator(), false, p->SourceCode()}; - ArenaVector toCheck {p->Allocator()->Adapter()}; - toCheck.push_back(p->Ast()); - for (const auto &externalSource : p->ExternalSources()) { - for (const auto external : externalSource.second) { - toCheck.push_back(external->Ast()); - } - } - for (const auto *ast : toCheck) { - if (!verifier.VerifyFull(ast)) { - return false; - } - } - return true; - }; -#endif - const auto *options = ctx->compilerContext->Options(); const auto name = std::string {Name()}; if (options->skipPhases.count(name) > 0) { @@ -139,8 +141,6 @@ bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) CheckOptionsAfterPhase(options, program, name); #ifndef NDEBUG - checkProgram(program); - if (!Postcondition(ctx, program)) { ctx->checker->ThrowTypeError({"Postcondition check failed for ", util::StringView {Name()}}, lexer::SourcePosition {}); diff --git a/ets2panda/compiler/lowering/plugin_phase.h b/ets2panda/compiler/lowering/plugin_phase.h index 58c56a2d704f66eb520ceb49a0b07014cbd07cfb..042c29118129eea38d7df49f296cf15f840f6036 100644 --- a/ets2panda/compiler/lowering/plugin_phase.h +++ b/ets2panda/compiler/lowering/plugin_phase.h @@ -16,6 +16,7 @@ #ifndef ES2PANDA_COMPILER_PLUGIN_PHASE_H #define ES2PANDA_COMPILER_PLUGIN_PHASE_H +#include "compiler/core/ASTVerifier.h" #include "compiler/lowering/phase.h" #include "util/plugin.h" diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index 83e5b723819f8150aa82418fe7ae10e571a1c254..d7d43bcd671c8c85f55e10abda7bdb7411009ce3 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -562,31 +562,31 @@ void ScopeInitTyped::VisitClassDefinition(ir::ClassDefinition *classDef) IterateNoTParams(classDef); } -void ScopesInitPhaseTs::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl) +void InitScopesPhaseTs::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *exportDecl) { ExportDeclarationContext exportDeclCtx(VarBinder()); Iterate(exportDecl); } -void ScopesInitPhaseTs::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) +void InitScopesPhaseTs::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) { ExportDeclarationContext exportDeclCtx(VarBinder()); Iterate(exportDecl); } -void ScopesInitPhaseTs::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration) +void InitScopesPhaseTs::VisitImportDeclaration(ir::ImportDeclaration *importDeclaration) { ImportDeclarationContext importCtx(VarBinder()); Iterate(importDeclaration); } -void ScopesInitPhaseTs::VisitTSFunctionType(ir::TSFunctionType *constrType) +void InitScopesPhaseTs::VisitTSFunctionType(ir::TSFunctionType *constrType) { auto lexicalScope = HandleFunctionSig(constrType->TypeParams(), constrType->Params(), constrType->ReturnType()); BindScopeNode(lexicalScope, constrType); } -void ScopesInitPhaseTs::CreateFuncDecl(ir::ScriptFunction *func) +void InitScopesPhaseTs::CreateFuncDecl(ir::ScriptFunction *func) { const auto identNode = func->Id(); const auto startLoc = identNode->Start(); @@ -609,46 +609,46 @@ void ScopesInitPhaseTs::CreateFuncDecl(ir::ScriptFunction *func) decl->Add(func); } -void ScopesInitPhaseTs::VisitTSConstructorType(ir::TSConstructorType *constrT) +void InitScopesPhaseTs::VisitTSConstructorType(ir::TSConstructorType *constrT) { auto funcParamScope = HandleFunctionSig(constrT->TypeParams(), constrT->Params(), constrT->ReturnType()); BindScopeNode(funcParamScope, constrT); } -void ScopesInitPhaseTs::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowFExpr) +void InitScopesPhaseTs::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowFExpr) { auto typeParamsCtx = varbinder::LexicalScope(VarBinder()); Iterate(arrowFExpr); } -void ScopesInitPhaseTs::VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *signDecl) +void InitScopesPhaseTs::VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *signDecl) { auto funcParamScope = HandleFunctionSig(signDecl->TypeParams(), signDecl->Params(), signDecl->ReturnTypeAnnotation()); BindScopeNode(funcParamScope, signDecl); } -void ScopesInitPhaseTs::VisitTSMethodSignature(ir::TSMethodSignature *methodSign) +void InitScopesPhaseTs::VisitTSMethodSignature(ir::TSMethodSignature *methodSign) { auto funcParamScope = HandleFunctionSig(methodSign->TypeParams(), methodSign->Params(), methodSign->ReturnTypeAnnotation()); BindScopeNode(funcParamScope, methodSign); } -void ScopesInitPhaseETS::RunExternalNode(ir::AstNode *node, varbinder::VarBinder *varbinder) +void InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, varbinder::VarBinder *varbinder) { auto program = parser::Program(varbinder->Allocator(), varbinder); RunExternalNode(node, &program); } -void ScopesInitPhaseETS::RunExternalNode(ir::AstNode *node, parser::Program *ctx) +void InitScopesPhaseETS::RunExternalNode(ir::AstNode *node, parser::Program *ctx) { - auto scopesPhase = ScopesInitPhaseETS(); + auto scopesPhase = InitScopesPhaseETS(); scopesPhase.SetProgram(ctx); scopesPhase.CallNode(node); } -bool ScopesInitPhaseETS::Perform(PhaseContext *ctx, parser::Program *program) +bool InitScopesPhaseETS::Perform(PhaseContext *ctx, parser::Program *program) { Prepare(ctx, program); @@ -662,7 +662,7 @@ bool ScopesInitPhaseETS::Perform(PhaseContext *ctx, parser::Program *program) return true; } -void ScopesInitPhaseETS::HandleProgram(parser::Program *program) +void InitScopesPhaseETS::HandleProgram(parser::Program *program) { for (auto &[_, prog_list] : program->ExternalSources()) { (void)_; @@ -678,7 +678,7 @@ void ScopesInitPhaseETS::HandleProgram(parser::Program *program) BindScopeNode(prog->VarBinder()->GetScope(), prog->Ast()); prog->VarBinder()->ResetTopScope(globalScope); if (mainProg->Ast() != nullptr) { - ScopesInitPhaseETS().Perform(Context(), prog); + InitScopesPhaseETS().Perform(Context(), prog); } } program->VarBinder()->ResetTopScope(savedTopScope); @@ -688,7 +688,7 @@ void ScopesInitPhaseETS::HandleProgram(parser::Program *program) HandleETSScript(program->Ast()); } -void ScopesInitPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl, +void InitScopesPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *init, varbinder::Decl *decl, varbinder::Variable *var) { binding->SetVariable(var); @@ -697,7 +697,7 @@ void ScopesInitPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *in decl->BindNode(init); } -void ScopesInitPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock) +void InitScopesPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock) { const auto func = staticBlock->Function(); @@ -724,7 +724,7 @@ void ScopesInitPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock func->Id()->SetVariable(var); } -void ScopesInitPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec) +void InitScopesPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *importSpec) { if (importSpec->Local()->Name().Empty()) { return; @@ -734,7 +734,7 @@ void ScopesInitPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecif Iterate(importSpec); } -void ScopesInitPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) +void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) { const auto methodName = method->Id(); @@ -794,7 +794,7 @@ void ScopesInitPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) } } -void ScopesInitPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr) +void InitScopesPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr) { auto *const var = std::get<1>(VarBinder()->AddParamDecl(paramExpr)); paramExpr->Ident()->SetVariable(var); @@ -802,7 +802,7 @@ void ScopesInitPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression Iterate(paramExpr); } -void ScopesInitPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl) +void InitScopesPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl) { ImportDeclarationContext importCtx(VarBinder()); if (importDecl->Language().IsDynamic()) { @@ -811,7 +811,7 @@ void ScopesInitPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *imp Iterate(importDecl); } -void ScopesInitPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enumMember) +void InitScopesPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enumMember) { auto ident = enumMember->Key()->AsIdentifier(); auto [decl, var] = VarBinder()->NewVarDecl(ident->Start(), ident->Name()); @@ -822,7 +822,7 @@ void ScopesInitPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enumMember) Iterate(enumMember); } -void ScopesInitPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method) +void InitScopesPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method) { auto *curScope = VarBinder()->GetScope(); const auto methodName = method->Id(); @@ -834,7 +834,7 @@ void ScopesInitPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method) DeclareClassMethod(method); } -void ScopesInitPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *funcType) +void InitScopesPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *funcType) { auto typeParamsCtx = varbinder::LexicalScope(VarBinder()); varbinder::LexicalScope lexicalScope(VarBinder()); @@ -843,7 +843,7 @@ void ScopesInitPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *funcType) Iterate(funcType); } -void ScopesInitPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr) +void InitScopesPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr) { CallNode(newClassExpr->GetArguments()); CallNode(newClassExpr->GetTypeRef()); @@ -865,7 +865,7 @@ void ScopesInitPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInsta } } -void ScopesInitPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *typeParam) +void InitScopesPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *typeParam) { auto [decl, var] = VarBinder()->NewVarDecl(typeParam->Name()->Start(), typeParam->Name()->Name()); @@ -875,7 +875,7 @@ void ScopesInitPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *typeParam) decl->BindNode(typeParam); } -void ScopesInitPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl) +void InitScopesPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interfaceDecl) { { auto typeParamsCtx = varbinder::LexicalScope(VarBinder()); @@ -891,7 +891,7 @@ void ScopesInitPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration decl->AsInterfaceDecl()->Add(interfaceDecl); } -void ScopesInitPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl) +void InitScopesPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl) { { const auto enumCtx = varbinder::LexicalScope(VarBinder()); @@ -904,14 +904,14 @@ void ScopesInitPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enumDecl) decl->BindScope(enumDecl->Scope()); } -void ScopesInitPhaseETS::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAlias) +void InitScopesPhaseETS::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *typeAlias) { VarBinder()->AddDecl(typeAlias->Id()->Start(), typeAlias->Id()->Name(), typeAlias); auto typeParamsCtx = varbinder::LexicalScope(VarBinder()); Iterate(typeAlias); } -void ScopesInitPhaseETS::AddGlobalToBinder(parser::Program *program) +void InitScopesPhaseETS::AddGlobalToBinder(parser::Program *program) { auto globalId = program->GlobalClass()->Ident(); @@ -926,7 +926,7 @@ void ScopesInitPhaseETS::AddGlobalToBinder(parser::Program *program) globalId->SetVariable(var); } -void ScopesInitPhaseETS::HandleETSScript(ir::BlockStatement *script) +void InitScopesPhaseETS::HandleETSScript(ir::BlockStatement *script) { for (auto decl : script->Statements()) { if (decl->IsETSImportDeclaration()) { @@ -944,7 +944,7 @@ void ScopesInitPhaseETS::HandleETSScript(ir::BlockStatement *script) } } -void ScopesInitPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef) +void InitScopesPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef) { if (classDef->IsGlobal()) { ParseGlobalClass(classDef); @@ -960,13 +960,13 @@ void ScopesInitPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef) BindScopeNode(classScope, classDef); } -void ScopesInitPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody) +void InitScopesPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody) { Iterate(interfBody); FilterInterfaceOverloads(interfBody->Body()); } -void ScopesInitPhaseETS::FilterInterfaceOverloads(ArenaVector &props) +void InitScopesPhaseETS::FilterInterfaceOverloads(ArenaVector &props) { auto condition = [](ir::AstNode *prop) { if (prop->IsMethodDefinition()) { @@ -978,7 +978,7 @@ void ScopesInitPhaseETS::FilterInterfaceOverloads(ArenaVector &props) +void InitScopesPhaseETS::FilterOverloads(ArenaVector &props) { auto condition = [](ir::AstNode *prop) { if (prop->IsMethodDefinition()) { @@ -990,7 +990,7 @@ void ScopesInitPhaseETS::FilterOverloads(ArenaVector &prop props.erase(std::remove_if(props.begin(), props.end(), condition), props.end()); } -void ScopesInitPhaseETS::VisitClassProperty(ir::ClassProperty *classProp) +void InitScopesPhaseETS::VisitClassProperty(ir::ClassProperty *classProp) { auto curScope = VarBinder()->GetScope(); if (classProp->IsClassStaticBlock()) { @@ -1022,7 +1022,7 @@ void ScopesInitPhaseETS::VisitClassProperty(ir::ClassProperty *classProp) Iterate(classProp); } -void ScopesInitPhaseETS::ParseGlobalClass(ir::ClassDefinition *global) +void InitScopesPhaseETS::ParseGlobalClass(ir::ClassDefinition *global) { for (auto decl : global->Body()) { if (decl->IsDefaultExported()) { @@ -1036,7 +1036,7 @@ void ScopesInitPhaseETS::ParseGlobalClass(ir::ClassDefinition *global) FilterOverloads(global->Body()); } -void ScopesInitPhaseETS::AddGlobalDeclaration(ir::AstNode *node) +void InitScopesPhaseETS::AddGlobalDeclaration(ir::AstNode *node) { ir::Identifier *ident = nullptr; bool isBuiltin = false; @@ -1080,12 +1080,12 @@ void ScopesInitPhaseETS::AddGlobalDeclaration(ir::AstNode *node) } } -void ScopesInitPhaseAS::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) +void InitScopesPhaseAS::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) { Iterate(arrowExpr); } -void ScopesInitPhaseAS::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) +void InitScopesPhaseAS::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) { ExportDeclarationContext exportDeclCtx(VarBinder()); Iterate(exportDecl); diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h index 2338b5d7c9c15e8ca5569d0d551871e61a3470a9..8a7135cc419bf2df339c27aebf959ee8671580ac 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h @@ -16,11 +16,11 @@ #ifndef ES2PANDA_COMPILER_CORE_SCOPES_INIT_PHASE_H #define ES2PANDA_COMPILER_CORE_SCOPES_INIT_PHASE_H +#include "compiler/lowering/phase.h" #include "util/helpers.h" #include "parser/parserFlags.h" #include "varbinder/tsBinding.h" #include "varbinder/ETSBinder.h" -#include "compiler/lowering/phase.h" #include "compiler/lowering/scopesInit/savedBindingsCtx.h" #include "checker/checker.h" #include "compiler/core/compilerContext.h" @@ -42,7 +42,7 @@ public: std::string_view Name() override { - return "scopes"; + return "ScopesInitPhase"; } bool Perform(PhaseContext *ctx, parser::Program *program) override; @@ -220,16 +220,16 @@ public: void VisitClassDefinition(ir::ClassDefinition *classDef) override; }; -class ScopesInitPhaseJs : public ScopesInitPhase { +class InitScopesPhaseJs : public ScopesInitPhase { public: - ScopesInitPhaseJs() = default; - NO_COPY_SEMANTIC(ScopesInitPhaseJs); - NO_MOVE_SEMANTIC(ScopesInitPhaseJs); + InitScopesPhaseJs() = default; + NO_COPY_SEMANTIC(InitScopesPhaseJs); + NO_MOVE_SEMANTIC(InitScopesPhaseJs); - ~ScopesInitPhaseJs() override = default; + ~InitScopesPhaseJs() override = default; }; -class ScopesInitPhaseTs : public ScopeInitTyped { +class InitScopesPhaseTs : public ScopeInitTyped { protected: bool AllowInterfaceRedeclaration() override { @@ -250,11 +250,11 @@ protected: void CreateFuncDecl(ir::ScriptFunction *func) override; }; -class ScopesInitPhaseETS : public ScopeInitTyped { +class InitScopesPhaseETS : public ScopeInitTyped { public: - ScopesInitPhaseETS() = default; - NO_COPY_SEMANTIC(ScopesInitPhaseETS); - NO_MOVE_SEMANTIC(ScopesInitPhaseETS); + InitScopesPhaseETS() = default; + NO_COPY_SEMANTIC(InitScopesPhaseETS); + NO_MOVE_SEMANTIC(InitScopesPhaseETS); /** * Set scopes for ast-subtree @@ -307,7 +307,7 @@ public: */ bool Perform(PhaseContext *ctx, parser::Program *program) override; - ~ScopesInitPhaseETS() override = default; + ~InitScopesPhaseETS() override = default; private: void HandleProgram(parser::Program *program); @@ -361,12 +361,12 @@ private: void FilterOverloads(ArenaVector &props); }; -class ScopesInitPhaseAS : public ScopesInitPhase { +class InitScopesPhaseAS : public ScopesInitPhase { public: - NO_COPY_SEMANTIC(ScopesInitPhaseAS); - NO_MOVE_SEMANTIC(ScopesInitPhaseAS); - ScopesInitPhaseAS() = default; - ~ScopesInitPhaseAS() override = default; + NO_COPY_SEMANTIC(InitScopesPhaseAS); + NO_MOVE_SEMANTIC(InitScopesPhaseAS); + InitScopesPhaseAS() = default; + ~InitScopesPhaseAS() override = default; private: void VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrowExpr) override; diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index be3639d81fdfb9bc40453f5b77c6097e999ffa44..5c4631985329143d6a748a6db5f006ba4f1c983d 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -257,6 +257,9 @@ builtins: - name: Error package: PKG_ESCOMPAT ref: BUILTIN_ERROR + - name: BigInt + package: PKG_ESCOMPAT + ref: BUILTIN_BIGINT - name: AssertionError package: PKG_ESCOMPAT ref: BUILTIN_ASSERTION_ERROR @@ -337,6 +340,132 @@ signatures: return_type: PRIMITIVE_VOID ref: BUILTIN_ASSERTION_ERROR_CTOR + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [BUILTIN_STRING] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR + + - callee: BUILTIN_BIGINT + method_name: $CTOR + params: [] + return_type: PRIMITIVE_VOID + ref: BUILTIN_BIGINT_CTOR_EMPTY + + - callee: BUILTIN_BIGINT + method_name: equals + params: [BUILTIN_BIGINT] + return_type: PRIMITIVE_BOOLEAN + ref: BUILTIN_BIGINT_EQUALS + + - callee: BUILTIN_BIGINT + method_name: negate + params: [] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_NEGATE + + - callee: BUILTIN_BIGINT + method_name: operatorAdd + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_ADD + + - callee: BUILTIN_BIGINT + method_name: operatorSubtract + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_SUBTRACT + + - callee: BUILTIN_BIGINT + method_name: operatorMultiply + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_MULTIPLY + + - callee: BUILTIN_BIGINT + method_name: operatorDivide + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_DIVIDE + + - callee: BUILTIN_BIGINT + method_name: operatorModule + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_MODULE + + - callee: BUILTIN_BIGINT + method_name: operatorBitwiseOr + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_BITWISE_OR + + - callee: BUILTIN_BIGINT + method_name: operatorBitwiseAnd + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_BITWISE_AND + + - callee: BUILTIN_BIGINT + method_name: operatorBitwiseXor + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_BITWISE_XOR + + - callee: BUILTIN_BIGINT + method_name: operatorGreaterThan + params: [BUILTIN_BIGINT] + return_type: PRIMITIVE_BOOLEAN + ref: BUILTIN_BIGINT_OPERATOR_GREATER_THAN + + - callee: BUILTIN_BIGINT + method_name: operatorLessThan + params: [BUILTIN_BIGINT] + return_type: PRIMITIVE_BOOLEAN + ref: BUILTIN_BIGINT_OPERATOR_LESS_THAN + + - callee: BUILTIN_BIGINT + method_name: operatorGreaterThanEqual + params: [BUILTIN_BIGINT] + return_type: PRIMITIVE_BOOLEAN + ref: BUILTIN_BIGINT_OPERATOR_GREATER_THAN_EQUAL + + - callee: BUILTIN_BIGINT + method_name: operatorLessThanEqual + params: [BUILTIN_BIGINT] + return_type: PRIMITIVE_BOOLEAN + ref: BUILTIN_BIGINT_OPERATOR_LESS_THAN_EQUAL + + - callee: BUILTIN_BIGINT + method_name: operatorLeftShift + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_LEFT_SHIFT + + - callee: BUILTIN_BIGINT + method_name: operatorRightShift + params: [BUILTIN_BIGINT] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_RIGHT_SHIFT + + - callee: BUILTIN_BIGINT + method_name: operatorIncrement + params: [] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_INCREMENT + + - callee: BUILTIN_BIGINT + method_name: operatorDecrement + params: [] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_DECREMENT + + - callee: BUILTIN_BIGINT + method_name: operatorBitwiseNot + params: [] + return_type: BUILTIN_BIGINT + ref: BUILTIN_BIGINT_OPERATOR_BITWISE_NOT + - callee: BUILTIN_THROWABLE method_name: $CTOR params: [] diff --git a/ets2panda/es2panda.h b/ets2panda/es2panda.h index 38269eeb795007d993f58065c990712f01253deb..7f11b3340c8c41e5cc32d7b1876a764b55c97d17 100644 --- a/ets2panda/es2panda.h +++ b/ets2panda/es2panda.h @@ -103,6 +103,8 @@ struct CompilerOptions { std::string tsDeclOut {}; std::vector plugins {}; std::unordered_set skipPhases {}; + std::unordered_set verifierWarnings {}; + std::unordered_set verifierErrors {}; std::unordered_set dumpBeforePhases {}; std::unordered_set dumpEtsSrcBeforePhases {}; std::unordered_set dumpAfterPhases {}; diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.h b/ets2panda/ir/ets/etsNewClassInstanceExpression.h index 371a904f9e5a1e239940735036bf74fc85f00ff4..e93e44518a271598e7fa48acb88a9e97ceb3f762 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.h @@ -70,11 +70,16 @@ public: return typeReference_; } - [[nodiscard]] ArenaVector GetArguments() const noexcept + [[nodiscard]] const ArenaVector &GetArguments() const noexcept { return arguments_; } + [[nodiscard]] checker::Signature *GetSignature() const noexcept + { + return signature_; + } + void SetSignature(checker::Signature *const signature) noexcept { signature_ = signature; diff --git a/ets2panda/ir/ets/etsScript.h b/ets2panda/ir/ets/etsScript.h index 60505c6d5cbaa32af867970a3b6ccef65a7305df..652d2e9d279ab0ced081d5ccec94e2b3f3273efb 100644 --- a/ets2panda/ir/ets/etsScript.h +++ b/ets2panda/ir/ets/etsScript.h @@ -29,6 +29,7 @@ public: explicit ETSScript(ArenaAllocator *allocator, ArenaVector &&statementList, parser::Program *program) : BlockStatement(allocator, std::move(statementList)), program_(program) { + type_ = AstNodeType::ETS_SCRIPT; } parser::Program *Program() diff --git a/ets2panda/ir/ets/etsTuple.cpp b/ets2panda/ir/ets/etsTuple.cpp index 1be5a6ad56fb322f535c5594d53e23fb810ba5cb..3e40d189db18667aa16f8d30f72733c7fb33fa5d 100644 --- a/ets2panda/ir/ets/etsTuple.cpp +++ b/ets2panda/ir/ets/etsTuple.cpp @@ -53,9 +53,9 @@ void ETSTuple::Dump(ir::AstDumper *const dumper) const void ETSTuple::Dump(ir::SrcDumper *const dumper) const { dumper->Add("["); - for (auto typeAnnot : typeAnnotationList_) { + for (const auto *const typeAnnot : typeAnnotationList_) { typeAnnot->Dump(dumper); - if (typeAnnot != typeAnnotationList_.back() || spreadType_ != nullptr) { + if ((typeAnnot != typeAnnotationList_.back()) || (spreadType_ != nullptr)) { dumper->Add(", "); } } @@ -63,7 +63,7 @@ void ETSTuple::Dump(ir::SrcDumper *const dumper) const dumper->Add("..."); spreadType_->Dump(dumper); } - dumper->Add(("]")); + dumper->Add("]"); } void ETSTuple::Compile([[maybe_unused]] compiler::PandaGen *const pg) const {} @@ -79,6 +79,17 @@ checker::Type *ETSTuple::Check([[maybe_unused]] checker::ETSChecker *const check return GetType(checker); } +void ETSTuple::SetNullUndefinedFlags(std::pair &containsNullOrUndefined, const checker::Type *const type) +{ + if (type->HasTypeFlag(checker::TypeFlag::NULLISH)) { + containsNullOrUndefined.first = true; + } + + if (type->HasTypeFlag(checker::TypeFlag::UNDEFINED)) { + containsNullOrUndefined.second = true; + } +} + checker::Type *ETSTuple::CalculateLUBForTuple(checker::ETSChecker *const checker, ArenaVector &typeList, checker::Type *const spreadType) { @@ -86,11 +97,17 @@ checker::Type *ETSTuple::CalculateLUBForTuple(checker::ETSChecker *const checker return spreadType == nullptr ? checker->GlobalETSObjectType() : spreadType; } - bool allElementsAreSame = std::all_of(typeList.begin(), typeList.end(), [&checker, &typeList](auto *element) { - return checker->Relation()->IsIdenticalTo(typeList[0], element); - }); + std::pair containsNullOrUndefined = {false, false}; + + bool allElementsAreSame = + std::all_of(typeList.begin(), typeList.end(), + [this, &checker, &typeList, &containsNullOrUndefined](checker::Type *const element) { + SetNullUndefinedFlags(containsNullOrUndefined, element); + return checker->Relation()->IsIdenticalTo(typeList[0], element); + }); if (spreadType != nullptr) { + SetNullUndefinedFlags(containsNullOrUndefined, spreadType); allElementsAreSame = allElementsAreSame && checker->Relation()->IsIdenticalTo(typeList[0], spreadType); } @@ -121,6 +138,16 @@ checker::Type *ETSTuple::CalculateLUBForTuple(checker::ETSChecker *const checker lubType = checker->FindLeastUpperBound(lubType, getBoxedTypeOrType(spreadType)); } + const auto nullishUndefinedFlags = + (containsNullOrUndefined.first ? checker::TypeFlag::NULLISH | checker::TypeFlag::NULL_TYPE + : checker::TypeFlag::NONE) | + (containsNullOrUndefined.second ? checker::TypeFlag::UNDEFINED : checker::TypeFlag::NONE); + + if (nullishUndefinedFlags != checker::TypeFlag::NONE) { + lubType = checker->CreateNullishType(lubType, nullishUndefinedFlags, checker->Allocator(), checker->Relation(), + checker->GetGlobalTypesHolder()); + } + checker->Relation()->SetNode(savedRelationNode); return lubType; diff --git a/ets2panda/ir/ets/etsTuple.h b/ets2panda/ir/ets/etsTuple.h index 9d03e58faa7a611b8a840b01cb56bcd74942981d..6cb0e0353dc6edaf12c8165bba358a45c03d832a 100644 --- a/ets2panda/ir/ets/etsTuple.h +++ b/ets2panda/ir/ets/etsTuple.h @@ -75,6 +75,7 @@ public: checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + void SetNullUndefinedFlags(std::pair &containsNullOrUndefined, const checker::Type *type); checker::Type *CalculateLUBForTuple(checker::ETSChecker *checker, ArenaVector &typeList, checker::Type *spreadType); diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index b77ee5d33b59563beb07bbe4e9d395041e7d7d1b..00cc5f99654db626c41e66e88d185f0f4c62b975 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -377,4 +377,26 @@ checker::Type *ArrayExpression::Check(checker::ETSChecker *checker) { return checker->GetAnalyzer()->Check(this); } + +void ArrayExpression::GetPrefferedTypeFromFuncParam(checker::ETSChecker *checker, Expression *param, + checker::TypeRelationFlag flags) +{ + if (preferredType_ != nullptr) { + return; + } + auto paramType = param->Check(checker); + if (paramType->IsETSArrayType()) { + paramType = paramType->AsETSArrayType()->ElementType(); + } + bool isAssignable = true; + for (auto elem : elements_) { + auto assignCtx = checker::AssignmentContext(checker->Relation(), elem, elem->Check(checker), paramType, + elem->Start(), {""}, checker::TypeRelationFlag::NO_THROW | flags); + isAssignable &= assignCtx.IsAssignable(); + } + if (isAssignable) { + preferredType_ = param->Check(checker); + } +} + } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index 8e3e1f0547cfc74225cb9b39de0728f383f4f119..66efed5421e1c01121f15bcffe94bb4f6defa543 100644 --- a/ets2panda/ir/expressions/arrayExpression.h +++ b/ets2panda/ir/expressions/arrayExpression.h @@ -18,6 +18,7 @@ #include "ir/expression.h" #include "ir/validationInfo.h" +#include "checker/types/ets/etsArrayType.h" namespace panda::es2panda::checker { class ETSAnalyzer; @@ -140,6 +141,9 @@ public: v->Accept(this); } + void GetPrefferedTypeFromFuncParam(checker::ETSChecker *checker, Expression *param, + checker::TypeRelationFlag flags); + private: ArenaVector decorators_; ArenaVector elements_; diff --git a/ets2panda/ir/expressions/literals/bigIntLiteral.cpp b/ets2panda/ir/expressions/literals/bigIntLiteral.cpp index a12339916cf09c833b73c2bb68976b8dfc8dcdc6..e3fbbd8c8f8f3187b5d30e1b2b765966dd92cf77 100644 --- a/ets2panda/ir/expressions/literals/bigIntLiteral.cpp +++ b/ets2panda/ir/expressions/literals/bigIntLiteral.cpp @@ -19,6 +19,7 @@ #include "compiler/core/ETSGen.h" #include "compiler/core/pandagen.h" #include "ir/astDump.h" +#include "checker/ETSchecker.h" #include "ir/srcDump.h" namespace panda::es2panda::ir { diff --git a/ets2panda/ir/expressions/literals/bigIntLiteral.h b/ets2panda/ir/expressions/literals/bigIntLiteral.h index 0ae06c26404386e01c7bb54e8af482b40257ef71..424c37bcb16d662b6debda9058c93b3c9c871cb2 100644 --- a/ets2panda/ir/expressions/literals/bigIntLiteral.h +++ b/ets2panda/ir/expressions/literals/bigIntLiteral.h @@ -42,10 +42,10 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Dump(ir::SrcDumper *dumper) const override; - void Compile(compiler::PandaGen *pg) const override; + void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; void Compile(compiler::ETSGen *etsg) const override; - checker::Type *Check(checker::TSChecker *checker) override; - checker::Type *Check(checker::ETSChecker *checker) override; + checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; + checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/ir/expressions/literals/undefinedLiteral.cpp b/ets2panda/ir/expressions/literals/undefinedLiteral.cpp index 27bddb8b4078d63f8edf4676ad83d07621c24b6f..3d28d6c06b465d322edcff248eab416ca5c69398 100644 --- a/ets2panda/ir/expressions/literals/undefinedLiteral.cpp +++ b/ets2panda/ir/expressions/literals/undefinedLiteral.cpp @@ -56,4 +56,17 @@ checker::Type *UndefinedLiteral::Check([[maybe_unused]] checker::ETSChecker *che SetTsType(checker->GlobalETSUndefinedType()); return TsType(); } + +// NOLINTNEXTLINE(google-default-arguments) +UndefinedLiteral *UndefinedLiteral::Clone(ArenaAllocator *allocator, AstNode *parent) +{ + if (auto *const clone = allocator->New(); clone != nullptr) { + if (parent != nullptr) { + clone->SetParent(parent); + } + return clone; + } + + throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR); +} } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/literals/undefinedLiteral.h b/ets2panda/ir/expressions/literals/undefinedLiteral.h index 818867cde59e9820577967e67411f4bf873a9e30..2de04789a1848e381481fc2d21f6fef1f379bc7e 100644 --- a/ets2panda/ir/expressions/literals/undefinedLiteral.h +++ b/ets2panda/ir/expressions/literals/undefinedLiteral.h @@ -23,6 +23,9 @@ class UndefinedLiteral : public Literal { public: explicit UndefinedLiteral() : Literal(AstNodeType::UNDEFINED_LITERAL) {} + // NOLINTNEXTLINE(google-default-arguments) + [[nodiscard]] UndefinedLiteral *Clone(ArenaAllocator *allocator, AstNode *parent = nullptr) override; + void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/expressions/memberExpression.cpp b/ets2panda/ir/expressions/memberExpression.cpp index f30789293634a9512bc6be9a50aaa09e109ce2f6..f3f3e761a2775a77001a2174f8e3b22dc384ef94 100644 --- a/ets2panda/ir/expressions/memberExpression.cpp +++ b/ets2panda/ir/expressions/memberExpression.cpp @@ -221,7 +221,7 @@ checker::Type *MemberExpression::AdjustType(checker::ETSChecker *checker, checke if (PropVar() != nullptr) { uncheckedType_ = checker->GuaranteedTypeForUncheckedPropertyAccess(PropVar()); } - if (IsOptional() && Object()->TsType()->IsNullishOrNullLike()) { + if (IsOptional() && checker->MayHaveNulllikeValue(Object()->TsType())) { checker->Relation()->SetNode(this); type = checker->CreateOptionalResultType(type); checker->Relation()->SetNode(nullptr); diff --git a/ets2panda/ir/expressions/unaryExpression.cpp b/ets2panda/ir/expressions/unaryExpression.cpp index 82601c41bfc70b374a26224a45c501f7d357d86a..77160e124d6f40dd57178b94a51aa9d899b61c52 100644 --- a/ets2panda/ir/expressions/unaryExpression.cpp +++ b/ets2panda/ir/expressions/unaryExpression.cpp @@ -16,6 +16,7 @@ #include "unaryExpression.h" #include "varbinder/variable.h" +#include "checker/types/typeFlag.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" #include "checker/TSchecker.h" diff --git a/ets2panda/ir/ts/tsEnumDeclaration.h b/ets2panda/ir/ts/tsEnumDeclaration.h index 1ef96909aceb2ec6e033369cc0953462d7d055f9..07da87553a09ee5586d2648cc6b7f34d2c48f455 100644 --- a/ets2panda/ir/ts/tsEnumDeclaration.h +++ b/ets2panda/ir/ts/tsEnumDeclaration.h @@ -31,16 +31,20 @@ class TSEnumMember; class TSEnumDeclaration : public TypedStatement { public: explicit TSEnumDeclaration(ArenaAllocator *allocator, Identifier *key, ArenaVector &&members, - bool isConst, bool isStatic = false) + bool isConst, bool isStatic = false, bool isDeclare = false) : TypedStatement(AstNodeType::TS_ENUM_DECLARATION), decorators_(allocator->Adapter()), key_(key), members_(std::move(members)), - isConst_(isConst) + isConst_(isConst), + isDeclare_(isDeclare) { if (isStatic) { AddModifier(ModifierFlags::STATIC); } + if (isDeclare) { + AddModifier(ModifierFlags::DECLARE); + } } bool IsScopeBearer() const override @@ -88,6 +92,11 @@ public: return isConst_; } + bool IsDeclare() const + { + return isDeclare_; + } + const ArenaVector &Decorators() const { return decorators_; @@ -131,6 +140,7 @@ private: ArenaVector members_; util::StringView internalName_; bool isConst_; + bool isDeclare_; }; } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeAliasDeclaration.h b/ets2panda/ir/ts/tsTypeAliasDeclaration.h index e82a3a9d219f15c48bab69b2abf1d2281065f094..275026d757d4bdd962135ae27653ba0ab56c2195 100644 --- a/ets2panda/ir/ts/tsTypeAliasDeclaration.h +++ b/ets2panda/ir/ts/tsTypeAliasDeclaration.h @@ -34,6 +34,7 @@ public: decorators_(allocator->Adapter()), id_(id), typeParams_(typeParams), + typeParamTypes_(allocator->Adapter()), declare_(declare) { } @@ -43,6 +44,7 @@ public: decorators_(allocator->Adapter()), id_(id), typeParams_(nullptr), + typeParamTypes_(allocator->Adapter()), declare_(false) { } @@ -57,7 +59,7 @@ public: return id_; } - const TSTypeParameterDeclaration *TypeParams() const + TSTypeParameterDeclaration *TypeParams() const { return typeParams_; } @@ -77,7 +79,7 @@ public: return &Decorators(); } - void AddTypeParameters(ir::TSTypeParameterDeclaration *typeParams) + void SetTypeParameters(ir::TSTypeParameterDeclaration *typeParams) { typeParams_ = typeParams; } @@ -92,6 +94,16 @@ public: return !inTs; } + void SetTypeParameterTypes(ArenaVector &&typeParamTypes) + { + typeParamTypes_ = std::move(typeParamTypes); + } + + ArenaVector const &TypeParameterTypes() const + { + return typeParamTypes_; + } + void TransformChildren(const NodeTransformer &cb) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; @@ -110,6 +122,7 @@ private: ArenaVector decorators_; Identifier *id_; TSTypeParameterDeclaration *typeParams_; + ArenaVector typeParamTypes_; bool declare_; }; } // namespace panda::es2panda::ir diff --git a/ets2panda/lexer/ETSLexer.h b/ets2panda/lexer/ETSLexer.h index 1387f703be9abc2195c03b1d8d7f10922a77860a..ad4557def127942341189d0701573fc65a01c184 100644 --- a/ets2panda/lexer/ETSLexer.h +++ b/ets2panda/lexer/ETSLexer.h @@ -17,6 +17,7 @@ #define ES2PANDA_PARSER_CORE_ETS_LEXER_H #include "lexer/lexer.h" +#include "token/letters.h" namespace panda::es2panda::lexer { class ETSLexer final : public Lexer { @@ -40,12 +41,25 @@ public: void ScanNumberLeadingZero() override { const auto savedLexerPosition = Save(); + + bool allowBigint = false; + if (Iterator().Peek() == LEX_CHAR_LOWERCASE_N) { + // 0n is the only allowed bigint literal with leading 0 + allowBigint = true; + } + try { ScanNumberLeadingZeroImpl(); } catch (...) { Rewind(savedLexerPosition); ScanNumberLeadingZeroImpl(); } + + if ((GetToken().flags_ & TokenFlags::NUMBER_BIGINT) != 0) { + if (!allowBigint) { + ThrowError("Invalid BigInt number"); + } + } } void CheckNumberLiteralEnd() override; diff --git a/ets2panda/lexer/scripts/keywords.yaml b/ets2panda/lexer/scripts/keywords.yaml index 690264b0981106674467fef736124b6ffb62a266..287aa8319889050bafc93d9c60036e0dafe33951 100644 --- a/ets2panda/lexer/scripts/keywords.yaml +++ b/ets2panda/lexer/scripts/keywords.yaml @@ -296,6 +296,7 @@ keywords: - name: 'namespace' token: KEYW_NAMESPACE + keyword: [ets] keyword_like: [as, ts] - name: 'native' diff --git a/ets2panda/parser/ASparser.cpp b/ets2panda/parser/ASparser.cpp index 6b88eb17c2bffcb77be165a7263a9c5b6ee9a4cc..657d56be4d5024c7e531b23fa07402c73aaf440d 100644 --- a/ets2panda/parser/ASparser.cpp +++ b/ets2panda/parser/ASparser.cpp @@ -15,6 +15,7 @@ #include "ASparser.h" +#include "parserFlags.h" #include "util/helpers.h" #include "varbinder/privateBinding.h" #include "varbinder/scope.h" @@ -1350,58 +1351,72 @@ ir::AstNode *ASParser::ParseImportDefaultSpecifier(ArenaVector *s return nullptr; } -ir::Expression *ASParser::ParseCoverParenthesizedExpressionAndArrowParameterList() +ir::Expression *ASParser::ParseArrowFunctionRestParameter(lexer::SourcePosition start) { - ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); - lexer::SourcePosition start = Lexer()->GetToken().Start(); - Lexer()->NextToken(); - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN); - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { - ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN); + restElement->SetGrouped(); + restElement->SetStart(start); - restElement->SetGrouped(); - restElement->SetStart(start); + ValidateArrowFunctionRestParameter(restElement); - ValidateArrowFunctionRestParameter(restElement); + Lexer()->NextToken(); - Lexer()->NextToken(); + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { + ThrowSyntaxError(":' expected"); + } - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { - ThrowSyntaxError(":' expected"); - } + Lexer()->NextToken(); // eat ':' - Lexer()->NextToken(); // eat ':' + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options); - ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options); + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + ThrowSyntaxError("'=>' expected"); + } - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { - ThrowSyntaxError("'=>' expected"); - } + return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false); +} + +ir::Expression *ASParser::ParseArrowFunctionNoParameter(lexer::SourcePosition start) +{ + Lexer()->NextToken(); - return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false); + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { + ThrowSyntaxError(":' expected"); } - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - Lexer()->NextToken(); + Lexer()->NextToken(); // eat ':' - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { - ThrowSyntaxError(":' expected"); - } + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options); - Lexer()->NextToken(); // eat ':' + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + ThrowSyntaxError("'=>' expected"); + } - ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options); + auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false); + arrowExpr->SetStart(start); + arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start); - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { - ThrowSyntaxError("'=>' expected"); - } + return arrowExpr; +} + +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *ASParser::ParseCoverParenthesizedExpressionAndArrowParameterList( + [[maybe_unused]] ExpressionParseFlags flags) +{ + ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); + lexer::SourcePosition start = Lexer()->GetToken().Start(); + Lexer()->NextToken(); + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false); - arrowExpr->SetStart(start); - arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start); + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { + return ParseArrowFunctionRestParameter(start); + } - return arrowExpr; + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + return ParseArrowFunctionNoParameter(start); } ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST | diff --git a/ets2panda/parser/ASparser.h b/ets2panda/parser/ASparser.h index 6d1348f51c185ed704fbfa79ba1ac0fbfe7060fc..4a69e8214c7ef750d0fe3109396fa581ea510f4c 100644 --- a/ets2panda/parser/ASparser.h +++ b/ets2panda/parser/ASparser.h @@ -17,6 +17,7 @@ #define ES2PANDA_PARSER_CORE_AS_PARSER_H #include "TypedParser.h" +#include "parserFlags.h" namespace panda::es2panda::parser { class ASParser : public TypedParser { @@ -72,7 +73,11 @@ private: const ArenaVector ¶ms, ParserStatus newStatus, ParserStatus contextStatus) override; ir::AstNode *ParseImportDefaultSpecifier(ArenaVector *specifiers) override; std::tuple ParseInterfacePropertyKey() override; - ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList() override; + // NOLINTNEXTLINE(google-default-arguments) + ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList( + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; + ir::Expression *ParseArrowFunctionRestParameter(lexer::SourcePosition start); + ir::Expression *ParseArrowFunctionNoParameter(lexer::SourcePosition start); ir::Expression *ParsePrefixAssertionExpression() override; ir::Statement *ParseConstStatement(StatementParsingFlags flags) override; ir::AnnotatedExpression *ParseVariableDeclaratorKey(VariableParsingFlags flags) override; diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 5db2c3fd0598625849960af7386f3e93cfa01f06..0d5eff251f56b36384c262e6401bc8a9705ebd5f 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -188,7 +188,9 @@ void ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector end(items)); for (const auto &item : items) { - parsedSources_.push_back(ResolveImportPath(item)); + auto resolved = ResolveImportPath(item); + resolvedParsedSources_.emplace(item, resolved); + parsedSources_.push_back(resolved); } }; // clang-format on @@ -676,22 +678,6 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVector globalProperties(Allocator()->Adapter()); fieldMap_.clear(); exportNameMap_.clear(); - bool defaultExport = false; - - using ParserFunctionPtr = std::function; - auto const parseType = [this, &statements, &defaultExport](std::size_t const currentPos, - ParserFunctionPtr const &parserFunction) -> void { - ir::Statement *node = nullptr; - - node = parserFunction(this); - if (node != nullptr) { - if (currentPos != std::numeric_limits::max()) { - MarkNodeAsExported(node, node->Start(), defaultExport); - defaultExport = false; - } - statements.push_back(node); - } - }; // Add special '_$init$_' method that will hold all the top-level variable initializations (as assignments) and // statements. By default it will be called in the global class static constructor but also it can be called @@ -702,6 +688,43 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVector &statements, bool &defaultExport, + std::size_t const currentPos, + std::function const &parserFunction) +{ + ir::Statement *node = nullptr; + + node = parserFunction(this); + if (node != nullptr) { + if (currentPos != std::numeric_limits::max()) { + MarkNodeAsExported(node, node->Start(), defaultExport); + defaultExport = false; + } + statements.push_back(node); + } +} + +void ETSParser::ParseTopLevelNextToken(ArenaVector &statements, + ArenaVector &globalProperties, ir::ScriptFunction *initFunction) +{ + bool defaultExport = false; + while (Lexer()->GetToken().Type() != lexer::TokenType::EOS) { if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { Lexer()->NextToken(); @@ -742,44 +765,20 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVectorNextToken(); auto *memberName = ExpectIdentifier(); - ParseClassFieldDefiniton(memberName, memberModifiers, &globalProperties, initFunction, &startLoc); + ParseClassFieldDefinition(memberName, memberModifiers, &globalProperties, initFunction, &startLoc); break; } case lexer::TokenType::KEYW_ASYNC: case lexer::TokenType::KEYW_NATIVE: { - bool isAsync = tokenType == lexer::TokenType::KEYW_ASYNC; - - if (isAsync) { - memberModifiers |= ir::ModifierFlags::ASYNC; - } else { - memberModifiers |= ir::ModifierFlags::NATIVE; - } - - Lexer()->NextToken(); - - if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION) { - ThrowSyntaxError( - {isAsync ? "'async'" : "'native'", " flags must be used for functions at top-level."}); - } + ParseTokenOfNative(tokenType, memberModifiers); [[fallthrough]]; } case lexer::TokenType::KEYW_FUNCTION: { - Lexer()->NextToken(); - // check whether it is an extension function - ir::Identifier *className = nullptr; - if (Lexer()->Lookahead() == lexer::LEX_CHAR_DOT) { - className = ExpectIdentifier(); - Lexer()->NextToken(); - } - - auto *memberName = ExpectIdentifier(); - auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers, className); - classMethod->SetStart(startLoc); - if (!classMethod->Function()->IsOverload()) { - globalProperties.push_back(classMethod); - } + ParseTokenOfFunction(memberModifiers, startLoc, globalProperties); break; } + case lexer::TokenType::KEYW_NAMESPACE: + [[fallthrough]]; case lexer::TokenType::KEYW_STATIC: [[fallthrough]]; case lexer::TokenType::KEYW_ABSTRACT: @@ -791,18 +790,21 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVectorParseTypeDeclaration(false); }); + ParseTopLevelType(statements, defaultExport, currentPos, + [](ETSParser *obj) { return obj->ParseTypeDeclaration(false); }); break; } @@ -827,18 +829,42 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVectorNextToken(); + + if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION) { + ThrowSyntaxError({isAsync ? "'async'" : "'native'", " flags must be used for functions at top-level."}); + } +} + +void ETSParser::ParseTokenOfFunction(ir::ModifierFlags memberModifiers, lexer::SourcePosition startLoc, + ArenaVector &globalProperties) +{ + Lexer()->NextToken(); + // check whether it is an extension function + ir::Identifier *className = nullptr; + if (Lexer()->Lookahead() == lexer::LEX_CHAR_DOT) { + className = ExpectIdentifier(); + Lexer()->NextToken(); + } + + auto *memberName = ExpectIdentifier(); + auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers, className); + classMethod->SetStart(startLoc); + if (!classMethod->Function()->IsOverload()) { + globalProperties.push_back(classMethod); } - return globalProperties; } // NOLINTNEXTLINE(google-default-arguments) @@ -1264,9 +1290,9 @@ ir::ModifierFlags ETSParser::ParseClassMethodModifiers(bool seenStatic) } // NOLINTNEXTLINE(google-default-arguments) -void ETSParser::ParseClassFieldDefiniton(ir::Identifier *fieldName, ir::ModifierFlags modifiers, - ArenaVector *declarations, ir::ScriptFunction *initFunction, - lexer::SourcePosition *letLoc) +void ETSParser::ParseClassFieldDefinition(ir::Identifier *fieldName, ir::ModifierFlags modifiers, + ArenaVector *declarations, ir::ScriptFunction *initFunction, + lexer::SourcePosition *letLoc) { lexer::SourcePosition startLoc = letLoc != nullptr ? *letLoc : Lexer()->GetToken().Start(); lexer::SourcePosition endLoc = startLoc; @@ -1290,28 +1316,7 @@ void ETSParser::ParseClassFieldDefiniton(ir::Identifier *fieldName, ir::Modifier // performed multiple times. if (initFunction != nullptr && (modifiers & ir::ModifierFlags::CONST) == 0U && initializer != nullptr && !initializer->IsArrowFunctionExpression()) { - if (auto *const funcBody = initFunction->Body(); funcBody != nullptr && funcBody->IsBlockStatement()) { - auto *ident = AllocNode(fieldName->Name(), Allocator()); - ident->SetReference(); - ident->SetRange(fieldName->Range()); - - auto *assignmentExpression = - AllocNode(ident, initializer, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - endLoc = initializer->End(); - assignmentExpression->SetRange({fieldName->Start(), endLoc}); - assignmentExpression->SetParent(funcBody); - - auto expressionStatement = AllocNode(assignmentExpression); - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { - endLoc = Lexer()->GetToken().End(); - } - expressionStatement->SetRange({startLoc, endLoc}); - funcBody->AsBlockStatement()->Statements().emplace_back(expressionStatement); - - if (typeAnnotation != nullptr && !typeAnnotation->IsETSFunctionType()) { - initializer = nullptr; - } - } + endLoc = InitializeGlobalVariable(fieldName, initializer, initFunction, startLoc, typeAnnotation); } bool isDeclare = (modifiers & ir::ModifierFlags::DECLARE) != 0; @@ -1334,10 +1339,41 @@ void ETSParser::ParseClassFieldDefiniton(ir::Identifier *fieldName, ir::Modifier if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { Lexer()->NextToken(); ir::Identifier *nextName = ExpectIdentifier(false, true); - ParseClassFieldDefiniton(nextName, modifiers, declarations); + ParseClassFieldDefinition(nextName, modifiers, declarations); } } +lexer::SourcePosition ETSParser::InitializeGlobalVariable(ir::Identifier *fieldName, ir::Expression *&initializer, + ir::ScriptFunction *initFunction, + lexer::SourcePosition &startLoc, ir::TypeNode *typeAnnotation) +{ + lexer::SourcePosition endLoc = startLoc; + + if (auto *const funcBody = initFunction->Body(); funcBody != nullptr && funcBody->IsBlockStatement()) { + auto *ident = AllocNode(fieldName->Name(), Allocator()); + ident->SetReference(); + ident->SetRange(fieldName->Range()); + + auto *assignmentExpression = + AllocNode(ident, initializer, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + endLoc = initializer->End(); + assignmentExpression->SetRange({fieldName->Start(), endLoc}); + assignmentExpression->SetParent(funcBody); + + auto expressionStatement = AllocNode(assignmentExpression); + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { + endLoc = Lexer()->GetToken().End(); + } + expressionStatement->SetRange({startLoc, endLoc}); + funcBody->AsBlockStatement()->Statements().emplace_back(expressionStatement); + + if (typeAnnotation != nullptr && !typeAnnotation->IsETSFunctionType()) { + initializer = nullptr; + } + } + return endLoc; +} + ir::MethodDefinition *ETSParser::ParseClassMethodDefinition(ir::Identifier *methodName, ir::ModifierFlags modifiers, ir::Identifier *className, ir::Identifier *identNode) { @@ -1552,8 +1588,10 @@ ir::AstNode *ETSParser::ParseClassElement([[maybe_unused]] const ArenaVectorRewind(savedPos); @@ -1578,6 +1616,9 @@ ir::AstNode *ETSParser::ParseClassElement([[maybe_unused]] const ArenaVectorGetToken().Type(); + if (type == lexer::TokenType::KEYW_FUNCTION || type == lexer::TokenType::KEYW_LET || + type == lexer::TokenType::KEYW_CONST) { + Lexer()->NextToken(); + } + } + + auto *memberName = ExpectIdentifier(); if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS || Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { @@ -1622,7 +1671,7 @@ ir::AstNode *ETSParser::ParseClassElement([[maybe_unused]] const ArenaVector fieldDeclarations(Allocator()->Adapter()); auto *placeholder = AllocNode(std::move(fieldDeclarations)); - ParseClassFieldDefiniton(memberName, memberModifiers, placeholder->BodyPtr()); + ParseClassFieldDefinition(memberName, memberModifiers, placeholder->BodyPtr()); return placeholder; } @@ -1728,6 +1777,15 @@ ir::Statement *ETSParser::ParseTypeDeclaration(bool allowStatic) case lexer::TokenType::KEYW_INTERFACE: { return ParseInterfaceDeclaration(false); } + case lexer::TokenType::KEYW_NAMESPACE: { + if (!InAmbientContext()) { + ThrowSyntaxError("Namespaces are declare only"); + } + GetContext().Status() |= ParserStatus::IN_NAMESPACE; + auto *ns = ParseClassDeclaration(modifiers, ir::ModifierFlags::STATIC); + GetContext().Status() &= ~ParserStatus::IN_NAMESPACE; + return ns; + } case lexer::TokenType::KEYW_CLASS: { return ParseClassDeclaration(modifiers); } @@ -1802,7 +1860,7 @@ ir::TSTypeAliasDeclaration *ETSParser::ParseTypeAliasDeclaration() auto options = TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE; ir::TSTypeParameterDeclaration *params = ParseTypeParameterDeclaration(&options); - typeAliasDecl->AddTypeParameters(params); + typeAliasDecl->SetTypeParameters(params); params->SetParent(typeAliasDecl); } @@ -2318,7 +2376,20 @@ std::string ETSParser::GetNameForTypeNode(const ir::TypeNode *typeAnnotation, bo } if (typeAnnotation->IsETSTypeReference()) { - return adjustNullish(typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8()); + std::string typeParamNames; + auto typeParam = typeAnnotation->AsETSTypeReference()->Part()->TypeParams(); + if (typeParam != nullptr && typeParam->IsTSTypeParameterInstantiation()) { + typeParamNames = "<"; + auto paramList = typeParam->Params(); + for (auto param : paramList) { + std::string typeParamName = GetNameForTypeNode(param); + typeParamNames += typeParamName + ","; + } + typeParamNames.pop_back(); + typeParamNames += ">"; + } + return adjustNullish(typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8() + + typeParamNames); } if (typeAnnotation->IsETSFunctionType()) { @@ -2742,17 +2813,7 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota switch (Lexer()->GetToken().Type()) { case lexer::TokenType::LITERAL_IDENT: { - if (const auto keyword = Lexer()->GetToken().KeywordType(); - keyword == lexer::TokenType::KEYW_IN || keyword == lexer::TokenType::KEYW_OUT) { - typeAnnotation = ParseWildcardType(options); - } else { - if (Lexer()->GetToken().IsDefinableTypeName()) { - typeAnnotation = GetTypeAnnotationOfPrimitiveType(Lexer()->GetToken().KeywordType(), options); - } else { - typeAnnotation = ParseTypeReference(options); - } - } - + typeAnnotation = ParseLiteralIdent(options); if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 && (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) { return std::make_pair(typeAnnotation, false); @@ -2811,17 +2872,7 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota typeAnnotation = ParseUnionType(typeAnnotation); } - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - if (((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0) { - ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); - } - - Lexer()->Rewind(savedPos); - typeAnnotation = nullptr; - } else { - Lexer()->NextToken(); // eat ')' - } - + ParseRightParenthesis(options, typeAnnotation, savedPos); break; } case lexer::TokenType::PUNCTUATOR_FORMAT: { @@ -2844,6 +2895,35 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota return std::make_pair(typeAnnotation, true); } +ir::TypeNode *ETSParser::ParseLiteralIdent(TypeAnnotationParsingOptions *options) +{ + if (const auto keyword = Lexer()->GetToken().KeywordType(); + keyword == lexer::TokenType::KEYW_IN || keyword == lexer::TokenType::KEYW_OUT) { + return ParseWildcardType(options); + } + + if (Lexer()->GetToken().IsDefinableTypeName()) { + return GetTypeAnnotationOfPrimitiveType(Lexer()->GetToken().KeywordType(), options); + } + + return ParseTypeReference(options); +} + +void ETSParser::ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&typeAnnotation, + lexer::LexerPosition savedPos) +{ + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + if (((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0) { + ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); + } + + Lexer()->Rewind(savedPos); + typeAnnotation = nullptr; + } else { + Lexer()->NextToken(); // eat ')' + } +} + ir::TypeNode *ETSParser::ParseThisType(TypeAnnotationParsingOptions *options) { ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS); @@ -3805,7 +3885,7 @@ ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags) return ParseCharLiteral(); } case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { - return ParseCoverParenthesizedExpressionAndArrowParameterList(); + return ParseCoverParenthesizedExpressionAndArrowParameterList(flags); } case lexer::TokenType::KEYW_THIS: { return ParseThisExpression(); @@ -3906,7 +3986,8 @@ ir::ArrowFunctionExpression *ETSParser::ParseArrowFunctionExpression() return arrowFuncNode; } -ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterList() +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags) { ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); if (IsArrowFunctionExpressionStart()) { @@ -3916,7 +3997,12 @@ ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterLis lexer::SourcePosition start = Lexer()->GetToken().Start(); Lexer()->NextToken(); - ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); + ExpressionParseFlags newFlags = ExpressionParseFlags::ACCEPT_COMMA; + if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) { + newFlags |= ExpressionParseFlags::INSTANCEOF; + }; + + ir::Expression *expr = ParseExpression(newFlags); if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { ThrowSyntaxError("Unexpected token, expected ')'"); @@ -4288,7 +4374,7 @@ ir::TSEnumDeclaration *ETSParser::ParseEnumMembers(ir::Identifier *const key, co } auto *const enumDeclaration = - AllocNode(Allocator(), key, std::move(members), isConst, isStatic); + AllocNode(Allocator(), key, std::move(members), isConst, isStatic, InAmbientContext()); enumDeclaration->SetRange({enumStart, Lexer()->GetToken().End()}); Lexer()->NextToken(); // eat '}' @@ -4594,6 +4680,24 @@ bool ETSParser::IsStructKeyword() const Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT); } +void ETSParser::ValidateInstanceOfExpression(ir::Expression *expr) +{ + ValidateGroupedExpression(expr); + lexer::TokenType tokenType = Lexer()->GetToken().Type(); + if (tokenType == lexer::TokenType::PUNCTUATOR_LESS_THAN) { + auto options = TypeAnnotationParsingOptions::NO_OPTS; + + // Run checks to validate type declarations + // Should provide helpful messages with incorrect declarations like the following: + // `instanceof A;` + ThrowSyntaxError("Invalid right-hand side in 'instanceof' expression"); + } +} + // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) { @@ -4605,6 +4709,10 @@ ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) } ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags); + if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) { + ValidateInstanceOfExpression(unaryExpressionNode); + } + ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags); if (Lexer()->GetToken().NewLine()) { @@ -4662,6 +4770,7 @@ void ETSParser::CheckDeclare() case lexer::TokenType::KEYW_CLASS: case lexer::TokenType::KEYW_NAMESPACE: case lexer::TokenType::KEYW_ENUM: + case lexer::TokenType::KEYW_TYPE: case lexer::TokenType::KEYW_ABSTRACT: case lexer::TokenType::KEYW_INTERFACE: { return; diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 8fb369d0c28f815afa56ad64f269bd1cd8c7e353..c271015998c940ceba16847e1789da99dc44fa9c 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -17,6 +17,7 @@ #define ES2PANDA_PARSER_CORE_ETS_PARSER_H #include +#include "parserFlags.h" #include "util/arktsconfig.h" #include "TypedParser.h" @@ -105,6 +106,13 @@ private: [[nodiscard]] std::unique_ptr InitLexer(const SourceFile &sourceFile) override; void ParsePackageDeclaration(ArenaVector &statements); ArenaVector ParseTopLevelStatements(ArenaVector &statements); + void ParseTopLevelType(ArenaVector &statements, bool &defaultExport, std::size_t currentPos, + std::function const &parserFunction); + void ParseTopLevelNextToken(ArenaVector &statements, ArenaVector &globalProperties, + ir::ScriptFunction *initFunction); + void ParseTokenOfNative(panda::es2panda::lexer::TokenType tokenType, ir::ModifierFlags &memberModifiers); + void ParseTokenOfFunction(ir::ModifierFlags memberModifiers, lexer::SourcePosition startLoc, + ArenaVector &globalProperties); #ifdef USE_FTW static int NFTWCallBack(const char *fpath, const struct stat * /*unused*/, int tflag, struct FTW * /*unused*/); #endif @@ -159,9 +167,12 @@ private: ir::Expression *CreateParameterThis(util::StringView className) override; // NOLINTNEXTLINE(google-default-arguments) - void ParseClassFieldDefiniton(ir::Identifier *fieldName, ir::ModifierFlags modifiers, - ArenaVector *declarations, ir::ScriptFunction *initFunction = nullptr, - lexer::SourcePosition *letLoc = nullptr); + void ParseClassFieldDefinition(ir::Identifier *fieldName, ir::ModifierFlags modifiers, + ArenaVector *declarations, ir::ScriptFunction *initFunction = nullptr, + lexer::SourcePosition *letLoc = nullptr); + lexer::SourcePosition InitializeGlobalVariable(ir::Identifier *fieldName, ir::Expression *&initializer, + ir::ScriptFunction *initFunction, lexer::SourcePosition &startLoc, + ir::TypeNode *typeAnnotation); std::tuple ParseTypeReferencePart( TypeAnnotationParsingOptions *options); ir::TypeNode *ParseTypeReference(TypeAnnotationParsingOptions *options); @@ -187,12 +198,17 @@ private: void ThrowIfVarDeclaration(VariableParsingFlags flags) override; std::pair GetTypeAnnotationFromToken(TypeAnnotationParsingOptions *options); + ir::TypeNode *ParseLiteralIdent(TypeAnnotationParsingOptions *options); + void ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&typeAnnotation, + lexer::LexerPosition savedPos); ir::TypeNode *ParseTypeAnnotation(TypeAnnotationParsingOptions *options) override; ir::TSTypeAliasDeclaration *ParseTypeAliasDeclaration() override; void ValidateForInStatement() override; - ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList() override; + // NOLINTNEXTLINE(google-default-arguments) + ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList( + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; ir::Statement *ParseTryStatement() override; ir::DebuggerStatement *ParseDebuggerStatement() override; void ParseExport(lexer::SourcePosition startLoc); @@ -264,6 +280,7 @@ private: // NOLINTNEXTLINE(google-default-arguments) ir::Statement *ParseEnumDeclaration(bool isConst = false, bool isStatic = false) override; ir::Expression *ParseLaunchExpression(ExpressionParseFlags flags); + void ValidateInstanceOfExpression(ir::Expression *expr); void ValidateRestParameter(ir::Expression *param) override; void CheckIndexAccessMethod(ir::ScriptFunction const *function, const lexer::SourcePosition &position) const; @@ -338,6 +355,7 @@ private: ir::TypeNode *CreateTypeAnnotation(TypeAnnotationParsingOptions *options, std::string_view sourceCode, std::string_view fileName = DEFAULT_SOURCE_FILE); // NOLINTEND(google-default-arguments) + friend class ExternalSourceParser; friend class InnerSourceParser; diff --git a/ets2panda/parser/TSparser.cpp b/ets2panda/parser/TSparser.cpp index fc337a581f20108da9fe57a268281b85f877bbb0..fc0ffe75e3c3d56fc6776eb8e830feb394e75dd6 100644 --- a/ets2panda/parser/TSparser.cpp +++ b/ets2panda/parser/TSparser.cpp @@ -15,6 +15,7 @@ #include "TSparser.h" +#include "parserFlags.h" #include "util/helpers.h" #include "varbinder/privateBinding.h" #include "varbinder/scope.h" @@ -2598,54 +2599,68 @@ ir::Statement *TSParser::ParseExportDeclaration(StatementParsingFlags flags) } } -ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList() +ir::Expression *TSParser::ParseArrowFunctionRestParameter(lexer::SourcePosition start) { - ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); - lexer::SourcePosition start = Lexer()->GetToken().Start(); - Lexer()->NextToken(); - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN); - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { - ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN); + restElement->SetGrouped(); + restElement->SetStart(start); - restElement->SetGrouped(); - restElement->SetStart(start); + ValidateArrowFunctionRestParameter(restElement); - ValidateArrowFunctionRestParameter(restElement); + Lexer()->NextToken(); - Lexer()->NextToken(); + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + ir::TypeNode *returnTypeAnnotation = nullptr; + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + Lexer()->NextToken(); // eat ':' + returnTypeAnnotation = ParseTypeAnnotation(&options); + } - ir::TypeNode *returnTypeAnnotation = nullptr; - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - Lexer()->NextToken(); // eat ':' - returnTypeAnnotation = ParseTypeAnnotation(&options); - } + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + ThrowSyntaxError("Unexpected token"); + } - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { - ThrowSyntaxError("Unexpected token"); - } + return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false); +} + +ir::Expression *TSParser::ParseArrowFunctionNoParameter(lexer::SourcePosition start) +{ + Lexer()->NextToken(); - return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false); + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + ir::TypeNode *returnTypeAnnotation = nullptr; + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + Lexer()->NextToken(); // eat ':' + returnTypeAnnotation = ParseTypeAnnotation(&options); } - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - Lexer()->NextToken(); + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + ThrowSyntaxError("Unexpected token"); + } - ir::TypeNode *returnTypeAnnotation = nullptr; - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - Lexer()->NextToken(); // eat ':' - returnTypeAnnotation = ParseTypeAnnotation(&options); - } + auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false); + arrowExpr->SetStart(start); + arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start); - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { - ThrowSyntaxError("Unexpected token"); - } + return arrowExpr; +} - auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false); - arrowExpr->SetStart(start); - arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start); +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList( + [[maybe_unused]] ExpressionParseFlags flags) +{ + ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); + lexer::SourcePosition start = Lexer()->GetToken().Start(); + Lexer()->NextToken(); + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - return arrowExpr; + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { + return ParseArrowFunctionRestParameter(start); + } + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + return ParseArrowFunctionNoParameter(start); } ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST | diff --git a/ets2panda/parser/TSparser.h b/ets2panda/parser/TSparser.h index 916abde6242ad7e8c9d13520dafae7d3b8fa9462..76a2dd47cf59630e8cc60a149a3817d2a2309ee8 100644 --- a/ets2panda/parser/TSparser.h +++ b/ets2panda/parser/TSparser.h @@ -17,6 +17,7 @@ #define ES2PANDA_PARSER_CORE_TS_PARSER_H #include "TypedParser.h" +#include "parserFlags.h" namespace panda::es2panda::ir { class Decorator; @@ -121,7 +122,11 @@ private: const ArenaVector ¶ms, ParserStatus newStatus, ParserStatus contextStatus) override; ir::AstNode *ParseImportDefaultSpecifier(ArenaVector *specifiers) override; ir::Statement *ParseExportDeclaration(StatementParsingFlags flags) override; - ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList() override; + // NOLINTNEXTLINE(google-default-arguments) + ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList( + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; + ir::Expression *ParseArrowFunctionRestParameter(lexer::SourcePosition start); + ir::Expression *ParseArrowFunctionNoParameter(lexer::SourcePosition start); ir::Statement *ParseConstStatement(StatementParsingFlags flags) override; ir::Statement *ParsePotentialConstEnum(VariableParsingFlags flags) override; void ParseCatchParamTypeAnnotation(ir::AnnotatedExpression *param) override; diff --git a/ets2panda/parser/context/parserContext.h b/ets2panda/parser/context/parserContext.h index 3176b9f922b1718763329ec3b0097657016d52be..bf8f42719c5c4bcf2b4ce3d4fca5accb4c1eef93 100644 --- a/ets2panda/parser/context/parserContext.h +++ b/ets2panda/parser/context/parserContext.h @@ -26,7 +26,7 @@ namespace panda::es2panda::parser { class Program; -enum class ParserStatus : uint32_t { +enum class ParserStatus : uint64_t { NO_OPTS = 0U, DIRECT_EVAL = 1U << 0U, @@ -65,6 +65,7 @@ enum class ParserStatus : uint32_t { IN_DEFAULT_IMPORTS = 1U << 29U, IN_EXTENSION_FUNCTION = 1U << 30U, FUNCTION_HAS_RETURN_STATEMENT = 1U << 31U, + IN_NAMESPACE = 1ULL << 32ULL, }; DEFINE_BITOPS(ParserStatus) diff --git a/ets2panda/parser/expressionParser.cpp b/ets2panda/parser/expressionParser.cpp index 56bd5ec91c56f1c378a7a6caa1dd114c165f25b9..51c3d7c837eaa5f15127388097c16c34db725a51 100644 --- a/ets2panda/parser/expressionParser.cpp +++ b/ets2panda/parser/expressionParser.cpp @@ -420,7 +420,9 @@ void ParserImpl::ValidateArrowFunctionRestParameter([[maybe_unused]] ir::SpreadE } } -ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterList() +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterList( + [[maybe_unused]] ExpressionParseFlags flags) { ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); lexer::SourcePosition start = lexer_->GetToken().Start(); @@ -492,6 +494,20 @@ void ParserImpl::CheckInvalidDestructuring(const ir::AstNode *object) const }); } +void ParserImpl::ValidateGroupedExpression(ir::Expression *lhsExpression) +{ + lexer::TokenType tokenType = lexer_->GetToken().Type(); + if (lhsExpression->IsGrouped() && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) { + if (lhsExpression->IsSequenceExpression()) { + for (auto *seq : lhsExpression->AsSequenceExpression()->Sequence()) { + ValidateParenthesizedExpression(seq); + } + } else { + ValidateParenthesizedExpression(lhsExpression); + } + } +} + void ParserImpl::ValidateParenthesizedExpression(ir::Expression *lhsExpression) { switch (lhsExpression->Type()) { @@ -542,17 +558,9 @@ ir::Expression *ParserImpl::ParsePrefixAssertionExpression() ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpression, ExpressionParseFlags flags) { - lexer::TokenType tokenType = lexer_->GetToken().Type(); - if (lhsExpression->IsGrouped() && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) { - if (lhsExpression->IsSequenceExpression()) { - for (auto *seq : lhsExpression->AsSequenceExpression()->Sequence()) { - ValidateParenthesizedExpression(seq); - } - } else { - ValidateParenthesizedExpression(lhsExpression); - } - } + ValidateGroupedExpression(lhsExpression); + lexer::TokenType tokenType = lexer_->GetToken().Type(); switch (tokenType) { case lexer::TokenType::PUNCTUATOR_QUESTION_MARK: { lexer_->NextToken(); @@ -1191,7 +1199,7 @@ void ParserImpl::CreateAmendedBinaryExpression(ir::Expression *const left, ir::E SetAmendedChildExpression(right, binaryExpr); } -ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left) +ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left, ExpressionParseFlags flags) { lexer::TokenType operatorType = lexer_->GetToken().Type(); ASSERT(lexer::Token::IsBinaryToken(operatorType)); @@ -1206,7 +1214,12 @@ ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left) lexer_->NextToken(); - ir::Expression *rightExpr = ParseExpression(ExpressionParseFlags::DISALLOW_YIELD); + ExpressionParseFlags newFlags = ExpressionParseFlags::DISALLOW_YIELD; + if ((operatorType == lexer::TokenType::KEYW_INSTANCEOF) || ((flags & ExpressionParseFlags::INSTANCEOF) != 0)) { + newFlags |= ExpressionParseFlags::INSTANCEOF; + } + + ir::Expression *rightExpr = ParseExpression(newFlags); ir::ConditionalExpression *conditionalExpr = nullptr; if (rightExpr->IsConditionalExpression() && !rightExpr->IsGrouped()) { diff --git a/ets2panda/parser/parserFlags.h b/ets2panda/parser/parserFlags.h index 792114ad56d706b46972c37cd16270c3df4620e1..6d71e66beb91d4ecb995e92a8deac4f4a3304269 100644 --- a/ets2panda/parser/parserFlags.h +++ b/ets2panda/parser/parserFlags.h @@ -60,6 +60,7 @@ enum class ExpressionParseFlags : uint32_t { IMPORT = 1U << 10U, POTENTIAL_CLASS_LITERAL = 1U << 11U, IN_FOR = 1U << 12U, + INSTANCEOF = 1U << 13U, }; DEFINE_BITOPS(ExpressionParseFlags) diff --git a/ets2panda/parser/parserImpl.h b/ets2panda/parser/parserImpl.h index 1965b6dcd5d1131c716befa9ea0fff8ceed162bd..b73e0aa8fab7a4fec8e886e37b1376dc7f9954cc 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -227,13 +227,15 @@ protected: // ExpressionParser.Cpp ir::Expression *ParseKeywordExpression(); - ir::Expression *ParseBinaryExpression(ir::Expression *left); + ir::Expression *ParseBinaryExpression(ir::Expression *left, + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); void ValidateUpdateExpression(ir::Expression *returnExpression, bool isChainExpression); ir::Expression *ParseMemberExpression(bool ignoreCallExpression = false, ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); ir::MetaProperty *ParsePotentialNewTarget(); void CheckInvalidDestructuring(const ir::AstNode *object) const; void ValidateParenthesizedExpression(ir::Expression *lhsExpression); + void ValidateGroupedExpression(ir::Expression *lhsExpression); ir::Expression *ParseImportExpression(); ir::Expression *ParseOptionalChain(ir::Expression *leftSideExpr); ir::Expression *ParsePropertyKey(ExpressionParseFlags flags); @@ -480,7 +482,9 @@ protected: virtual void ThrowIllegalNewLineErrorAfterThrow(); virtual void ThrowIfVarDeclaration(VariableParsingFlags flags); virtual ir::Expression *ParsePrefixAssertionExpression(); - virtual ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList(); + // NOLINTNEXTLINE(google-default-arguments) + virtual ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList( + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); virtual void ThrowErrorIfStaticConstructor(ir::ModifierFlags flags); virtual std::tuple ParseComputedClassFieldOrIndexSignature(ir::Expression **propName); // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 61605f9160487959a505ee50debbd5772603f62c..048c7cd93fc1a43c991491ab909f8dede5d227fd 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -129,34 +129,6 @@ static char const *ArenaStrdup(ArenaAllocator *allocator, char const *src) return res; } -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FOR_ALL_MODIFIER_FLAGS(_) \ - _(STATIC) \ - _(ASYNC) \ - _(PUBLIC) \ - _(PROTECTED) \ - _(PRIVATE) \ - _(DECLARE) \ - _(READONLY) \ - _(OPTIONAL) \ - _(DEFINITE) \ - _(ABSTRACT) \ - _(CONST) \ - _(FINAL) \ - _(NATIVE) \ - _(OVERRIDE) \ - _(CONSTRUCTOR) \ - _(SYNCHRONIZED) \ - _(FUNCTIONAL) \ - _(IN) \ - _(OUT) \ - _(INTERNAL) \ - _(NULL_ASSIGNABLE) \ - _(UNDEFINED_ASSIGNABLE) \ - _(EXPORT) \ - _(SETTER) \ - _(DEFAULT_EXPORT) - static ir::ModifierFlags E2pToIrModifierFlags(es2panda_ModifierFlags e2p_flags) { ir::ModifierFlags ir_flags {ir::ModifierFlags::NONE}; @@ -191,30 +163,6 @@ static es2panda_ModifierFlags IrToE2pModifierFlags(ir::ModifierFlags ir_flags) return e2p_flags; } -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FOR_ALL_SCRIPT_FUNCTION_FLAGS(_) \ - _(GENERATOR) \ - _(ASYNC) \ - _(ARROW) \ - _(EXPRESSION) \ - _(OVERLOAD) \ - _(CONSTRUCTOR) \ - _(METHOD) \ - _(STATIC_BLOCK) \ - _(HIDDEN) \ - _(IMPLICIT_SUPER_CALL_NEEDED) \ - _(ENUM) \ - _(EXTERNAL) \ - _(PROXY) \ - _(THROWS) \ - _(RETHROWS) \ - _(GETTER) \ - _(SETTER) \ - _(DEFAULT_PARAM_PROXY) \ - _(ENTRY_POINT) \ - _(INSTANCE_EXTENSION_METHOD) \ - _(HAS_RETURN) - static ir::ScriptFunctionFlags E2pToIrScriptFunctionFlags(es2panda_ScriptFunctionFlags e2p_flags) { ir::ScriptFunctionFlags ir_flags {ir::ScriptFunctionFlags::NONE}; @@ -398,7 +346,7 @@ static Context *InitScopes(Context *ctx) ASSERT(ctx->state == ES2PANDA_STATE_PARSED); try { - compiler::ScopesInitPhaseETS scopesInit; + compiler::InitScopesPhaseETS scopesInit; scopesInit.Perform(ctx, ctx->parserProgram); do { if (ctx->currentPhase >= ctx->phases.size()) { @@ -1467,13 +1415,6 @@ extern "C" es2panda_AstNode *ImportSpecifierLocal(es2panda_AstNode *ast) return reinterpret_cast(node->Local()); } -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FOR_ALL_MEMBER_EXPRESSION_KINDS(_) \ - _(ELEMENT_ACCESS) \ - _(PROPERTY_ACCESS) \ - _(GETTER) \ - _(SETTER) - static ir::MemberExpressionKind E2pToIrMemberExpressionKind(es2panda_MemberExpressionKind e2p_kind) { ir::MemberExpressionKind ir_kind = ir::MemberExpressionKind::NONE; diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index c28f1e708bb70b292dd0eea0e7751f6a3b7150be..fcbd4db52b34a38384d24587cecbe9dcb4217e89 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -28,6 +28,65 @@ extern "C" { #define ES2PANDA_LIB_VERSION 1 +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define FOR_ALL_MODIFIER_FLAGS(_) \ + _(STATIC) \ + _(ASYNC) \ + _(PUBLIC) \ + _(PROTECTED) \ + _(PRIVATE) \ + _(DECLARE) \ + _(READONLY) \ + _(OPTIONAL) \ + _(DEFINITE) \ + _(ABSTRACT) \ + _(CONST) \ + _(FINAL) \ + _(NATIVE) \ + _(OVERRIDE) \ + _(CONSTRUCTOR) \ + _(SYNCHRONIZED) \ + _(FUNCTIONAL) \ + _(IN) \ + _(OUT) \ + _(INTERNAL) \ + _(NULL_ASSIGNABLE) \ + _(UNDEFINED_ASSIGNABLE) \ + _(EXPORT) \ + _(SETTER) \ + _(DEFAULT_EXPORT) + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define FOR_ALL_SCRIPT_FUNCTION_FLAGS(_) \ + _(GENERATOR) \ + _(ASYNC) \ + _(ARROW) \ + _(EXPRESSION) \ + _(OVERLOAD) \ + _(CONSTRUCTOR) \ + _(METHOD) \ + _(STATIC_BLOCK) \ + _(HIDDEN) \ + _(IMPLICIT_SUPER_CALL_NEEDED) \ + _(ENUM) \ + _(EXTERNAL) \ + _(PROXY) \ + _(THROWS) \ + _(RETHROWS) \ + _(GETTER) \ + _(SETTER) \ + _(DEFAULT_PARAM_PROXY) \ + _(ENTRY_POINT) \ + _(INSTANCE_EXTENSION_METHOD) \ + _(HAS_RETURN) + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define FOR_ALL_MEMBER_EXPRESSION_KINDS(_) \ + _(ELEMENT_ACCESS) \ + _(PROPERTY_ACCESS) \ + _(GETTER) \ + _(SETTER) + typedef struct es2panda_Config es2panda_Config; typedef struct es2panda_Context es2panda_Context; diff --git a/ets2panda/test/compiler/ets/StructTest1-expected.txt b/ets2panda/test/compiler/ets/StructTest1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..50b26e476663ff7fed5b30f4c80a94562f4b5271 --- /dev/null +++ b/ets2panda/test/compiler/ets/StructTest1-expected.txt @@ -0,0 +1,1216 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "CommonStruct0", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 20 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "K", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 20 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "value": { + "type": "NumberLiteral", + "value": 5, + "loc": { + "start": { + "line": 17, + "column": 20 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 19 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "GetF", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "GetF", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 20 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 20 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 20 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "property": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 22 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 24 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 20, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 20, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 20, + "column": 5 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 4 + }, + "end": { + "line": 20, + "column": 5 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 2 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 24 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + { + "type": "ETSStructDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "CE", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 23, + "column": 10 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "CommonStruct0", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "CE", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "x", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 6 + }, + "end": { + "line": 24, + "column": 7 + } + } + }, + "value": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 24, + "column": 15 + }, + "end": { + "line": 24, + "column": 16 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 14 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 6 + }, + "end": { + "line": 24, + "column": 16 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 2 + }, + "end": { + "line": 25, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "CE", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 11 + }, + "end": { + "line": 28, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 11 + }, + "end": { + "line": 28, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 11 + }, + "end": { + "line": 28, + "column": 15 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 8 + }, + "end": { + "line": 28, + "column": 9 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "CE", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 20 + }, + "end": { + "line": 28, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 20 + }, + "end": { + "line": 28, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 20 + }, + "end": { + "line": 28, + "column": 23 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 28, + "column": 16 + }, + "end": { + "line": 28, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 8 + }, + "end": { + "line": 28, + "column": 23 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 28, + "column": 4 + }, + "end": { + "line": 28, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 23 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } +} diff --git a/ets2panda/test/compiler/ets/StructTest1.ets b/ets2panda/test/compiler/ets/StructTest1.ets new file mode 100644 index 0000000000000000000000000000000000000000..711e89a2f60e391f9671898148513d59c63b3574 --- /dev/null +++ b/ets2panda/test/compiler/ets/StructTest1.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class CommonStruct0 { + public f: Int = 5; + public GetF() : Int { + return this.f; + } +} + +struct CE { + x: Int = 1; +} + +function main(): void { + let a: CE = new CE; +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/StructTest2-expected.txt b/ets2panda/test/compiler/ets/StructTest2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..5e9b0511ba87bcf0eed5836f040fb28a52ed588d --- /dev/null +++ b/ets2panda/test/compiler/ets/StructTest2-expected.txt @@ -0,0 +1,1413 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "CommonStruct0", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 20 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "K", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 20 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "value": { + "type": "NumberLiteral", + "value": 5, + "loc": { + "start": { + "line": 17, + "column": 20 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 19 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "GetF", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "GetF", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 11 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 20 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 20 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 20 + }, + "end": { + "line": 18, + "column": 25 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "property": { + "type": "Identifier", + "name": "f", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 22 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 24 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 24 + }, + "end": { + "line": 20, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 20, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 20, + "column": 5 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 4 + }, + "end": { + "line": 20, + "column": 5 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 2 + }, + "end": { + "line": 21, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 24 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 21, + "column": 2 + } + } + }, + { + "type": "ETSStructDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "CE", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 23, + "column": 10 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "K", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 23, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 23, + "column": 13 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 10 + }, + "end": { + "line": 23, + "column": 13 + } + } + }, + "superClass": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "CommonStruct0", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "CE", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "K", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "x", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 6 + }, + "end": { + "line": 24, + "column": 7 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "K", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 10 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 11 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 6 + }, + "end": { + "line": 24, + "column": 11 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 2 + }, + "end": { + "line": 25, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 14 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 10 + }, + "end": { + "line": 27, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 18 + }, + "end": { + "line": 27, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "CE", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 11 + }, + "end": { + "line": 28, + "column": 13 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 14 + }, + "end": { + "line": 28, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 14 + }, + "end": { + "line": 28, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 14 + }, + "end": { + "line": 28, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 28, + "column": 13 + }, + "end": { + "line": 28, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 11 + }, + "end": { + "line": 28, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 11 + }, + "end": { + "line": 28, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 8 + }, + "end": { + "line": 28, + "column": 9 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "CE", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 25 + }, + "end": { + "line": 28, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 28 + }, + "end": { + "line": 28, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 28 + }, + "end": { + "line": 28, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 28 + }, + "end": { + "line": 28, + "column": 32 + } + } + } + ], + "loc": { + "start": { + "line": 28, + "column": 27 + }, + "end": { + "line": 28, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 25 + }, + "end": { + "line": 28, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 25 + }, + "end": { + "line": 28, + "column": 33 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 28, + "column": 21 + }, + "end": { + "line": 28, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 8 + }, + "end": { + "line": 28, + "column": 35 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 28, + "column": 4 + }, + "end": { + "line": 28, + "column": 35 + } + } + } + ], + "loc": { + "start": { + "line": 27, + "column": 23 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 14 + }, + "end": { + "line": 29, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + } +} diff --git a/ets2panda/test/compiler/ets/StructTest2.ets b/ets2panda/test/compiler/ets/StructTest2.ets new file mode 100644 index 0000000000000000000000000000000000000000..88f388511e85094318b35186973240488012fd58 --- /dev/null +++ b/ets2panda/test/compiler/ets/StructTest2.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class CommonStruct0 { + public f: Int = 5; + public GetF() : Int { + return this.f; + } +} + +struct CE { + x: K; +} + +function main(): void { + let a: CE = new CE(); +} \ No newline at end of file diff --git a/ets2panda/test/compiler/ets/class_def_varargs_1-expected.txt b/ets2panda/test/compiler/ets/class_def_varargs_1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..a040ec69693735dbc6f57651a4bfecfde3ac5c79 --- /dev/null +++ b/ets2panda/test/compiler/ets/class_def_varargs_1-expected.txt @@ -0,0 +1,916 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "Foo", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 10 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 13 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 13 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "rest parameter": { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "o", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 20 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 26 + }, + "end": { + "line": 17, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 27 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 27 + } + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 17, + "column": 28 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "of", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "of", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "rest parameter": { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "vl", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 21 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 30 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 31 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Foo", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 34 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 38 + }, + "end": { + "line": 18, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 38 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 38 + }, + "end": { + "line": 18, + "column": 40 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 37 + }, + "end": { + "line": 18, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 34 + }, + "end": { + "line": 18, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 34 + }, + "end": { + "line": 18, + "column": 42 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 18, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 18, + "column": 17 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "r", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 15 + }, + "end": { + "line": 19, + "column": 16 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Foo", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 26 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 27 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 27 + }, + "end": { + "line": 19, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 27 + }, + "end": { + "line": 19, + "column": 29 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 26 + }, + "end": { + "line": 19, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 23 + }, + "end": { + "line": 19, + "column": 30 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 19, + "column": 19 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 15 + }, + "end": { + "line": 20, + "column": 15 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 20, + "column": 15 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "r", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 17 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 41 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 21, + "column": 6 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 23, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/class_def_varargs_1.ets b/ets2panda/test/compiler/ets/class_def_varargs_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..1bfff1689091f24049947c64dd6c31f370a55ce7 --- /dev/null +++ b/ets2panda/test/compiler/ets/class_def_varargs_1.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class Foo { + constructor(...o: T[]) {} + static of(...vl: int[]) : Foo { + const r = new Foo() + return r + } +} diff --git a/ets2panda/test/compiler/ets/class_def_varargs_2-expected.txt b/ets2panda/test/compiler/ets/class_def_varargs_2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..6cdfc1a60f600ee63e897c7bb670488f67b6bad7 --- /dev/null +++ b/ets2panda/test/compiler/ets/class_def_varargs_2-expected.txt @@ -0,0 +1,721 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "rest parameter": { + "type": "RestElement", + "argument": { + "type": "Identifier", + "name": "items", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 26 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 28 + }, + "end": { + "line": 17, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 28 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 28 + }, + "end": { + "line": 17, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 36 + }, + "end": { + "line": 17, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 37 + } + } + } + ], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 17, + "column": 37 + }, + "end": { + "line": 17, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 39 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 39 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 21, + "column": 10 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 17 + }, + "end": { + "line": 21, + "column": 19 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 21, + "column": 13 + }, + "end": { + "line": 21, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 21, + "column": 19 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 21, + "column": 5 + }, + "end": { + "line": 21, + "column": 19 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "right": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 13 + }, + "end": { + "line": 22, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 13 + }, + "end": { + "line": 22, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 13 + }, + "end": { + "line": 22, + "column": 15 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 22, + "column": 15 + }, + "end": { + "line": 22, + "column": 16 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 19 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 22, + "column": 21 + }, + "end": { + "line": 22, + "column": 22 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 23, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 23, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 24, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/class_def_varargs_2.ets b/ets2panda/test/compiler/ets/class_def_varargs_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..46f74c9970d3c0abd6b8a1824a0f8fb5c1a598bf --- /dev/null +++ b/ets2panda/test/compiler/ets/class_def_varargs_2.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + constructor(... items :Object[]){} +} + +function main() { + let a = new A; + a = new A(1, 2, 3) +} diff --git a/ets2panda/test/compiler/ets/override18-expected.txt b/ets2panda/test/compiler/ets/override18-expected.txt index 198ef735ad261d2facf5a02cc7b7419c8013d6ab..a3d01a0fb6531e631db5cadfe0e58d4eefa8f134 100644 --- a/ets2panda/test/compiler/ets/override18-expected.txt +++ b/ets2panda/test/compiler/ets/override18-expected.txt @@ -174,7 +174,7 @@ "type": "MethodDefinition", "key": { "type": "Identifier", - "name": "hashCode", + "name": "$_hashCode", "decorators": [], "loc": { "start": { @@ -183,7 +183,7 @@ }, "end": { "line": 20, - "column": 13 + "column": 15 } } }, @@ -198,7 +198,7 @@ "type": "ScriptFunction", "id": { "type": "Identifier", - "name": "hashCode", + "name": "$_hashCode", "decorators": [], "loc": { "start": { @@ -207,7 +207,7 @@ }, "end": { "line": 20, - "column": 13 + "column": 15 } } }, @@ -220,11 +220,11 @@ "loc": { "start": { "line": 20, - "column": 16 + "column": 18 }, "end": { "line": 20, - "column": 19 + "column": 21 } } }, @@ -263,7 +263,7 @@ "loc": { "start": { "line": 20, - "column": 19 + "column": 21 }, "end": { "line": 22, @@ -274,7 +274,7 @@ "loc": { "start": { "line": 20, - "column": 13 + "column": 15 }, "end": { "line": 22, @@ -285,7 +285,7 @@ "loc": { "start": { "line": 20, - "column": 13 + "column": 15 }, "end": { "line": 22, @@ -907,7 +907,7 @@ }, "property": { "type": "Identifier", - "name": "hashCode", + "name": "$_hashCode", "decorators": [], "loc": { "start": { @@ -916,7 +916,7 @@ }, "end": { "line": 30, - "column": 22 + "column": 24 } } }, @@ -929,7 +929,7 @@ }, "end": { "line": 30, - "column": 22 + "column": 24 } } }, @@ -942,7 +942,7 @@ }, "end": { "line": 30, - "column": 24 + "column": 26 } } }, @@ -952,11 +952,11 @@ "loc": { "start": { "line": 30, - "column": 28 + "column": 30 }, "end": { "line": 30, - "column": 29 + "column": 31 } } }, @@ -967,7 +967,7 @@ }, "end": { "line": 30, - "column": 29 + "column": 31 } } }, @@ -979,7 +979,7 @@ }, "end": { "line": 30, - "column": 29 + "column": 31 } } } diff --git a/ets2panda/test/compiler/ets/override18.ets b/ets2panda/test/compiler/ets/override18.ets index f822161147eaacbe0a090193f48a14175aa6faf3..e6494ec0c68e3b510978b279b4be6af56ef5576d 100644 --- a/ets2panda/test/compiler/ets/override18.ets +++ b/ets2panda/test/compiler/ets/override18.ets @@ -17,7 +17,7 @@ interface J{ toString(): String { return ""; } - hashCode():int{ + $_hashCode():int{ return 4; } } @@ -27,5 +27,5 @@ class JImpl implements J{ function main(): void { let o: JImpl = new JImpl() - assert o.hashCode() == 4 + assert o.$_hashCode() == 4 } diff --git a/ets2panda/test/compiler/ets/override19-expected.txt b/ets2panda/test/compiler/ets/override19-expected.txt index b7d5f654a9fea727af8638d2605d02b2458c2037..c84d6058093bd1380b95849f3d614c84b4a86138 100644 --- a/ets2panda/test/compiler/ets/override19-expected.txt +++ b/ets2panda/test/compiler/ets/override19-expected.txt @@ -189,7 +189,7 @@ "type": "MethodDefinition", "key": { "type": "Identifier", - "name": "hashCode", + "name": "$_hashCode", "decorators": [], "loc": { "start": { @@ -198,7 +198,7 @@ }, "end": { "line": 20, - "column": 22 + "column": 24 } } }, @@ -213,7 +213,7 @@ "type": "ScriptFunction", "id": { "type": "Identifier", - "name": "hashCode", + "name": "$_hashCode", "decorators": [], "loc": { "start": { @@ -222,7 +222,7 @@ }, "end": { "line": 20, - "column": 22 + "column": 24 } } }, @@ -235,11 +235,11 @@ "loc": { "start": { "line": 20, - "column": 26 + "column": 28 }, "end": { "line": 20, - "column": 29 + "column": 31 } } }, @@ -277,7 +277,7 @@ "loc": { "start": { "line": 20, - "column": 30 + "column": 32 }, "end": { "line": 22, @@ -288,7 +288,7 @@ "loc": { "start": { "line": 20, - "column": 22 + "column": 24 }, "end": { "line": 22, @@ -299,7 +299,7 @@ "loc": { "start": { "line": 20, - "column": 22 + "column": 24 }, "end": { "line": 22, @@ -983,7 +983,7 @@ }, "property": { "type": "Identifier", - "name": "hashCode", + "name": "$_hashCode", "decorators": [], "loc": { "start": { @@ -992,7 +992,7 @@ }, "end": { "line": 30, - "column": 22 + "column": 24 } } }, @@ -1005,7 +1005,7 @@ }, "end": { "line": 30, - "column": 22 + "column": 24 } } }, @@ -1018,7 +1018,7 @@ }, "end": { "line": 30, - "column": 24 + "column": 26 } } }, @@ -1028,11 +1028,11 @@ "loc": { "start": { "line": 30, - "column": 28 + "column": 30 }, "end": { "line": 30, - "column": 29 + "column": 31 } } }, @@ -1043,7 +1043,7 @@ }, "end": { "line": 30, - "column": 29 + "column": 31 } } }, @@ -1055,7 +1055,7 @@ }, "end": { "line": 30, - "column": 29 + "column": 31 } } } diff --git a/ets2panda/test/compiler/ets/override19.ets b/ets2panda/test/compiler/ets/override19.ets index 45fb347bb3336291c29c35c81105b83c0a99de23..81a746586769ae009e53238a0f9dac6fbf5c57fb 100644 --- a/ets2panda/test/compiler/ets/override19.ets +++ b/ets2panda/test/compiler/ets/override19.ets @@ -17,7 +17,7 @@ class O{ override toString(): String { return ""; } - override hashCode(): int { + override $_hashCode(): int { return 4; } } @@ -27,5 +27,5 @@ class OExt extends O{ function main(): void { let o: OExt = new OExt() - assert o.hashCode() == 4 + assert o.$_hashCode() == 4 } diff --git a/ets2panda/test/compiler/ets/tuple_types_17-expected.txt b/ets2panda/test/compiler/ets/tuple_types_17-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..9ed30ce235a5fc15625b543517da5111b31314ff --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_17-expected.txt @@ -0,0 +1,543 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Two", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 9 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 13 + }, + "end": { + "line": 16, + "column": 17 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 28 + }, + "end": { + "line": 16, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 28 + }, + "end": { + "line": 16, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 28 + }, + "end": { + "line": 16, + "column": 35 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 18 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "t", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Two", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + { + "type": "StringLiteral", + "value": "Test", + "loc": { + "start": { + "line": 18, + "column": 30 + }, + "end": { + "line": 18, + "column": 36 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 18 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 37 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 38 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 20, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_17.ets b/ets2panda/test/compiler/ets/tuple_types_17.ets new file mode 100644 index 0000000000000000000000000000000000000000..b7924a6f10f60512ccb7c28544f4bd7ec659dabc --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_17.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type Two = [Int|undefined, string] +function main(): void { + let t: Two = [undefined, "Test"]; +} diff --git a/ets2panda/test/compiler/ets/tuple_types_18-expected.txt b/ets2panda/test/compiler/ets/tuple_types_18-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..ebe6fc8aab0430bd1258bc40e988200307b78fb7 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_18-expected.txt @@ -0,0 +1,585 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "One", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 6 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "spreadType": null, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 18, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 18, + "column": 5 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Two", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 6 + }, + "end": { + "line": 18, + "column": 9 + } + } + }, + "typeAnnotation": { + "type": "ETSTuple", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "One", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 13 + }, + "end": { + "line": 18, + "column": 17 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "string", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 28 + }, + "end": { + "line": 18, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 28 + }, + "end": { + "line": 18, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 28 + }, + "end": { + "line": 18, + "column": 35 + } + } + } + ], + "spreadType": null, + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 24 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "t", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Two", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 17 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 21, + "column": 10 + } + } + }, + "init": { + "type": "ArrayExpression", + "elements": [ + { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 21, + "column": 19 + }, + "end": { + "line": 21, + "column": 28 + } + } + }, + { + "type": "StringLiteral", + "value": "Test", + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 36 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 21, + "column": 37 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 21, + "column": 5 + }, + "end": { + "line": 21, + "column": 38 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 23 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 22, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 23, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/tuple_types_18.ets b/ets2panda/test/compiler/ets/tuple_types_18.ets new file mode 100644 index 0000000000000000000000000000000000000000..b0cfb9a33d44785cfe41de0edabbb38c2d275047 --- /dev/null +++ b/ets2panda/test/compiler/ets/tuple_types_18.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +type One = [] +type Two = [One|undefined, string] + +function main(): void { + let t: Two = [undefined, "Test"]; +} diff --git a/ets2panda/test/parser/ets/OptionalParametersWithGenericReturnTypes-expected.txt b/ets2panda/test/parser/ets/OptionalParametersWithGenericReturnTypes-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..e93759c2243f392338aa46f83c9ca3eca341abe8 --- /dev/null +++ b/ets2panda/test/parser/ets/OptionalParametersWithGenericReturnTypes-expected.txt @@ -0,0 +1,2377 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 10 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 11 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "param", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "initializer": { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 24 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 26 + }, + "end": { + "line": 17, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 28 + }, + "end": { + "line": 17, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 28 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 28 + }, + "end": { + "line": 17, + "column": 30 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 27 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 26 + }, + "end": { + "line": 17, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 26 + }, + "end": { + "line": 17, + "column": 32 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 18, + "column": 16 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 20 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 31 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "param", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "$proxy_mask$", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "BinaryExpression", + "operator": "&", + "left": { + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "$proxy_mask$", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "consequent": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "param", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "alternate": null, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "property": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "param", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 2 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 7 + }, + "end": { + "line": 22, + "column": 8 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 10 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 11 + } + } + }, + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "U", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 11 + }, + "end": { + "line": 22, + "column": 12 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 11 + }, + "end": { + "line": 22, + "column": 13 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 8 + }, + "end": { + "line": 22, + "column": 13 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 8 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 23, + "column": 8 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "param", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 17 + }, + "end": { + "line": 23, + "column": 24 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 24 + } + } + }, + "initializer": { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 24 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 26 + }, + "end": { + "line": 23, + "column": 27 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 28 + }, + "end": { + "line": 23, + "column": 30 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "U", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 30 + }, + "end": { + "line": 23, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 30 + }, + "end": { + "line": 23, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 30 + }, + "end": { + "line": 23, + "column": 32 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 27 + }, + "end": { + "line": 23, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 26 + }, + "end": { + "line": 23, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 26 + }, + "end": { + "line": 23, + "column": 34 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 24, + "column": 16 + }, + "end": { + "line": 24, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 20 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 33 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + "overloads": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo_proxy", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "param", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Number", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "$proxy_mask$", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "B", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "typeParams": { + "type": "TSTypeParameterInstantiation", + "params": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "U", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "BinaryExpression", + "operator": "&", + "left": { + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "$proxy_mask$", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "consequent": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "param", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "right": { + "type": "UndefinedLiteral", + "value": undefined, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "alternate": null, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "property": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "param", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 3 + }, + "end": { + "line": 1, + "column": 3 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 3 + } + } + } + ], + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 2 + }, + "end": { + "line": 26, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 28, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/OptionalParametersWithGenericReturnTypes.ets b/ets2panda/test/parser/ets/OptionalParametersWithGenericReturnTypes.ets new file mode 100644 index 0000000000000000000000000000000000000000..8eabddf519e6bf3289ed9dfe42503ff51113908b --- /dev/null +++ b/ets2panda/test/parser/ets/OptionalParametersWithGenericReturnTypes.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + foo(param?: Number): A { + return this + } +} + +class B { + foo(param?: Number): B { + return this + } +} + diff --git a/ets2panda/test/parser/ets/class-instance-field-redeclaration-expected.txt b/ets2panda/test/parser/ets/class-instance-field-redeclaration-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..95028a2c1860cf8bdea912b8cb5f93740a97a585 --- /dev/null +++ b/ets2panda/test/parser/ets/class-instance-field-redeclaration-expected.txt @@ -0,0 +1 @@ +SyntaxError: Variable 'foo' has already been declared. [class-instance-field-redeclaration.ets:18:5] diff --git a/ets2panda/test/parser/ets/class-instance-field-redeclaration.ets b/ets2panda/test/parser/ets/class-instance-field-redeclaration.ets new file mode 100644 index 0000000000000000000000000000000000000000..3f2f82c517b33608f37ac1bd6ad69a7d93e892c0 --- /dev/null +++ b/ets2panda/test/parser/ets/class-instance-field-redeclaration.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class C { + foo: int = 10; + foo: int = 20; +} diff --git a/ets2panda/test/parser/ets/class-static-field-redeclaration-expected.txt b/ets2panda/test/parser/ets/class-static-field-redeclaration-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..7b1e62f3048c64ed08015624b19a4a938cf5837b --- /dev/null +++ b/ets2panda/test/parser/ets/class-static-field-redeclaration-expected.txt @@ -0,0 +1 @@ +SyntaxError: Variable 'foo' has already been declared. [class-static-field-redeclaration.ets:18:12] diff --git a/ets2panda/test/parser/ets/class-static-field-redeclaration.ets b/ets2panda/test/parser/ets/class-static-field-redeclaration.ets new file mode 100644 index 0000000000000000000000000000000000000000..3c6d509fc05a5bc2e70945eae2c76ca710ec8f68 --- /dev/null +++ b/ets2panda/test/parser/ets/class-static-field-redeclaration.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class C { + static foo: int = 10; + static foo: int = 20; +} diff --git a/ets2panda/test/parser/ets/declare_enum-expected.txt b/ets2panda/test/parser/ets/declare_enum-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..99104b74758a74b7f127841dc9f231d9f0aafb01 --- /dev/null +++ b/ets2panda/test/parser/ets/declare_enum-expected.txt @@ -0,0 +1,268 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSEnumDeclaration", + "id": { + "type": "Identifier", + "name": "Enum", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 18 + } + } + }, + "members": [ + { + "type": "TSEnumMember", + "id": { + "type": "Identifier", + "name": "AAA", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "initializer": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + { + "type": "TSEnumMember", + "id": { + "type": "Identifier", + "name": "BBB", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 8 + } + } + }, + "initializer": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 8 + } + } + } + ], + "const": false, + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 20, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/declare_enum.ets b/ets2panda/test/parser/ets/declare_enum.ets new file mode 100644 index 0000000000000000000000000000000000000000..44b78d6bf6581f4ac7098e0a3aa3abe357d64772 --- /dev/null +++ b/ets2panda/test/parser/ets/declare_enum.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare enum Enum { + AAA, + BBB +} diff --git a/ets2panda/test/parser/ets/declare_namespace-expected.txt b/ets2panda/test/parser/ets/declare_namespace-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..bd586f4105cecd7b674c906123d9fdf57c913a42 --- /dev/null +++ b/ets2panda/test/parser/ets/declare_namespace-expected.txt @@ -0,0 +1,290 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "name", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 19 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 24 + }, + "end": { + "line": 16, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 26 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 17, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/declare_namespace.ets b/ets2panda/test/parser/ets/declare_namespace.ets new file mode 100644 index 0000000000000000000000000000000000000000..47849cb880b375583deec12868f6893ae8af9857 --- /dev/null +++ b/ets2panda/test/parser/ets/declare_namespace.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare namespace name {} diff --git a/ets2panda/test/parser/ets/declare_namespace_2-expected.txt b/ets2panda/test/parser/ets/declare_namespace_2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..ef0198eda6f78a50a67e0f22eb177e38cd1a6393 --- /dev/null +++ b/ets2panda/test/parser/ets/declare_namespace_2-expected.txt @@ -0,0 +1,411 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "NAME", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 19 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "foo", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "void", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 2 + }, + "end": { + "line": 18, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 24 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 19, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/declare_namespace_2.ets b/ets2panda/test/parser/ets/declare_namespace_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..fb6d637df3eac7563422b79a288c52fc74565473 --- /dev/null +++ b/ets2panda/test/parser/ets/declare_namespace_2.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare namespace NAME { + foo():void; +} diff --git a/ets2panda/test/parser/ets/declare_type-expected.txt b/ets2panda/test/parser/ets/declare_type-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..0259aa62df8b138cf76932dc593730bc23d6c52e --- /dev/null +++ b/ets2panda/test/parser/ets/declare_type-expected.txt @@ -0,0 +1,194 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "t", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 17, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/declare_type.ets b/ets2panda/test/parser/ets/declare_type.ets new file mode 100644 index 0000000000000000000000000000000000000000..0ee4caa1c1977bae58858e33346e55a75a01ccb3 --- /dev/null +++ b/ets2panda/test/parser/ets/declare_type.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare type t = int; diff --git a/ets2panda/test/parser/ets/import_tests/check_exported_default_class-expected.txt b/ets2panda/test/parser/ets/import_tests/check_exported_default_class-expected.txt index d13c5c166f781ef1cddef635b08527d0286b3a61..b91e82403884a057a0ac77e059b2601800c70ee6 100644 --- a/ets2panda/test/parser/ets/import_tests/check_exported_default_class-expected.txt +++ b/ets2panda/test/parser/ets/import_tests/check_exported_default_class-expected.txt @@ -13,7 +13,7 @@ }, "end": { "line": 16, - "column": 76 + "column": 75 } } }, @@ -54,7 +54,7 @@ }, "end": { "line": 16, - "column": 77 + "column": 76 } } }, diff --git a/ets2panda/test/parser/ets/import_tests/check_exported_default_class.ets b/ets2panda/test/parser/ets/import_tests/check_exported_default_class.ets index 03c02fe1ec2157fb38b15c0536a251300e284f19..836eeba03d6ec92ad8a414e90fe80b07c1733907 100644 --- a/ets2panda/test/parser/ets/import_tests/check_exported_default_class.ets +++ b/ets2panda/test/parser/ets/import_tests/check_exported_default_class.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -import ExportDefaultClass from "import_tests/modules/struct_default_module"; +import ExportDefaultClass from "import_tests/modules/class_default_module"; function main() { let test_class: ExportDefaultClass = new ExportDefaultClass(); diff --git a/ets2panda/test/parser/ets/import_tests/import_interface_test-expected.txt b/ets2panda/test/parser/ets/import_tests/import_interface_test-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..dcc9310ba5ef1afbe2753680ff45a4c449de199e --- /dev/null +++ b/ets2panda/test/parser/ets/import_tests/import_interface_test-expected.txt @@ -0,0 +1,1162 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ImportDeclaration", + "source": { + "type": "StringLiteral", + "value": "./", + "loc": { + "start": { + "line": 16, + "column": 25 + }, + "end": { + "line": 16, + "column": 52 + } + } + }, + "specifiers": [ + { + "type": "ImportSpecifier", + "local": { + "type": "Identifier", + "name": "MyClass", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 17 + } + } + }, + "imported": { + "type": "Identifier", + "name": "MyClass", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 17 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 53 + } + } + }, + { + "type": "ImportDeclaration", + "source": { + "type": "StringLiteral", + "value": "./", + "loc": { + "start": { + "line": 17, + "column": 31 + }, + "end": { + "line": 17, + "column": 58 + } + } + }, + "specifiers": [ + { + "type": "ImportSpecifier", + "local": { + "type": "Identifier", + "name": "SameInterface", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + "imported": { + "type": "Identifier", + "name": "SameInterface", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 59 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "MyClass2", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 15 + } + } + }, + "superClass": null, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "SameInterface", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 27 + }, + "end": { + "line": 19, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 27 + }, + "end": { + "line": 19, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 27 + }, + "end": { + "line": 19, + "column": 42 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 27 + }, + "end": { + "line": 19, + "column": 42 + } + } + } + ], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "test", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "test", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 20, + "column": 9 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 20, + "column": 13 + }, + "end": { + "line": 20, + "column": 16 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 21, + "column": 16 + }, + "end": { + "line": 21, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 21, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 22, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 2 + }, + "end": { + "line": 23, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 41 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 23, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 10 + }, + "end": { + "line": 25, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 10 + }, + "end": { + "line": 25, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "myclass1", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 11 + }, + "end": { + "line": 26, + "column": 19 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "MyClass", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 26 + }, + "end": { + "line": 26, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 26 + }, + "end": { + "line": 26, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 26 + }, + "end": { + "line": 26, + "column": 34 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 26, + "column": 22 + }, + "end": { + "line": 26, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 26, + "column": 11 + }, + "end": { + "line": 26, + "column": 36 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 26, + "column": 5 + }, + "end": { + "line": 26, + "column": 36 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "myclass2", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 11 + }, + "end": { + "line": 27, + "column": 19 + } + } + }, + "init": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "MyClass2", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 26 + }, + "end": { + "line": 27, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 26 + }, + "end": { + "line": 27, + "column": 35 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 26 + }, + "end": { + "line": 27, + "column": 35 + } + } + }, + "arguments": [], + "loc": { + "start": { + "line": 27, + "column": 22 + }, + "end": { + "line": 27, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 27, + "column": 11 + }, + "end": { + "line": 27, + "column": 37 + } + } + } + ], + "kind": "const", + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 37 + } + } + }, + { + "type": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "myclass1", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 10 + }, + "end": { + "line": 28, + "column": 18 + } + } + }, + "property": { + "type": "Identifier", + "name": "test", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 19 + }, + "end": { + "line": 28, + "column": 23 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 28, + "column": 10 + }, + "end": { + "line": 28, + "column": 23 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 28, + "column": 10 + }, + "end": { + "line": 28, + "column": 25 + } + } + }, + "right": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "myclass2", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 28 + }, + "end": { + "line": 28, + "column": 36 + } + } + }, + "property": { + "type": "Identifier", + "name": "test", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 37 + }, + "end": { + "line": 28, + "column": 41 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 28, + "column": 28 + }, + "end": { + "line": 28, + "column": 41 + } + } + }, + "arguments": [], + "optional": false, + "loc": { + "start": { + "line": 28, + "column": 28 + }, + "end": { + "line": 28, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 9 + }, + "end": { + "line": 28, + "column": 44 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 28, + "column": 48 + }, + "end": { + "line": 28, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 28, + "column": 9 + }, + "end": { + "line": 28, + "column": 49 + } + } + }, + "consequent": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 29, + "column": 16 + }, + "end": { + "line": 29, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 29, + "column": 9 + }, + "end": { + "line": 29, + "column": 17 + } + } + } + ], + "loc": { + "start": { + "line": 28, + "column": 51 + }, + "end": { + "line": 30, + "column": 6 + } + } + }, + "alternate": null, + "loc": { + "start": { + "line": 28, + "column": 5 + }, + "end": { + "line": 30, + "column": 6 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 31, + "column": 12 + }, + "end": { + "line": 31, + "column": 13 + } + } + }, + "loc": { + "start": { + "line": 31, + "column": 5 + }, + "end": { + "line": 31, + "column": 13 + } + } + } + ], + "loc": { + "start": { + "line": 25, + "column": 17 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 14 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 25, + "column": 14 + }, + "end": { + "line": 32, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 1 + }, + "end": { + "line": 32, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 33, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/import_tests/import_interface_test.ets b/ets2panda/test/parser/ets/import_tests/import_interface_test.ets new file mode 100644 index 0000000000000000000000000000000000000000..24a8dd3bb411778ea1e44f0a0d7738146c7bf14a --- /dev/null +++ b/ets2panda/test/parser/ets/import_tests/import_interface_test.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { MyClass } from './import_interface_test_2'; +import { SameInterface } from './import_interface_test_1'; + +class MyClass2 implements SameInterface { + test(): int { + return 2; + } +} + +function main() { + const myclass1 = new MyClass(); + const myclass2 = new MyClass2(); + if ((myclass1.test() + myclass2.test()) == 3) { + return 0 + } + return 1 +} diff --git a/ets2panda/test/parser/ets/import_tests/import_interface_test_1-expected.txt b/ets2panda/test/parser/ets/import_tests/import_interface_test_1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..ba2937c49319a4f8c54bcaa1e855a2468567fc0b --- /dev/null +++ b/ets2panda/test/parser/ets/import_tests/import_interface_test_1-expected.txt @@ -0,0 +1,291 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "test", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "test", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "declare": true, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 16 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 32 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "id": { + "type": "Identifier", + "name": "SameInterface", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 31 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 19, + "column": 1 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 19, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/import_tests/import_interface_test_1.ets b/ets2panda/test/parser/ets/import_tests/import_interface_test_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..6dd7e5a2672bbce30e8f3effe84895885eda056c --- /dev/null +++ b/ets2panda/test/parser/ets/import_tests/import_interface_test_1.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface SameInterface { + test():int; +} diff --git a/ets2panda/test/parser/ets/import_tests/import_interface_test_2-expected.txt b/ets2panda/test/parser/ets/import_tests/import_interface_test_2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..016b5bf1883430813a4aa70878d53911445406a7 --- /dev/null +++ b/ets2panda/test/parser/ets/import_tests/import_interface_test_2-expected.txt @@ -0,0 +1,552 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ImportDeclaration", + "source": { + "type": "StringLiteral", + "value": "./", + "loc": { + "start": { + "line": 16, + "column": 31 + }, + "end": { + "line": 16, + "column": 58 + } + } + }, + "specifiers": [ + { + "type": "ImportSpecifier", + "local": { + "type": "Identifier", + "name": "SameInterface", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "imported": { + "type": "Identifier", + "name": "SameInterface", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 59 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "MyClass", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + "superClass": null, + "implements": [ + { + "type": "TSClassImplements", + "expression": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "SameInterface", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 48 + } + } + } + ], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "test", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "test", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 9 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 19, + "column": 13 + }, + "end": { + "line": 19, + "column": 16 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 20, + "column": 16 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 2 + }, + "end": { + "line": 22, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 47 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 8 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 22, + "column": 2 + } + } +} diff --git a/ets2panda/test/parser/ets/import_tests/import_interface_test_2.ets b/ets2panda/test/parser/ets/import_tests/import_interface_test_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..44c393de3388fb4add7b87545ca3087190f08e41 --- /dev/null +++ b/ets2panda/test/parser/ets/import_tests/import_interface_test_2.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { SameInterface } from './import_interface_test_1'; + +export class MyClass implements SameInterface { + test(): int { + return 1; + } +} \ No newline at end of file diff --git a/ets2panda/test/parser/ets/test-type-alias-call1-expected.txt b/ets2panda/test/parser/ets/test-type-alias-call1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..94885993386b408d4ef41c61022be77705ea7f4f --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call1-expected.txt @@ -0,0 +1,645 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 14 + } + } + }, + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "n", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 24 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 29 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 18, + "column": 20 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 12 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 13 + } + } + }, + "property": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 14 + }, + "end": { + "line": 20, + "column": 22 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 22 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 20, + "column": 23 + }, + "end": { + "line": 20, + "column": 24 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 25 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 24 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 2 + }, + "end": { + "line": 22, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 23, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call1.ets b/ets2panda/test/parser/ets/test-type-alias-call1.ets new file mode 100644 index 0000000000000000000000000000000000000000..2899e73c5241f48ca95942cd2126b7744cbca842 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call1.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type Callback = (n: int) => int +class A { + public callback: Callback + public increment() { + this.callback(1) + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call2-expected.txt b/ets2panda/test/parser/ets/test-type-alias-call2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..8913c68014579744e7baf6c09dd9ae66619cd4eb --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call2-expected.txt @@ -0,0 +1,783 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "First", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "n", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 21 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 5 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Second", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 6 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "First", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 18, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 18, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 18, + "column": 5 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 6 + }, + "end": { + "line": 18, + "column": 14 + } + } + }, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Second", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 20, + "column": 20 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 20, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 21, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 22 + }, + "end": { + "line": 21, + "column": 11 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 12 + }, + "end": { + "line": 21, + "column": 11 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 21 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 13 + } + } + }, + "property": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 22 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 22, + "column": 23 + }, + "end": { + "line": 22, + "column": 24 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 9 + }, + "end": { + "line": 22, + "column": 25 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 24 + }, + "end": { + "line": 23, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 21 + }, + "end": { + "line": 23, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 21 + }, + "end": { + "line": 23, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 5 + }, + "end": { + "line": 23, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 2 + }, + "end": { + "line": 24, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 25, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call2.ets b/ets2panda/test/parser/ets/test-type-alias-call2.ets new file mode 100644 index 0000000000000000000000000000000000000000..93b91c0087cd435ac5e160d434706e3d0d4808c9 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call2.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type First = (n: int) => int +type Second = First +type Callback = Second +class A { + public callback: Callback + public increment() { + this.callback(1) + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call3-expected.txt b/ets2panda/test/parser/ets/test-type-alias-call3-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..1076dcd57a43547560e86ee86f796e5e6239436b --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call3-expected.txt @@ -0,0 +1,647 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 14 + } + } + }, + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "n", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 24 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 29 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 12 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "property": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 11 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 20, + "column": 20 + }, + "end": { + "line": 20, + "column": 21 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 22 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 24 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 21 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 2 + }, + "end": { + "line": 22, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 23, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call3.ets b/ets2panda/test/parser/ets/test-type-alias-call3.ets new file mode 100644 index 0000000000000000000000000000000000000000..89743c8d482cac517a27efd44fb3e6e072a85d7b --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call3.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type Callback = (n: int) => int +class A { + public static callback: Callback + public increment() { + A.callback(1) + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call4-expected.txt b/ets2panda/test/parser/ets/test-type-alias-call4-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..9c15b8c34fd5f0befe93abdeb17d31be72204829 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call4-expected.txt @@ -0,0 +1,647 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 14 + } + } + }, + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "n", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 24 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 29 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 16, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 17, + "column": 6 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 27 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 37 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 19, + "column": 11 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 19 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 19 + }, + "end": { + "line": 19, + "column": 28 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 10 + } + } + }, + "property": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 11 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 20, + "column": 20 + }, + "end": { + "line": 20, + "column": 21 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 20, + "column": 22 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 31 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 28 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 28 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 21, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 2 + }, + "end": { + "line": 22, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 22, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 23, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call4.ets b/ets2panda/test/parser/ets/test-type-alias-call4.ets new file mode 100644 index 0000000000000000000000000000000000000000..d02aa961d9774ac9f25c52c85f2324d54d43d082 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call4.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type Callback = (n: int) => int +class A { + public static callback: Callback + public static increment() { + A.callback(1) + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call5-expected.txt b/ets2panda/test/parser/ets/test-type-alias-call5-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..f26b502997d24965defa200d3d48540daf5dba01 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call5-expected.txt @@ -0,0 +1,839 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "First", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "n", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 21 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 30 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Second", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 6 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "First", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 18, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 18, + "column": 5 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 18, + "column": 5 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 6 + }, + "end": { + "line": 18, + "column": 14 + } + } + }, + "typeAnnotation": { + "type": "ETSUnionType", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "First", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Second", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 32 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 17 + }, + "end": { + "line": 18, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 32 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 7 + }, + "end": { + "line": 20, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 20 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 22 + }, + "end": { + "line": 21, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 22 + }, + "end": { + "line": 21, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 22 + }, + "end": { + "line": 21, + "column": 31 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 31 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 12 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 12 + }, + "end": { + "line": 22, + "column": 21 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 13 + } + } + }, + "property": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 14 + }, + "end": { + "line": 23, + "column": 22 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 22 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 23, + "column": 23 + }, + "end": { + "line": 23, + "column": 24 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 9 + }, + "end": { + "line": 23, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 22, + "column": 24 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 21 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 21 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 5 + }, + "end": { + "line": 24, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 2 + }, + "end": { + "line": 25, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 9 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 25, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 26, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call5.ets b/ets2panda/test/parser/ets/test-type-alias-call5.ets new file mode 100644 index 0000000000000000000000000000000000000000..8a7f8a3e988376706badcf726943c4d7a5612a7e --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call5.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type First = (n: int) => int; +type Second = First +type Callback = First | Second; + +class A { + public callback: Callback; + public increment() { + this.callback(1); + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call6-expected.txt b/ets2panda/test/parser/ets/test-type-alias-call6-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..3a470a4b777360172ed45c359e69fda11d46ccf3 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call6-expected.txt @@ -0,0 +1,908 @@ +{ + "type": "Program", + "statements": [ + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "First", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 11 + } + } + }, + "typeAnnotation": { + "type": "ETSFunctionType", + "params": [ + { + "type": "ETSParameterExpression", + "name": { + "type": "Identifier", + "name": "n", + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 18 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 15 + }, + "end": { + "line": 16, + "column": 21 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 26 + }, + "end": { + "line": 16, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 16, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 30 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Second", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 6 + }, + "end": { + "line": 17, + "column": 12 + } + } + }, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "First", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Third", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 6 + }, + "end": { + "line": 18, + "column": 11 + } + } + }, + "typeAnnotation": { + "type": "ETSUnionType", + "types": [ + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "First", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Second", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 29 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 14 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 1 + }, + "end": { + "line": 18, + "column": 29 + } + } + }, + { + "type": "TSTypeAliasDeclaration", + "id": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 6 + }, + "end": { + "line": 19, + "column": 14 + } + } + }, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Third", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 17 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 1 + }, + "end": { + "line": 19, + "column": 23 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 7 + }, + "end": { + "line": 21, + "column": 8 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 12 + }, + "end": { + "line": 22, + "column": 20 + } + } + }, + "accessibility": "public", + "static": false, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Callback", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 22 + }, + "end": { + "line": 22, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 22 + }, + "end": { + "line": 22, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 22 + }, + "end": { + "line": 22, + "column": 31 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 12 + }, + "end": { + "line": 22, + "column": 31 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 12 + }, + "end": { + "line": 23, + "column": 21 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "increment", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 12 + }, + "end": { + "line": 23, + "column": 21 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 13 + } + } + }, + "property": { + "type": "Identifier", + "name": "callback", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 14 + }, + "end": { + "line": 24, + "column": 22 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 22 + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 24, + "column": 23 + }, + "end": { + "line": 24, + "column": 24 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 25 + } + } + }, + "loc": { + "start": { + "line": 24, + "column": 9 + }, + "end": { + "line": 24, + "column": 26 + } + } + } + ], + "loc": { + "start": { + "line": 23, + "column": 24 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 21 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 5 + }, + "end": { + "line": 25, + "column": 6 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "constructor", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 2 + }, + "end": { + "line": 26, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 21, + "column": 9 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 26, + "column": 2 + } + } + }, + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 27, + "column": 1 + } + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call6.ets b/ets2panda/test/parser/ets/test-type-alias-call6.ets new file mode 100644 index 0000000000000000000000000000000000000000..8801b22e5489a74fa0732d9aa1da248a873233b5 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call6.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type First = (n: int) => int; +type Second = First; +type Third = First | Second; +type Callback = Third; + +class A { + public callback: Callback; + public increment() { + this.callback(1); + } +} diff --git a/ets2panda/test/parser/ets/test-type-alias-call7.ets b/ets2panda/test/parser/ets/test-type-alias-call7.ets new file mode 100644 index 0000000000000000000000000000000000000000..cc764f60c61f4d3f4865a30a86edaa5e76f35f69 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call7.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type Callback = (n: int) => int +export type {Callback} diff --git a/ets2panda/test/parser/ets/test-type-alias-call8.ets b/ets2panda/test/parser/ets/test-type-alias-call8.ets new file mode 100644 index 0000000000000000000000000000000000000000..27b26e180ac5a620cd40427a9128ce2bff47bec0 --- /dev/null +++ b/ets2panda/test/parser/ets/test-type-alias-call8.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Callback } from './test-type-alias-call3.ets'; +class A { + public callback: Callback + public increment(){ + this.callback(1) + } +} diff --git a/ets2panda/test/runtime/ets/BigInt.ets b/ets2panda/test/runtime/ets/BigInt.ets new file mode 100644 index 0000000000000000000000000000000000000000..d2fa645b16c4c61ea3a1576403745e23c553a233 --- /dev/null +++ b/ets2panda/test/runtime/ets/BigInt.ets @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function test_bitwise_and(): void { + assert new BigInt("10").operatorBitwiseAnd(new BigInt("2")).toString().equals("2"); + assert new BigInt("256").operatorBitwiseAnd(new BigInt("1")).toString().equals("0"); + assert new BigInt("3124378143267041203423").operatorBitwiseAnd(new BigInt("43621978")).toString().equals("41948250"); + assert new BigInt("256").operatorBitwiseAnd(new BigInt("256")).toString().equals("256"); + assert new BigInt("12345678").operatorBitwiseAnd(new BigInt("1234")).toString().equals("66"); +} + +function test_bitwise_or(): void { + assert new BigInt("10").operatorBitwiseOr(new BigInt("2")).toString().equals("10"); + assert new BigInt("256").operatorBitwiseOr(new BigInt("1")).toString().equals("257"); + assert new BigInt("256").operatorBitwiseOr(new BigInt("256")).toString().equals("256"); + assert new BigInt("3124378143267041203423").operatorBitwiseOr(new BigInt("43621978")).toString().equals("3124378143267042877151"); + assert new BigInt("12345678").operatorBitwiseOr(new BigInt("1234")).toString().equals("12346846"); +} + +function test_bitwise_xor(): void { + assert new BigInt("10").operatorBitwiseXor(new BigInt("2")).toString().equals("8"); + assert new BigInt("256").operatorBitwiseXor(new BigInt("1")).toString().equals("257"); + assert new BigInt("256").operatorBitwiseXor(new BigInt("256")).toString().equals("0"); + assert new BigInt("3124378143267041203423").operatorBitwiseXor(new BigInt("43621978")).toString().equals("3124378143267000928901"); + assert new BigInt("12345678").operatorBitwiseXor(new BigInt("1234")).toString().equals("12346780"); +} + +function test_left_shift(): void { + assert new BigInt("0").operatorLeftShift(new BigInt("0")).toString().equals("0"); + assert new BigInt("0").operatorLeftShift(new BigInt("1")).toString().equals("0"); + assert new BigInt("1").operatorLeftShift(new BigInt("0")).toString().equals("1"); + assert new BigInt("10").operatorLeftShift(new BigInt("2")).toString().equals("40"); + assert new BigInt("255").operatorLeftShift(new BigInt("41")).toString().equals("560750930165760"); + assert new BigInt("65535").operatorLeftShift(new BigInt("60")).toString().equals("75556710804409716572160"); + assert new BigInt("4294967295").operatorLeftShift(new BigInt("5")).toString().equals("137438953440"); + assert new BigInt("18446744073709551615").operatorLeftShift(new BigInt("6")).toString().equals("1180591620717411303360"); + assert new BigInt("1275418875248948586535904902545412130").operatorLeftShift(new BigInt("123")).toString().equals("13562579802667292602585801202159372574330573695725523059072421474640855040"); + assert new BigInt("2").operatorLeftShift(new BigInt("218")).toString().equals("842498333348457493583344221469363458551160763204392890034487820288"); + assert new BigInt("-1").operatorLeftShift(new BigInt("0")).toString().equals("-1"); + assert new BigInt("-12").operatorLeftShift(new BigInt("4")).toString().equals("-192"); + assert new BigInt("-255").operatorLeftShift(new BigInt("19")).toString().equals("-133693440"); + assert new BigInt("-65535").operatorLeftShift(new BigInt("73")).toString().equals("-618960574909724398159134720"); + assert new BigInt("-4294967295").operatorLeftShift(new BigInt("24")).toString().equals("-72057594021150720"); + assert new BigInt("-18446744073709551615").operatorLeftShift(new BigInt("31")).toString().equals("-39614081257132168794624491520"); + assert new BigInt("-4095059032950818422890113130149234924134").operatorLeftShift(new BigInt("103")).toString().equals("-41528832328721100931613913139905162112381494314462183326283215847555072"); +} + +function test_right_shift(): void { + assert new BigInt("-200").operatorRightShift(new BigInt("2")).toString().equals("-50"); + assert new BigInt("-12").operatorRightShift(new BigInt("2")).toString().equals("-3"); + assert new BigInt("-1").operatorRightShift(new BigInt("0")).toString().equals("-1"); + assert new BigInt("0").operatorRightShift(new BigInt("0")).toString().equals("0"); + assert new BigInt("0").operatorRightShift(new BigInt("1")).toString().equals("0"); + assert new BigInt("1").operatorRightShift(new BigInt("0")).toString().equals("1"); + assert new BigInt("55").operatorRightShift(new BigInt("2")).toString().equals("13"); + assert new BigInt("-50").operatorRightShift(new BigInt("2")).toString().equals("-13"); + assert new BigInt("255").operatorRightShift(new BigInt("4")).toString().equals("15"); + assert new BigInt("255").operatorRightShift(new BigInt("8")).toString().equals("0"); + assert new BigInt("65535").operatorRightShift(new BigInt("10")).toString().equals("63"); + assert new BigInt("4294967295").operatorRightShift(new BigInt("17")).toString().equals("32767"); + assert new BigInt("4294967295").operatorRightShift(new BigInt("48")).toString().equals("0"); + assert new BigInt("18446744073709551615").operatorRightShift(new BigInt("55")).toString().equals("511"); + assert new BigInt("4930493049034092989191918392837727383823827").operatorRightShift(new BigInt("129")).toString().equals("7244"); + assert new BigInt("34930693049034092980065918370009389341341932481328231493102392100010239").operatorRightShift(new BigInt("41")).toString().equals("15884640128676479880626138024130973163365493965706369405371"); + assert new BigInt("34095405903900293499034024029409200000000000000000000094049304394284993939382949384984981018480144184891848991934893429489324901148449849382222222222222888384932890000103010381803018300103180381030084545225875678328499213403403984398439489384984287113383827387373382328328194394892948392222219791749717949183748237").operatorRightShift(new BigInt("511")).toString().equals("5085903091997271218878067997324523590835536101241386224503069830700984460490307918626942225457432781938207872710051592009243523341752202627425621983245162030428"); + assert new BigInt("-255").operatorRightShift(new BigInt("2")).toString().equals("-64"); + assert new BigInt("-65535").operatorRightShift(new BigInt("12")).toString().equals("-16"); + assert new BigInt("-4294967295").operatorRightShift(new BigInt("18")).toString().equals("-16384"); + assert new BigInt("-18446744073709551615").operatorRightShift(new BigInt("38")).toString().equals("-67108864"); + assert new BigInt("-4095059032950818422890113130149234924134").operatorRightShift(new BigInt("99")).toString().equals("-6460863952"); + assert new BigInt("-3294302940940294094923040592059302590950294502940294029029409029429042942049028100104029439420990952").operatorRightShift(new BigInt("100")).toString().equals("-2598746800062401791237527125433630339355687972972274247737341685088307"); +} + +function test_module(): void { + assert new BigInt("10").operatorModule(new BigInt("3")).toString().equals("1"); + assert new BigInt("10").operatorModule(new BigInt("-3")).toString().equals("1"); + assert new BigInt("-10").operatorModule(new BigInt("3")).toString().equals("-1"); + assert new BigInt("-10").operatorModule(new BigInt("-3")).toString().equals("-1"); + assert new BigInt("100").operatorModule(new BigInt("50")).toString().equals("0"); + assert new BigInt("100").operatorModule(new BigInt("-50")).toString().equals("0"); + assert new BigInt("-100").operatorModule(new BigInt("50")).toString().equals("0"); + assert new BigInt("-100").operatorModule(new BigInt("-50")).toString().equals("0"); + assert new BigInt("3124378143267041203423").operatorModule(new BigInt("43621978")).toString().equals("18802883"); + assert new BigInt("-3124378143267041203423").operatorModule(new BigInt("43621978")).toString().equals("-18802883"); + assert new BigInt("3124378143267041203423").operatorModule(new BigInt("-43621978")).toString().equals("18802883"); + assert new BigInt("-3124378143267041203423").operatorModule(new BigInt("-43621978")).toString().equals("-18802883"); + assert new BigInt("100").operatorModule(new BigInt("250")).toString().equals("100"); + assert new BigInt("-100").operatorModule(new BigInt("250")).toString().equals("-100"); + assert new BigInt("100").operatorModule(new BigInt("-250")).toString().equals("100"); + assert new BigInt("-100").operatorModule(new BigInt("-250")).toString().equals("-100"); + assert new BigInt("0").operatorModule(new BigInt("8")).toString().equals("0"); +} + +function test_divide(): void { + assert new BigInt("10").operatorDivide(new BigInt("3")).toString().equals("3"); + assert new BigInt("-10").operatorDivide(new BigInt("3")).toString().equals("-3"); + assert new BigInt("10").operatorDivide(new BigInt("-3")).toString().equals("-3"); + assert new BigInt("-10").operatorDivide(new BigInt("-3")).toString().equals("3"); + assert new BigInt("100").operatorDivide(new BigInt("50")).toString().equals("2"); + assert new BigInt("100").operatorDivide(new BigInt("-50")).toString().equals("-2"); + assert new BigInt("-100").operatorDivide(new BigInt("50")).toString().equals("-2"); + assert new BigInt("-100").operatorDivide(new BigInt("-50")).toString().equals("2"); + assert new BigInt("3124378143267041203423").operatorDivide(new BigInt("43621978")).toString().equals("71623944775430"); + assert new BigInt("-3124378143267041203423").operatorDivide(new BigInt("43621978")).toString().equals("-71623944775430"); + assert new BigInt("3124378143267041203423").operatorDivide(new BigInt("-43621978")).toString().equals("-71623944775430"); + assert new BigInt("-3124378143267041203423").operatorDivide(new BigInt("-43621978")).toString().equals("71623944775430"); + assert new BigInt("100").operatorDivide(new BigInt("250")).toString().equals("0"); + assert new BigInt("100").operatorDivide(new BigInt("-250")).toString().equals("0"); + assert new BigInt("-100").operatorDivide(new BigInt("250")).toString().equals("0"); + assert new BigInt("-100").operatorDivide(new BigInt("-250")).toString().equals("0"); + assert new BigInt("65000").operatorDivide(new BigInt("100")).toString().equals("650"); + assert new BigInt("65000").operatorDivide(new BigInt("-100")).toString().equals("-650"); + assert new BigInt("-65000").operatorDivide(new BigInt("100")).toString().equals("-650"); + assert new BigInt("-65000").operatorDivide(new BigInt("-100")).toString().equals("650"); +} + +function test_unary_minus(): void { + assert new BigInt("10").negate().toString().equals("-10"); + assert new BigInt("1000").negate().toString().equals("-1000"); + assert new BigInt("-1").negate().toString().equals("1"); + assert new BigInt("-10").negate().toString().equals("10"); + assert new BigInt("-100").negate().toString().equals("100"); + assert new BigInt("0").negate().toString().equals("0"); +} + +function test_plus(): void { + assert new BigInt("10").operatorAdd(new BigInt("20")).toString() == "30"; + assert new BigInt("1000").operatorAdd(new BigInt("10")).toString() == "1010"; + assert new BigInt("-10").operatorAdd(new BigInt("9")).toString() == "-1"; + assert new BigInt("-10").operatorAdd(new BigInt("10")).toString() == "0"; + assert new BigInt("-100").operatorAdd(new BigInt("10")).toString() == "-90"; + assert new BigInt("100").operatorAdd(new BigInt("10")).toString() == "110"; + assert new BigInt("65535").operatorAdd(new BigInt("65535")).toString() == "131070"; + assert new BigInt("65500").operatorAdd(new BigInt("1")).toString().equals("65501"); + assert new BigInt("65500").operatorAdd(new BigInt("-1")).toString().equals("65499"); + assert new BigInt("-65500").operatorAdd(new BigInt("-1")).toString().equals("-65501"); + assert new BigInt("-65500").operatorAdd(new BigInt("1")).toString().equals("-65499"); + assert new BigInt("-65500").operatorAdd(new BigInt("100000")).toString().equals("34500"); + assert new BigInt("100").operatorAdd(new BigInt("0")).toString().equals("100"); + assert new BigInt("-100").operatorAdd(new BigInt("0")).toString().equals("-100"); + assert new BigInt("-10").operatorAdd(new BigInt("-10")).toString().equals("-20"); +} + +function test_minus(): void { + assert new BigInt("10").operatorSubtract(new BigInt("2")).toString().equals("8"); + assert new BigInt("2").operatorSubtract(new BigInt("10")).toString().equals("-8"); + assert new BigInt("-10").operatorSubtract(new BigInt("-2")).toString().equals("-8"); + assert new BigInt("-100").operatorSubtract(new BigInt("1")).toString().equals("-101"); + assert new BigInt("-100").operatorSubtract(new BigInt("-1")).toString().equals("-99"); + assert new BigInt("-1000").operatorSubtract(new BigInt("10")).toString().equals("-1010"); + assert new BigInt("1237840127434312471243").operatorSubtract(new BigInt("234112342314526914672342143621463921469")).toString().equals("-234112342314526913434502016187151450226"); + assert new BigInt("-1237840127434312471243").operatorSubtract(new BigInt("234112342314526914672342143621463921469")).toString().equals("-234112342314526915910182271055776392712"); + assert new BigInt("1237840127434312471243").operatorSubtract(new BigInt("-234112342314526914672342143621463921469")).toString().equals("234112342314526915910182271055776392712"); + assert new BigInt("-1237840127434312471243").operatorSubtract(new BigInt("-234112342314526914672342143621463921469")).toString().equals("234112342314526913434502016187151450226"); + assert new BigInt("-1000").operatorSubtract(new BigInt("-10")).toString().equals("-990"); + assert new BigInt("-100").operatorSubtract(new BigInt("0")).toString().equals("-100"); + assert new BigInt("0").operatorSubtract(new BigInt("-100")).toString().equals("100"); + assert new BigInt("0").operatorSubtract(new BigInt("100")).toString().equals("-100"); + assert new BigInt("65500").operatorSubtract(new BigInt("1")).toString().equals("65499"); + assert new BigInt("65500").operatorSubtract(new BigInt("-1")).toString().equals("65501"); + assert new BigInt("-65500").operatorSubtract(new BigInt("-1")).toString().equals("-65499"); + assert new BigInt("-65500").operatorSubtract(new BigInt("1")).toString().equals("-65501"); + assert new BigInt("65500").operatorSubtract(new BigInt("100000")).toString().equals("-34500"); + assert new BigInt("49798775").operatorSubtract(new BigInt("43621978")).toString().equals("6176797"); + assert new BigInt("10").operatorSubtract(new BigInt("20")).toString().equals("-10"); +} + +function test_multiply(): void { + assert new BigInt("10").operatorMultiply(new BigInt("10")).toString() == "100"; + assert new BigInt("0").operatorMultiply(new BigInt("50")).toString() == "0"; + assert new BigInt("1").operatorMultiply(new BigInt("50")).toString() == "50"; + assert new BigInt("50").operatorMultiply(new BigInt("5")).toString() == "250"; + assert new BigInt("50").operatorMultiply(new BigInt("-5")).toString() == "-250"; + assert new BigInt("-1").operatorMultiply(new BigInt("-5")).toString() == "5"; + assert new BigInt("0").operatorMultiply(new BigInt("0")).toString() == "0"; + assert new BigInt("123").operatorMultiply(new BigInt("1")).toString() == "123"; + assert new BigInt("1234").operatorMultiply(new BigInt("987")).toString() == "1217958"; + assert new BigInt("3241847031247230147213740214703214721047312").operatorMultiply(new BigInt("412343124123421347812304712431421204731024")).toString() == "1336753332794721625246945391107220242430725631478413717131017736872102322242538207488"; + assert new BigInt("-3241847031247230147213740214703214721047312").operatorMultiply(new BigInt("-412343124123421347812304712431421204731024")).toString() == "1336753332794721625246945391107220242430725631478413717131017736872102322242538207488"; + assert new BigInt("-3241847031247230147213740214703214721047312").operatorMultiply(new BigInt("412343124123421347812304712431421204731024")).toString() == "-1336753332794721625246945391107220242430725631478413717131017736872102322242538207488"; + assert new BigInt("3241847031247230147213740214703214721047312").operatorMultiply(new BigInt("-412343124123421347812304712431421204731024")).toString() == "-1336753332794721625246945391107220242430725631478413717131017736872102322242538207488"; + assert new BigInt("256").operatorMultiply(new BigInt("256")).toString() == "65536"; +} + +function test_create_empty_bigint(): void { + let a = new BigInt() + assert a.positive() + assert a.toString() == "0" + + let b = new BigInt("") + assert b.positive() + assert b.toString() == "0" +} + +function test_invalid_bigint(): void { + // NOTE(kkonsw): implement validation +} + +function test_bigint_as_string(): void { + assert new BigInt("10").toString() == "10" + assert new BigInt("1000").toString() == "1000" + assert new BigInt("-1000").toString() == "-1000" + assert new BigInt("-1").toString() == "-1" + assert new BigInt("-10").toString() == "-10" + assert new BigInt("-100").toString() == "-100" + assert new BigInt("-100000000000000").toString() == "-100000000000000" + assert new BigInt("0").toString() == "0" +} + +function test_type(): void { + let num0 = 0n; + let num1 = 100_100_100_100_100_100n + let num2 = -57896044618658097711785492504343953926634992332820282019728792003956564819967n + + assert (num0 instanceof bigint) + assert (num1 instanceof bigint) + assert (num2 instanceof bigint) +} + +function test_assignment(): void { + let a = -24059059045444224545405903904190343043049209420234290480n + let b = a + assert (a instanceof bigint) + assert (b instanceof bigint) + assert (a.toString() == b.toString()); + + a = 123n; + assert (a instanceof bigint) + assert (a.toString() == "123"); + assert (a == 123n); + + const zero = 0n; + let c = zero; + assert (zero instanceof bigint) + assert (c instanceof bigint) + assert (zero.toString() == c.toString()); +} + +function test_compare(): void { + const a = 24400569094091093912039019089543850580328542852805043n + const b = 34034240244909504590902901119302940942904944029040950n + + assert 44493059209094029409209402940924902n < 140044940590459049067274048929058908989042385n + assert 44493059209094029409209402940924902n < a + assert a < 34034240244909504590902901119302940942904944029040950n + assert a < b + + assert 44493059209094029409209402940924902n <= 140044940590459049067274048929058908989042385n + assert 44493059209094029409209402940924902n <= a + assert a <= 34034240244909504590902901119302940942904944029040950n + assert a <= b + + assert 44493059209094029409209402940924902n <= 44493059209094029409209402940924902n + assert 24400569094091093912039019089543850580328542852805043n <= a + assert a <= 24400569094091093912039019089543850580328542852805043n + assert a <= a + + assert 40044940590459049067274048929058908989042385n > 44493059209094029409209402940924902n + assert 34034240244909504590902901119302940942904944029040950n > a + assert a > 140044940590459049067274048929058908989042385n + assert b > a + + assert 40044940590459049067274048929058908989042385n >= 44493059209094029409209402940924902n + assert 34034240244909504590902901119302940942904944029040950n >= a + assert a >= 140044940590459049067274048929058908989042385n + assert b >= a + + assert 44493059209094029409209402940924902n <= 44493059209094029409209402940924902n + assert 24400569094091093912039019089543850580328542852805043n <= a + assert a <= 24400569094091093912039019089543850580328542852805043n + assert a <= a +} + +function test_literals() : void { + let num0 = 0n + assert (num0.toString() == "0") + + let num1 = 127n + assert (num1.toString() == "127") + + let num2 = 32767n + assert (num2.toString() == "32767") + + let num3 = 2147483647n + assert (num3.toString() == "2147483647") + + let num4 = 9223372036854775807n + assert (num4.toString() == "9223372036854775807") + + let num5 = 170141183460469231731687303715884105727n + assert (num5.toString() == "170141183460469231731687303715884105727") + + let num6 = 57896044618658097711785492504343953926634992332820282019728792003956564819967n + assert (num6.toString() == "57896044618658097711785492504343953926634992332820282019728792003956564819967") + + let num1_n = -128n + assert (num1_n.toString() == "-128") + + let num2_n = -32768n + assert (num2_n.toString() == "-32768") + + let num3_n = -2147483648n + assert (num3_n.toString() == "-2147483648") + + let num4_n = -9223372036854775808n + assert (num4_n.toString() == "-9223372036854775808") + + let num5_n = -170141183460469231731687303715884105728n + assert (num5_n.toString() == "-170141183460469231731687303715884105728") + + let num6_n = -57896044618658097711785492504343953926634992332820282019728792003956564819968n + assert (num6_n.toString() == "-57896044618658097711785492504343953926634992332820282019728792003956564819968") + + let num1_sep = 1_991_653_125_841_217_555_434419_9091_123000000_3_3313_5775_3282_29n + assert (num1_sep.toString() == "19916531258412175554344199091123000000333135775328229") + + let num2_sep = -422_12_3333_9844_3333_3443_34111_43434_1111_11_1_3_3_411909_990081n + assert (num2_sep.toString() == "-4221233339844333334433411143434111111133411909990081") + + let num0_t: bigint = 0n + assert (num0_t.toString() == "0") + + let num1_t: bigint = 57896044618658097711785492504343953926634992332820282019728792003956564819967n + assert (num1_t.toString() == "57896044618658097711785492504343953926634992332820282019728792003956564819967") + + let num2_t: bigint = -9223372036854775808n + assert (num2_t.toString() == "-9223372036854775808") + + let num3_t: bigint = 1_991_653_125_841_217_555_434419_9091_123000000_3_3313_5775_3282_29n + assert (num3_t.toString() == "19916531258412175554344199091123000000333135775328229") + + let num4_t: bigint = -422_12_3333_9844_3333_3443_34111_43434_1111_11_1_3_3_411909_990081n + assert (num4_t.toString() == "-4221233339844333334433411143434111111133411909990081") + + const num0_c = 0n + assert (num0_c.toString() == "0") + + const num1_c = 1267650600228229401496703205376n + assert (num1_c.toString() == "1267650600228229401496703205376") + + const num2_c = -1427247692705959881058285969449495136382746624n + assert (num2_c.toString() == "-1427247692705959881058285969449495136382746624") + + const num3_c = 4_000_000_000_000_000_000_000_100n + assert (num3_c.toString() == "4000000000000000000000100") + + const num4_c: bigint = -7777777_666666_55555_4444_333_22_1n + assert (num4_c.toString() == "-7777777666666555554444333221") +} + +function test_cast(): void { + const v = 1559053 + const b: byte = 44 + const s: short = -17600 + const i: int = 1150483640 + const l: long = -8223372036854775808 + + // NOTE(kkonsw): casts currently do not work +} + +function test_bigint_methods(): void { + const b: byte = 44 + const s: short = -17600 + const i: int = 1150483640 + const l: long = -8223372036854775808 + + /* Testing BigInt constructor */ + let n0 = new BigInt(0) + assert n0 == 0n + assert(n0.toString() == "0") + + let n1 = new BigInt(654093) + assert(n1.toString() == "654093") + assert n1 == 654093n + + let n2 = new BigInt(b) + assert(n2.toString() == "44") + assert n2 == 44n + + let n3 = new BigInt(s) + assert(n3.toString() == "-17600") + assert n3 == -17600n + + let n4 = new BigInt(i) + assert(n4.toString() == "1150483640") + assert n4 == 1150483640n + + let n5 = new BigInt(l) + assert(n5.toString() == "-8223372036854775808") + assert n5 == -8223372036854775808n + + let dec = new BigInt("-12392320390239294724747283477947923471101032") + assert dec == -12392320390239294724747283477947923471101032n + + const n7 = 12392320390239294724747283477947923471101032n + + /* Testing asIntN() static method */ + // assert BigInt.asIntN(0, n7) == 0n + // assert BigInt.asIntN(8, n7) == 104n + // assert BigInt.asIntN(16, n7) == 27752n + // assert BigInt.asIntN(32, n7) == -737317784n + // assert BigInt.asIntN(64, n7) == -7098331616643290008n + + /* Testing asUintN() static method */ + // assert BigInt.asUintN(0, n7) == 0n + // assert BigInt.asUintN(8, n7) == 104n + // assert BigInt.asUintN(16, n7) == 27752n + // assert BigInt.asUintN(32, n7) == 3557649512n + // assert BigInt.asUintN(64, n7) == 11348412457066261608n +} + +function test_unary(): void { + let n = -128n + assert (n.toString() == "-128") + + let a = 123n; + assert(a == 123n); + assert(a.toString() == "123"); + + a = -123n; + assert(a == -123n); + assert(a.toString() == "-123"); + + a = 123n + assert(a == 123n); + assert(a.toString() == "123"); + + a = -a; + assert(a == -123n); + assert(a.toString() == "-123"); + + a = -a; + assert(a == 123n); + assert(a.toString() == "123"); + + let e: bigint; + assert(a == 123n); + assert(a.toString() == "123"); + e = -a; + + // Check that original value does not change + assert(a == 123n); + assert(a.toString() == "123"); + assert(e == -123n); + assert(e.toString() == "-123"); + e = a; + assert(e == 123n); + assert(e.toString() == "123"); + + let b = -123n; + assert(b == -123n) + assert(b.toString() == "-123"); + + let c = -(123n); + assert(c == -123n) + assert(c.toString() == "-123"); + + // Double unary minus + let d = -(-123n); + assert(d == 123n); + assert(d.toString() == "123"); + + // Triple unary minux + let f = -(-(-123n)); + assert(f == -123n); + assert(f.toString() == "-123"); + + a = new BigInt(321); + assert(a.toString() == "321") + assert(a == 321n) + + b = -a; + assert(a.toString() == "321") + assert(a == 321n) + assert(b == -321n); + assert(b.toString() == "-321"); +} + +function test_multiplication(): void { + const a = 23443495146314363289895841n + const b = 245000234343499329134n + const c = -245000234343499329134n + + /* Multiplication testing (*) */ + assert 978667632325344545n * 4534000101n == 4437279143808543031889799045n + assert a * b == 5743661804677708098900659843374372544236731694n + assert a * c == -5743661804677708098900659843374372544236731694n + assert a * 0n == 0n + assert c * 0n == 0n + + + /* Division testing (/) */ + assert 39735235034886462n / 89221422n == 445355321n + assert a / b == 95687n + assert a / c == -95687n + assert 0n / a == 0n + + let err = false; + try { + a / 0n + } catch (e) { + if (e instanceof Error) { + err = true + } + } + assert err + + /* Remainder of the division (%) */ + assert 493433405047004109n % 111114444n == 18100749n + assert a % b == a % c + assert 0n % a == 0n + + err = false; + try { + a % 0n + } catch (e) { + if (e instanceof Error) { + err = true + } + } + assert err +} + +function test_addition_1(): void { + const a = 97567789101304567800013210071n + const b = -533923234343411557221n + const c = 0n; + + /* Minus testing (-) */ + assert (-a == -97567789101304567800013210071n) + assert (-b == 533923234343411557221n) + assert (-c == -0n) + assert (-(-a) == a) + assert (-(-b) == b) + assert (-(-c) == c) + + /* Plus testing (+) */ + assert +a == a + assert +b == b + assert +c == 0n +} + +function test_addition_2(): void { + const a = 18446744073709551616n; + const b = 36893488147419103232n; + const c = -10000000000000000000n; + + /* Addition testing (+) */ + assert 999999999999999n + 1n == 1000000000000000n + assert a + b == 55340232221128654848n + assert a + a == b + assert a + c == 8446744073709551616n + assert a + b + b == 92233720368547758080n +} + +function test_subtraction(): void { + const a = 18446744073709551616n; + const b = 36893488147419103232n; + const c = -10000000000000000000n; + + // /* Subtraction testing (-) */ + assert 999999999999999n - 1n == 999999999999998n + assert b - a == a + assert a - b == -18446744073709551616n + assert b - a - a == 0n +} + +function test_inc_dec(): void { + const a = 340282366920938463463374607431768211456n + const b = -2313455919991034304490n + + /* Increment testing */ + /* Decrement testing */ +} + +function test_shift(): void { + const a = 245599210405555256299145n + + /* Testing left shift (<<) */ + assert a << 100n == 311333986486181324779687697000809288883015536628203520n + assert a << 0n == a + + /* Testing right shift (>>) */ + assert a >> 60n == 213023n + assert a >> 0n == a +} + +function test_bitwise(): void { + const a = 123456789123456789123456789123456789123456789123456789n + let b = 123456790n + const zero = 0n + + /* Testing bitwise NOT (~) */ + assert ~zero == -1n + assert ~a == -123456789123456789123456789123456789123456789123456790n + + /* Testing bitwise AND (&) */ + /* Testing bitwise XOR (^) */ + /* Testing bitwise OR (|) */ +} + +function main() : void { + test_create_empty_bigint(); + test_bigint_as_string(); + test_invalid_bigint(); + test_multiply(); + test_plus(); + test_minus(); + test_unary_minus(); + test_divide(); + test_module(); + test_bitwise_and(); + test_bitwise_or(); + test_bitwise_xor(); + test_left_shift(); + test_right_shift(); + test_type(); + test_assignment(); + test_compare(); + test_literals(); + test_cast(); + test_bigint_methods(); + test_unary(); + test_multiplication(); + test_addition_1(); + test_addition_2(); + test_subtraction(); + test_inc_dec(); + test_shift(); + test_bitwise(); +} diff --git a/ets2panda/test/runtime/ets/BitwiseOperationsOnFloat.ets b/ets2panda/test/runtime/ets/BitwiseOperationsOnFloat.ets new file mode 100644 index 0000000000000000000000000000000000000000..816928325c8749a9a27469d3161a1d996577f7a9 --- /dev/null +++ b/ets2panda/test/runtime/ets/BitwiseOperationsOnFloat.ets @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function And(a: double, b: double): long { + return a & b +} + +function Or(a: double, b: double): long { + return a | b +} + +function Xor(a: double, b: double): long { + return a ^ b +} + +function LeftShift(a: double, b: double): long { + return a << b +} + +function RightShift(a: double, b: double): long { + return a >> b +} + +function UnsignedRightShift(a: double, b: double): long { + return a >>> b +} + +function Inversion(a: double): long { + return ~a; +} + +function main(): void { + /* ---- Compile time tests ---- */ + + // Testing "and" operator: + assert (542.910991 & -1903.2040221) == 16 + assert (-542.910991 & 1903.2040221) == 1378 + assert (-542.910991 & -1903.2040221) == -1920 + assert (9E120 & 56.75) == 56 + assert (0.0 & 0.0) == 0 + assert (NaN & 42.131330352) == 0 + assert (-NaN & -23432.34110144432) == 0 + assert (Infinity & -94.24445985981884) == 9223372036854775714 + assert (-Infinity & 94.24445985981884) == 0 + + // Testing "or" operator: + assert (542.910991 | 1903.2040221) == 1919 + assert (542.910991 | -1903.2040221) == -1377 + assert (-542.910991 | 1903.2040221) == -17 + assert (-542.910991 | -1903.2040221) == -525 + assert (9E120 | 0) == 9223372036854775807 + assert (824E3 | 21.018763) == 824021 + assert (1.0 | 0.1) == 1 + assert (NaN | 0.2) == 0 + assert (-NaN | 0.3) == 0 + assert (Infinity | 0.4) == 9223372036854775807 + assert (-Infinity | 0.5) == -9223372036854775808 + + // Testing "xor" operator: + assert (542.910991 ^ 1903.2040221) == 1393 + assert (542.910991 ^ -1903.2040221) == -1393 + assert (-542.910991 ^ 1903.2040221) == -1395 + assert (-542.910991 ^ -1903.2040221) == 1395 + assert (49509.2348100001 ^ 49509.2348100001) == 0 + assert (9E120 ^ 1.2) == 9223372036854775806 + assert (824E3 ^ 21.018763) == 824021 + assert (NaN ^ 99854258.24) == 99854258 + assert (-NaN ^ 30483040.293244) == 30483040 + assert (Infinity ^ 1.2) == 9223372036854775806 + assert (-Infinity ^ 10049329.80001) == -9223372036844726479 + + // Testing "left shift" operator: + assert (1E-100 << 0.0) == 0 + assert (0.00003 << 12.13) == 0 + assert (42.109 << 0.0120939) == 42 + assert (1.409240940 << 17.3) == 131072 + assert (4342435.309421 << 3.1) == 34739480 + assert (9010034745.3449093132 << 7.000000000001) == 1153284447360 + assert (-423.14981 << 20.32) == -443547648 + assert (500.13 << 128.3440) == 500 + assert (500.45 << 121.10000002) == -1729382256910270464 + assert (NaN << 330.3911) == 0 + assert (-NaN << 12.91213) == 0 + assert (Infinity << 1.0092) == -2 + assert (-Infinity << 1.0092) == 0 + assert (-52242.2301 << -8.7) == -1297036692682702848 + assert (52242.2301 << -8.7) == 1297036692682702848 + + // Testing "right shift" operator: + assert (1E-100 >> 0.0) == 0 + assert (0.00003 >> 12.13) == 0 + assert (42.109 >> 0.0120939) == 42 + assert (1.409240940 >> 17.3) == 0 + assert (4342435.309421 >> 3.1) == 542804 + assert (9010034.3449093132 >> 3.000000000001) == 1126254 + assert (-4599090490.24 >> 11) == -2245650 + assert (500.13 >> 128.3440) == 500 + assert (500.45 >> 121.10000002) == 0 + assert (NaN >> 11.000003) == 0 + assert (-NaN >> 7.912130001) == 0 + assert (Infinity >> 61) == 3 + assert (-Infinity >> 61) == -4 + assert (132090941883.34343 >> -32.2) == 30 + assert (-132090941883.34343 >> -32.2) == -31 + + // Testing "unsigned right shift" operator: + assert (1E-100 >>> 0.0) == 0 + assert (0.00003 >>> 12.13) == 0 + assert (42.109 >>> 0.0120939) == 42 + assert (1.409240940 >>> 17.3) == 0 + assert (4342435.309421 >>> 3.1) == 542804 + assert (9010034.3449093132 >>> 3.000000000001) == 1126254 + assert (-4599090490.24 >>> 11) == 9007199252495342 + assert (500.13 >>> 128.3440) == 500 + assert (500.45 >>> 121.10000002) == 0 + assert (NaN >>> 11.000003) == 0 + assert (-NaN >>> 7.912130001) == 0 + assert (Infinity >>> 61.8) == 3 + assert (-Infinity >>> 61.8) == 4 + assert (132090941883.34343 >>> -32.2) == 30 + assert (-132090941883.34343 >>> -32.2) == 4294967265 + + // Testing "bitwise complement" operator + assert ~0 == -1 + assert ~0.000034 == -1 + assert ~39530.93 == -39531 + assert ~93718001.5424230894 == -93718002 + assert ~Infinity == -9223372036854775808 + assert ~-Infinity == 9223372036854775807 + assert ~NaN == -1 + assert ~-NaN == -1 + assert ~1E210 == -9223372036854775808 + assert ~-1E210 == 9223372036854775807 + assert ~56E5 == -5600001 + assert ~-56E5 == 5599999 + + /* ---- Run time tests ---- */ + + // Testing "and" operator: + assert And(542.910991, -1903.2040221) == 16 + assert And(-542.910991, 1903.2040221) == 1378 + assert And(-542.910991, -1903.2040221) == -1920 + assert And(9E120, 56.75) == 56 + assert And(0.0, 0.0) == 0 + assert And(NaN, 42.131330352) == 0 + assert And(-NaN, -23432.34110144432) == 0 + assert And(Infinity, -94.24445985981884) == 9223372036854775714 + assert And(-Infinity, 94.24445985981884) == 0 + + // Testing "or" operator: + assert Or(542.910991, 1903.2040221) == 1919 + assert Or(542.910991, -1903.2040221) == -1377 + assert Or(-542.910991, 1903.2040221) == -17 + assert Or(-542.910991, -1903.2040221) == -525 + assert Or(9E120, 0) == 9223372036854775807 + assert Or(824E3, 21.018763) == 824021 + assert Or(1.0, 0.1) == 1 + assert Or(NaN, 0.2) == 0 + assert Or(-NaN, 0.3) == 0 + assert Or(Infinity, 0.4) == 9223372036854775807 + assert Or(-Infinity, 0.5) == -9223372036854775808 + + // Testing "xor" operator: + assert Xor(542.910991, 1903.2040221) == 1393 + assert Xor(542.910991, -1903.2040221) == -1393 + assert Xor(-542.910991, 1903.2040221) == -1395 + assert Xor(-542.910991, -1903.2040221) == 1395 + assert Xor(49509.2348100001, 49509.2348100001) == 0 + assert Xor(9E120, 1.2) == 9223372036854775806 + assert Xor(824E3, 21.018763) == 824021 + assert Xor(NaN, 99854258.24) == 99854258 + assert Xor(-NaN, 30483040.293244) == 30483040 + assert Xor(Infinity, 1.2) == 9223372036854775806 + assert Xor(-Infinity, 10049329.80001) == -9223372036844726479 + + // Testing "left shift" operator: + assert LeftShift(1E-100, 0.0) == 0 + assert LeftShift(0.00003, 12.13) == 0 + assert LeftShift(42.109, 0.0120939) == 42 + assert LeftShift(1.409240940, 17.3) == 131072 + assert LeftShift(4342435.309421, 3.1) == 34739480 + assert LeftShift(9010034745.3449093132, 7.000000000001) == 1153284447360 + assert LeftShift(-423.14981, 20.32) == -443547648 + assert LeftShift(500.13, 128.3440) == 500 + assert LeftShift(500.45, 121.10000002) == -1729382256910270464 + assert LeftShift(NaN, 330.3911) == 0 + assert LeftShift(-NaN, 12.91213) == 0 + assert LeftShift(Infinity, 1.0092) == -2 + assert LeftShift(-Infinity, 1.0092) == 0 + assert LeftShift(-52242.2301, -8.7) == -1297036692682702848 + assert LeftShift(52242.2301,-8.7) == 1297036692682702848 + + // Testing "right shift" operator: + assert RightShift(1E-100, 0.0) == 0 + assert RightShift(0.00003, 12.13) == 0 + assert RightShift(42.109, 0.0120939) == 42 + assert RightShift(1.409240940, 17.3) == 0 + assert RightShift(4342435.309421, 3.1) == 542804 + assert RightShift(9010034.3449093132, 3.000000000001) == 1126254 + assert RightShift(-4599090490.24, 11) == -2245650 + assert RightShift(500.13, 128.3440) == 500 + assert RightShift(500.45, 121.10000002) == 0 + assert RightShift(NaN, 11.000003) == 0 + assert RightShift(-NaN, 7.912130001) == 0 + assert RightShift(Infinity, 61) == 3 + assert RightShift(-Infinity, 61) == -4 + assert RightShift(132090941883.34343, -32.2) == 30 + assert RightShift(-132090941883.34343, -32.2) == -31 + + // Testing "unsigned right shift" operator: + assert UnsignedRightShift(1E-100, 0.0) == 0 + assert UnsignedRightShift(0.00003,12.13) == 0 + assert UnsignedRightShift(42.109, 0.0120939) == 42 + assert UnsignedRightShift(1.409240940, 17.3) == 0 + assert UnsignedRightShift(4342435.309421, 3.1) == 542804 + assert UnsignedRightShift(9010034.3449093132, 3.000000000001) == 1126254 + assert UnsignedRightShift(-4599090490.24, 11) == 9007199252495342 + assert UnsignedRightShift(500.13, 128.3440) == 500 + assert UnsignedRightShift(500.45, 121.10000002) == 0 + assert UnsignedRightShift(NaN, 11.000003) == 0 + assert UnsignedRightShift(-NaN, 7.912130001) == 0 + assert UnsignedRightShift(Infinity, 61.8) == 3 + assert UnsignedRightShift(-Infinity, 61.8) == 4 + assert UnsignedRightShift(132090941883.34343, -32.2) == 30 + assert UnsignedRightShift(-132090941883.34343, -32.2) == 4294967265 + + // Testing "bitwise complement" operator + assert Inversion(0) == -1 + assert Inversion(0.000034) == -1 + assert Inversion(39530.93) == -39531 + assert Inversion(93718001.5424230894) == -93718002 + assert Inversion(Infinity) == -9223372036854775808 + assert Inversion(-Infinity) == 9223372036854775807 + assert Inversion(NaN) == -1 + assert Inversion(-NaN) == -1 + assert Inversion(1E210) == -9223372036854775808 + assert Inversion(-1E210) == 9223372036854775807 + assert Inversion(56E5) == -5600001 + assert Inversion(-56E5) == 5599999 +} diff --git a/ets2panda/test/runtime/ets/InterfaceOverrideReturnTypes.ets b/ets2panda/test/runtime/ets/InterfaceOverrideReturnTypes.ets new file mode 100644 index 0000000000000000000000000000000000000000..87e57dfd1cfe85a7c12a5c7a82774664b8394819 --- /dev/null +++ b/ets2panda/test/runtime/ets/InterfaceOverrideReturnTypes.ets @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface A { + foo(): A +} + +interface B extends A { + foo(): B +} + +class C implements A { + private value: string; + + foo(): A { + this.value = "foo(): A" + return new C(); + } + + getValue(): string { + return this.value; + } +} + +class D implements B { + private value: string; + + foo(): B { + this.value = "foo(): B" + return new D(); + } + + getValue(): string { + return this.value; + } +} + +function main() { + let c = new C(); + c.foo(); + assert c.getValue() == "foo(): A" + + let d = new D(); + d.foo(); + assert d.getValue() == "foo(): B" +} diff --git a/ets2panda/test/runtime/ets/NoConstraint.ets b/ets2panda/test/runtime/ets/NoConstraint.ets new file mode 100644 index 0000000000000000000000000000000000000000..7c54f31ebbdc9146bb92fd75be8d9366c5b8b230 --- /dev/null +++ b/ets2panda/test/runtime/ets/NoConstraint.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type NullishFoo = Object | null | undefined; + +function foo(x: T): NullishFoo { + return x; +} + +function bar(x: T): NullishFoo { + return x; +} + +function main() { + foo(new Object()); + bar(new Object()); +} diff --git a/ets2panda/test/runtime/ets/array-object.ets b/ets2panda/test/runtime/ets/array-object.ets index 0228add708c70ff3c90a15eaccdabda4c6a1bd83..9e656739d90180635a2f7d387eb97009f885f8cb 100644 --- a/ets2panda/test/runtime/ets/array-object.ets +++ b/ets2panda/test/runtime/ets/array-object.ets @@ -27,11 +27,11 @@ function main(): void { object.toString(); // TypeError: Cannot access property of non-object or non-enum type -// arr1.hashCode(); -// arr2.hashCode(); -// object_array.hashCode(); +// arr1.$_hashCode(); +// arr2.$_hashCode(); +// object_array.$_hashCode(); - object.hashCode(); + object.$_hashCode(); assert(arr1 == arr1); assert(arr1 == object_array); diff --git a/ets2panda/test/runtime/ets/array_inf.ets b/ets2panda/test/runtime/ets/array_inf.ets new file mode 100644 index 0000000000000000000000000000000000000000..eb4ed7c67b339240970dc9c95258daf8eafba69d --- /dev/null +++ b/ets2panda/test/runtime/ets/array_inf.ets @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + foo(p: Object[]): int { + let s = 0 + for (let v of p) { + s += v instanceof A ? 1 : 0 + } + return s + } + bar(p: A[]): int { + let s = 0 + for (let v of p) { + s += v instanceof A ? 1 : 0 + } + return s + } +} + + +class B extends A{} + +function main() { + assert new A().foo([new Object(), new Long(), new Int()]) == 0 + assert new A().foo([new A(), new A(), new Object()]) == 2 + assert new A().foo(["aaa", new A(), new Object()]) == 1 + assert new A().foo([1, "hello", new A()]) == 1 + assert new A().bar([new B(), new B(), new A()]) == 3 +} diff --git a/ets2panda/test/runtime/ets/class-fields-same-name.ets b/ets2panda/test/runtime/ets/class-fields-same-name.ets new file mode 100644 index 0000000000000000000000000000000000000000..ab04034da7b64008c273c30d5b88f4c3fe2eeadc --- /dev/null +++ b/ets2panda/test/runtime/ets/class-fields-same-name.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class C { + public static foo: int = 10 + public foo: int = 20 +} + +class D extends C { + public static foo: int = 30 + public foo: int = 40 +} + +function main(): void { + assert (C.foo == 10) + assert (new C().foo == 20) + assert (D.foo == 30) + assert (new D().foo == 40) +} diff --git a/ets2panda/test/runtime/ets/conditionalExpression.ets b/ets2panda/test/runtime/ets/conditionalExpression1.ets similarity index 100% rename from ets2panda/test/runtime/ets/conditionalExpression.ets rename to ets2panda/test/runtime/ets/conditionalExpression1.ets diff --git a/ets2panda/test/runtime/ets/conditionalExpression2.ets b/ets2panda/test/runtime/ets/conditionalExpression2.ets new file mode 100644 index 0000000000000000000000000000000000000000..59805a5873c2ec89786d3fe9a33f0ab90133a434 --- /dev/null +++ b/ets2panda/test/runtime/ets/conditionalExpression2.ets @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function foo(form?: String) { + const f = (form == undefined) ? "abc" : form! + switch (f) { + case "abc": + return 41 + case "xyz": + return 42 + default: + return 0 + } +} + +class A{} + +function main(): void { + assert foo() == 41: "Error! foo() must be equal 41"; + assert foo("xyz") == 42: "Error! foo(\"xyz\") must be equal 42"; + assert foo("NFD") == 0: "Error! foo(\"NFD\") must be equal 0"; + let x = foo() == 41 ? new A() : undefined; + assert x instanceof A; + let y = foo("wxyz") == 42 ? "TRUE" : new A(); + assert y instanceof A; + y = "JK"; + assert y == "JK"; +} diff --git a/ets2panda/test/runtime/ets/conditionalExpressionLUB.ets b/ets2panda/test/runtime/ets/conditionalExpressionLUB.ets index 3b36957fdec43265bdb4526cf2e289a7754ab292..6d20bf0e10229ddeea97c3a82cdd287a56750fa8 100644 --- a/ets2panda/test/runtime/ets/conditionalExpressionLUB.ets +++ b/ets2panda/test/runtime/ets/conditionalExpressionLUB.ets @@ -61,23 +61,23 @@ function sameTypeLUB(): void { function objectLUB(): void { let a : A = new A(); let b : Int = 2; - let c = true ? a : b; // Object + let c = true ? a : b; // A | Int assert(foo(c) == 1); let arr : Int[] | null = null; - let d = true ? a : arr; // Object + let d = true ? a : arr; // A | Int[] | null assert(foo(d) == 1); } function forkSubtypeLUB(): void { let a : F = new F(); let b : D = new D(); - let c = true ? a : b; // A + let c = true ? a : b; // F | D => call most specific foo(A) assert(foo(c) == 2); let d : A = new A(); - let e = true ? a : b; // A + let e = true ? a : d; // F | A => normalize to A assert(foo(e) == 2); let f : B = new B(); - let g = true ? a : f; // B + let g = true ? a : f; // F | B => normalize to B assert(foo(g) == 3); } diff --git a/ets2panda/test/runtime/ets/generic-function1.ets b/ets2panda/test/runtime/ets/generic-function1.ets new file mode 100644 index 0000000000000000000000000000000000000000..dec1e8fb55ffea6de0cbbfc31fa12d3841f97670 --- /dev/null +++ b/ets2panda/test/runtime/ets/generic-function1.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + static instantiate(factory: () => T, content: () => void): T { + const instance = factory() + instance.__initializeStruct() + content() + return instance + } + __initializeStruct(): A { + return this + } +} + +class B extends A { + constructor() {} + override __initializeStruct(): A { + return this + } +} + +export function main(): int { + console.println("Start") + + B(){} + + return 0; +} diff --git a/ets2panda/test/runtime/ets/generic_constructor_with_union.ets b/ets2panda/test/runtime/ets/generic_constructor_with_union.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ec5964d829f315163a3b5cb5c75ebd0cdfeab1c --- /dev/null +++ b/ets2panda/test/runtime/ets/generic_constructor_with_union.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main(): void { + let x = new Array<(Number|String)>(); +} \ No newline at end of file diff --git a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt index 586ace81baf350d3b57dcb6aa0e61024e69607a4..b4b2ab58ce345a0b98abebf54c3e0ef1727ba4e5 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -34,3 +34,13 @@ trailing-lambda-with-capture.ets # ignored until union types are properly implemented and non nullish base type of array types can be properly handled notNullMultidimensionalArray.ets + +# ignored until verifier can't handle if a field name can be static and non-static at the same time +class-fields-same-name.ets + +# Disabled temporarily #I8EM2T implementation struct directly expanded to class +struct-identifier.ets +struct-init.ets +struct-init2.ets +struct_implements.ets +top_level_03.ets diff --git a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..de27323be467022892a7ff1d56c6205e070690fa 100644 --- a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt @@ -0,0 +1,13 @@ +parser/ets/test-type-alias-call7.ets +parser/ets/test-type-alias-call8.ets + +# Disabled temporarily #I8EM2T implementation struct directly expanded to class +parser/ets/struct_init.ets +parser/ets/struct_static_initializer.ets +parser/ets/struct_identifier.ets +parser/ets/struct_invalid_extends1.ets +parser/ets/struct_templete.ets +parser/ets/import_tests/modules/struct_module.ets +parser/ets/import_tests/check_exported_default_struct.ets +parser/ets/import_tests/modules/struct_default_module.ets +parser/ets/import_tests/check_exported_struct.ets diff --git a/ets2panda/test/test-lists/parser/parser-js-ignored.txt b/ets2panda/test/test-lists/parser/parser-js-ignored.txt index 49f4f01669340ff604b4971beeec37ff7c5e0fc0..a0cac35d0e8d349ebf833c8793d6cfe4aae7a44a 100644 --- a/ets2panda/test/test-lists/parser/parser-js-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-js-ignored.txt @@ -69,3 +69,12 @@ parser/ets/trailing_lambda_tests/trailing_lambda_define_lambda_in_body_capture_v # Bad test shadows Object with type parameter name #14913 compiler/ets/override13.ets + +# 15095 +compiler/ets/methodOverrideCovariantReturnType.ets +compiler/ets/override16.ets +compiler/ets/override17.ets +parser/ets/static_function_hide_2.ets + +# 14595 +compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets diff --git a/ets2panda/test/unit/ast_dumper_test.cpp b/ets2panda/test/unit/ast_dumper_test.cpp index 4f3b1c5196f8e62eba9f905b956b4b6c4f169cc6..047ce9a9fa939dea264bca5fe6c2c7c7b25e50a5 100644 --- a/ets2panda/test/unit/ast_dumper_test.cpp +++ b/ets2panda/test/unit/ast_dumper_test.cpp @@ -18,7 +18,6 @@ #include "macros.h" #include "assembler/assembly-program.h" -#include "compiler/core/ASTVerifier.h" #include "ir/astDump.h" #include "ir/expressions/literals/stringLiteral.h" diff --git a/ets2panda/test/unit/lowerings/scopes_initialization.cpp b/ets2panda/test/unit/lowerings/scopes_initialization.cpp index acdd11dc9f677268d834fff7306a0f1729a51bbc..dc0849d9c264866dd461102dde12fbfebe871209 100644 --- a/ets2panda/test/unit/lowerings/scopes_initialization.cpp +++ b/ets2panda/test/unit/lowerings/scopes_initialization.cpp @@ -81,7 +81,7 @@ TEST_F(ScopesInitPhaseTest, TestForUpdateLoop) */ auto varbinder = varbinder::VarBinder(Allocator()); auto forNode = NodeGen().CreateForUpdate(); - compiler::ScopesInitPhaseETS::RunExternalNode(forNode, &varbinder); + compiler::InitScopesPhaseETS::RunExternalNode(forNode, &varbinder); auto blockScope = forNode->Body()->AsBlockStatement()->Scope(); auto loopScope = forNode->Scope(); @@ -111,7 +111,7 @@ TEST_F(ScopesInitPhaseTest, CreateWhile) auto varbinder = varbinder::VarBinder(Allocator()); auto whileNode = NodeGen().CreateWhile(); - compiler::ScopesInitPhaseETS::RunExternalNode(whileNode, &varbinder); + compiler::InitScopesPhaseETS::RunExternalNode(whileNode, &varbinder); auto whileScope = whileNode->Scope(); auto bodyScope = whileNode->Body()->AsBlockStatement()->Scope(); @@ -124,4 +124,4 @@ TEST_F(ScopesInitPhaseTest, CreateWhile) ASSERT_EQ(bodyBindings.begin()->second, name->Variable()); } -} // namespace panda::es2panda \ No newline at end of file +} // namespace panda::es2panda diff --git a/ets2panda/test/unit/public/ast_verifier_test.cpp b/ets2panda/test/unit/public/ast_verifier_test.cpp index add3b8abdfeddf94c3655da97f8cf4b50ecba2d7..2968017c40ad5e8705142ed79471be771bd66b64 100644 --- a/ets2panda/test/unit/public/ast_verifier_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_test.cpp @@ -14,7 +14,6 @@ */ #include "checker/ETSchecker.h" -#include "compiler/core/ASTVerifier.h" #include "ir/expressions/literals/stringLiteral.h" #include "ir/expressions/identifier.h" #include "ir/expressions/literals/numberLiteral.h" @@ -22,26 +21,34 @@ #include "macros.h" #include "parser/ETSparser.h" #include "varbinder/ETSBinder.h" -#include "public/es2panda_lib.h" +#include "compiler/core/ASTVerifier.h" -#include #include -// NOLINTBEGIN(cppcoreguidelines-macro-usage) -#define TREE(node) \ - ([&]() { \ - using namespace panda::es2panda::ir; \ - return node; \ - }()) - -#define NODE(Type, ...) allocator->New(__VA_ARGS__) -#define NODES(Type, ...) \ - ([&]() -> ArenaVector { \ - auto v = ArenaVector {allocator->Adapter()}; \ - v.insert(v.end(), {__VA_ARGS__}); \ - return v; \ - }()) -// NOLINTEND(cppcoreguidelines-macro-usage) +using panda::es2panda::CompilerOptions; +using panda::es2panda::ScriptExtension; +using panda::es2panda::checker::ETSChecker; +using panda::es2panda::compiler::ASTVerifier; +using panda::es2panda::ir::AstNode; +using panda::es2panda::ir::BinaryExpression; +using panda::es2panda::ir::BooleanLiteral; +using panda::es2panda::ir::ETSScript; +using panda::es2panda::ir::Expression; +using panda::es2panda::ir::Identifier; +using panda::es2panda::ir::NumberLiteral; +using panda::es2panda::ir::SequenceExpression; +using panda::es2panda::ir::StringLiteral; +using panda::es2panda::lexer::Number; +using panda::es2panda::lexer::TokenType; +using panda::es2panda::parser::ETSParser; +using panda::es2panda::parser::Program; +using panda::es2panda::util::StringView; +using panda::es2panda::varbinder::ETSBinder; +using panda::es2panda::varbinder::FunctionScope; +using panda::es2panda::varbinder::LetDecl; +using panda::es2panda::varbinder::LocalScope; +using panda::es2panda::varbinder::LocalVariable; +using panda::es2panda::varbinder::VariableFlags; class ASTVerifierTest : public testing::Test { public: @@ -68,6 +75,26 @@ public: NO_MOVE_SEMANTIC(ASTVerifierTest); protected: + template + Type *Tree(Type *node) + { + return node; + } + + template + Type *Node(Args &&...args) + { + return allocator_->New(std::forward(args)...); + } + + template + panda::ArenaVector Nodes(Args &&...args) + { + auto v = panda::ArenaVector {allocator_->Adapter()}; + v.insert(v.end(), {std::forward(args)...}); + return v; + } + // NOLINTBEGIN(misc-non-private-member-variables-in-classes) es2panda_Impl const *impl_; es2panda_Config *cfg_; @@ -77,196 +104,210 @@ protected: TEST_F(ASTVerifierTest, NullParent) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - panda::es2panda::ir::StringLiteral emptyNode; - - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("HasParent"); - bool hasParent = verifier.Verify(&emptyNode, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; - - ASSERT_EQ(hasParent, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(name, "HasParent"); - ASSERT_EQ(error.message, "NULL_PARENT: STR_LITERAL "); + ASTVerifier verifier {Allocator()}; + StringLiteral emptyNode; + + const auto check = "NodeHasParent"; + auto checks = ASTVerifier::InvariantSet {}; + checks.insert(check); + const auto [warnings, errors] = verifier.Verify({{"NodeHasParent"}}, {{}}, &emptyNode, checks); + bool hasParent = warnings.empty(); + ASSERT_FALSE(hasParent); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_EQ(warnings[0].GetName(), check); } TEST_F(ASTVerifierTest, NullType) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - panda::es2panda::ir::StringLiteral emptyNode; - - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("HasType"); - bool hasType = verifier.Verify(&emptyNode, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; - + ASTVerifier verifier {Allocator()}; + StringLiteral emptyNode; + + auto check = "NodeHasType"; + auto checks = ASTVerifier::InvariantSet {}; + checks.insert(check); + const auto [warnings, errors] = verifier.Verify({{"NodeHasType"}}, {{}}, &emptyNode, checks); + bool hasType = warnings.empty(); ASSERT_EQ(hasType, false); - ASSERT_NE(errors.size(), 0); - ASSERT_EQ(name, "HasType"); - ASSERT_EQ(error.message, "NULL_TS_TYPE: STR_LITERAL "); + ASSERT_NE(warnings.size(), 0); + + ASSERT_EQ(warnings[0].GetName(), check); } TEST_F(ASTVerifierTest, WithoutScope) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - panda::es2panda::ir::StringLiteral emptyNode; + ASTVerifier verifier {Allocator()}; + StringLiteral emptyNode; - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("HasScope"); - bool hasScope = verifier.Verify(&emptyNode, checks); - const auto &errors = verifier.GetErrors(); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("VariableHasScope"); + const auto [warnings, errors] = verifier.Verify({{"VariableHasScope"}}, {{}}, &emptyNode, checks); - ASSERT_EQ(hasScope, true); - ASSERT_EQ(errors.size(), 0); + ASSERT_EQ(warnings.size(), 0); } TEST_F(ASTVerifierTest, ScopeTest) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - panda::es2panda::ir::Identifier ident(panda::es2panda::util::StringView("var_decl"), Allocator()); - panda::es2panda::varbinder::LetDecl decl("test", &ident); - panda::es2panda::varbinder::LocalVariable local(&decl, panda::es2panda::varbinder::VariableFlags::LOCAL); + ASTVerifier verifier {Allocator()}; + Identifier ident(StringView("var_decl"), Allocator()); + LetDecl decl("test", &ident); + LocalVariable local(&decl, VariableFlags::LOCAL); ident.SetVariable(&local); - panda::es2panda::varbinder::LocalScope scope(Allocator(), nullptr); - panda::es2panda::varbinder::FunctionScope parentScope(Allocator(), nullptr); + LocalScope scope(Allocator(), nullptr); + FunctionScope parentScope(Allocator(), nullptr); scope.SetParent(&parentScope); - scope.AddDecl(Allocator(), &decl, panda::es2panda::ScriptExtension::ETS); + scope.AddDecl(Allocator(), &decl, ScriptExtension::ETS); scope.BindNode(&ident); local.SetScope(&scope); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("HasScope"); - bool isOk = verifier.Verify(&ident, checks); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("VariableHasScope"); + const auto [warnings, errors] = verifier.Verify({{"VariableHasScope"}}, {{}}, &ident, checks); - ASSERT_EQ(isOk, true); + ASSERT_EQ(warnings.size(), 0); } TEST_F(ASTVerifierTest, ScopeNodeTest) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - panda::es2panda::ir::Identifier ident(panda::es2panda::util::StringView("var_decl"), Allocator()); - panda::es2panda::varbinder::LetDecl decl("test", &ident); - panda::es2panda::varbinder::LocalVariable local(&decl, panda::es2panda::varbinder::VariableFlags::LOCAL); + ASTVerifier verifier {Allocator()}; + Identifier ident(StringView("var_decl"), Allocator()); + LetDecl decl("test", &ident); + LocalVariable local(&decl, VariableFlags::LOCAL); ident.SetVariable(&local); - panda::es2panda::varbinder::LocalScope scope(Allocator(), nullptr); - panda::es2panda::varbinder::FunctionScope parentScope(Allocator(), nullptr); + LocalScope scope(Allocator(), nullptr); + FunctionScope parentScope(Allocator(), nullptr); scope.SetParent(&parentScope); - scope.AddDecl(Allocator(), &decl, panda::es2panda::ScriptExtension::ETS); + scope.AddDecl(Allocator(), &decl, ScriptExtension::ETS); scope.BindNode(&ident); parentScope.BindNode(&ident); local.SetScope(&scope); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyScopeNode"); - bool isOk = verifier.Verify(&ident, checks); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("VariableHasEnclosingScope"); + const auto [warnings, errors] = verifier.Verify({{"VariableHasEnclosingScope"}}, {{}}, &ident, checks); - ASSERT_EQ(isOk, true); + ASSERT_EQ(warnings.size(), 0); } TEST_F(ASTVerifierTest, ArithmeticExpressionCorrect1) { - panda::es2panda::checker::ETSChecker etschecker {}; - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - auto program = panda::es2panda::parser::Program::NewProgram(Allocator()); - auto parser = panda::es2panda::parser::ETSParser(&program, panda::es2panda::CompilerOptions {}); + ETSChecker etschecker {}; + ASTVerifier verifier {Allocator()}; + auto program = Program::NewProgram(Allocator()); + auto parser = ETSParser(&program, CompilerOptions {}); - auto left = panda::es2panda::ir::NumberLiteral(panda::es2panda::lexer::Number {1}); - auto right = panda::es2panda::ir::NumberLiteral(panda::es2panda::lexer::Number {6}); - auto arithmeticExpression = - panda::es2panda::ir::BinaryExpression(&left, &right, panda::es2panda::lexer::TokenType::PUNCTUATOR_PLUS); + auto left = NumberLiteral(Number {1}); + auto right = NumberLiteral(Number {6}); + auto arithmeticExpression = BinaryExpression(&left, &right, TokenType::PUNCTUATOR_PLUS); left.SetTsType(etschecker.GlobalIntType()); right.SetTsType(etschecker.GlobalIntType()); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("CheckArithmeticExpression"); - bool isCorrect = verifier.Verify(arithmeticExpression.AsBinaryExpression(), checks); - ASSERT_EQ(isCorrect, true); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("ArithmeticOperationValid"); + const auto [warnings, errors] = + verifier.Verify({{"ArithmeticOperationValid"}}, {{}}, arithmeticExpression.AsBinaryExpression(), checks); + ASSERT_EQ(warnings.size(), 0); } TEST_F(ASTVerifierTest, ArithmeticExpressionCorrect2) { - panda::es2panda::checker::ETSChecker etschecker {}; - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - auto program = panda::es2panda::parser::Program::NewProgram(Allocator()); - auto parser = panda::es2panda::parser::ETSParser(&program, panda::es2panda::CompilerOptions {}); + ETSChecker etschecker {}; + ASTVerifier verifier {Allocator()}; + auto program = Program::NewProgram(Allocator()); + auto parser = ETSParser(&program, CompilerOptions {}); constexpr uint32_t LEFT1_PARAM = 1; constexpr uint32_t LEFT2_PARAM = 12; constexpr uint32_t RIGHT2_PARAM = 6; - auto left1 = panda::es2panda::ir::NumberLiteral(panda::es2panda::lexer::Number {LEFT1_PARAM}); - auto left2 = panda::es2panda::ir::NumberLiteral(panda::es2panda::lexer::Number {LEFT2_PARAM}); - auto right2 = panda::es2panda::ir::NumberLiteral(panda::es2panda::lexer::Number {RIGHT2_PARAM}); - auto right1 = - panda::es2panda::ir::BinaryExpression(&left2, &right2, panda::es2panda::lexer::TokenType::PUNCTUATOR_MULTIPLY); - auto arithmeticExpression = - panda::es2panda::ir::BinaryExpression(&left1, &right1, panda::es2panda::lexer::TokenType::PUNCTUATOR_PLUS); + auto left1 = NumberLiteral(Number {LEFT1_PARAM}); + auto left2 = NumberLiteral(Number {LEFT2_PARAM}); + auto right2 = NumberLiteral(Number {RIGHT2_PARAM}); + auto right1 = BinaryExpression(&left2, &right2, TokenType::PUNCTUATOR_MULTIPLY); + auto arithmeticExpression = BinaryExpression(&left1, &right1, TokenType::PUNCTUATOR_PLUS); left1.SetTsType(etschecker.GlobalIntType()); right1.SetTsType(etschecker.GlobalIntType()); left2.SetTsType(etschecker.GlobalIntType()); right2.SetTsType(etschecker.GlobalIntType()); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("CheckArithmeticExpression"); - bool isCorrect = verifier.Verify(arithmeticExpression.AsBinaryExpression(), checks); - ASSERT_EQ(isCorrect, true); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("ArithmeticOperationValid"); + const auto [warnings, errors] = + verifier.Verify({{"ArithmeticOperationValid"}}, {{}}, arithmeticExpression.AsBinaryExpression(), checks); + ASSERT_EQ(warnings.size(), 0); } TEST_F(ASTVerifierTest, ArithmeticExpressionNegative1) { - panda::es2panda::checker::ETSChecker etschecker {}; - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - auto program = panda::es2panda::parser::Program::NewProgram(Allocator()); - auto parser = panda::es2panda::parser::ETSParser(&program, panda::es2panda::CompilerOptions {}); + ETSChecker etschecker {}; + ASTVerifier verifier {Allocator()}; + auto program = Program::NewProgram(Allocator()); + auto parser = ETSParser(&program, CompilerOptions {}); - const panda::es2panda::util::StringView leftParam("1"); + const StringView leftParam("1"); constexpr uint32_t RIGHT_PARAM = 1; - auto left = panda::es2panda::ir::StringLiteral(leftParam); - auto right = panda::es2panda::ir::NumberLiteral(panda::es2panda::lexer::Number {RIGHT_PARAM}); - auto arithmeticExpression = - panda::es2panda::ir::BinaryExpression(&left, &right, panda::es2panda::lexer::TokenType::PUNCTUATOR_DIVIDE); + auto left = StringLiteral(leftParam); + auto right = NumberLiteral(Number {RIGHT_PARAM}); + auto arithmeticExpression = BinaryExpression(&left, &right, TokenType::PUNCTUATOR_DIVIDE); left.SetTsType(etschecker.GlobalETSStringLiteralType()); right.SetTsType(etschecker.GlobalIntType()); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("CheckArithmeticExpression"); - bool isCorrect = verifier.Verify(arithmeticExpression.AsBinaryExpression(), checks); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("ArithmeticOperationValid"); + const auto [warnings, errors] = + verifier.Verify({{"ArithmeticOperationValid"}}, {{}}, arithmeticExpression.AsBinaryExpression(), checks); - ASSERT_EQ(isCorrect, false); + ASSERT_EQ(warnings.size(), 0); } TEST_F(ASTVerifierTest, ArithmeticExpressionNegative2) { - panda::es2panda::checker::ETSChecker etschecker {}; - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; - auto program = panda::es2panda::parser::Program::NewProgram(Allocator()); - auto parser = panda::es2panda::parser::ETSParser(&program, panda::es2panda::CompilerOptions {}); - auto left = panda::es2panda::ir::BooleanLiteral(true); - auto right = panda::es2panda::ir::NumberLiteral(panda::es2panda::lexer::Number {1}); - auto arithmeticExpression = - panda::es2panda::ir::BinaryExpression(&left, &right, panda::es2panda::lexer::TokenType::PUNCTUATOR_DIVIDE); + ETSChecker etschecker {}; + ASTVerifier verifier {Allocator()}; + auto program = Program::NewProgram(Allocator()); + auto parser = ETSParser(&program, CompilerOptions {}); + auto left = BooleanLiteral(true); + auto right = NumberLiteral(Number {1}); + auto arithmeticExpression = BinaryExpression(&left, &right, TokenType::PUNCTUATOR_DIVIDE); left.SetTsType(etschecker.GlobalETSStringLiteralType()); right.SetTsType(etschecker.GlobalIntType()); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("CheckArithmeticExpression"); - bool isCorrect = verifier.Verify(arithmeticExpression.AsBinaryExpression(), checks); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("ArithmeticOperationValid"); + const auto [warnings, errors] = + verifier.Verify({{"ArithmeticOperationValid"}}, {{}}, arithmeticExpression.AsBinaryExpression(), checks); - ASSERT_EQ(isCorrect, false); + ASSERT_EQ(warnings.size(), 0); +} + +TEST_F(ASTVerifierTest, SequenceExpressionType) +{ + ASTVerifier verifier {Allocator()}; + auto checker = ETSChecker(); + auto *last = Tree(Node(Number {3})); + auto *sequenceExpression = Tree(Node( + Nodes(Node(Number {1}), Node(Number {2}), last))); + + last->SetTsType(checker.GlobalIntType()); + sequenceExpression->SetTsType(checker.GlobalIntType()); + + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("SequenceExpressionHasLastType"); + const auto [warnings, errors] = + verifier.Verify({{"SequenceExpressionHasLastType"}}, {{}}, sequenceExpression, checks); + + ASSERT_EQ(warnings.size(), 0); } constexpr char const *PRIVATE_PROTECTED_PUBLIC_TEST = - R"XXX( + R"( class Base { public a: int = 1; protected b: int = 2; @@ -307,46 +348,44 @@ constexpr char const *PRIVATE_PROTECTED_PUBLIC_TEST = let c = derived2.a; derived2.publicMethod(); } - )XXX"; + )"; TEST_F(ASTVerifierTest, PrivateProtectedPublicAccessTestCorrect) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, PRIVATE_PROTECTED_PUBLIC_TEST, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); - ASSERT_EQ(isCorrect, true); - ASSERT_EQ(errors.size(), 0); + ASSERT_EQ(warnings.size(), 0); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, PrivateAccessTestNegative1) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; } class Derived extends Base { public b: int = this.a; } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -355,23 +394,21 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative1) ->AsClassProperty() ->AddModifier(panda::es2panda::ir::ModifierFlags::PRIVATE); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR MUST BE UNREACHABLE.ID a"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, PrivateAccessTestNegative2) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; } @@ -379,14 +416,14 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative2) let base: Base = new Base(); let a = base.a; } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -395,23 +432,21 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative2) ->AsClassProperty() ->AddModifier(panda::es2panda::ir::ModifierFlags::PRIVATE); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID base.ID a"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, PrivateAccessTestNegative3) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; } @@ -420,14 +455,14 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative3) let derived: Derived = new Derived(); let a = derived.a; } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -436,23 +471,21 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative3) ->AsClassProperty() ->AddModifier(panda::es2panda::ir::ModifierFlags::PRIVATE); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID derived.ID a"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, PrivateAccessTestNegative4) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; } @@ -461,14 +494,14 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative4) let derived: Base = new Derived(); let a = derived.a; } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -477,23 +510,21 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative4) ->AsClassProperty() ->AddModifier(panda::es2panda::ir::ModifierFlags::PRIVATE); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID derived.ID a"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, PrivateAccessTestNegative5) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; public privateMethod() { @@ -504,14 +535,14 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative5) let base: Base = new Base(); base.privateMethod(); } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -531,23 +562,21 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative5) ->Signature() ->AddSignatureFlag(panda::es2panda::checker::SignatureFlags::PRIVATE); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID base.ID privateMethod"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, PrivateAccessTestNegative6) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; public privateMethod() { @@ -559,14 +588,14 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative6) let derived: Derived = new Derived(); derived.privateMethod(); } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -586,23 +615,21 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative6) ->Signature() ->AddSignatureFlag(panda::es2panda::checker::SignatureFlags::PRIVATE); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID derived.ID privateMethod"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, PrivateAccessTestNegative7) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; public privateMethod() { @@ -614,14 +641,14 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative7) let derived: Base = new Derived(); derived.privateMethod(); } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -641,37 +668,35 @@ TEST_F(ASTVerifierTest, PrivateAccessTestNegative7) ->Signature() ->AddSignatureFlag(panda::es2panda::checker::SignatureFlags::PRIVATE); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID derived.ID privateMethod"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, ProtectedAccessTestCorrect) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class A { public a: int = 1; } class B extends A { public b: int = this.a; } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -680,21 +705,20 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestCorrect) ->AsClassProperty() ->AddModifier(panda::es2panda::ir::ModifierFlags::PROTECTED); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + + ASSERT_EQ(warnings.size(), 0); - ASSERT_EQ(isCorrect, true); - ASSERT_EQ(errors.size(), 0); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, ProtectedAccessTestNegative1) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; } @@ -702,14 +726,14 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative1) let base: Base = new Base(); let a = base.a; } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -718,23 +742,21 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative1) ->AsClassProperty() ->AddModifier(panda::es2panda::ir::ModifierFlags::PROTECTED); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID base.ID a"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, ProtectedAccessTestNegative2) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; } @@ -743,14 +765,14 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative2) let derived: Derived = new Derived(); let a = derived.a; } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -759,23 +781,21 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative2) ->AsClassProperty() ->AddModifier(panda::es2panda::ir::ModifierFlags::PROTECTED); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID derived.ID a"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, ProtectedAccessTestNegative3) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; } @@ -784,14 +804,14 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative3) let derived: Base = new Derived(); let a = derived.a; } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[1] ->AsClassDeclaration() ->Definition() @@ -800,23 +820,21 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative3) ->AsClassProperty() ->AddModifier(panda::es2panda::ir::ModifierFlags::PROTECTED); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID derived.ID a"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, ProtectedAccessTestNegative4) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; public protectedMethod() { @@ -827,14 +845,14 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative4) let base: Base = new Base(); base.protectedMethod(); } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -854,23 +872,21 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative4) ->Signature() ->AddSignatureFlag(panda::es2panda::checker::SignatureFlags::PROTECTED); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID base.ID protectedMethod"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, ProtectedAccessTestNegative5) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; public protectedMethod() { @@ -882,14 +898,14 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative5) let derived: Derived = new Derived(); derived.protectedMethod(); } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -909,23 +925,21 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative5) ->Signature() ->AddSignatureFlag(panda::es2panda::checker::SignatureFlags::PROTECTED); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID derived.ID protectedMethod"); impl_->DestroyContext(ctx); } TEST_F(ASTVerifierTest, ProtectedAccessTestNegative6) { - panda::es2panda::compiler::ASTVerifier verifier {Allocator()}; + ASTVerifier verifier {Allocator()}; - char const *text = R"XXX( + char const *text = R"( class Base { public a: int = 1; public protectedMethod() { @@ -937,14 +951,14 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative6) let derived: Base = new Derived(); derived.protectedMethod(); } - )XXX"; + )"; es2panda_Context *ctx = impl_->CreateContextFromString(cfg_, text, "dummy.ets"); impl_->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); ASSERT_EQ(impl_->ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); + auto *ast = reinterpret_cast(impl_->ProgramAst(impl_->ContextProgram(ctx))); - ast->AsBlockStatement() + ast->AsETSScript() ->Statements()[0] ->AsClassDeclaration() ->Definition() @@ -964,14 +978,13 @@ TEST_F(ASTVerifierTest, ProtectedAccessTestNegative6) ->Signature() ->AddSignatureFlag(panda::es2panda::checker::SignatureFlags::PROTECTED); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyModifierAccessRecursive"); - bool isCorrect = verifier.Verify(ast, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; + ASTVerifier::InvariantSet checks; + checks.insert("ModifierAccessValidForAll"); + + const auto [warnings, errors] = verifier.Verify({{"ModifierAccessValidForAll"}}, {{}}, ast, checks); + ASSERT_EQ(warnings.size(), 1); + + ASSERT_NE(checks.find(warnings[0].GetName() + "ForAll"), checks.end()); - ASSERT_EQ(isCorrect, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(error.message, "PROPERTY_NOT_VISIBLE_HERE: MEMBER_EXPR ID derived.ID protectedMethod"); impl_->DestroyContext(ctx); } diff --git a/ets2panda/test/unit/union_normalization_test.cpp b/ets2panda/test/unit/union_normalization_test.cpp index a77e9ae81c051916162122f79aca71546da708ae..ce42d051e2a08d91ccf4f0970dbe7126dd5eac4c 100644 --- a/ets2panda/test/unit/union_normalization_test.cpp +++ b/ets2panda/test/unit/union_normalization_test.cpp @@ -433,6 +433,54 @@ TEST_F(UnionNormalizationTest, UnionLinearization) ASSERT_EQ(ut3->ConstituentTypes().at(IDX2), checker.GetGlobalTypesHolder()->GlobalDoubleBuiltinType()); } +TEST_F(UnionNormalizationTest, UnionStringLiterals) +{ + // NOLINTNEXTLINE(modernize-avoid-c-arrays) + const char *argv = "../../../bin/es2panda"; + checker::ETSChecker checker; + auto program = parser::Program::NewProgram(Allocator()); + InitializeChecker(&argv, "_.ets", "", &checker, &program); + + // Test normalization: string | "abc" ==> string + ArenaVector unionConstituents1(checker.Allocator()->Adapter()); + unionConstituents1.emplace_back(checker.GlobalBuiltinETSStringType()); + unionConstituents1.emplace_back(checker.CreateETSStringLiteralType("abc")); + + // Create union type, which will be normalized inside creation function + auto *const normalizedType1 = checker.CreateETSUnionType(std::move(unionConstituents1)); + ASSERT_NE(normalizedType1, nullptr); + ASSERT_TRUE(normalizedType1->IsETSObjectType()); + ASSERT_EQ(normalizedType1, checker.GlobalBuiltinETSStringType()); + + // Test normalization: "abc" | string | string ==> string + ArenaVector unionConstituents2(checker.Allocator()->Adapter()); + unionConstituents2.emplace_back(checker.CreateETSStringLiteralType("abc")); + unionConstituents2.emplace_back(checker.GlobalBuiltinETSStringType()); + unionConstituents2.emplace_back(checker.GlobalBuiltinETSStringType()); + + // Create union type, which will be normalized inside creation function + auto *const normalizedType2 = checker.CreateETSUnionType(std::move(unionConstituents2)); + ASSERT_NE(normalizedType2, nullptr); + ASSERT_TRUE(normalizedType2->IsETSObjectType()); + ASSERT_EQ(normalizedType2, checker.GlobalBuiltinETSStringType()); + + // Test normalization: number | "abc" | string | "xy" ==> number | string + ArenaVector unionConstituents3(checker.Allocator()->Adapter()); + unionConstituents3.emplace_back(checker.GlobalDoubleType()); + unionConstituents3.emplace_back(checker.CreateETSStringLiteralType("abc")); + unionConstituents3.emplace_back(checker.GlobalBuiltinETSStringType()); + unionConstituents3.emplace_back(checker.CreateETSStringLiteralType("xy")); + + // Create union type, which will be normalized inside creation function + auto *const normalizedType3 = checker.CreateETSUnionType(std::move(unionConstituents3)); + ASSERT_NE(normalizedType3, nullptr); + ASSERT_TRUE(normalizedType3->IsETSUnionType()); + auto *const unionType = normalizedType3->AsETSUnionType(); + ASSERT_EQ(unionType->ConstituentTypes().size(), SIZE2); + ASSERT_EQ(unionType->ConstituentTypes().at(IDX0), checker.GetGlobalTypesHolder()->GlobalDoubleBuiltinType()); + ASSERT_EQ(unionType->ConstituentTypes().at(IDX1), checker.GlobalBuiltinETSStringType()); +} + TEST_F(UnionNormalizationTest, UnionWithNever) { // Test normalization: int | never | number ==> number diff --git a/ets2panda/util/options.cpp b/ets2panda/util/options.cpp index f49a3d8d91809c9cb1bc239b1b07fea25cffc715..eea4000cc3759d974a71743d391a77b760bbcbc2 100644 --- a/ets2panda/util/options.cpp +++ b/ets2panda/util/options.cpp @@ -181,6 +181,8 @@ bool Options::Parse(int argc, const char **argv) panda::PandArg genStdLib("gen-stdlib", false, "Gen standard library"); panda::PandArg plugins("plugins", "", "Plugins"); panda::PandArg skipPhases("skip-phases", "", "Phases to skip"); + panda::PandArg verifierWarnings("verifier-warnings", "", "Show warnings form verifier"); + panda::PandArg verifierErrors("verifier-errors", "", "Show warnings form verifier"); panda::PandArg dumpBeforePhases("dump-before-phases", "", "Generate program dump before running phases in the list"); panda::PandArg dumpEtsSrcBeforePhases( @@ -222,10 +224,12 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&genStdLib); argparser_->Add(&plugins); argparser_->Add(&skipPhases); + argparser_->Add(&verifierWarnings); + argparser_->Add(&verifierErrors); argparser_->Add(&dumpBeforePhases); argparser_->Add(&dumpEtsSrcBeforePhases); argparser_->Add(&dumpAfterPhases); - argparser_->Add(&dumpEtsSrcAfterPhases); + argparser_->Add(&dumpEtsSrcBeforePhases); argparser_->Add(&arktsConfig); argparser_->Add(&opTsDeclOut); @@ -401,7 +405,7 @@ bool Options::Parse(int argc, const char **argv) } } - if ((dumpEtsSrcBeforePhases.GetValue().size() + dumpEtsSrcAfterPhases.GetValue().size() > 0) && + if ((dumpEtsSrcAfterPhases.GetValue().size() + dumpEtsSrcAfterPhases.GetValue().size() > 0) && extension_ != es2panda::ScriptExtension::ETS) { errorMsg_ = "--dump-ets-src-* option is valid only with ETS extension"; return false; @@ -420,9 +424,11 @@ bool Options::Parse(int argc, const char **argv) compilerOptions_.isEtsModule = opEtsModule.GetValue(); compilerOptions_.plugins = SplitToStringVector(plugins.GetValue()); compilerOptions_.skipPhases = SplitToStringSet(skipPhases.GetValue()); + compilerOptions_.verifierWarnings = SplitToStringSet(verifierWarnings.GetValue()); + compilerOptions_.verifierErrors = SplitToStringSet(verifierErrors.GetValue()); compilerOptions_.dumpBeforePhases = SplitToStringSet(dumpBeforePhases.GetValue()); compilerOptions_.dumpEtsSrcBeforePhases = SplitToStringSet(dumpEtsSrcBeforePhases.GetValue()); - compilerOptions_.dumpAfterPhases = SplitToStringSet(dumpAfterPhases.GetValue()); + compilerOptions_.dumpAfterPhases = SplitToStringSet(dumpBeforePhases.GetValue()); compilerOptions_.dumpEtsSrcAfterPhases = SplitToStringSet(dumpEtsSrcAfterPhases.GetValue()); return true; diff --git a/ets2panda/varbinder/scope.cpp b/ets2panda/varbinder/scope.cpp index 0281394b50c346dd97809398730965309a4a7c49..a1f13194b8c7ae936e958eea6e97b01e9e929d8e 100644 --- a/ets2panda/varbinder/scope.cpp +++ b/ets2panda/varbinder/scope.cpp @@ -741,8 +741,18 @@ Variable *ClassScope::AddBinding(ArenaAllocator *allocator, [[maybe_unused]] Var SetBindingProps(newDecl, &props, isStatic); - if (FindLocal(newDecl->Name(), ResolveBindingOptions::ALL) != nullptr) { - return nullptr; + const auto *foundVar = FindLocal(newDecl->Name(), ResolveBindingOptions::ALL); + if (foundVar != nullptr) { + if (!newDecl->IsLetOrConstDecl()) { + return nullptr; + } + + foundVar = FindLocal(newDecl->Name(), + ResolveBindingOptions::ALL ^ (isStatic ? ResolveBindingOptions::VARIABLES + : ResolveBindingOptions::STATIC_VARIABLES)); + if (foundVar != nullptr) { + return nullptr; + } } auto *var = props.GetTargetScope()->AddBinding(allocator, nullptr, newDecl, extension);