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 6ce1e33e3fb05564ff3633498088db21f8d6fb91..27894723e2b7d21152fe79a95654ffa99def7cc0 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 @@ -973,9 +975,41 @@ checker::Type *ETSAnalyzer::Check(ir::BlockExpression *st) const UNREACHABLE(); } -ArenaVector &ChooseSignatures(checker::Type *callee_type, bool is_constructor_call, - bool is_functional_interface) +ArenaVector GetUnionTypeSignatures(ETSChecker *checker, checker::ETSUnionType *ets_union_type) +{ + ArenaVector call_signatures(checker->Allocator()->Adapter()); + + for (auto *constituent_type : ets_union_type->ConstituentTypes()) { + if (constituent_type->IsETSObjectType()) { + ArenaVector tmp_call_signatures(checker->Allocator()->Adapter()); + tmp_call_signatures = constituent_type->AsETSObjectType() + ->GetOwnProperty("invoke") + ->TsType() + ->AsETSFunctionType() + ->CallSignatures(); + call_signatures.insert(call_signatures.end(), tmp_call_signatures.begin(), tmp_call_signatures.end()); + } + if (constituent_type->IsETSFunctionType()) { + ArenaVector tmp_call_signatures(checker->Allocator()->Adapter()); + tmp_call_signatures = constituent_type->AsETSFunctionType()->CallSignatures(); + call_signatures.insert(call_signatures.end(), tmp_call_signatures.begin(), tmp_call_signatures.end()); + } + if (constituent_type->IsETSUnionType()) { + ArenaVector tmp_call_signatures(checker->Allocator()->Adapter()); + tmp_call_signatures = GetUnionTypeSignatures(checker, constituent_type->AsETSUnionType()); + call_signatures.insert(call_signatures.end(), tmp_call_signatures.begin(), tmp_call_signatures.end()); + } + } + + return call_signatures; +} + +ArenaVector &ChooseSignatures(ETSChecker *checker, checker::Type *callee_type, + bool is_constructor_call, bool is_functional_interface, + bool is_union_type_with_functional_interface) { + static ArenaVector union_signatures(checker->Allocator()->Adapter()); + union_signatures.clear(); if (is_constructor_call) { return callee_type->AsETSObjectType()->ConstructSignatures(); } @@ -986,6 +1020,10 @@ ArenaVector &ChooseSignatures(checker::Type *callee_type, bool is_c ->AsETSFunctionType() ->CallSignatures(); } + if (is_union_type_with_functional_interface) { + union_signatures = GetUnionTypeSignatures(checker, callee_type->AsETSUnionType()); + return union_signatures; + } return callee_type->AsETSFunctionType()->CallSignatures(); } @@ -1003,7 +1041,8 @@ checker::ETSObjectType *ChooseCalleeObj(ETSChecker *checker, ir::CallExpression } checker::Signature *ResolveSignature(ETSChecker *checker, ir::CallExpression *expr, checker::Type *callee_type, - bool is_constructor_call, bool is_functional_interface) + bool is_constructor_call, bool is_functional_interface, + bool is_union_type_with_functional_interface) { bool extension_function_type = expr->Callee()->IsMemberExpression() && checker->ExtensionETSFunctionType(callee_type); @@ -1014,7 +1053,8 @@ checker::Signature *ResolveSignature(ETSChecker *checker, ir::CallExpression *ex if (extension_function_type) { return ResolveCallExtensionFunction(callee_type->AsETSFunctionType(), checker, expr); } - auto &signatures = ChooseSignatures(callee_type, is_constructor_call, is_functional_interface); + auto &signatures = ChooseSignatures(checker, callee_type, is_constructor_call, is_functional_interface, + is_union_type_with_functional_interface); checker::Signature *signature = checker->ResolveCallExpressionAndTrailingLambda(signatures, expr, expr->Start()); if (signature->Function()->IsExtensionMethod()) { checker->ThrowTypeError({"No matching call signature"}, expr->Start()); @@ -1026,6 +1066,9 @@ checker::Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, checker::Typ { ETSChecker *checker = GetETSChecker(); bool is_constructor_call = expr->IsETSConstructorCall(); + bool is_union_type_with_functional_interface = + callee_type->IsETSUnionType() && + callee_type->AsETSUnionType()->HasObjectType(checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); bool is_functional_interface = callee_type->IsETSObjectType() && callee_type->AsETSObjectType()->HasObjectFlag( checker::ETSObjectFlags::FUNCTIONAL_INTERFACE); bool ets_extension_func_helper_type = callee_type->IsETSExtensionFuncHelperType(); @@ -1036,12 +1079,12 @@ checker::Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, checker::Typ } if (!is_functional_interface && !callee_type->IsETSFunctionType() && !is_constructor_call && - !ets_extension_func_helper_type) { + !ets_extension_func_helper_type && !is_union_type_with_functional_interface) { checker->ThrowTypeError("This expression is not callable.", expr->Start()); } - checker::Signature *signature = - ResolveSignature(checker, expr, callee_type, is_constructor_call, is_functional_interface); + checker::Signature *signature = ResolveSignature(checker, expr, callee_type, is_constructor_call, + is_functional_interface, is_union_type_with_functional_interface); checker->CheckObjectLiteralArguments(signature, expr->Arguments()); checker->AddUndefinedParamsForDefaultParams(signature, expr->Arguments(), checker); @@ -1113,7 +1156,7 @@ checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const // NOTE(vpukhov): #14902 substituted signature is not updated } expr->SetOptionalType(return_type); - if (expr->IsOptional() && callee_type->IsNullishOrNullLike()) { + if (expr->IsOptional() && checker->MayHaveNulllikeValue(expr->Callee()->Check(checker))) { checker->Relation()->SetNode(expr); return_type = checker->CreateOptionalResultType(return_type); checker->Relation()->SetNode(nullptr); @@ -1185,7 +1228,7 @@ checker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const builtin_alternate_type = alternate_type; } - expr->SetTsType(checker->FindLeastUpperBound(builtin_conseq_type, builtin_alternate_type)); + expr->SetTsType(checker->CreateETSUnionType(builtin_conseq_type, builtin_alternate_type)); } } @@ -1498,6 +1541,38 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const auto unboxed_operand_type = is_cond_expr ? checker->ETSBuiltinTypeAsConditionalType(arg_type) : checker->ETSBuiltinTypeAsPrimitiveType(arg_type); + if (arg_type != nullptr && arg_type->IsETSBigIntType() && + arg_type->HasTypeFlag(checker::TypeFlag::BIGINT_LITERAL)) { + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_MINUS: { + checker::Type *type = checker->CreateETSBigIntLiteralType(arg_type->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 (arg_type != nullptr && arg_type->IsETSBigIntType()) { + switch (expr->OperatorType()) { + case lexer::TokenType::PUNCTUATOR_MINUS: + case lexer::TokenType::PUNCTUATOR_PLUS: + case lexer::TokenType::PUNCTUATOR_TILDE: { + expr->SetTsType(arg_type); + return expr->TsType(); + } + default: + break; + } + } + switch (expr->OperatorType()) { case lexer::TokenType::PUNCTUATOR_MINUS: case lexer::TokenType::PUNCTUATOR_PLUS: { @@ -1516,17 +1591,17 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const break; } case lexer::TokenType::PUNCTUATOR_TILDE: { - if (operand_type == nullptr || !operand_type->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL)) { - checker->ThrowTypeError("Bad operand type, the type of the operand must be integral type.", + if (operand_type == nullptr || !operand_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + checker->ThrowTypeError("Bad operand type, the type of the operand must be numeric type.", expr->Argument()->Start()); } if (operand_type->HasTypeFlag(checker::TypeFlag::CONSTANT)) { - expr->SetTsType(checker->BitwiseNegateIntegralType(operand_type, expr)); + expr->SetTsType(checker->BitwiseNegateNumericType(operand_type, expr)); break; } - expr->SetTsType(operand_type); + expr->SetTsType(checker->SelectGlobalIntegerTypeForNumeric(operand_type)); break; } case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { @@ -1563,7 +1638,7 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const } } - if (arg_type->IsETSObjectType() && (unboxed_operand_type != nullptr) && + if ((arg_type != nullptr) && arg_type->IsETSObjectType() && (unboxed_operand_type != nullptr) && unboxed_operand_type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { expr->Argument()->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(unboxed_operand_type)); } @@ -1593,6 +1668,11 @@ checker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const } } + if (operand_type->IsETSBigIntType()) { + expr->SetTsType(operand_type); + return expr->TsType(); + } + auto unboxed_type = checker->ETSBuiltinTypeAsPrimitiveType(operand_type); if (unboxed_type == nullptr || !unboxed_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { checker->ThrowTypeError("Bad operand type, the type of the operand must be numeric type.", @@ -1615,7 +1695,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 @@ -2671,6 +2753,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()) { @@ -2685,8 +2768,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 86acb390afd3a387444ff48c3de13c72fb23780c..08adfd216f44aab57d6ebab7b6120a9b7ae23673 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 *call_expr) VarBinder()->AsETSBinder()->HandleCustomNodes(call_expr); } +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 1783bf654dc6e639b2879876286be731ab764e0b..d20eb82595b279a4f3bf77b2c022be7730f77692 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 *type_annotation); // 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 *element_type); Type *CreateETSUnionType(ArenaVector &&constituent_types); + template + Type *CreateETSUnionType(Types &&...types) + { + ArenaVector constituent_types(Allocator()->Adapter()); + (constituent_types.push_back(types), ...); + return CreateETSUnionType(std::move(constituent_types)); + } 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 operation_type, lexer::SourcePosition pos, bool force_promotion = false); @@ -255,6 +271,7 @@ public: checker::Type *CheckBinaryOperatorNullishCoalescing(ir::Expression *right, lexer::SourcePosition pos, checker::Type *left_type, checker::Type *right_type); Type *HandleArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type); + Type *HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type); void FlagExpressionWithUnboxing(Type *type, Type *unboxed_type, ir::Expression *type_expression); template Type *PerformArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type); @@ -284,6 +301,7 @@ public: { return Allocator()->New>(Allocator()->Adapter()); } + ArenaVector CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration const *type_params); [[nodiscard]] bool EnhanceSubstitutionForType(const ArenaVector &type_params, Type *param_type, Type *argument_type, Substitution *substitution, ArenaUnorderedSet *instantiated_type_params); @@ -525,6 +543,7 @@ public: bool ExtensionETSFunctionType(checker::Type *type); void ValidateTupleMinElementSize(ir::ArrayExpression *array_expr, ETSTupleType *tuple); void ModifyPreferredType(ir::ArrayExpression *array_expr, Type *new_preferred_type); + Type *SelectGlobalIntegerTypeForNumeric(Type *type); // Exception ETSObjectType *CheckExceptionOrErrorType(checker::Type *type, lexer::SourcePosition pos); @@ -642,12 +661,12 @@ private: return is_construct ? &dynamic_new_intrinsics_ : &dynamic_call_intrinsics_; } - ArenaVector CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration *type_params); - using Type2TypeMap = std::unordered_map; void CheckTypeParameterConstraint(ir::TSTypeParameter *param, Type2TypeMap &extends); void SetUpTypeParameterConstraint(ir::TSTypeParameter *param); + ETSObjectType *UpdateGlobalType(ETSObjectType *obj_type, util::StringView name); + ETSObjectType *UpdateBoxedGlobalType(ETSObjectType *obj_type, util::StringView name); ETSObjectType *CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *decl_node, ETSObjectFlags flags); void CheckProgram(parser::Program *program, bool run_analysis = false); @@ -655,8 +674,8 @@ private: template UType HandleModulo(UType left_value, UType right_value); - template - UType HandleBitWiseArithmetic(UType left_value, UType right_value, lexer::TokenType operation_type); + template + Type *HandleBitWiseArithmetic(Type *left_value, Type *right_value, lexer::TokenType operation_type); template typename TargetType::UType GetOperand(Type *type); diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index d411772aa97bf49a0118b174df0a6989f0b94de0..04d7708dfbf0f645ee49cb110455c41b31a9b1de 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -134,6 +134,11 @@ public: return unchecked_castable_results_; } + RelationHolder &SupertypeResults() + { + return supertype_results_; + } + std::unordered_set &TypeStack() { return type_stack_; @@ -212,6 +217,7 @@ private: RelationHolder assignable_results_; RelationHolder comparable_results_; RelationHolder unchecked_castable_results_; + RelationHolder supertype_results_; std::unordered_set type_stack_; }; diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index fe8d0cd47345b53fc79081591dd2bac96cd0c6d2..7595d94e775f374dde3fe122ff790fcf63fcd40b 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, operation_type); } +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 operation_type, lexer::SourcePosition pos, bool is_equal_op, checker::Type *const left_type, @@ -165,6 +213,11 @@ checker::Type *ETSChecker::CheckBinaryOperatorPlus(ir::Expression *left, ir::Exp } if (left_type->IsETSStringType() || right_type->IsETSStringType()) { + if (operation_type == lexer::TokenType::PUNCTUATOR_MINUS || + operation_type == lexer::TokenType::PUNCTUATOR_MINUS_EQUAL) { + ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); + } + return HandleStringConcatenation(left_type, right_type); } @@ -200,13 +253,13 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift(ir::Expression *left, ir::Ex FlagExpressionWithUnboxing(left_type, unboxed_l, left); FlagExpressionWithUnboxing(right_type, unboxed_r, right); - if (promoted_left_type == nullptr || !promoted_left_type->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL) || - promoted_right_type == nullptr || !promoted_right_type->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL)) { - ThrowTypeError("Bad operand type, the types of the operands must be integral type.", pos); + if (promoted_left_type == nullptr || !promoted_left_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC) || + promoted_right_type == nullptr || !promoted_right_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); } if (promoted_left_type->HasTypeFlag(TypeFlag::CONSTANT) && promoted_right_type->HasTypeFlag(TypeFlag::CONSTANT)) { - return HandleArithmeticOperationOnTypes(promoted_left_type, promoted_right_type, operation_type); + return HandleBitwiseOperationOnTypes(promoted_left_type, promoted_right_type, operation_type); } switch (ETSType(promoted_left_type)) { @@ -219,10 +272,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: { @@ -249,20 +304,20 @@ checker::Type *ETSChecker::CheckBinaryOperatorBitwise(ir::Expression *left, ir:: } auto [promotedType, bothConst] = - ApplyBinaryOperatorPromotion(unboxed_l, unboxed_r, TypeFlag::ETS_INTEGRAL, !is_equal_op); + ApplyBinaryOperatorPromotion(unboxed_l, unboxed_r, TypeFlag::ETS_NUMERIC, !is_equal_op); FlagExpressionWithUnboxing(left_type, unboxed_l, left); FlagExpressionWithUnboxing(right_type, unboxed_r, 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(left_type, right_type, operation_type); + return HandleBitwiseOperationOnTypes(left_type, right_type, operation_type); } - return promotedType; + return SelectGlobalIntegerTypeForNumeric(promotedType); } checker::Type *ETSChecker::CheckBinaryOperatorLogical(ir::Expression *left, ir::Expression *right, ir::Expression *expr, @@ -477,83 +532,87 @@ Type *ETSChecker::CheckBinaryOperatorNullishCoalescing(ir::Expression *right, le return FindLeastUpperBound(non_nullish_left_type, right_type); } -// NOLINTNEXTLINE(readability-function-size) -std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, ir::Expression *right, - ir::Expression *expr, lexer::TokenType operation_type, - lexer::SourcePosition pos, bool force_promotion) +using CheckBinaryFunction = std::function; + +std::map &GetCheckMap() { - checker::Type *const left_type = left->Check(this); - checker::Type *const right_type = right->Check(this); - const bool is_logical_extended_operator = (operation_type == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) || - (operation_type == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); - Type *unboxed_l = is_logical_extended_operator ? ETSBuiltinTypeAsConditionalType(left_type) - : ETSBuiltinTypeAsPrimitiveType(left_type); - Type *unboxed_r = is_logical_extended_operator ? ETSBuiltinTypeAsConditionalType(right_type) - : ETSBuiltinTypeAsPrimitiveType(right_type); + static std::map check_map = { + {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 check_map; +} +struct BinaryOperatorParams { + ir::Expression *left; + ir::Expression *right; + ir::Expression *expr; + lexer::TokenType operation_type; + lexer::SourcePosition pos; + bool is_equal_op; +}; + +struct TypeParams { + checker::Type *left_type; + checker::Type *right_type; + Type *unboxed_l; + Type *unboxed_r; +}; + +static std::tuple CheckBinaryOperatorHelper(ETSChecker *checker, + const BinaryOperatorParams &binary_params, + const TypeParams &type_params) +{ + ir::Expression *left = binary_params.left; + ir::Expression *right = binary_params.right; + lexer::SourcePosition pos = binary_params.pos; + checker::Type *const left_type = type_params.left_type; + checker::Type *const right_type = type_params.right_type; + Type *unboxed_l = type_params.unboxed_l; + Type *unboxed_r = type_params.unboxed_r; checker::Type *ts_type {}; - bool is_equal_op = (operation_type > lexer::TokenType::PUNCTUATOR_SUBSTITUTION && - operation_type < lexer::TokenType::PUNCTUATOR_ARROW) && - !force_promotion; - - switch (operation_type) { - 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: { - ts_type = CheckBinaryOperatorMulDivMod(left, right, operation_type, pos, is_equal_op, left_type, right_type, - unboxed_l, unboxed_r); - break; - } - case lexer::TokenType::PUNCTUATOR_MINUS: - case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: { - if (left_type->IsETSStringType() || right_type->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: { - ts_type = CheckBinaryOperatorPlus(left, right, operation_type, pos, is_equal_op, left_type, right_type, - unboxed_l, unboxed_r); - 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: { - ts_type = CheckBinaryOperatorShift(left, right, operation_type, pos, is_equal_op, left_type, right_type, - unboxed_l, unboxed_r); - 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: { - ts_type = CheckBinaryOperatorBitwise(left, right, operation_type, pos, is_equal_op, left_type, right_type, - unboxed_l, unboxed_r); - break; - } + switch (binary_params.operation_type) { case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { - ts_type = CheckBinaryOperatorLogical(left, right, expr, pos, left_type, right_type, unboxed_l, unboxed_r); + ts_type = checker->CheckBinaryOperatorLogical(left, right, binary_params.expr, pos, left_type, right_type, + unboxed_l, unboxed_r); break; } case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { - return CheckBinaryOperatorStrictEqual(left, pos, left_type, right_type); + return checker->CheckBinaryOperatorStrictEqual(left, pos, left_type, right_type); } case lexer::TokenType::PUNCTUATOR_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - std::tuple res = - CheckBinaryOperatorEqual(left, right, operation_type, pos, left_type, right_type, unboxed_l, unboxed_r); + std::tuple res = checker->CheckBinaryOperatorEqual( + left, right, binary_params.operation_type, pos, left_type, right_type, unboxed_l, unboxed_r); if (!(std::get<0>(res) == nullptr && std::get<1>(res) == nullptr)) { return res; } @@ -563,18 +622,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, operation_type, pos, is_equal_op, left_type, right_type, - unboxed_l, unboxed_r); + return checker->CheckBinaryOperatorLessGreater(left, right, binary_params.operation_type, pos, + binary_params.is_equal_op, left_type, right_type, unboxed_l, + unboxed_r); } case lexer::TokenType::KEYW_INSTANCEOF: { - return CheckBinaryOperatorInstanceOf(pos, left_type, right_type); + return checker->CheckBinaryOperatorInstanceOf(pos, left_type, right_type); } case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: { - ts_type = CheckBinaryOperatorNullishCoalescing(right, pos, left_type, right_type); + ts_type = checker->CheckBinaryOperatorNullishCoalescing(right, pos, left_type, right_type); break; } default: { - // NOTE UNREACHABLE(); break; } @@ -583,6 +642,51 @@ std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, return {ts_type, ts_type}; } +std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, ir::Expression *right, + ir::Expression *expr, lexer::TokenType op, + lexer::SourcePosition pos, bool force_promotion) +{ + checker::Type *const left_type = left->Check(this); + checker::Type *const right_type = right->Check(this); + if ((left_type == nullptr) || (right_type == nullptr)) { + ThrowTypeError("Unexpected type error in binary expression", pos); + } + + const bool is_logical_extended_operator = + (op == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) || (op == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + Type *unboxed_l = is_logical_extended_operator ? ETSBuiltinTypeAsConditionalType(left_type) + : ETSBuiltinTypeAsPrimitiveType(left_type); + Type *unboxed_r = is_logical_extended_operator ? ETSBuiltinTypeAsConditionalType(right_type) + : ETSBuiltinTypeAsPrimitiveType(right_type); + + checker::Type *ts_type {}; + bool is_equal_op = + (op > lexer::TokenType::PUNCTUATOR_SUBSTITUTION && op < lexer::TokenType::PUNCTUATOR_ARROW) && !force_promotion; + + if (CheckBinaryOperatorForBigInt(left_type, right_type, 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 {left_type, right_type}; + } + }; + + auto check_map = GetCheckMap(); + if (check_map.find(op) != check_map.end()) { + auto check = check_map[op]; + ts_type = check(this, left, right, op, pos, is_equal_op, left_type, right_type, unboxed_l, unboxed_r); + return {ts_type, ts_type}; + } + + BinaryOperatorParams binary_params {left, right, expr, op, pos, is_equal_op}; + TypeParams type_params {left_type, right_type, unboxed_l, unboxed_r}; + return CheckBinaryOperatorHelper(this, binary_params, type_params); +} + Type *ETSChecker::HandleArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type) { ASSERT(left->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC) && @@ -603,6 +707,26 @@ Type *ETSChecker::HandleArithmeticOperationOnTypes(Type *left, Type *right, lexe return PerformArithmeticOperationOnTypes(left, right, operation_type); } +Type *ETSChecker::HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type) +{ + ASSERT(left->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC) && + right->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC)); + + if (left->IsDoubleType() || right->IsDoubleType()) { + return HandleBitWiseArithmetic(left, right, operation_type); + } + + if (left->IsFloatType() || right->IsFloatType()) { + return HandleBitWiseArithmetic(left, right, operation_type); + } + + if (left->IsLongType() || right->IsLongType()) { + return HandleBitWiseArithmetic(left, right, operation_type); + } + + return HandleBitWiseArithmetic(left, right, operation_type); +} + void ETSChecker::FlagExpressionWithUnboxing(Type *type, Type *unboxed_type, ir::Expression *type_expression) { if (type->IsETSObjectType() && (unboxed_type != nullptr)) { diff --git a/ets2panda/checker/ets/arithmetic.h b/ets2panda/checker/ets/arithmetic.h index 0eb9a9792986862aa336fb6fd436f3af3e9bb80e..c521113a21ddcf682135aab521eeb37ce1408810 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(left_value, right_value, operation_type); + UNREACHABLE(); } } @@ -172,63 +171,69 @@ inline DoubleType::UType panda::es2panda::checker::ETSChecker::HandleModulo -UType ETSChecker::HandleBitWiseArithmetic(UType left_value, UType right_value, lexer::TokenType operation_type) +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 operation_type) { - using UnsignedType = std::make_unsigned_t; - auto unsigned_left_value = static_cast(left_value); - auto unsigned_right_value = static_cast(right_value); - size_t mask = std::numeric_limits::digits - 1U; - size_t shift = static_cast(unsigned_right_value) & mask; + using IntegerUType = typename IntegerType::UType; + using UnsignedUType = std::make_unsigned_t; + + UnsignedUType result = 0; + UnsignedUType unsigned_left_value = CastIfFloat(GetOperand(left)); + UnsignedUType unsigned_right_value = CastIfFloat(GetOperand(right)); + + auto mask = std::numeric_limits::digits - 1U; + auto shift = unsigned_right_value & mask; switch (operation_type) { case lexer::TokenType::PUNCTUATOR_BITWISE_AND: case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: { - return unsigned_left_value & unsigned_right_value; + result = unsigned_left_value & unsigned_right_value; + break; } case lexer::TokenType::PUNCTUATOR_BITWISE_OR: case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: { - return unsigned_left_value | unsigned_right_value; + result = unsigned_left_value | unsigned_right_value; + break; } case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: { - return unsigned_left_value ^ unsigned_right_value; + result = unsigned_left_value ^ unsigned_right_value; + break; } case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: { - static_assert(sizeof(UType) == 4 || sizeof(UType) == 8); - return unsigned_left_value << shift; + static_assert(sizeof(UnsignedUType) == 4 || sizeof(UnsignedUType) == 8); + result = unsigned_left_value << shift; + break; } case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: { - static_assert(sizeof(UType) == 4 || sizeof(UType) == 8); - return left_value >> shift; // NOLINT(hicpp-signed-bitwise) + static_assert(sizeof(IntegerUType) == 4 || sizeof(IntegerUType) == 8); + result = static_cast(unsigned_left_value) >> 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 unsigned_left_value >> shift; + static_assert(sizeof(UnsignedUType) == 4 || sizeof(UnsignedUType) == 8); + result = unsigned_left_value >> shift; + break; } default: { UNREACHABLE(); } } -} - -template <> -inline FloatType::UType ETSChecker::HandleBitWiseArithmetic( - [[maybe_unused]] FloatType::UType left_value, [[maybe_unused]] FloatType::UType right_value, - [[maybe_unused]] lexer::TokenType operation_type) -{ - return 0.0; -} -template <> -inline DoubleType::UType ETSChecker::HandleBitWiseArithmetic( - [[maybe_unused]] DoubleType::UType left_value, [[maybe_unused]] DoubleType::UType right_value, - [[maybe_unused]] lexer::TokenType operation_type) -{ - 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 226eb0a57150834eac380649a2e24ebca9c5a00c..4d4833b4af91009029df8cfd97a534ffeb204b12 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 30c36a8dc14dc09257873fe6f9638806f702691f..7259535dd04b3978c901decec194940a7c688592 100644 --- a/ets2panda/checker/ets/enum.cpp +++ b/ets2panda/checker/ets/enum.cpp @@ -139,7 +139,7 @@ template varbinder::FunctionParamScope *const param_scope, ArenaVector &¶ms, ArenaVector &&body, - ir::TypeNode *const return_type_annotation) + ir::TypeNode *const return_type_annotation, bool is_declare) { auto *const function_scope = varbinder->Allocator()->New(checker->Allocator(), param_scope); @@ -149,9 +149,15 @@ template auto *const body_block = checker->Allocator()->New(checker->Allocator(), std::move(body)); body_block->SetScope(function_scope); + auto flags = ir::ModifierFlags::PUBLIC; + + if (is_declare) { + flags |= ir::ModifierFlags::DECLARE; + } + auto *const function = checker->Allocator()->New( ir::FunctionSignature(nullptr, std::move(params), return_type_annotation), body_block, - ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::PUBLIC, false, Language(Language::Id::ETS)); + ir::ScriptFunctionFlags::METHOD, flags, is_declare, Language(Language::Id::ETS)); function->SetScope(function_scope); varbinder->AsETSBinder()->BuildInternalName(function); @@ -335,7 +341,7 @@ ETSEnumType::Method ETSChecker::CreateEnumFromIntMethod(ir::Identifier *const na auto *const enum_type_annotation = MakeTypeReference(Allocator(), enum_type->GetName()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), param_scope, std::move(params), - std::move(body), enum_type_annotation); + std::move(body), enum_type_annotation, enum_type->GetDecl()->IsDeclare()); function->AddFlag(ir::ScriptFunctionFlags::THROWS); auto *const ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::FROM_INT_METHOD_NAME); @@ -372,7 +378,7 @@ ETSEnumType::Method ETSChecker::CreateEnumToStringMethod(ir::Identifier *const s auto *const string_type_annotation = MakeTypeReference(Allocator(), GlobalBuiltinETSStringType()->Name()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), param_scope, std::move(params), - std::move(body), string_type_annotation); + std::move(body), string_type_annotation, enum_type->GetDecl()->IsDeclare()); auto *const function_ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::TO_STRING_METHOD_NAME); @@ -410,7 +416,7 @@ ETSEnumType::Method ETSChecker::CreateEnumGetValueMethod(ir::Identifier *const v auto *const int_type_annotation = Allocator()->New(ir::PrimitiveType::INT); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), param_scope, std::move(params), - std::move(body), int_type_annotation); + std::move(body), int_type_annotation, enum_type->GetDecl()->IsDeclare()); auto *const function_ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::GET_VALUE_METHOD_NAME); @@ -449,7 +455,7 @@ ETSEnumType::Method ETSChecker::CreateEnumGetNameMethod(ir::Identifier *const na auto *const string_type_annotation = MakeTypeReference(Allocator(), GlobalBuiltinETSStringType()->Name()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), param_scope, std::move(params), - std::move(body), string_type_annotation); + std::move(body), string_type_annotation, enum_type->GetDecl()->IsDeclare()); auto *const function_ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::GET_NAME_METHOD_NAME); @@ -573,7 +579,7 @@ ETSEnumType::Method ETSChecker::CreateEnumValueOfMethod(ir::Identifier *const na auto *const enum_type_annotation = MakeTypeReference(Allocator(), enum_type->GetName()); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), param_scope, std::move(params), - std::move(body), enum_type_annotation); + std::move(body), enum_type_annotation, enum_type->GetDecl()->IsDeclare()); function->AddFlag(ir::ScriptFunctionFlags::THROWS); auto *const function_ident = @@ -605,7 +611,7 @@ ETSEnumType::Method ETSChecker::CreateEnumValuesMethod(ir::Identifier *const ite Allocator()->New(MakeTypeReference(Allocator(), enum_type->GetName())); auto *const function = MakeFunction(this, VarBinder()->AsETSBinder(), param_scope, std::move(params), - std::move(body), enum_array_type_annotation); + std::move(body), enum_array_type_annotation, enum_type->GetDecl()->IsDeclare()); auto *const function_ident = MakeQualifiedIdentifier(Allocator(), enum_type->GetDecl(), ETSEnumType::VALUES_METHOD_NAME); diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 04d093b1f360562c93a25eb156f7465367400da2..54fe77d4108c6e5bd2855f5068a3aa11a6540def 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 *type_param, Type *type_argument, const Substitution *substitution) { @@ -76,21 +77,8 @@ bool ETSChecker::IsCompatibleTypeArgument(ETSTypeParameter *type_param, Type *ty if (!type_argument->IsETSTypeParameter() && !IsReferenceType(type_argument)) { return false; } - if (type_argument->IsETSUnionType()) { - auto const &constitutent = type_argument->AsETSUnionType()->ConstituentTypes(); - return std::all_of(constitutent.begin(), constitutent.end(), [this, type_param, substitution](Type *type_arg) { - return IsCompatibleTypeArgument(type_param->AsETSTypeParameter(), type_arg, substitution); - }); - } - - if (auto *constraint = type_param->GetConstraintType(); constraint != nullptr) { - constraint = constraint->Substitute(Relation(), substitution); - constraint->IsSupertypeOf(Relation(), type_argument); - if (!Relation()->IsTrue()) { - return false; - } - } - return true; + auto *constraint = type_param->GetConstraintType()->Substitute(Relation(), substitution); + return Relation()->IsSupertypeOf(constraint, type_argument); } /* 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, substituted_sig->Function()->Params()[index], flags); + } + auto *const argument_type = argument->Check(this); if (auto const invocation_ctx = checker::InvocationContext( @@ -1051,9 +1044,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); @@ -1075,7 +1068,6 @@ bool ETSChecker::IsMethodOverridesOther(Signature *target, Signature *source) if (Relation()->IsTrue()) { CheckThrowMarkers(source, target); - CheckStaticHide(target, source); if (source->HasSignatureFlag(SignatureFlags::STATIC)) { return false; } @@ -1194,7 +1186,8 @@ bool ETSChecker::CheckOverride(Signature *signature, ETSObjectType *site) (it_subst->Function()->IsGetter() && !signature->Function()->IsGetter())) { continue; } - } else if (!IsMethodOverridesOther(it_subst, signature)) { + } + if (!IsMethodOverridesOther(it_subst, signature)) { continue; } @@ -2601,8 +2594,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 d9d2cf1fdde46973941f04947c433cbe6d46b0dc..ef38c31e6e84662e5c437ec29d58b0e4eae5979e 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; } @@ -775,6 +781,10 @@ std::tuple ETSChecker::ApplyBinaryOperatorPromotion(Type *left, Ty return {GlobalLongType(), both_const}; } + if (unboxed_l->IsCharType() && unboxed_r->IsCharType()) { + return {GlobalCharType(), both_const}; + } + return {GlobalIntType(), both_const}; } @@ -1561,7 +1571,7 @@ bool ETSChecker::IsFunctionContainsSignature(ETSFunctionType *func_type, Signatu void ETSChecker::CheckFunctionContainsClashingSignature(const ETSFunctionType *func_type, Signature *signature) { for (auto *it : func_type->CallSignatures()) { - SavedTypeRelationFlagsContext strf_ctx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK); + SavedTypeRelationFlagsContext strf_ctx(Relation(), TypeRelationFlag::NONE); Relation()->IsIdenticalTo(it, signature); if (Relation()->IsTrue() && it->Function()->Id()->Name() == signature->Function()->Id()->Name()) { std::stringstream ss; @@ -1665,7 +1675,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 node_type, const ir::AstNode *node, @@ -2614,6 +2624,19 @@ void ETSChecker::ModifyPreferredType(ir::ArrayExpression *const array_expr, Type } } +std::string GenerateImplicitInstantiateArg(varbinder::LocalVariable *instantiate_method, const std::string &class_name) +{ + auto call_signatures = instantiate_method->TsType()->AsETSFunctionType()->CallSignatures(); + ASSERT(!call_signatures.empty()); + auto method_owner = std::string(call_signatures[0]->Owner()->Name()); + std::string implicit_instantiate_argument = "()=>{return new " + class_name + "()"; + if (method_owner != class_name) { + implicit_instantiate_argument.append(" as " + method_owner); + } + implicit_instantiate_argument.append("}"); + return implicit_instantiate_argument; +} + bool ETSChecker::TryTransformingToStaticInvoke(ir::Identifier *const ident, const Type *resolved_type) { ASSERT(ident->Parent()->IsCallExpression()); @@ -2657,13 +2680,14 @@ bool ETSChecker::TryTransformingToStaticInvoke(ir::Identifier *const ident, cons call_expr->SetCallee(transformed_callee); if (instantiate_method != nullptr) { - std::string implicit_instantiate_argument = "()=>{return new " + std::string(class_name) + "()}"; + std::string implicit_instantiate_argument = + GenerateImplicitInstantiateArg(instantiate_method, std::string(class_name)); parser::Program program(Allocator(), VarBinder()); es2panda::CompilerOptions options; auto parser = parser::ETSParser(&program, options, parser::ParserStatus::NO_OPTS); auto *arg_expr = parser.CreateExpression(implicit_instantiate_argument); - compiler::ScopesInitPhaseETS::RunExternalNode(arg_expr, &program); + compiler::InitScopesPhaseETS::RunExternalNode(arg_expr, &program); arg_expr->SetParent(call_expr); arg_expr->SetRange(ident->Range()); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index de5ecff0c97db0f202ebf2267b9c259653f507a4..bcf80ce47039cefaf328ff3967ce74d1fb167df2 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 *type_params) +ArenaVector ETSChecker::CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration const *type_params) { ArenaVector result {Allocator()->Adapter()}; checker::ScopeContext scope_ctx(this, type_params->Scope()); @@ -247,12 +249,14 @@ void ETSChecker::SetUpTypeParameterConstraint(ir::TSTypeParameter *const param) ThrowTypeError("Extends constraint must be an object", param->Constraint()->Start()); } param_type->SetConstraintType(constraint); + } else { + param_type->SetConstraintType(GlobalETSNullishObjectType()); } + if (param->DefaultType() != nullptr) { traverse_referenced(param->DefaultType()); - auto *const dflt = param->DefaultType()->GetType(this); // NOTE: #14993 ensure default matches constraint - param_type->SetDefaultType(dflt); + param_type->SetDefaultType(MaybePromotedBuiltinType(param->DefaultType()->GetType(this))); } } @@ -263,6 +267,8 @@ ETSTypeParameter *ETSChecker::SetUpParameterType(ir::TSTypeParameter *const para param_type->AddTypeFlag(TypeFlag::GENERIC); param_type->SetDeclNode(param); param_type->SetVariable(param->Variable()); + // NOTE: #15026 recursive type parameter workaround + param_type->SetConstraintType(GlobalETSNullishObjectType()); param->Name()->Variable()->SetTsType(param_type); return param_type; @@ -405,6 +411,12 @@ void ETSChecker::ResolveDeclaredMembersOfObject(ETSObjectType *type) if (class_prop->TypeAnnotation() != nullptr && class_prop->TypeAnnotation()->IsETSFunctionType()) { type->AddProperty(it->AsLocalVariable()); it->AddFlag(varbinder::VariableFlags::METHOD_REFERENCE); + } else if (class_prop->TypeAnnotation() != nullptr && class_prop->TypeAnnotation()->IsETSTypeReference()) { + bool has_function_type = HasETSFunctionType(class_prop->TypeAnnotation()); + if (has_function_type) { + type->AddProperty(it->AsLocalVariable()); + it->AddFlag(varbinder::VariableFlags::METHOD_REFERENCE); + } } } @@ -418,6 +430,12 @@ void ETSChecker::ResolveDeclaredMembersOfObject(ETSObjectType *type) if (class_prop->TypeAnnotation() != nullptr && class_prop->TypeAnnotation()->IsETSFunctionType()) { type->AddProperty(it->AsLocalVariable()); it->AddFlag(varbinder::VariableFlags::METHOD_REFERENCE); + } else if (class_prop->TypeAnnotation() != nullptr && class_prop->TypeAnnotation()->IsETSTypeReference()) { + bool has_function_type = HasETSFunctionType(class_prop->TypeAnnotation()); + if (has_function_type) { + 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 *type_annotation) +{ + if (type_annotation->IsETSFunctionType()) { + return true; + } + std::unordered_set children_set; + + if (type_annotation->IsETSTypeReference()) { + auto *type_decl = + type_annotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Variable()->Declaration(); + if (type_decl != nullptr && type_decl->IsTypeAliasDecl()) { + type_annotation = type_decl->Node()->AsTSTypeAliasDeclaration()->TypeAnnotation(); + if (type_annotation->IsETSUnionType()) { + for (auto *type : type_annotation->AsETSUnionType()->Types()) { + if (type->IsETSTypeReference()) { + children_set.insert(type); + } + } + } else { + children_set.insert(type_annotation); + } + } + + for (auto *child : children_set) { + if (HasETSFunctionType(child)) { + return true; + } + } + } + + return false; +} + std::vector ETSChecker::CollectAbstractSignaturesFromObject(const ETSObjectType *obj_type) { std::vector abstracts; @@ -1481,22 +1532,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 checker_ctx(this->Relation(), TypeRelationFlag::IGNORE_TYPE_PARAMETERS); @@ -1505,13 +1559,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; } @@ -1544,8 +1596,7 @@ ETSObjectType *ETSChecker::GetClosestCommonAncestor(ETSObjectType *source, ETSOb auto *source_base = GetOriginalBaseType(source); auto *source_type = source_base == nullptr ? source : source_base; - target_type->IsSupertypeOf(Relation(), source_type); - if (Relation()->IsTrue()) { + if (Relation()->IsSupertypeOf(target_type, source_type)) { // NOTE: TorokG. Extending the search to find intersection types return target_type; } diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 243fd358958ecfb1f637f142828b32d574ff8354..63977bde5d103532a1fb0c269d24700bce970b6c 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(class_method_type, extension_function_type); } +std::map &GetNameToTypeIdMap() +{ + static std::map name_to_type_id = { + {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 name_to_type_id; +} + +std::map> &GetNameToGlobalTypeMap() +{ + static std::map> name_to_global_type = { + {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 name_to_global_type; +} + +std::map> &GetNameToGlobalBoxTypeMap() +{ + static std::map> name_to_global_box_type = { + {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 name_to_global_box_type; +} + +ETSObjectType *ETSChecker::UpdateBoxedGlobalType(ETSObjectType *obj_type, util::StringView name) +{ + auto name_to_global_box_type = GetNameToGlobalBoxTypeMap(); + auto name_to_type_id = GetNameToTypeIdMap(); + + if (name_to_global_box_type.find(name) != name_to_global_box_type.end()) { + std::function global_type = name_to_global_box_type[name]; + if (GlobalBuiltinBoxType(global_type(this)) != nullptr) { + return GlobalBuiltinBoxType(global_type(this)); + } + + auto id = name_to_type_id.find(name); + if (id != name_to_type_id.end()) { + GetGlobalTypesHolder()->GlobalTypes()[static_cast(id->second)] = obj_type; + } + } + + return obj_type; +} + +ETSObjectType *ETSChecker::UpdateGlobalType(ETSObjectType *obj_type, util::StringView name) +{ + auto name_to_global_type = GetNameToGlobalTypeMap(); + auto name_to_type_id = GetNameToTypeIdMap(); + + if (name_to_global_type.find(name) != name_to_global_type.end()) { + std::function global_type = name_to_global_type[name]; + if (global_type(this) != nullptr) { + return global_type(this); + } + + auto id = name_to_type_id.find(name); + if (id != name_to_type_id.end()) { + GetGlobalTypesHolder()->GlobalTypes()[static_cast(id->second)] = obj_type; + } + + if (name == compiler::Signatures::BUILTIN_OBJECT_CLASS) { + auto *nullish = CreateNullishType(obj_type, checker::TypeFlag::NULLISH, Allocator(), Relation(), + GetGlobalTypesHolder()); + GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_NULLISH_OBJECT)] = nullish; + } + } + + return obj_type; +} + ETSObjectType *ETSChecker::CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *decl_node, 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, decl_node, 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 *obj_type = CreateNewETSObjectType(name, decl_node, flags); - - if (name == compiler::Signatures::BUILTIN_OBJECT_CLASS) { - if (GlobalETSObjectType() != nullptr) { - return GlobalETSObjectType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_OBJECT_BUILTIN)] = obj_type; - auto *nullish = - CreateNullishType(obj_type, 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)] = obj_type; - } else if (name == compiler::Signatures::BUILTIN_ERROR_CLASS) { - if (GlobalBuiltinErrorType() != nullptr) { - return GlobalBuiltinErrorType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_ERROR_BUILTIN)] = obj_type; - } else if (name == compiler::Signatures::BUILTIN_TYPE_CLASS) { - if (GlobalBuiltinTypeType() != nullptr) { - return GlobalBuiltinTypeType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_TYPE_BUILTIN)] = obj_type; - } else if (name == compiler::Signatures::BUILTIN_PROMISE_CLASS) { - if (GlobalBuiltinPromiseType() != nullptr) { - return GlobalBuiltinPromiseType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_PROMISE_BUILTIN)] = obj_type; - } else if (name == compiler::Signatures::BUILTIN_BOX_CLASS) { - if (GlobalBuiltinBoxType(GlobalETSObjectType()) != nullptr) { - return GlobalBuiltinBoxType(GlobalETSObjectType()); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_BOX_BUILTIN)] = obj_type; - } 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)] = obj_type; - } 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)] = obj_type; - } 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)] = obj_type; - } 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)] = obj_type; - } 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)] = obj_type; - } 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)] = obj_type; - } 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)] = obj_type; - } 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)] = obj_type; - } 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)] = obj_type; - } else if (name == compiler::Signatures::BUILTIN_VOID_CLASS) { - if (GlobalBuiltinVoidType() != nullptr) { - return GlobalBuiltinVoidType(); - } - GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_VOID_BUILTIN)] = obj_type; + auto name_to_global_box_type = GetNameToGlobalBoxTypeMap(); + if (name_to_global_box_type.find(name) != name_to_global_box_type.end()) { + return UpdateBoxedGlobalType(obj_type, name); } - return obj_type; + return UpdateGlobalType(obj_type, name); } ETSObjectType *ETSChecker::CreateETSObjectType(util::StringView name, ir::AstNode *decl_node, ETSObjectFlags flags) @@ -441,8 +484,9 @@ ETSObjectType *ETSChecker::CreateNewETSObjectType(util::StringView name, ir::Ast if (containing_obj_type != nullptr) { prefix = containing_obj_type->AssemblerName(); - } else if (decl_node->GetTopStatement()->Type() != - ir::AstNodeType::BLOCK_STATEMENT) { // NOTE: should not occur, fix for TS_INTERFACE_DECLARATION + } else if (const auto *top_statement = decl_node->GetTopStatement(); + top_statement->Type() != + ir::AstNodeType::ETS_SCRIPT) { // NOTE: should not occur, fix for TS_INTERFACE_DECLARATION ASSERT(decl_node->IsTSInterfaceDeclaration()); assembler_name = decl_node->AsTSInterfaceDeclaration()->InternalName(); } else { diff --git a/ets2panda/checker/ets/typeRelationContext.cpp b/ets2panda/checker/ets/typeRelationContext.cpp index cbc061f0b9a54cacb5d3f3b0a0221e7b59c411b5..04139740239a859d8384539b91d295a89e84ac9c 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" @@ -61,12 +62,15 @@ bool InstantiationContext::ValidateTypeArguments(ETSObjectType *type, ir::TSType extends "Comparable", we will get an error here. */ - auto const get_types = [this, &type_args, type](size_t idx) -> std::pair { + auto const is_defaulted = [type_args](size_t idx) { + return type_args == nullptr || idx >= type_args->Params().size(); + }; + + auto const get_types = [this, &type_args, type, is_defaulted](size_t idx) -> std::pair { auto *type_param = type->TypeArguments().at(idx)->AsETSTypeParameter(); - if (type_args != nullptr && idx < type_args->Params().size()) { - return {type_param, type_args->Params().at(idx)->GetType(checker_)}; - } - return {type_param, type_param->GetDefaultType()}; + return {type_param, is_defaulted(idx) + ? type_param->GetDefaultType() + : checker_->MaybePromotedBuiltinType(type_args->Params().at(idx)->GetType(checker_))}; }; auto *const substitution = checker_->NewSubstitution(); @@ -88,7 +92,7 @@ bool InstantiationContext::ValidateTypeArguments(ETSObjectType *type, ir::TSType if (!ValidateTypeArg(constraint, type_arg) && type_args != nullptr && !checker_->Relation()->NoThrowGenericTypeAlias()) { checker_->ThrowTypeError({"Type '", type_arg, "' is not assignable to constraint type '", constraint, "'."}, - type_args->Params().at(idx)->Start()); + is_defaulted(idx) ? pos : type_args->Params().at(idx)->Start()); } } @@ -97,16 +101,10 @@ bool InstantiationContext::ValidateTypeArguments(ETSObjectType *type, ir::TSType bool InstantiationContext::ValidateTypeArg(Type *constraint_type, Type *type_arg) { - if (!ETSChecker::IsReferenceType(type_arg)) { - return false; - } - - if (type_arg->IsETSUnionType()) { - auto const &constituent_types = type_arg->AsETSUnionType()->ConstituentTypes(); - return std::all_of(constituent_types.begin(), constituent_types.end(), - [this, constraint_type](Type *c_type) { return ValidateTypeArg(constraint_type, c_type); }); + // NOTE: #14993 enforce ETSChecker::IsReferenceType + if (type_arg->IsWildcardType()) { + return true; } - return checker_->Relation()->IsAssignableTo(type_arg, constraint_type); } diff --git a/ets2panda/checker/ets/typeRelationContext.h b/ets2panda/checker/ets/typeRelationContext.h index d0148f37d9f0ab27bf8628c5c8485e69ee83f51e..ca9ebda4a736a29b807952c0fd795713a3f2b16f 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..883554170c3d8e21af39888af15a8de0368b2ec9 --- /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 *global_types) +{ + 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..5703107e899a48b7dfb155d200817c21ece45956 --- /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 *global_types) 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 3964d454fab1836252c86262b5392ad60a8bea69..78964c18b01fa1e5f982aac1f6f988a2511df209 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 unbox_flags, @@ -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 ets_checker = 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 == ets_checker->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 == ets_checker->GlobalETSObjectType()) { + if (base == ets_checker->GlobalETSObjectType() || base == ets_checker->GlobalETSNullishObjectType()) { relation->Result(true); return; } @@ -643,16 +649,14 @@ void ETSObjectType::IsSupertypeOf(TypeRelation *relation, Type *source) ETSObjectType *source_obj = source->AsETSObjectType(); if (auto *source_super = source_obj->SuperType(); source_super != nullptr) { - IsSupertypeOf(relation, source_super); - if (relation->IsTrue()) { + if (relation->IsSupertypeOf(this, source_super)) { return; } } if (HasObjectFlag(ETSObjectFlags::INTERFACE)) { for (auto *itf : source_obj->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 b978b6b48a7793ad45113ea33b221f06af15d055..ce2fbc5ffdf98145eaaa72d7c8e0a61f9fdb0f45 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 d19a6ef1162b28ee9fc728d3aad613230c6d612d..abd24eecdb7c79a867327b6bed1cf0ea3a8f52ad 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() && !repl_type->ContainsNull()) || (ContainsUndefined() && !repl_type->ContainsUndefined()))) { // this type is explicitly marked as nullish - ASSERT(repl_type->IsETSObjectType() || repl_type->IsETSArrayType() || repl_type->IsETSFunctionType() || - repl_type->IsETSTypeParameter()); + ASSERT(ETSChecker::IsReferenceType(repl_type)); auto nullish_flags = TypeFlag(TypeFlags() & TypeFlag::NULLISH); auto *new_repl_type = checker->CreateNullishType(repl_type, nullish_flags, 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 d39645a555dfe14069f16b32f5030132dc098b0f..79657fa0b68d5adb86cf0cc03bd66e48bbb43e07 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 *global_types) 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 18d2fcbde0ba9cf8f44e3bc792424b230b417367..98653a97328cae1341625f6c693e650eba02ff7f 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 } } constituent_types = copied_constituents; + // Removing subtypes should be in the next iteration, especially needed for proper literals removal + auto check_subtyping = [relation](Type *lhs, Type *rhs) { + if (lhs == rhs) { + return false; + } + relation->Result(false); + lhs->IsSupertypeOf(relation, rhs); + bool inheritance_relation = relation->IsTrue(); + rhs->IsSupertypeOf(relation, lhs); + inheritance_relation = inheritance_relation || relation->IsTrue(); + return inheritance_relation; + }; // Secondly, remove identical types auto cmp_it = constituent_types.begin(); while (cmp_it != constituent_types.end()) { auto it = std::next(cmp_it); while (it != constituent_types.end()) { - if (relation->IsIdenticalTo(*it, *cmp_it)) { + if (relation->IsIdenticalTo(*it, *cmp_it) && !check_subtyping(*it, *cmp_it)) { it = constituent_types.erase(it); } else { ++it; @@ -196,9 +208,9 @@ void ETSUnionType::NormalizeTypes(TypeRelation *relation, ArenaVector &c while (cmp_it != constituent_types.end()) { auto new_end = std::remove_if( constituent_types.begin(), constituent_types.end(), [relation, checker, cmp_it, number_found](Type *ct) { - relation->Result(false); - (*cmp_it)->IsSupertypeOf(relation, ct); - bool remove_subtype = ct != *cmp_it && relation->IsTrue(); + bool both_constants = (*cmp_it)->HasTypeFlag(TypeFlag::CONSTANT) && ct->HasTypeFlag(TypeFlag::CONSTANT); + relation->IsSupertypeOf((*cmp_it), ct); + bool remove_subtype = ct != *cmp_it && !both_constants && relation->IsTrue(); bool remove_numeric = number_found && 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 &source_ctype : source->AsETSUnionType()->ConstituentTypes()) { - if (IsSupertypeOf(relation, source_ctype), !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 39dc90ec1f4f6df012d752577675c16c5dbf8fd2..2c6da2652c58e5b81af2172abaf65f6ae4e5836d 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 5c6eb9a07bda67acea569de3d9e42d559e285f07..6fcac6fa77a68e5d0ac49c84b52277129286d303 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) : builtin_name_m builtin_name_mappings_.emplace("ClassNotFoundException", GlobalTypeId::ETS_CLASS_NOT_FOUND_EXCEPTION_BUILTIN); builtin_name_mappings_.emplace("ClassCastException", GlobalTypeId::ETS_CLASS_CAST_EXCEPTION_BUILTIN); builtin_name_mappings_.emplace("String", GlobalTypeId::ETS_STRING_BUILTIN); + builtin_name_mappings_.emplace("BigInt", GlobalTypeId::ETS_BIG_INT_BUILTIN); builtin_name_mappings_.emplace("StringBuilder", GlobalTypeId::ETS_STRING_BUILDER_BUILTIN); builtin_name_mappings_.emplace("Type", GlobalTypeId::ETS_TYPE_BUILTIN); builtin_name_mappings_.emplace("Types", GlobalTypeId::ETS_TYPES_BUILTIN); @@ -511,6 +513,16 @@ Type *GlobalTypesHolder::GlobalETSStringBuiltinType() return global_types_.at(static_cast(GlobalTypeId::ETS_STRING_BUILTIN)); } +Type *GlobalTypesHolder::GlobalETSBigIntBuiltinType() +{ + return global_types_.at(static_cast(GlobalTypeId::ETS_BIG_INT_BUILTIN)); +} + +Type *GlobalTypesHolder::GlobalETSBigIntLiteralType() +{ + return global_types_.at(static_cast(GlobalTypeId::ETS_BIG_INT)); +} + Type *GlobalTypesHolder::GlobalStringBuilderBuiltinType() { return global_types_.at(static_cast(GlobalTypeId::ETS_STRING_BUILDER_BUILTIN)); diff --git a/ets2panda/checker/types/globalTypesHolder.h b/ets2panda/checker/types/globalTypesHolder.h index e0e370b4599bf17a0dd767f591e32da91d7d1b7a..8808a17352a19a9ce774a68f46443f9884c18d7f 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 c28e55dcf5e77f156655442d9a9432f9e5121eb8..239bcf008029f87776bb644796f7cb6c8e05f2c2 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 *source_var) { return nullptr; diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 3f5185007d92099a711b83a8c63a20fbb94a2f95..b0bd53e4b0f9dfbe2b4770e89eb15cd3d1c36983 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 *source_var); virtual Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *global_types); diff --git a/ets2panda/checker/types/typeRelation.cpp b/ets2panda/checker/types/typeRelation.cpp index a3453c5190d4467829a12d5a6e89e4c07c168d0a..2e0b44bf40ce81d3906d489369b00a099ddce5b0 100644 --- a/ets2panda/checker/types/typeRelation.cpp +++ b/ets2panda/checker/types/typeRelation.cpp @@ -173,6 +173,29 @@ 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 &err_msg, const lexer::SourcePosition &loc) const { checker_->ThrowTypeError(err_msg, loc); diff --git a/ets2panda/checker/types/typeRelation.h b/ets2panda/checker/types/typeRelation.h index 4e7cff3141aac5328cba1a678fd29c4e862c2375..b7f5002b6f01599b1330b9597328a77ca8a3052b 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 &err_msg, 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 d2abcf956930a75c6c9c30f7dae2f79f52208806..73d41b3740c3d47dfb8659fb223382dd8f8226c6 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(bin_expr, return_right_true_label); } +bool Condition::CompileBinaryExprForBigInt(ETSGen *etsg, const ir::BinaryExpression *expr, Label *false_label) +{ + 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, false_label); + + return true; +} + bool Condition::CompileBinaryExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label) { + if (CompileBinaryExprForBigInt(etsg, bin_expr, false_label)) { + return true; + } + switch (bin_expr->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 6380ba538ea054cc711217737c042649cfcc5ba7..30b3b27cadb3b84df4cb6c0682e58034aa31a4a9 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 *bin_expr, Label *false_label); static void CompileLogicalAndExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label); static void CompileLogicalOrExpr(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label); + static bool CompileBinaryExprForBigInt(ETSGen *etsg, const ir::BinaryExpression *bin_expr, Label *false_label); }; } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/core/ASTVerifier.cpp b/ets2panda/compiler/core/ASTVerifier.cpp index 17265d29955d85811dbc48a5912b92756397b86b..98695bdf7cbce84a9e1fc46bc66638ed34460214 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 has_parent = func(ast); - ast->IterateRecursively([func, &has_parent](ir::AstNode *child) { has_parent &= func(child); }); - return has_parent; - }; -} - 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 *obj_type_d return current_top_statement == object_top_statement || (package_name_current == package_name_object && !package_name_current.Empty()); } -bool ValidateVariableAccess(const varbinder::LocalVariable *prop_var, const ir::MemberExpression *ast) + +static bool ValidateVariableAccess(const varbinder::LocalVariable *prop_var, const ir::MemberExpression *ast) { const auto *prop_var_decl = prop_var->Declaration(); if (prop_var_decl == nullptr) { @@ -189,7 +166,7 @@ bool ValidateVariableAccess(const varbinder::LocalVariable *prop_var, const ir:: return false; } -bool ValidateMethodAccess(const ir::MemberExpression *member_expression, const ir::CallExpression *ast) +static bool ValidateMethodAccess(const ir::MemberExpression *member_expression, const ir::CallExpression *ast) { auto *member_obj_type = member_expression->ObjType(); if (member_obj_type == nullptr) { @@ -236,693 +213,569 @@ bool ValidateMethodAccess(const ir::MemberExpression *member_expression, const i 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 is_ets_script = ast->IsETSScript(); + const auto has_parent = ast->Parent() != nullptr; + if (!is_ets_script && !has_parent) { + 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 maybe_var = GetLocalScopeVariable(allocator_, ctx, ast); maybe_var.has_value()) { + const auto var = *maybe_var; + 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()); - } - case ir::AstNodeType::CLASS_DECLARATION: { - return "CLS_DECL " + ToStringHelper(ast->AsClassDeclaration()->Definition()); + static std::optional GetLocalScopeVariable(ArenaAllocator &allocator, + ASTVerifier::ErrorContext &ctx, + const ir::AstNode *ast) + { + if (!ast->IsIdentifier()) { + return std::nullopt; } - 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 invariant_has_variable = IdentifierHasVariable {allocator}; + const auto variable = ast->AsIdentifier()->Variable(); + if ((invariant_has_variable(ctx, ast) == ASTVerifier::CheckResult::SUCCESS) && variable->IsLocalVariable()) { + const auto local_var = variable->AsLocalVariable(); + if (local_var->HasFlag(varbinder::VariableFlags::LOCAL)) { + return local_var; } - 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 is_ok = true; + if (scope->Bindings().count(var->Name()) == 0) { + ctx.AddInvariantError(name, "SCOPE_DO_NOT_ENCLOSE_LOCAL_VAR", *node); + is_ok = false; } - case ir::AstNodeType::TS_CLASS_IMPLEMENTS: { - return "TS_CLASS_IMPL " + ToStringHelper(ast->AsTSClassImplements()->Expr()); + const auto scope_node = scope->Node(); + auto var_node = node; + if (!IsContainedIn(var_node, scope_node) || scope_node == nullptr) { + ctx.AddInvariantError(name, "SCOPE_NODE_DONT_DOMINATE_VAR_NODE", *node); + is_ok = false; } - default: { - return "MUST BE UNREACHABLE"; + const auto &decls = scope->Decls(); + const auto decl_dominate = std::count(decls.begin(), decls.end(), var->Declaration()); + if (decl_dominate == 0) { + ctx.AddInvariantError(name, "SCOPE_DECL_DONT_DOMINATE_VAR_DECL", *node); + is_ok = false; } + return is_ok; } -} -// 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}); \ - all_checks_.insert(#Name); \ - checks_.emplace_back(NamedCheck {#Name "Recursive", RecursiveCheck(check)}); \ - all_checks_.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 maybe_var = GetLocalScopeVariable(ast)) { + ASTVerifier::CheckResult operator()(ASTVerifier::ErrorContext &ctx, const ir::AstNode *ast) + { + const auto maybe_var = VariableHasScope::GetLocalScopeVariable(allocator_, ctx, ast); + if (!maybe_var) { + return ASTVerifier::CheckResult::SUCCESS; + } const auto var = *maybe_var; 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 enclose_scope = scope->EnclosingVariableScope(); + if (enclose_scope == nullptr) { + ctx.AddInvariantError(name, "NO_ENCLOSING_VAR_SCOPE", *ast); + return ASTVerifier::CheckResult::FAILED; + } + 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); } - return ScopeEncloseVariable(var); + if (!IsContainedIn(scope, enclose_scope)) { + 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_; +}; - const auto variable = ast->AsIdentifier()->Variable(); - if (HasVariable(ast) && variable->IsLocalVariable()) { - const auto local_var = variable->AsLocalVariable(); - if (local_var->HasFlag(varbinder::VariableFlags::LOCAL)) { - return local_var; +class SequenceExpressionHasLastType { +public: + explicit SequenceExpressionHasLastType([[maybe_unused]] ArenaAllocator &allocator) {} + + 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 is_ok = true; - ast->Iterate([&](const auto node) { - if (ast != node->Parent()) { - AddError("INCORRECT_PARENT_REF: " + ToStringHelper(node), node->Start()); - is_ok = false; - } - }); - return is_ok; -} +private: +}; -bool ASTVerifier::VerifyScopeNode(const ir::AstNode *ast) -{ - ASSERT(ast); - const auto maybe_var = GetLocalScopeVariable(ast); - if (!maybe_var) { - return true; - } - const auto var = *maybe_var; - const auto scope = var->GetScope(); - if (scope == nullptr) { - // already checked - return false; - } - const auto enclose_scope = scope->EnclosingVariableScope(); - if (enclose_scope == nullptr) { - AddError("NO_ENCLOSING_VAR_SCOPE: " + ToStringHelper(ast), ast->Start()); - return false; - } - const auto node = scope->Node(); - bool is_ok = true; - if (!IsContainedIn(ast, node)) { - is_ok = false; - AddError("VARIABLE_NOT_ENCLOSE_SCOPE: " + ToStringHelper(ast), ast->Start()); - } - if (!IsContainedIn(scope, enclose_scope)) { - is_ok = false; - AddError("VARIABLE_NOT_ENCLOSE_SCOPE: " + ToStringHelper(ast), ast->Start()); - } - return is_ok; -} +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 var_start = node->Start(); - bool is_ok = true; - if (scope->Bindings().count(var->Name()) == 0) { - AddError("SCOPE_DO_NOT_ENCLOSE_LOCAL_VAR: " + ToStringHelper(node), var_start); - is_ok = false; - } - const auto scope_node = scope->Node(); - auto var_node = node; - if (!IsContainedIn(var_node, scope_node) || scope_node == nullptr) { - AddError("SCOPE_NODE_DONT_DOMINATE_VAR_NODE: " + ToStringHelper(node), var_start); - is_ok = false; - } - const auto &decls = scope->Decls(); - const auto decl_dominate = std::count(decls.begin(), decls.end(), var->Declaration()); - if (decl_dominate == 0) { - AddError("SCOPE_DECL_DONT_DOMINATE_VAR_DECL: " + ToStringHelper(node), var_start); - is_ok = false; - } - return is_ok; -} + 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 is_correct = true; - ast->Iterate([&is_correct](ir::AstNode *child) { is_correct &= (IsNumericType(child)); }); - return is_correct; - } - 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 has_exit = body->IsBreakStatement() || body->IsReturnStatement(); + body->IterateRecursively([&has_exit](ir::AstNode *child) { + has_exit |= child->IsBreakStatement() || child->IsReturnStatement(); + }); + if (!has_exit) { + // 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 *prop_var = ast->AsMemberExpression()->PropVar(); + if (prop_var != nullptr && prop_var->HasFlag(varbinder::VariableFlags::PROPERTY) && + !ValidateVariableAccess(prop_var, ast->AsMemberExpression())) { + ctx.AddInvariantError(name, "PROPERTY_NOT_VISIBLE_HERE", *ast); + return ASTVerifier::CheckResult::FAILED; + } + } + if (ast->IsCallExpression()) { + const auto *call_expr = ast->AsCallExpression(); + const auto *callee = call_expr->Callee(); + if (callee != nullptr && callee->IsMemberExpression()) { + const auto *callee_member = callee->AsMemberExpression(); + const auto *prop_var_callee = callee_member->PropVar(); + if (prop_var_callee != nullptr && prop_var_callee->HasFlag(varbinder::VariableFlags::METHOD) && + !ValidateMethodAccess(callee_member, 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 imported_variables {}; + if (ast->IsETSImportDeclaration()) { + const auto import_decl = 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 : import_decl) { + imported_variables.emplace(name(import)); + } } + const auto name = "ImportExportAccessValid"; + if (ast->IsCallExpression()) { + const auto *call_expr = ast->AsCallExpression(); + const auto *callee = call_expr->Callee(); + if (callee != nullptr && callee->IsIdentifier() && + !HandleImportExportIdentifier(imported_variables, callee->AsIdentifier(), call_expr)) { + ctx.AddInvariantError(name, "PROPERTY_NOT_VISIBLE_HERE(NOT_EXPORTED)", *callee); + return ASTVerifier::CheckResult::FAILED; + } + } + if (ast->IsIdentifier() && !HandleImportExportIdentifier(imported_variables, 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 has_exit = body->IsBreakStatement() || body->IsReturnStatement(); - body->IterateRecursively([&has_exit](ir::AstNode *child) { - has_exit |= child->IsBreakStatement() || child->IsReturnStatement(); - }); - if (!has_exit) { - // an infinite loop - AddError("WARNING: NULL FOR-TEST AND FOR-BODY doesn't exit: " + ToStringHelper(ast), ast->Start()); - } + bool InvariantImportExportMethod(const ASTVerifier::InvariantSet &imported_variables, + const varbinder::Variable *var_callee, const ir::AstNode *call_expr, + util::StringView name) + { + auto *signature = call_expr->AsCallExpression()->Signature(); + if (signature->Owner() == nullptr) { + // NOTE(vpukhov): Add a synthetic owner for dynamic signatures + ASSERT(call_expr->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 && var_callee->Declaration() != nullptr && + var_callee->Declaration()->Node() != nullptr && + !IsContainedIn(var_callee->Declaration()->Node(), signature->Owner()->GetDeclNode()) && + var_callee->Declaration()->Node() != signature->Owner()->GetDeclNode()) { + if (imported_variables.find(name.Mutf8()) != imported_variables.end() || + imported_variables.find("") != imported_variables.end()) { + return ValidateExport(var_callee); + } return false; } + return true; } - return true; -} - -bool ASTVerifier::AreForLoopsCorrectInitialized(const ir::AstNode *ast) -{ - if (ast == nullptr) { - return false; - } - - bool is_for_initialized = IsForLoopCorrectInitialized(ast); - ast->IterateRecursively( - [this, &is_for_initialized](ir::AstNode *child) { is_for_initialized &= IsForLoopCorrectInitialized(child); }); - return is_for_initialized; -} -bool ASTVerifier::VerifyModifierAccess(const ir::AstNode *ast) -{ - if (ast == nullptr) { - return false; - } - if (ast->IsMemberExpression()) { - const auto *prop_var = ast->AsMemberExpression()->PropVar(); - if (prop_var == nullptr || (prop_var->HasFlag(varbinder::VariableFlags::PROPERTY) && - !ValidateVariableAccess(prop_var, ast->AsMemberExpression()))) { - AddError("PROPERTY_NOT_VISIBLE_HERE: " + ToStringHelper(ast), ast->Start()); - return false; - } - } - if (ast->IsCallExpression()) { - const auto *call_expr = ast->AsCallExpression(); - const auto *callee = call_expr->Callee(); - if (callee == nullptr) { - return false; - } - if (callee->IsMemberExpression()) { - const auto *callee_member = callee->AsMemberExpression(); - const auto *prop_var_callee = callee_member->PropVar(); - if (prop_var_callee == nullptr || (prop_var_callee->HasFlag(varbinder::VariableFlags::METHOD) && - !ValidateMethodAccess(callee_member, ast->AsCallExpression()))) { - AddError("PROPERTY_NOT_VISIBLE_HERE: " + ToStringHelper(callee), callee->Start()); + bool InvariantImportExportVariable(const ASTVerifier::InvariantSet &imported_variables, + 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 var_parent = var->Declaration()->Node()->Parent(); + if (var_parent != nullptr && !IsContainedIn(ident->Parent(), var_parent) && ident->Parent() != var_parent) { + if (var->GetScope() != nullptr && var->GetScope()->Parent() != nullptr && + var->GetScope()->Parent()->IsGlobalScope() && + ident->GetTopStatement() == var_parent->GetTopStatement()) { + return true; + } + if (imported_variables.find(name.Mutf8()) != imported_variables.end() || + imported_variables.find("") != imported_variables.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 import_decl = 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 &imported_variables, const ir::Identifier *ident, + const ir::AstNode *call_expr) + { + if (ident->IsReference()) { + const auto *var = ident->Variable(); + if (var != nullptr) { + if (var->HasFlag(varbinder::VariableFlags::METHOD) && call_expr != nullptr) { + return InvariantImportExportMethod(imported_variables, var, call_expr, ident->Name()); + } + return InvariantImportExportVariable(imported_variables, var, ident, ident->Name()); } - return specifier->AsImportDefaultSpecifier()->Local()->Name(); - }; - for (const auto import : import_decl) { - imported_variables_.emplace(name(import)); } - } - if (ast->IsCallExpression()) { - const auto *call_expr = ast->AsCallExpression(); - const auto *callee = call_expr->Callee(); - if (callee != nullptr && callee->IsIdentifier() && - !HandleImportExportIdentifier(callee->AsIdentifier(), call_expr)) { - 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 *var_callee, const ir::AstNode *call_expr, - util::StringView name) -{ - auto *signature = call_expr->AsCallExpression()->Signature(); - if (signature->Owner() == nullptr) { - // NOTE(vpukhov): Add a synthetic owner for dynamic signatures - ASSERT(call_expr->AsCallExpression()->Callee()->TsType()->HasTypeFlag(checker::TypeFlag::ETS_DYNAMIC_FLAG)); return true; } +}; + +class ArithmeticOperationValid { +public: + explicit ArithmeticOperationValid([[maybe_unused]] ArenaAllocator &allocator) {} - if (signature != nullptr && var_callee->Declaration() != nullptr && var_callee->Declaration()->Node() != nullptr && - !IsContainedIn(var_callee->Declaration()->Node(), signature->Owner()->GetDeclNode()) && - var_callee->Declaration()->Node() != signature->Owner()->GetDeclNode()) { - if (imported_variables_.find(name) != imported_variables_.end() || - imported_variables_.find(util::StringView("")) != imported_variables_.end()) { - return ValidateExport(var_callee); + 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 var_parent = var->Declaration()->Node()->Parent(); - if (var_parent != nullptr && !IsContainedIn(ident->Parent(), var_parent) && ident->Parent() != var_parent) { - if (var->GetScope() != nullptr && var->GetScope()->Parent() != nullptr && - var->GetScope()->Parent()->IsGlobalScope() && - ident->GetTopStatement() == var_parent->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 (imported_variables_.find(name) != imported_variables_.end() || - imported_variables_.find(util::StringView("")) != imported_variables_.end()) { - return ValidateExport(var); + const auto new_result = func(ctx, child); + if (new_result == ASTVerifier::CheckResult::SKIP_SUBTREE) { + return; } - return false; - } - } - return true; + result = new_result; + child->Iterate(aux); + }; + aux(ast); + return result; + }; } -bool ASTVerifier::HandleImportExportIdentifier(const ir::Identifier *ident, const ir::AstNode *call_expr) +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) && call_expr != nullptr) { - return CheckImportExportMethod(var, call_expr, ident->Name()); - } - return CheckImportExportVariable(var, ident, ident->Name()); - } - } - return true; + invariants_checks_[name] = invariant; + invariants_names_.insert(name); + invariants_checks_[name + RECURSIVE_SUFFIX] = RecursiveInvariant(invariant); + invariants_names_.insert(name + RECURSIVE_SUFFIX); } -ASTVerifier::ASTVerifier(ArenaAllocator *allocator, bool save_errors, util::StringView source_code) - : save_errors_(save_errors), - allocator_ {allocator}, - named_errors_ {allocator_->Adapter()}, - encountered_errors_ {allocator_->Adapter()}, - checks_ {allocator_->Adapter()}, - all_checks_(allocator_->Adapter()) +ASTVerifier::ASTVerifier(ArenaAllocator *allocator) { - if (!source_code.Empty()) { - index_.emplace(source_code); - } - - 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, all_checks_); + auto recursive_checks = InvariantSet {}; + std::copy_if(invariants_names_.begin(), invariants_names_.end(), + std::inserter(recursive_checks, recursive_checks.end()), + [](const std::string &s) { return s.find(RECURSIVE_SUFFIX) != s.npos; }); + return Verify(warnings, asserts, ast, recursive_checks); } -bool ASTVerifier::Verify(const ir::AstNode *ast, const CheckSet &check_set) +std::tuple ASTVerifier::Verify( + const std::unordered_set &warnings, const std::unordered_set &asserts, + const ir::AstNode *ast, const InvariantSet &invariant_set) { - bool is_correct = true; - auto check_and_report = [&is_correct, this](util::StringView name, const CheckFunction &check, - const ir::AstNode *node) { - if (node == nullptr) { - return; - } + ErrorContext warning_ctx {}; + AssertsContext assert_ctx {}; - is_correct &= check(node); - if (!is_correct) { - for (const auto &error : encountered_errors_) { - named_errors_.emplace_back(NamedError {name, error}); - } - encountered_errors_.clear(); - } - }; + const auto contains_invariants = + std::includes(invariants_names_.begin(), invariants_names_.end(), invariant_set.begin(), invariant_set.end()); - const auto contains_checks = - std::includes(all_checks_.begin(), all_checks_.end(), check_set.begin(), check_set.end()); - if (!contains_checks) { - auto invalid_checks = CheckSet {allocator_->Adapter()}; - for (const auto &check : check_set) { - if (all_checks_.find(check) == all_checks_.end()) { - invalid_checks.insert(check); + if (!contains_invariants) { + auto invalid_invariants = InvariantSet {}; + for (const auto &invariant : invariant_set) { + if (invariants_names_.find(invariant) == invariants_names_.end()) { + invalid_invariants.insert(invariant.data()); } } - for (const auto &check : invalid_checks) { - const auto &message = check.Mutf8() + " check is not found"; - named_errors_.emplace_back(NamedError {"Check", Error {message, lexer::SourceLocation {}}}); + for (const auto &invariant : invalid_invariants) { + assert_ctx.AddError(std::string {"invariant was not found: "} + invariant); } } - for (const auto &[name, check] : checks_) { - if (check_set.find(name) != check_set.end()) { - check_and_report(name, check, ast); + for (const auto &invariant_name : invariant_set) { + if (warnings.count(invariant_name) > 0) { + invariants_checks_[invariant_name](warning_ctx, ast); + } else if (asserts.count(invariant_name) > 0) { + invariants_checks_[invariant_name](assert_ctx, ast); } } - return is_correct; + + return std::make_tuple(warning_ctx.GetErrors(), assert_ctx.GetErrors()); } } // namespace panda::es2panda::compiler diff --git a/ets2panda/compiler/core/ASTVerifier.h b/ets2panda/compiler/core/ASTVerifier.h index 906c97c3cf6b6477bd341716e3402df91f6da430..007aa5ebf18e788f71d82c62238a93e564e56e91 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) + : invariant_name_ {std::move(name)}, error_ {std::move(error)} + { + } + std::function DumpJSON() const + { + return [&](JsonObjectBuilder &body) { + body.AddProperty("invariant", invariant_name_); + body.AddProperty("cause", error_.cause); + body.AddProperty("message", error_.message); + body.AddProperty("line", error_.line + 1); + }; + } + const std::string &GetName() const + { + return invariant_name_; + } + + private: + std::string invariant_name_; + 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 check_name; - 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 check_name; - 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 invariant_name; + InvariantCheck invariant; + }; + using Invariants = std::map; NO_COPY_SEMANTIC(ASTVerifier); NO_MOVE_SEMANTIC(ASTVerifier); - explicit ASTVerifier(ArenaAllocator *allocator, bool save_errors = true, util::StringView source_code = ""); + 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 &check_set); + std::tuple Verify(const std::unordered_set &warnings, + const std::unordered_set &asserts, + const ir::AstNode *ast, + const InvariantSet &invariant_set); - Errors GetErrors() const +private: + void AddInvariant(const std::string &name, const InvariantCheck &invariant); + + Invariants invariants_checks_; + InvariantSet invariants_names_; +}; + +class ASTVerifierContext final { +public: + explicit ASTVerifierContext(ASTVerifier &verifier) : verifier_ {verifier} {} + + void IntroduceNewInvariants(util::StringView phase_name) { - return named_errors_; + auto invariant_set = [phase_name]() -> std::optional { + (void)phase_name; + if (phase_name == "ScopesInitPhase") { + return {{ + "NodeHasParentForAll", + "EveryChildHasValidParentForAll", + "VariableHasScopeForAll", + }}; + } + if (phase_name == "CheckerPhase") { + return {{ + "NodeHasTypeForAll", + "IdentifierHasVariableForAll", + "ArithmeticOperationValidForAll", + "SequenceExpressionHasLastTypeForAll", + "ForLoopCorrectlyInitializedForAll", + "VariableHasEnclosingScopeForAll", + "ModifierAccessValidForAll", + "ImportExportAccessValid", + }}; + } + const std::set without_additional_checks = {"PromiseVoidInferencePhase", + "StructLowering", + "GenerateTsDeclarationsPhase", + "InterfacePropertyDeclarationsPhase", + "LambdaConstructionPhase", + "ObjectIndexLowering", + "OpAssignmentLowering", + "PromiseVoidInferencePhase", + "TupleLowering", + "UnionLowering", + "ExpandBracketsPhase"}; + if (without_additional_checks.count(phase_name.Mutf8()) > 0) { + return {{}}; + } + if (phase_name.Utf8().find("plugins") != std::string_view::npos) { + return {{}}; + } + return std::nullopt; + }(); + + ASSERT_PRINT(invariant_set.has_value(), + std::string {"Invariant set does not contain value for "} + phase_name.Mutf8()); + const auto &s = *invariant_set; + accumulated_checks_.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 *call_expr = nullptr); - bool CheckImportExportVariable(const varbinder::Variable *var, const ir::Identifier *ident, util::StringView name); - bool CheckImportExportMethod(const varbinder::Variable *var_callee, const ir::AstNode *call_expr, - 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 phase_name, util::StringView source_name) { - if (save_errors_) { - const auto loc = index_.has_value() ? index_->GetLocation(from) : lexer::SourceLocation {}; - encountered_errors_.emplace_back(Error {message, loc}); - } + auto [warns, asserts] = verifier_.Verify(warnings, errors, ast, accumulated_checks_); + std::for_each(warns.begin(), warns.end(), [this, &source_name, &phase_name](ASTVerifier::CheckError &e) { + warnings_.Add([e, source_name, phase_name](JsonObjectBuilder &err) { + err.AddProperty("from", source_name.Utf8()); + err.AddProperty("phase", phase_name.Utf8()); + err.AddProperty("error", e.DumpJSON()); + }); + }); + std::for_each(asserts.begin(), asserts.end(), [this, &source_name, &phase_name](ASTVerifier::CheckError &e) { + asserts_.Add([e, source_name, phase_name](JsonObjectBuilder &err) { + err.AddProperty("from", source_name.Utf8()); + err.AddProperty("phase", phase_name.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 save_errors_; - ArenaAllocator *allocator_; - Errors named_errors_; - ArenaVector encountered_errors_; - Checks checks_; - CheckSet all_checks_; - std::unordered_set imported_variables_; + ASTVerifier &verifier_; + JsonArrayBuilder warnings_; + JsonArrayBuilder asserts_; + ASTVerifier::InvariantSet accumulated_checks_ {}; }; -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 2ae78aa60713a4102701bc16d28e454f1cc22049..c19489b0e31997d3876842a76a9faee31675995a 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, obj_reg, qname_reg, signature, arguments); } +static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::ETSNewClassInstanceExpression *expr) +{ + if (expr->GetSignature()->RestVar() != nullptr) { + std::size_t const argument_count = expr->GetArguments().size(); + std::size_t const parameter_count = expr->GetSignature()->MinArgCount(); + ASSERT(argument_count >= parameter_count); + + auto &arguments = const_cast &>(expr->GetArguments()); + std::size_t i = parameter_count; + + if (i < argument_count && expr->GetArguments()[i]->IsSpreadElement()) { + arguments[i] = expr->GetArguments()[i]->AsSpreadElement()->Argument(); + } else { + ArenaVector elements(checker->Allocator()->Adapter()); + for (; i < argument_count; ++i) { + elements.emplace_back(expr->GetArguments()[i]); + } + auto *array_expression = checker->AllocNode(std::move(elements), checker->Allocator()); + array_expression->SetParent(const_cast(expr)); + array_expression->SetTsType(expr->GetSignature()->RestVar()->TsType()); + arguments.erase(expr->GetArguments().begin() + parameter_count, expr->GetArguments().end()); + arguments.emplace_back(array_expression); + } + } +} + 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, obj_reg, 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 bigint_signatures = { + {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 bigint_signatures; +} + +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 *operation_type = expr->OperationType(); + auto ttctx = compiler::TargetTypeContext(etsg, operation_type); + compiler::RegScope rs(etsg); + compiler::VReg lhs = etsg->AllocReg(); + expr->Left()->Compile(etsg); + etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, operation_type); + expr->Right()->Compile(etsg); + etsg->ApplyConversion(expr->Right(), operation_type); + 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, end_label); - 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 @@ -1065,7 +1169,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()); } @@ -1084,7 +1194,16 @@ void ETSCompiler::Compile(const ir::UpdateExpression *expr) const lref.GetValue(); expr->Argument()->SetBoxingUnboxingFlags(argument_unboxing_flags); etsg->ApplyConversion(expr->Argument(), nullptr); - etsg->Update(expr, expr->OperatorType()); + + if (expr->Argument()->TsType()->IsETSBigIntType()) { + compiler::RegScope rs(etsg); + compiler::VReg value_reg = etsg->AllocReg(); + etsg->StoreAccumulator(expr->Argument(), value_reg); + etsg->UpdateBigInt(expr, value_reg, expr->OperatorType()); + } else { + etsg->Update(expr, expr->OperatorType()); + } + expr->Argument()->SetBoxingUnboxingFlags(argument_boxing_flags); etsg->ApplyConversion(expr->Argument(), expr->Argument()->TsType()); lref.SetValue(); @@ -1101,7 +1220,12 @@ void ETSCompiler::Compile(const ir::UpdateExpression *expr) const expr->Argument()->SetBoxingUnboxingFlags(argument_unboxing_flags); etsg->ApplyConversion(expr->Argument(), nullptr); - etsg->Update(expr, expr->OperatorType()); + + if (expr->Argument()->TsType()->IsETSBigIntType()) { + etsg->UpdateBigInt(expr, original_value_reg, expr->OperatorType()); + } else { + etsg->Update(expr, expr->OperatorType()); + } expr->Argument()->SetBoxingUnboxingFlags(argument_boxing_flags); etsg->ApplyConversion(expr->Argument(), expr->Argument()->TsType()); @@ -1117,7 +1241,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 7022338e477ee6a5cda369b5144712f197e92dd2..f2cf172a2713729cafb387858dcaf82f655ecc67 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, dummy_reg_); +} + void ETSGen::CreateLambdaObjectFromIdentReference(const ir::AstNode *node, ir::ClassDefinition *lambda_obj) { auto *ctor = lambda_obj->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 (target_type->IsETSTypeParameter() && target_type->AsETSTypeParameter()->HasConstraint()) { + if (target_type->IsETSTypeParameter()) { CheckedReferenceNarrowing(node, target_type->AsETSTypeParameter()->GetConstraintType()); } else if (target_type->IsETSObjectType()) { CheckedReferenceNarrowing(node, target_type->AsETSObjectType()->GetConstOriginalBaseType()); @@ -2134,7 +2155,10 @@ void ETSGen::BinaryEqualityRef(const ir::AstNode *node, bool test_equal, VReg lh 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 61c79b6af6bfb2ef6c552f0157ebe43c9351eb03..5aaa0c3d2ccfa9560fce6eb4232782e772aa67a2 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -98,6 +98,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 *if_false); @@ -387,6 +388,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); @@ -551,6 +558,9 @@ public: void NewArray(const ir::AstNode *node, VReg arr, VReg dim, const checker::Type *arr_type); 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) @@ -635,6 +645,7 @@ public: } #endif // PANDA_WITH_ETS + void CreateBigIntObject(const ir::AstNode *node, VReg arg0); void CreateLambdaObjectFromIdentReference(const ir::AstNode *node, ir::ClassDefinition *lambda_obj); void CreateLambdaObjectFromMemberReference(const ir::AstNode *node, ir::Expression *obj, ir::ClassDefinition *lambda_obj); @@ -661,6 +672,7 @@ private: void EmitUnboxedCall(const ir::AstNode *node, std::string_view signature_flag, const checker::Type *target_type, const checker::Type *boxed_type); + void LoadConstantObject(const ir::Expression *node, const checker::Type *type); void StringBuilderAppend(const ir::AstNode *node, VReg builder); void AppendString(const ir::Expression *bin_expr, VReg builder); void StringBuilder(const ir::Expression *left, const ir::Expression *right, VReg builder); @@ -840,6 +852,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, if_false); break; diff --git a/ets2panda/compiler/core/ETSfunction.cpp b/ets2panda/compiler/core/ETSfunction.cpp index bddfa6ec04982f1dcaafe9b8164d1452034d4a71..75a1cb7e4bcb552611bcec6d4044f9a590445818 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 c9847b33cbe70a2af426ef5571670b66cc8d2bb4..87850b5124f7e4addf27ab46e22ecee0c9c87e48 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 verification_ctx = ASTVerifierContext {verifier}; + public_lib::Context public_context; SetupPublicContext(&public_context, &unit.input, &allocator, compiler_impl->Queue(), &compiler_impl->Plugins(), &parser, &context); @@ -142,7 +146,37 @@ static pandasm::Program *CreateCompiler(const CompilationUnit &unit, const Phase if (!phase->Apply(&public_context, &program)) { return nullptr; } +#ifndef NDEBUG + using NamedProgram = std::tuple; + ArenaVector to_check {program.Allocator()->Adapter()}; + to_check.push_back(std::make_tuple(program.SourceFilePath(), &program)); + for (const auto &external_source : program.ExternalSources()) { + for (const auto *external : external_source.second) { + to_check.push_back(std::make_tuple(external->SourceFilePath(), external)); + } + } + for (const auto &it : to_check) { + const auto &source_name = std::get<0>(it); + const auto &linked_program = std::get<1>(it); + verification_ctx.Verify(context.Options()->verifier_warnings, context.Options()->verifier_errors, + linked_program->Ast(), phase->Name(), source_name); + verification_ctx.IntroduceNewInvariants(phase->Name()); + } +#endif + } + +#ifndef NDEBUG + if (!context.Options()->verifier_warnings.empty()) { + if (auto errors = verification_ctx.DumpWarningsJSON(); errors != "[]") { + LOG(ERROR, ES2PANDA) << errors; + } + } + if (!context.Options()->verifier_errors.empty()) { + if (auto errors = verification_ctx.DumpAssertsJSON(); errors != "[]") { + ASSERT_PRINT(false, errors); + } } +#endif emitter.GenAnnotation(); diff --git a/ets2panda/compiler/lowering/checkerPhase.cpp b/ets2panda/compiler/lowering/checkerPhase.cpp index 9d9c74108751a71f1c2a22c1b528a50a259867ca..88fc8ebf4abce4307b9b0d90ab9d264e8e2b3672 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 fdda661afc8b6124abf0e1c1f5e1f21471f3a05e..715afb9ba55214025e4b844f476f9c815d880ec7 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, expr_type, ident->Clone(allocator), new_expression); sequence_expr->SetParent(new_expression->Parent()); - ScopesInitPhaseETS::RunExternalNode(sequence_expr, ctx->compiler_context->VarBinder()); + InitScopesPhaseETS::RunExternalNode(sequence_expr, ctx->compiler_context->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(sequence_expr, scope); sequence_expr->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 96472eae5015737399508c79f631274e485363d2..a2ca924836f9b1d119bf1f2a25cc45a803eac543 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 720bfc456e4e2b2ab4e1af17ef0eeec26ab62c0f..cc9fe7f2931650183eda8744fe976b1f85c7b0b6 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 is_setter) { 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 936fe080fe02c8e1136b8fa72bdc99b6a87f0725..dbf75f069bff648c814f7875def5f2208325ccc1 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 277f9026ff899ccd31345d290f2c05b3f080440e..70c48c5f80cc098d651f2c4843c0312484e9ca73 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 *assignment_expression) const { diff --git a/ets2panda/compiler/lowering/ets/objectIndexAccess.h b/ets2panda/compiler/lowering/ets/objectIndexAccess.h index 5150cd18a2b4ad75e2e04a0e87b54471eac84e43..3e64caa9c5dca50d166325230917bd6bc1400d33 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 c47f0e8c6a5426d9a0a707dbf251b51d4fc956e6..354127150b5ef83a161718837ee7fd6ce86d08f6 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, expr_type); lowering_result->SetParent(assignment->Parent()); - ScopesInitPhaseETS::RunExternalNode(lowering_result, ctx->compiler_context->VarBinder()); + InitScopesPhaseETS::RunExternalNode(lowering_result, ctx->compiler_context->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(lowering_result, scope); lowering_result->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 06d0bacff8970c2321eef77a57420168d99b5b9a..d098846e99fafa45af579169595a88ce4eb5370e 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; @@ -129,7 +123,16 @@ static bool CheckForPromiseVoid(const ir::TypeNode *type) return is_type_promise && is_param_void; } -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(); @@ -182,7 +185,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..67a3db3e003e9cba9e52d4a551f2cad43a5a7068 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/structLowering.cpp @@ -0,0 +1,107 @@ +/** + * 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 *ets_struc_declaration) +{ + auto *allocator = checker->Allocator(); + + ArenaVector params(allocator->Adapter()); + + ir::TSTypeParameterInstantiation *type_param_self_inst = nullptr; + + if (ets_struc_declaration->Definition()->TypeParams() != nullptr && + !ets_struc_declaration->Definition()->TypeParams()->Params().empty()) { + ArenaVector self_params(allocator->Adapter()); + ir::ETSTypeReferencePart *reference_part = nullptr; + + for (const auto ¶m : ets_struc_declaration->Definition()->TypeParams()->Params()) { + auto *ident_ref = checker->AllocNode(param->AsTSTypeParameter()->Name()->Name(), allocator); + ident_ref->AsIdentifier()->SetReference(); + + reference_part = checker->AllocNode(ident_ref, nullptr, nullptr); + + auto *type_reference = checker->AllocNode(reference_part); + + self_params.push_back(type_reference); + } + + type_param_self_inst = checker->AllocNode(std::move(self_params)); + } + + auto *ident_self_ref = + checker->AllocNode(ets_struc_declaration->Definition()->Ident()->Name(), allocator); + ident_self_ref->AsIdentifier()->SetReference(); + + auto *reference_self_part = + checker->AllocNode(ident_self_ref, type_param_self_inst, nullptr); + + auto *self_type_reference = checker->AllocNode(reference_self_part); + + params.push_back(self_type_reference); + + auto *type_param_inst = checker->AllocNode(std::move(params)); + + auto *ident_ref = checker->AllocNode(util::StringView(STRUCT_CLASS_NAME), allocator); + ident_ref->AsIdentifier()->SetReference(); + auto *reference_part = checker->AllocNode(ident_ref, type_param_inst, nullptr); + + auto *type_reference = checker->AllocNode(reference_part); + + return type_reference; +} + +bool StructLowering::Perform(public_lib::Context *ctx, parser::Program *program) +{ + for (auto &[_, ext_programs] : program->ExternalSources()) { + (void)_; + for (auto *ext_prog : ext_programs) { + Perform(ctx, ext_prog); + } + } + + checker::ETSChecker *checker = ctx->checker->AsETSChecker(); + + program->Ast()->TransformChildrenRecursively([checker](ir::AstNode *ast) -> ir::AstNode * { + if (ast->IsETSStructDeclaration()) { + auto *type_ref = CreateStructTypeReference(checker, ast->AsETSStructDeclaration()); + ast->AsETSStructDeclaration()->Definition()->SetSuper(type_ref); + 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 34ed65ad7dc0919f1cac0021d8a000fa7a8ac5f5..c8a9c7f2f9d4ec736d9e9ddac1690b35d70cb350 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 6460b495063c6895c33863cfd4b23314197fbf04..e5b6a9f9a3f39bc34f24031b9a3511836d357b9a 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 @@ -155,9 +152,9 @@ ir::TSAsExpression *HandleUnionCastToPrimitive(checker::ETSChecker *checker, ir: } if (source_type != nullptr && expr->Expr()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { if (expr->TsType()->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { - auto *const boxed_expr_type = checker::BoxingConverter::ETSTypeFromSource(checker, expr->TsType()); - auto *const as_expr = GenAsExpression(checker, boxed_expr_type, expr->Expr(), expr); - as_expr->SetBoxingUnboxingFlags(expr->Expr()->GetBoxingUnboxingFlags()); + auto *const as_expr = GenAsExpression(checker, source_type, expr->Expr(), expr); + as_expr->SetBoxingUnboxingFlags( + checker->GetUnboxingFlag(checker->ETSBuiltinTypeAsPrimitiveType(source_type))); expr->Expr()->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); expr->SetExpr(as_expr); } @@ -182,15 +179,24 @@ ir::BinaryExpression *GenInstanceofExpr(checker::ETSChecker *checker, ir::Expres rhs_type = checker::conversion::Boxing(checker->Relation(), constituent_type); checker->Relation()->SetNode(nullptr); } - auto *const rhs_expr = - checker->Allocator()->New(rhs_type->AsETSObjectType()->Name(), checker->Allocator()); + if (constituent_type->IsETSStringType()) { + rhs_type = checker->GlobalBuiltinETSStringType(); + } + ir::Expression *rhs_expr; + if (rhs_type->IsETSUndefinedType()) { + rhs_expr = checker->Allocator()->New(); + } else if (rhs_type->IsETSNullType()) { + rhs_expr = checker->Allocator()->New(); + } else { + rhs_expr = checker->Allocator()->New(rhs_type->AsETSObjectType()->Name(), checker->Allocator()); + auto rhs_var = NearestScope(union_node)->Find(rhs_expr->AsIdentifier()->Name()); + rhs_expr->AsIdentifier()->SetVariable(rhs_var.variable); + } auto *const instanceof_expr = checker->Allocator()->New(lhs_expr, rhs_expr, lexer::TokenType::KEYW_INSTANCEOF); lhs_expr->SetParent(instanceof_expr); rhs_expr->SetParent(instanceof_expr); - auto rhs_var = NearestScope(union_node)->Find(rhs_expr->Name()); - rhs_expr->SetVariable(rhs_var.variable); - rhs_expr->SetTsType(rhs_var.variable->TsType()); + rhs_expr->SetTsType(rhs_type); instanceof_expr->SetOperationType(checker->GlobalETSObjectType()); instanceof_expr->SetTsType(checker->GlobalETSBooleanType()); return instanceof_expr; @@ -272,7 +278,10 @@ ir::Expression *ProcessOperandsInBinaryExpr(checker::ETSChecker *checker, ir::Bi bool is_lhs_union; ir::Expression *union_node = (is_lhs_union = expr->Left()->TsType()->IsETSUnionType()) ? expr->Left() : expr->Right(); - auto *const as_expression = GenAsExpression(checker, constituent_type, union_node, expr); + checker::Type *type_to_cast = constituent_type->IsETSNullLike() + ? union_node->TsType()->AsETSUnionType()->GetLeastUpperBoundType() + : constituent_type; + auto *const as_expression = GenAsExpression(checker, type_to_cast, union_node, expr); if (is_lhs_union) { expr->SetLeft(as_expression); expr->SetRight(SetBoxFlagOrGenAsExpression(checker, constituent_type, 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 b64e813bc52d8c4ee33544eddb1a0867ba7e093a..14286b38164c467f3ecdd1e5b4c8347489747789 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,59 +47,71 @@ std::vector GetTrivialPhaseList() static InterfacePropertyDeclarationsPhase INTERFACE_PROP_DECL_PHASE; static GenerateTsDeclarationsPhase GENERATE_TS_DECLARATIONS_PHASE; -static LambdaLowering LAMBDA_LOWERING; +static LambdaConstructionPhase LAMBDA_CONSTRUCTION_PHASE; static OpAssignmentLowering OP_ASSIGNMENT_LOWERING; static ObjectIndexLowering OBJECT_INDEX_LOWERING; static TupleLowering TUPLE_LOWERING; // Can be only applied after checking phase, and OP_ASSIGNMENT_LOWERING phase static UnionLowering UNION_LOWERING; static ExpandBracketsPhase EXPAND_BRACKETS_PHASE; -static PromiseVoidLowering PROMISE_VOID_LOWERING; +static PromiseVoidInferencePhase PROMISE_VOID_INFERENCE_PHASE; +static StructLowering STRUCT_LOWERING; static PluginPhase PLUGINS_AFTER_PARSE {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse}; static PluginPhase PLUGINS_AFTER_CHECK {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}; static PluginPhase PLUGINS_AFTER_LOWERINGS {"plugins-after-lowering", ES2PANDA_STATE_LOWERED, &util::Plugin::AfterLowerings}; +// NOLINTBEGIN(fuchsia-statically-constructed-objects) +static InitScopesPhaseETS INIT_SCOPES_PHASE_ETS; +static InitScopesPhaseAS INIT_SCOPES_PHASE_AS; +static InitScopesPhaseTs INIT_SCOPES_PHASE_TS; +static InitScopesPhaseJs INIT_SCOPES_PHASE_JS; +// NOLINTEND(fuchsia-statically-constructed-objects) + +std::vector GetETSPhaseList() +{ + return { + &PLUGINS_AFTER_PARSE, &INIT_SCOPES_PHASE_ETS, &PROMISE_VOID_INFERENCE_PHASE, + &STRUCT_LOWERING, &LAMBDA_CONSTRUCTION_PHASE, &INTERFACE_PROP_DECL_PHASE, + &CHECKER_PHASE, &PLUGINS_AFTER_CHECK, &GENERATE_TS_DECLARATIONS_PHASE, + &OP_ASSIGNMENT_LOWERING, &OBJECT_INDEX_LOWERING, &TUPLE_LOWERING, + &UNION_LOWERING, &EXPAND_BRACKETS_PHASE, &PLUGINS_AFTER_LOWERINGS, + }; +} -std::vector GetPhaseList(ScriptExtension ext) +std::vector GetASPhaseList() +{ + return { + &INIT_SCOPES_PHASE_AS, + &CHECKER_PHASE, + }; +} + +std::vector GetTSPhaseList() +{ + return { + &INIT_SCOPES_PHASE_TS, + &CHECKER_PHASE, + }; +} + +std::vector GetJSPhaseList() { - static ScopesInitPhaseETS scopes_phase_ets; - static ScopesInitPhaseAS scopes_phase_as; - static ScopesInitPhaseTs scopes_phase_ts; - static ScopesInitPhaseJs scopes_phase_js; + return { + &INIT_SCOPES_PHASE_JS, + &CHECKER_PHASE, + }; +} +std::vector GetPhaseList(ScriptExtension ext) +{ switch (ext) { case ScriptExtension::ETS: - return { - &scopes_phase_ets, - &PLUGINS_AFTER_PARSE, - &PROMISE_VOID_LOWERING, - &LAMBDA_LOWERING, - &INTERFACE_PROP_DECL_PHASE, - &CHECKER_PHASE, - &PLUGINS_AFTER_CHECK, - &GENERATE_TS_DECLARATIONS_PHASE, - &OP_ASSIGNMENT_LOWERING, - &OBJECT_INDEX_LOWERING, - &TUPLE_LOWERING, - &UNION_LOWERING, - &EXPAND_BRACKETS_PHASE, - &PLUGINS_AFTER_LOWERINGS, - }; - + return GetETSPhaseList(); case ScriptExtension::AS: - return std::vector { - &scopes_phase_as, - &CHECKER_PHASE, - }; + return GetASPhaseList(); case ScriptExtension::TS: - return std::vector { - &scopes_phase_ts, - &CHECKER_PHASE, - }; + return GetTSPhaseList(); case ScriptExtension::JS: - return std::vector { - &scopes_phase_js, - &CHECKER_PHASE, - }; + return GetJSPhaseList(); default: UNREACHABLE(); } @@ -105,25 +119,6 @@ std::vector GetPhaseList(ScriptExtension ext) bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) { -#ifndef NDEBUG - const auto check_program = [](const parser::Program *p) { - ASTVerifier verifier {p->Allocator(), false, p->SourceCode()}; - ArenaVector to_check {p->Allocator()->Adapter()}; - to_check.push_back(p->Ast()); - for (const auto &external_source : p->ExternalSources()) { - for (const auto external : external_source.second) { - to_check.push_back(external->Ast()); - } - } - for (const auto *ast : to_check) { - if (!verifier.VerifyFull(ast)) { - return false; - } - } - return true; - }; -#endif - const auto *options = ctx->compiler_context->Options(); const auto name = std::string {Name()}; if (options->skip_phases.count(name) > 0) { @@ -146,8 +141,6 @@ bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) CheckOptionsAfterPhase(options, program, name); #ifndef NDEBUG - check_program(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 4cff33ec06cc614b88fc4b320843c51bb15c8145..dacdf6c84bbb8d91e2fbc4dfbedbaf782bfb6e7d 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 96be103dbb947e385dc4aab727da213e323b8aae..4165c0c057cee417f77b884ec1d427cf7bf2e719 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -563,31 +563,31 @@ void ScopeInitTyped::VisitClassDefinition(ir::ClassDefinition *class_def) IterateNoTParams(class_def); } -void ScopesInitPhaseTs::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *export_decl) +void InitScopesPhaseTs::VisitExportDefaultDeclaration(ir::ExportDefaultDeclaration *export_decl) { ExportDeclarationContext export_decl_ctx(VarBinder()); Iterate(export_decl); } -void ScopesInitPhaseTs::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *export_decl) +void InitScopesPhaseTs::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *export_decl) { ExportDeclarationContext export_decl_ctx(VarBinder()); Iterate(export_decl); } -void ScopesInitPhaseTs::VisitImportDeclaration(ir::ImportDeclaration *import_declaration) +void InitScopesPhaseTs::VisitImportDeclaration(ir::ImportDeclaration *import_declaration) { ImportDeclarationContext import_ctx(VarBinder()); Iterate(import_declaration); } -void ScopesInitPhaseTs::VisitTSFunctionType(ir::TSFunctionType *constr_type) +void InitScopesPhaseTs::VisitTSFunctionType(ir::TSFunctionType *constr_type) { auto lexical_scope = HandleFunctionSig(constr_type->TypeParams(), constr_type->Params(), constr_type->ReturnType()); BindScopeNode(lexical_scope, constr_type); } -void ScopesInitPhaseTs::CreateFuncDecl(ir::ScriptFunction *func) +void InitScopesPhaseTs::CreateFuncDecl(ir::ScriptFunction *func) { const auto ident_node = func->Id(); const auto start_loc = ident_node->Start(); @@ -610,46 +610,46 @@ void ScopesInitPhaseTs::CreateFuncDecl(ir::ScriptFunction *func) decl->Add(func); } -void ScopesInitPhaseTs::VisitTSConstructorType(ir::TSConstructorType *constr_t) +void InitScopesPhaseTs::VisitTSConstructorType(ir::TSConstructorType *constr_t) { auto func_param_scope = HandleFunctionSig(constr_t->TypeParams(), constr_t->Params(), constr_t->ReturnType()); BindScopeNode(func_param_scope, constr_t); } -void ScopesInitPhaseTs::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrow_f_expr) +void InitScopesPhaseTs::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrow_f_expr) { auto type_params_ctx = varbinder::LexicalScope(VarBinder()); Iterate(arrow_f_expr); } -void ScopesInitPhaseTs::VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *sign_decl) +void InitScopesPhaseTs::VisitTSSignatureDeclaration(ir::TSSignatureDeclaration *sign_decl) { auto func_param_scope = HandleFunctionSig(sign_decl->TypeParams(), sign_decl->Params(), sign_decl->ReturnTypeAnnotation()); BindScopeNode(func_param_scope, sign_decl); } -void ScopesInitPhaseTs::VisitTSMethodSignature(ir::TSMethodSignature *method_sign) +void InitScopesPhaseTs::VisitTSMethodSignature(ir::TSMethodSignature *method_sign) { auto func_param_scope = HandleFunctionSig(method_sign->TypeParams(), method_sign->Params(), method_sign->ReturnTypeAnnotation()); BindScopeNode(func_param_scope, method_sign); } -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 scopes_phase = ScopesInitPhaseETS(); + auto scopes_phase = InitScopesPhaseETS(); scopes_phase.SetProgram(ctx); scopes_phase.CallNode(node); } -bool ScopesInitPhaseETS::Perform(PhaseContext *ctx, parser::Program *program) +bool InitScopesPhaseETS::Perform(PhaseContext *ctx, parser::Program *program) { Prepare(ctx, program); @@ -663,7 +663,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)_; @@ -679,7 +679,7 @@ void ScopesInitPhaseETS::HandleProgram(parser::Program *program) BindScopeNode(prog->VarBinder()->GetScope(), prog->Ast()); prog->VarBinder()->ResetTopScope(global_scope); if (main_prog->Ast() != nullptr) { - ScopesInitPhaseETS().Perform(Context(), prog); + InitScopesPhaseETS().Perform(Context(), prog); } } program->VarBinder()->ResetTopScope(saved_top_scope); @@ -689,7 +689,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); @@ -698,7 +698,7 @@ void ScopesInitPhaseETS::BindVarDecl(ir::Identifier *binding, ir::Expression *in decl->BindNode(init); } -void ScopesInitPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *static_block) +void InitScopesPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *static_block) { const auto func = static_block->Function(); @@ -725,7 +725,7 @@ void ScopesInitPhaseETS::VisitClassStaticBlock(ir::ClassStaticBlock *static_bloc func->Id()->SetVariable(var); } -void ScopesInitPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *import_spec) +void InitScopesPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecifier *import_spec) { if (import_spec->Local()->Name().Empty()) { return; @@ -735,7 +735,7 @@ void ScopesInitPhaseETS::VisitImportNamespaceSpecifier(ir::ImportNamespaceSpecif Iterate(import_spec); } -void ScopesInitPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) +void InitScopesPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) { const auto method_name = method->Id(); @@ -795,7 +795,7 @@ void ScopesInitPhaseETS::DeclareClassMethod(ir::MethodDefinition *method) } } -void ScopesInitPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression *param_expr) +void InitScopesPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression *param_expr) { auto *const var = std::get<1>(VarBinder()->AddParamDecl(param_expr)); param_expr->Ident()->SetVariable(var); @@ -803,7 +803,7 @@ void ScopesInitPhaseETS::VisitETSParameterExpression(ir::ETSParameterExpression Iterate(param_expr); } -void ScopesInitPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *import_decl) +void InitScopesPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *import_decl) { ImportDeclarationContext import_ctx(VarBinder()); if (import_decl->Language().IsDynamic()) { @@ -812,7 +812,7 @@ void ScopesInitPhaseETS::VisitETSImportDeclaration(ir::ETSImportDeclaration *imp Iterate(import_decl); } -void ScopesInitPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enum_member) +void InitScopesPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enum_member) { auto ident = enum_member->Key()->AsIdentifier(); auto [decl, var] = VarBinder()->NewVarDecl(ident->Start(), ident->Name()); @@ -823,7 +823,7 @@ void ScopesInitPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enum_member) Iterate(enum_member); } -void ScopesInitPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method) +void InitScopesPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method) { auto *cur_scope = VarBinder()->GetScope(); const auto method_name = method->Id(); @@ -835,7 +835,7 @@ void ScopesInitPhaseETS::VisitMethodDefinition(ir::MethodDefinition *method) DeclareClassMethod(method); } -void ScopesInitPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *func_type) +void InitScopesPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *func_type) { auto type_params_ctx = varbinder::LexicalScope(VarBinder()); varbinder::LexicalScope lexical_scope(VarBinder()); @@ -844,7 +844,7 @@ void ScopesInitPhaseETS::VisitETSFunctionType(ir::ETSFunctionType *func_type) Iterate(func_type); } -void ScopesInitPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *new_class_expr) +void InitScopesPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *new_class_expr) { CallNode(new_class_expr->GetArguments()); CallNode(new_class_expr->GetTypeRef()); @@ -866,7 +866,7 @@ void ScopesInitPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInsta } } -void ScopesInitPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *type_param) +void InitScopesPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *type_param) { auto [decl, var] = VarBinder()->NewVarDecl(type_param->Name()->Start(), type_param->Name()->Name()); @@ -876,7 +876,7 @@ void ScopesInitPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *type_param) decl->BindNode(type_param); } -void ScopesInitPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interface_decl) +void InitScopesPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration *interface_decl) { { auto type_params_ctx = varbinder::LexicalScope(VarBinder()); @@ -892,7 +892,7 @@ void ScopesInitPhaseETS::VisitTSInterfaceDeclaration(ir::TSInterfaceDeclaration decl->AsInterfaceDecl()->Add(interface_decl); } -void ScopesInitPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enum_decl) +void InitScopesPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enum_decl) { { const auto enum_ctx = varbinder::LexicalScope(VarBinder()); @@ -905,14 +905,14 @@ void ScopesInitPhaseETS::VisitTSEnumDeclaration(ir::TSEnumDeclaration *enum_decl decl->BindScope(enum_decl->Scope()); } -void ScopesInitPhaseETS::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *type_alias) +void InitScopesPhaseETS::VisitTSTypeAliasDeclaration(ir::TSTypeAliasDeclaration *type_alias) { VarBinder()->AddDecl(type_alias->Id()->Start(), type_alias->Id()->Name(), type_alias); auto type_params_ctx = varbinder::LexicalScope(VarBinder()); Iterate(type_alias); } -void ScopesInitPhaseETS::AddGlobalToBinder(parser::Program *program) +void InitScopesPhaseETS::AddGlobalToBinder(parser::Program *program) { auto global_id = program->GlobalClass()->Ident(); @@ -927,7 +927,7 @@ void ScopesInitPhaseETS::AddGlobalToBinder(parser::Program *program) global_id->SetVariable(var); } -void ScopesInitPhaseETS::HandleETSScript(ir::BlockStatement *script) +void InitScopesPhaseETS::HandleETSScript(ir::BlockStatement *script) { for (auto decl : script->Statements()) { if (decl->IsETSImportDeclaration()) { @@ -945,7 +945,7 @@ void ScopesInitPhaseETS::HandleETSScript(ir::BlockStatement *script) } } -void ScopesInitPhaseETS::VisitClassDefinition(ir::ClassDefinition *class_def) +void InitScopesPhaseETS::VisitClassDefinition(ir::ClassDefinition *class_def) { if (class_def->IsGlobal()) { ParseGlobalClass(class_def); @@ -961,13 +961,13 @@ void ScopesInitPhaseETS::VisitClassDefinition(ir::ClassDefinition *class_def) BindScopeNode(class_scope, class_def); } -void ScopesInitPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interf_body) +void InitScopesPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interf_body) { Iterate(interf_body); FilterInterfaceOverloads(interf_body->Body()); } -void ScopesInitPhaseETS::FilterInterfaceOverloads(ArenaVector &props) +void InitScopesPhaseETS::FilterInterfaceOverloads(ArenaVector &props) { auto condition = [](ir::AstNode *prop) { if (prop->IsMethodDefinition()) { @@ -979,7 +979,7 @@ void ScopesInitPhaseETS::FilterInterfaceOverloads(ArenaVector &props) +void InitScopesPhaseETS::FilterOverloads(ArenaVector &props) { auto condition = [](ir::AstNode *prop) { if (prop->IsMethodDefinition()) { @@ -991,7 +991,7 @@ void ScopesInitPhaseETS::FilterOverloads(ArenaVector &prop props.erase(std::remove_if(props.begin(), props.end(), condition), props.end()); } -void ScopesInitPhaseETS::VisitClassProperty(ir::ClassProperty *class_prop) +void InitScopesPhaseETS::VisitClassProperty(ir::ClassProperty *class_prop) { auto cur_scope = VarBinder()->GetScope(); if (class_prop->IsClassStaticBlock()) { @@ -1023,7 +1023,7 @@ void ScopesInitPhaseETS::VisitClassProperty(ir::ClassProperty *class_prop) Iterate(class_prop); } -void ScopesInitPhaseETS::ParseGlobalClass(ir::ClassDefinition *global) +void InitScopesPhaseETS::ParseGlobalClass(ir::ClassDefinition *global) { for (auto decl : global->Body()) { if (decl->IsDefaultExported()) { @@ -1037,7 +1037,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 is_builtin = false; @@ -1081,12 +1081,12 @@ void ScopesInitPhaseETS::AddGlobalDeclaration(ir::AstNode *node) } } -void ScopesInitPhaseAS::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrow_expr) +void InitScopesPhaseAS::VisitArrowFunctionExpression(ir::ArrowFunctionExpression *arrow_expr) { Iterate(arrow_expr); } -void ScopesInitPhaseAS::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *export_decl) +void InitScopesPhaseAS::VisitExportNamedDeclaration(ir::ExportNamedDeclaration *export_decl) { ExportDeclarationContext export_decl_ctx(VarBinder()); Iterate(export_decl); diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h index b3f3f4de2f68c712dc3e4f3ec9bb0896547c21f9..99e824ccfd60fcef32b2de78be137a2a6663ea1a 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 *class_def) 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 *arrow_expr) 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 6cca648fb6cafafe144f1d1b3f88caf89dcb3cdf..4c7e2210f3e56ca68ad0132cfcbec0d0059f048e 100644 --- a/ets2panda/es2panda.h +++ b/ets2panda/es2panda.h @@ -103,6 +103,8 @@ struct CompilerOptions { std::string ts_decl_out {}; std::vector plugins {}; std::unordered_set skip_phases {}; + std::unordered_set verifier_warnings {}; + std::unordered_set verifier_errors {}; std::unordered_set dump_before_phases {}; std::unordered_set dump_ets_src_before_phases {}; std::unordered_set dump_after_phases {}; diff --git a/ets2panda/ir/ets/etsNewClassInstanceExpression.h b/ets2panda/ir/ets/etsNewClassInstanceExpression.h index 031531ca7439447d3bcfe41b3ee65cbbdda62ab0..6f4dd092a43abb3cb526868e626208f2f06ef7d5 100644 --- a/ets2panda/ir/ets/etsNewClassInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewClassInstanceExpression.h @@ -70,11 +70,16 @@ public: return type_reference_; } - [[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 52ce8c729c57643805777200483a13b93f997c41..f0bb73c1d4cfb9a894318b899e121a363fdb429e 100644 --- a/ets2panda/ir/ets/etsScript.h +++ b/ets2panda/ir/ets/etsScript.h @@ -29,6 +29,7 @@ public: explicit ETSScript(ArenaAllocator *allocator, ArenaVector &&statement_list, parser::Program *program) : BlockStatement(allocator, std::move(statement_list)), program_(program) { + type_ = AstNodeType::ETS_SCRIPT; } parser::Program *Program() diff --git a/ets2panda/ir/ets/etsTuple.cpp b/ets2panda/ir/ets/etsTuple.cpp index 13c879a2bf986a895be1aee3b7b2a3438c5d4d43..fd230df186fea9183cf1ab01c99a0393496287c0 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 type_annot : type_annotation_list_) { + for (const auto *const type_annot : type_annotation_list_) { type_annot->Dump(dumper); - if (type_annot != type_annotation_list_.back() || spread_type_ != nullptr) { + if ((type_annot != type_annotation_list_.back()) || (spread_type_ != nullptr)) { dumper->Add(", "); } } @@ -63,7 +63,7 @@ void ETSTuple::Dump(ir::SrcDumper *const dumper) const dumper->Add("..."); spread_type_->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 &contains_null_or_undefined, const checker::Type *const type) +{ + if (type->HasTypeFlag(checker::TypeFlag::NULLISH)) { + contains_null_or_undefined.first = true; + } + + if (type->HasTypeFlag(checker::TypeFlag::UNDEFINED)) { + contains_null_or_undefined.second = true; + } +} + checker::Type *ETSTuple::CalculateLUBForTuple(checker::ETSChecker *const checker, ArenaVector &type_list, checker::Type *const spread_type) { @@ -86,11 +97,17 @@ checker::Type *ETSTuple::CalculateLUBForTuple(checker::ETSChecker *const checker return spread_type == nullptr ? checker->GlobalETSObjectType() : spread_type; } - bool all_elements_are_same = std::all_of(type_list.begin(), type_list.end(), [&checker, &type_list](auto *element) { - return checker->Relation()->IsIdenticalTo(type_list[0], element); - }); + std::pair contains_null_or_undefined = {false, false}; + + bool all_elements_are_same = + std::all_of(type_list.begin(), type_list.end(), + [this, &checker, &type_list, &contains_null_or_undefined](checker::Type *const element) { + SetNullUndefinedFlags(contains_null_or_undefined, element); + return checker->Relation()->IsIdenticalTo(type_list[0], element); + }); if (spread_type != nullptr) { + SetNullUndefinedFlags(contains_null_or_undefined, spread_type); all_elements_are_same = all_elements_are_same && checker->Relation()->IsIdenticalTo(type_list[0], spread_type); } @@ -121,6 +138,16 @@ checker::Type *ETSTuple::CalculateLUBForTuple(checker::ETSChecker *const checker lub_type = checker->FindLeastUpperBound(lub_type, get_boxed_type_or_type(spread_type)); } + const auto nullish_undefined_flags = + (contains_null_or_undefined.first ? checker::TypeFlag::NULLISH | checker::TypeFlag::NULL_TYPE + : checker::TypeFlag::NONE) | + (contains_null_or_undefined.second ? checker::TypeFlag::UNDEFINED : checker::TypeFlag::NONE); + + if (nullish_undefined_flags != checker::TypeFlag::NONE) { + lub_type = checker->CreateNullishType(lub_type, nullish_undefined_flags, checker->Allocator(), + checker->Relation(), checker->GetGlobalTypesHolder()); + } + checker->Relation()->SetNode(saved_relation_node); return lub_type; diff --git a/ets2panda/ir/ets/etsTuple.h b/ets2panda/ir/ets/etsTuple.h index ce5af95a3a0f5c6d5b0e5f54a00b1de519257fd6..d9572b2b57099605e829877c9aa52fe50eb272cd 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 &contains_null_or_undefined, const checker::Type *type); checker::Type *CalculateLUBForTuple(checker::ETSChecker *checker, ArenaVector &type_list, checker::Type *spread_type); diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index b1b2ef87a7e0a3a03a1d4e129890ab665c9ef780..575c72d4b7e98c28d3a826c062bca9de4a52ee41 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -379,4 +379,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 (preferred_type_ != nullptr) { + return; + } + auto param_type = param->Check(checker); + if (param_type->IsETSArrayType()) { + param_type = param_type->AsETSArrayType()->ElementType(); + } + bool is_assignable = true; + for (auto elem : elements_) { + auto assign_ctx = checker::AssignmentContext(checker->Relation(), elem, elem->Check(checker), param_type, + elem->Start(), {""}, checker::TypeRelationFlag::NO_THROW | flags); + is_assignable &= assign_ctx.IsAssignable(); + } + if (is_assignable) { + preferred_type_ = param->Check(checker); + } +} + } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index cd5f4132d0dc8e5926802fea3e3e1f635875516e..f2699692ac4b351465e1c708a25fbaaf2ba3596e 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 68cfc53cbbf0fc54e86e521c87f8911b0e073153..1ff530e538cb15e5bc2d771f89f3624d0328a6b3 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) { unchecked_type_ = 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 a0d0c168b6afb63b6b6979801f32fbb9a6aa9d5a..319538c67e659b6ad2f4840782a46629b515e4d2 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 is_const, bool is_static = false) + bool is_const, bool is_static = false, bool is_declare = false) : TypedStatement(AstNodeType::TS_ENUM_DECLARATION), decorators_(allocator->Adapter()), key_(key), members_(std::move(members)), - is_const_(is_const) + is_const_(is_const), + is_declare_(is_declare) { if (is_static) { AddModifier(ModifierFlags::STATIC); } + if (is_declare) { + AddModifier(ModifierFlags::DECLARE); + } } bool IsScopeBearer() const override @@ -88,6 +92,11 @@ public: return is_const_; } + bool IsDeclare() const + { + return is_declare_; + } + const ArenaVector &Decorators() const { return decorators_; @@ -131,6 +140,7 @@ private: ArenaVector members_; util::StringView internal_name_; bool is_const_; + bool is_declare_; }; } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeAliasDeclaration.h b/ets2panda/ir/ts/tsTypeAliasDeclaration.h index 9c4415dd5a00d0716340b10c786ec83b63ccaa03..ef4ddcb84c6549e4c25164b7e7056720623cbb5b 100644 --- a/ets2panda/ir/ts/tsTypeAliasDeclaration.h +++ b/ets2panda/ir/ts/tsTypeAliasDeclaration.h @@ -34,6 +34,7 @@ public: decorators_(allocator->Adapter()), id_(id), type_params_(type_params), + type_param_types_(allocator->Adapter()), declare_(declare) { } @@ -43,6 +44,7 @@ public: decorators_(allocator->Adapter()), id_(id), type_params_(nullptr), + type_param_types_(allocator->Adapter()), declare_(false) { } @@ -57,7 +59,7 @@ public: return id_; } - const TSTypeParameterDeclaration *TypeParams() const + TSTypeParameterDeclaration *TypeParams() const { return type_params_; } @@ -77,7 +79,7 @@ public: return &Decorators(); } - void AddTypeParameters(ir::TSTypeParameterDeclaration *type_params) + void SetTypeParameters(ir::TSTypeParameterDeclaration *type_params) { type_params_ = type_params; } @@ -92,6 +94,16 @@ public: return !in_ts; } + void SetTypeParameterTypes(ArenaVector &&type_param_types) + { + type_param_types_ = std::move(type_param_types); + } + + ArenaVector const &TypeParameterTypes() const + { + return type_param_types_; + } + 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 *type_params_; + ArenaVector type_param_types_; bool declare_; }; } // namespace panda::es2panda::ir diff --git a/ets2panda/lexer/ETSLexer.h b/ets2panda/lexer/ETSLexer.h index 6c7c7b43e9dbfd0973688763c19f02a692152add..1349e8a8ad188437d4541ea2ebf4bf0fdb2bf980 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 saved_lexer_position = Save(); + + bool allow_bigint = false; + if (Iterator().Peek() == LEX_CHAR_LOWERCASE_N) { + // 0n is the only allowed bigint literal with leading 0 + allow_bigint = true; + } + try { ScanNumberLeadingZeroImpl(); } catch (...) { Rewind(saved_lexer_position); ScanNumberLeadingZeroImpl(); } + + if ((GetToken().flags_ & TokenFlags::NUMBER_BIGINT) != 0) { + if (!allow_bigint) { + 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 b74d7243cfdcd8b053f88e653d2fe4f53ef430c0..e3e06504f702132fb15fe003ac85825555be43e9 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,7 +1351,9 @@ ir::AstNode *ASParser::ParseImportDefaultSpecifier(ArenaVector *s return nullptr; } -ir::Expression *ASParser::ParseCoverParenthesizedExpressionAndArrowParameterList() +// 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(); diff --git a/ets2panda/parser/ASparser.h b/ets2panda/parser/ASparser.h index dbbf869c47b5cd21e5c28977b10a79b1d1a5fea0..fc7cdf98b60312ef2e4aa410d0f3dcc64e0415ed 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 { @@ -74,7 +75,9 @@ private: const ArenaVector ¶ms, ParserStatus new_status, ParserStatus context_status) 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 *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 a78f3e1ad6e113215d15f1cfc2ece7331dcafdc5..1713410b68065a4cc9e93f7f8c50cf0d68a391bc 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -187,7 +187,9 @@ void ETSParser::ParseETSGlobalScript(lexer::SourcePosition start_loc, ArenaVecto end(items)); for (const auto &item : items) { - parsed_sources_.push_back(ResolveImportPath(item)); + auto resolved = ResolveImportPath(item); + resolved_parsed_sources_.emplace(item, resolved); + parsed_sources_.push_back(resolved); } }; @@ -674,22 +676,6 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVector global_properties(Allocator()->Adapter()); field_map_.clear(); export_name_map_.clear(); - bool default_export = false; - - using ParserFunctionPtr = std::function; - auto const parse_type = [this, &statements, &default_export](std::size_t const current_pos, - ParserFunctionPtr const &parser_function) -> void { - ir::Statement *node = nullptr; - - node = parser_function(this); - if (node != nullptr) { - if (current_pos != std::numeric_limits::max()) { - MarkNodeAsExported(node, node->Start(), default_export); - default_export = 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 @@ -700,6 +686,43 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVector &statements, bool &default_export, + std::size_t const current_pos, + std::function const &parser_function) +{ + ir::Statement *node = nullptr; + + node = parser_function(this); + if (node != nullptr) { + if (current_pos != std::numeric_limits::max()) { + MarkNodeAsExported(node, node->Start(), default_export); + default_export = false; + } + statements.push_back(node); + } +} + +void ETSParser::ParseTopLevelNextToken(ArenaVector &statements, + ArenaVector &global_properties, ir::ScriptFunction *init_function) +{ + bool default_export = false; + while (Lexer()->GetToken().Type() != lexer::TokenType::EOS) { if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { Lexer()->NextToken(); @@ -740,44 +763,20 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVectorNextToken(); auto *member_name = ExpectIdentifier(); - ParseClassFieldDefiniton(member_name, member_modifiers, &global_properties, init_function, &start_loc); + ParseClassFieldDefinition(member_name, member_modifiers, &global_properties, init_function, &start_loc); break; } case lexer::TokenType::KEYW_ASYNC: case lexer::TokenType::KEYW_NATIVE: { - bool is_async = token_type == lexer::TokenType::KEYW_ASYNC; - - if (is_async) { - member_modifiers |= ir::ModifierFlags::ASYNC; - } else { - member_modifiers |= ir::ModifierFlags::NATIVE; - } - - Lexer()->NextToken(); - - if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION) { - ThrowSyntaxError( - {is_async ? "'async'" : "'native'", " flags must be used for functions at top-level."}); - } + ParseTokenOfNative(token_type, member_modifiers); [[fallthrough]]; } case lexer::TokenType::KEYW_FUNCTION: { - Lexer()->NextToken(); - // check whether it is an extension function - ir::Identifier *class_name = nullptr; - if (Lexer()->Lookahead() == lexer::LEX_CHAR_DOT) { - class_name = ExpectIdentifier(); - Lexer()->NextToken(); - } - - auto *member_name = ExpectIdentifier(); - auto *class_method = ParseClassMethodDefinition(member_name, member_modifiers, class_name); - class_method->SetStart(start_loc); - if (!class_method->Function()->IsOverload()) { - global_properties.push_back(class_method); - } + ParseTokenOfFunction(member_modifiers, start_loc, global_properties); break; } + case lexer::TokenType::KEYW_NAMESPACE: + [[fallthrough]]; case lexer::TokenType::KEYW_STATIC: [[fallthrough]]; case lexer::TokenType::KEYW_ABSTRACT: @@ -789,18 +788,21 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVectorParseTypeDeclaration(false); }); + ParseTopLevelType(statements, default_export, current_pos, + [](ETSParser *obj) { return obj->ParseTypeDeclaration(false); }); break; } @@ -825,18 +827,42 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVectorNextToken(); + + if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION) { + ThrowSyntaxError({is_async ? "'async'" : "'native'", " flags must be used for functions at top-level."}); + } +} + +void ETSParser::ParseTokenOfFunction(ir::ModifierFlags member_modifiers, lexer::SourcePosition start_loc, + ArenaVector &global_properties) +{ + Lexer()->NextToken(); + // check whether it is an extension function + ir::Identifier *class_name = nullptr; + if (Lexer()->Lookahead() == lexer::LEX_CHAR_DOT) { + class_name = ExpectIdentifier(); + Lexer()->NextToken(); + } + + auto *member_name = ExpectIdentifier(); + auto *class_method = ParseClassMethodDefinition(member_name, member_modifiers, class_name); + class_method->SetStart(start_loc); + if (!class_method->Function()->IsOverload()) { + global_properties.push_back(class_method); } - return global_properties; } // NOLINTNEXTLINE(google-default-arguments) @@ -1262,9 +1288,9 @@ ir::ModifierFlags ETSParser::ParseClassMethodModifiers(bool seen_static) } // NOLINTNEXTLINE(google-default-arguments) -void ETSParser::ParseClassFieldDefiniton(ir::Identifier *field_name, ir::ModifierFlags modifiers, - ArenaVector *declarations, ir::ScriptFunction *init_function, - lexer::SourcePosition *let_loc) +void ETSParser::ParseClassFieldDefinition(ir::Identifier *field_name, ir::ModifierFlags modifiers, + ArenaVector *declarations, ir::ScriptFunction *init_function, + lexer::SourcePosition *let_loc) { lexer::SourcePosition start_loc = let_loc != nullptr ? *let_loc : Lexer()->GetToken().Start(); lexer::SourcePosition end_loc = start_loc; @@ -1288,28 +1314,7 @@ void ETSParser::ParseClassFieldDefiniton(ir::Identifier *field_name, ir::Modifie // performed multiple times. if (init_function != nullptr && (modifiers & ir::ModifierFlags::CONST) == 0U && initializer != nullptr && !initializer->IsArrowFunctionExpression()) { - if (auto *const func_body = init_function->Body(); func_body != nullptr && func_body->IsBlockStatement()) { - auto *ident = AllocNode(field_name->Name(), Allocator()); - ident->SetReference(); - ident->SetRange(field_name->Range()); - - auto *assignment_expression = - AllocNode(ident, initializer, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - end_loc = initializer->End(); - assignment_expression->SetRange({field_name->Start(), end_loc}); - assignment_expression->SetParent(func_body); - - auto expression_statement = AllocNode(assignment_expression); - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { - end_loc = Lexer()->GetToken().End(); - } - expression_statement->SetRange({start_loc, end_loc}); - func_body->AsBlockStatement()->Statements().emplace_back(expression_statement); - - if (type_annotation != nullptr && !type_annotation->IsETSFunctionType()) { - initializer = nullptr; - } - } + end_loc = InitializeGlobalVariable(field_name, initializer, init_function, start_loc, type_annotation); } bool is_declare = (modifiers & ir::ModifierFlags::DECLARE) != 0; @@ -1332,10 +1337,42 @@ void ETSParser::ParseClassFieldDefiniton(ir::Identifier *field_name, ir::Modifie if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { Lexer()->NextToken(); ir::Identifier *next_name = ExpectIdentifier(false, true); - ParseClassFieldDefiniton(next_name, modifiers, declarations); + ParseClassFieldDefinition(next_name, modifiers, declarations); } } +lexer::SourcePosition ETSParser::InitializeGlobalVariable(ir::Identifier *field_name, ir::Expression *&initializer, + ir::ScriptFunction *init_function, + lexer::SourcePosition &start_loc, + ir::TypeNode *type_annotation) +{ + lexer::SourcePosition end_loc = start_loc; + + if (auto *const func_body = init_function->Body(); func_body != nullptr && func_body->IsBlockStatement()) { + auto *ident = AllocNode(field_name->Name(), Allocator()); + ident->SetReference(); + ident->SetRange(field_name->Range()); + + auto *assignment_expression = + AllocNode(ident, initializer, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + end_loc = initializer->End(); + assignment_expression->SetRange({field_name->Start(), end_loc}); + assignment_expression->SetParent(func_body); + + auto expression_statement = AllocNode(assignment_expression); + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { + end_loc = Lexer()->GetToken().End(); + } + expression_statement->SetRange({start_loc, end_loc}); + func_body->AsBlockStatement()->Statements().emplace_back(expression_statement); + + if (type_annotation != nullptr && !type_annotation->IsETSFunctionType()) { + initializer = nullptr; + } + } + return end_loc; +} + ir::MethodDefinition *ETSParser::ParseClassMethodDefinition(ir::Identifier *method_name, ir::ModifierFlags modifiers, ir::Identifier *class_name, ir::Identifier *ident_node) { @@ -1550,8 +1587,10 @@ ir::AstNode *ETSParser::ParseClassElement([[maybe_unused]] const ArenaVectorRewind(saved_pos); @@ -1576,6 +1615,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 *member_name = ExpectIdentifier(); if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS || Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { @@ -1620,7 +1670,7 @@ ir::AstNode *ETSParser::ParseClassElement([[maybe_unused]] const ArenaVector field_declarations(Allocator()->Adapter()); auto *placeholder = AllocNode(std::move(field_declarations)); - ParseClassFieldDefiniton(member_name, memberModifiers, placeholder->BodyPtr()); + ParseClassFieldDefinition(member_name, memberModifiers, placeholder->BodyPtr()); return placeholder; } @@ -1726,6 +1776,15 @@ ir::Statement *ETSParser::ParseTypeDeclaration(bool allow_static) 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); } @@ -1800,7 +1859,7 @@ ir::TSTypeAliasDeclaration *ETSParser::ParseTypeAliasDeclaration() auto options = TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE; ir::TSTypeParameterDeclaration *params = ParseTypeParameterDeclaration(&options); - type_alias_decl->AddTypeParameters(params); + type_alias_decl->SetTypeParameters(params); params->SetParent(type_alias_decl); } @@ -2318,7 +2377,20 @@ std::string ETSParser::GetNameForTypeNode(const ir::TypeNode *type_annotation, b } if (type_annotation->IsETSTypeReference()) { - return adjust_nullish(type_annotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8()); + std::string type_param_names; + auto type_param = type_annotation->AsETSTypeReference()->Part()->TypeParams(); + if (type_param != nullptr && type_param->IsTSTypeParameterInstantiation()) { + type_param_names = "<"; + auto param_list = type_param->Params(); + for (auto param : param_list) { + std::string type_param_name = GetNameForTypeNode(param); + type_param_names += type_param_name + ","; + } + type_param_names.pop_back(); + type_param_names += ">"; + } + return adjust_nullish(type_annotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8() + + type_param_names); } if (type_annotation->IsETSFunctionType()) { @@ -2742,17 +2814,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) { - type_annotation = ParseWildcardType(options); - } else { - if (Lexer()->GetToken().IsDefinableTypeName()) { - type_annotation = GetTypeAnnotationOfPrimitiveType(Lexer()->GetToken().KeywordType(), options); - } else { - type_annotation = ParseTypeReference(options); - } - } - + type_annotation = ParseLiteralIdent(options); if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 && (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) { return std::make_pair(type_annotation, false); @@ -2811,17 +2873,7 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota type_annotation = ParseUnionType(type_annotation); } - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - if (((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0) { - ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); - } - - Lexer()->Rewind(saved_pos); - type_annotation = nullptr; - } else { - Lexer()->NextToken(); // eat ')' - } - + ParseRightParenthesis(options, type_annotation, saved_pos); break; } case lexer::TokenType::PUNCTUATOR_FORMAT: { @@ -2844,6 +2896,35 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota return std::make_pair(type_annotation, 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 *&type_annotation, + lexer::LexerPosition saved_pos) +{ + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + if (((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0) { + ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); + } + + Lexer()->Rewind(saved_pos); + type_annotation = nullptr; + } else { + Lexer()->NextToken(); // eat ')' + } +} + ir::TypeNode *ETSParser::ParseThisType(TypeAnnotationParsingOptions *options) { ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS); @@ -3806,7 +3887,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(); @@ -3907,7 +3988,8 @@ ir::ArrowFunctionExpression *ETSParser::ParseArrowFunctionExpression() return arrow_func_node; } -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()) { @@ -3917,7 +3999,12 @@ ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterLis lexer::SourcePosition start = Lexer()->GetToken().Start(); Lexer()->NextToken(); - ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); + ExpressionParseFlags new_flags = ExpressionParseFlags::ACCEPT_COMMA; + if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) { + new_flags |= ExpressionParseFlags::INSTANCEOF; + }; + + ir::Expression *expr = ParseExpression(new_flags); if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { ThrowSyntaxError("Unexpected token, expected ')'"); @@ -4289,7 +4376,7 @@ ir::TSEnumDeclaration *ETSParser::ParseEnumMembers(ir::Identifier *const key, co } auto *const enum_declaration = - AllocNode(Allocator(), key, std::move(members), is_const, is_static); + AllocNode(Allocator(), key, std::move(members), is_const, is_static, InAmbientContext()); enum_declaration->SetRange({enum_start, Lexer()->GetToken().End()}); Lexer()->NextToken(); // eat '}' @@ -4595,6 +4682,24 @@ bool ETSParser::IsStructKeyword() const Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT); } +void ETSParser::ValidateInstanceOfExpression(ir::Expression *expr) +{ + ValidateGroupedExpression(expr); + lexer::TokenType token_type = Lexer()->GetToken().Type(); + if (token_type == 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) { @@ -4606,6 +4711,10 @@ ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) } ir::Expression *unary_expression_node = ParseUnaryOrPrefixUpdateExpression(flags); + if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) { + ValidateInstanceOfExpression(unary_expression_node); + } + ir::Expression *assignment_expression = ParseAssignmentExpression(unary_expression_node, flags); if (Lexer()->GetToken().NewLine()) { @@ -4663,6 +4772,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 ec1f1667deb052eee62f72a357e7df09efcd3354..e95f4dbdb441bd93c01a2dccc00aebc533dbbcf2 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 &source_file) override; void ParsePackageDeclaration(ArenaVector &statements); ArenaVector ParseTopLevelStatements(ArenaVector &statements); + void ParseTopLevelType(ArenaVector &statements, bool &default_export, std::size_t current_pos, + std::function const &parser_function); + void ParseTopLevelNextToken(ArenaVector &statements, ArenaVector &global_properties, + ir::ScriptFunction *init_function); + void ParseTokenOfNative(panda::es2panda::lexer::TokenType token_type, ir::ModifierFlags &member_modifiers); + void ParseTokenOfFunction(ir::ModifierFlags member_modifiers, lexer::SourcePosition start_loc, + ArenaVector &global_properties); #ifdef USE_FTW static int NFTWCallBack(const char *fpath, const struct stat * /*unused*/, int tflag, struct FTW * /*unused*/); #endif @@ -159,9 +167,13 @@ private: ir::Expression *CreateParameterThis(util::StringView class_name) override; // NOLINTNEXTLINE(google-default-arguments) - void ParseClassFieldDefiniton(ir::Identifier *field_name, ir::ModifierFlags modifiers, - ArenaVector *declarations, ir::ScriptFunction *init_function = nullptr, - lexer::SourcePosition *let_loc = nullptr); + void ParseClassFieldDefinition(ir::Identifier *field_name, ir::ModifierFlags modifiers, + ArenaVector *declarations, + ir::ScriptFunction *init_function = nullptr, + lexer::SourcePosition *let_loc = nullptr); + lexer::SourcePosition InitializeGlobalVariable(ir::Identifier *field_name, ir::Expression *&initializer, + ir::ScriptFunction *init_function, lexer::SourcePosition &start_loc, + ir::TypeNode *type_annotation); std::tuple ParseTypeReferencePart( TypeAnnotationParsingOptions *options); ir::TypeNode *ParseTypeReference(TypeAnnotationParsingOptions *options); @@ -187,12 +199,17 @@ private: void ThrowIfVarDeclaration(VariableParsingFlags flags) override; std::pair GetTypeAnnotationFromToken(TypeAnnotationParsingOptions *options); + ir::TypeNode *ParseLiteralIdent(TypeAnnotationParsingOptions *options); + void ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&type_annotation, + lexer::LexerPosition saved_pos); 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 start_loc); @@ -264,6 +281,7 @@ private: // NOLINTNEXTLINE(google-default-arguments) ir::Statement *ParseEnumDeclaration(bool is_const = false, bool is_static = 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; @@ -339,6 +357,7 @@ private: ir::TypeNode *CreateTypeAnnotation(TypeAnnotationParsingOptions *options, std::string_view source_code, std::string_view file_name = 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 29781c637d7d2150844d17df54056bc6c62d30b3..3204d0899d76ed71132839279d886c6058a419b4 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" @@ -2600,7 +2601,9 @@ ir::Statement *TSParser::ParseExportDeclaration(StatementParsingFlags flags) } } -ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList() +// 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(); diff --git a/ets2panda/parser/TSparser.h b/ets2panda/parser/TSparser.h index 376f7f0a2e01c7cc97b2351ee61206e29892fc6a..3e660ea9a05fe04b05dc79326fd7eff901e8560d 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; @@ -123,7 +124,9 @@ private: const ArenaVector ¶ms, ParserStatus new_status, ParserStatus context_status) 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::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 2751b480bede62fcf99825648b99619e7c7f01c3..631188ce5dae106f7561cc0ba7d31529c45f9966 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 09d10d86420b3643c2eb22ddbd82dfd9f3ae0726..ecfdfd2f8322f71a25530bd8504a1a551483f0e3 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 *lhs_expression) +{ + lexer::TokenType token_type = lexer_->GetToken().Type(); + if (lhs_expression->IsGrouped() && token_type != lexer::TokenType::PUNCTUATOR_ARROW) { + if (lhs_expression->IsSequenceExpression()) { + for (auto *seq : lhs_expression->AsSequenceExpression()->Sequence()) { + ValidateParenthesizedExpression(seq); + } + } else { + ValidateParenthesizedExpression(lhs_expression); + } + } +} + void ParserImpl::ValidateParenthesizedExpression(ir::Expression *lhs_expression) { switch (lhs_expression->Type()) { @@ -542,17 +558,9 @@ ir::Expression *ParserImpl::ParsePrefixAssertionExpression() ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhs_expression, ExpressionParseFlags flags) { - lexer::TokenType token_type = lexer_->GetToken().Type(); - if (lhs_expression->IsGrouped() && token_type != lexer::TokenType::PUNCTUATOR_ARROW) { - if (lhs_expression->IsSequenceExpression()) { - for (auto *seq : lhs_expression->AsSequenceExpression()->Sequence()) { - ValidateParenthesizedExpression(seq); - } - } else { - ValidateParenthesizedExpression(lhs_expression); - } - } + ValidateGroupedExpression(lhs_expression); + lexer::TokenType token_type = lexer_->GetToken().Type(); switch (token_type) { case lexer::TokenType::PUNCTUATOR_QUESTION_MARK: { lexer_->NextToken(); @@ -1191,7 +1199,7 @@ void ParserImpl::CreateAmendedBinaryExpression(ir::Expression *const left, ir::E SetAmendedChildExpression(right, binary_expr); } -ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left) +ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left, ExpressionParseFlags flags) { lexer::TokenType operator_type = lexer_->GetToken().Type(); ASSERT(lexer::Token::IsBinaryToken(operator_type)); @@ -1206,7 +1214,12 @@ ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left) lexer_->NextToken(); - ir::Expression *right_expr = ParseExpression(ExpressionParseFlags::DISALLOW_YIELD); + ExpressionParseFlags new_flags = ExpressionParseFlags::DISALLOW_YIELD; + if ((operator_type == lexer::TokenType::KEYW_INSTANCEOF) || ((flags & ExpressionParseFlags::INSTANCEOF) != 0)) { + new_flags |= ExpressionParseFlags::INSTANCEOF; + } + + ir::Expression *right_expr = ParseExpression(new_flags); ir::ConditionalExpression *conditional_expr = nullptr; if (right_expr->IsConditionalExpression() && !right_expr->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 b6f43c047163d472e6f34e8547e23f66545060de..7d0d74e3d98931fc13b5191690aa639ef5f7b369 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -229,13 +229,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 *return_expression, bool is_chain_expression); ir::Expression *ParseMemberExpression(bool ignore_call_expression = false, ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); ir::MetaProperty *ParsePotentialNewTarget(); void CheckInvalidDestructuring(const ir::AstNode *object) const; void ValidateParenthesizedExpression(ir::Expression *lhs_expression); + void ValidateGroupedExpression(ir::Expression *lhs_expression); ir::Expression *ParseImportExpression(); ir::Expression *ParseOptionalChain(ir::Expression *left_side_expr); ir::Expression *ParsePropertyKey(ExpressionParseFlags flags); @@ -482,7 +484,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 **prop_name); // NOLINTNEXTLINE(google-default-arguments) diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 84ab4a84a633cc8dbb6a0102f07c718c6f998cd8..2d48fdcc040e72d2fc6df55c7acb7751416ae2e9 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 scopes_init; + compiler::InitScopesPhaseETS scopes_init; scopes_init.Perform(ctx, ctx->parser_program); do { if (ctx->current_phase >= 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..5c09324c73c9a65d126c415696b3276b2640b7e5 --- /dev/null +++ b/ets2panda/test/runtime/ets/array_inf.ets @@ -0,0 +1,27 @@ +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 0ef51a441e77b3057fb83bf1485fcf9e5cc19eae..cb28d6709df88dba29f9658d930f32fb249c7237 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 a55b4e18de0cb895e2d72454016add6bef801213..55aeb0dec9f3d2ae27bc56211bd73e33f0994502 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 for_node = NodeGen().CreateForUpdate(); - compiler::ScopesInitPhaseETS::RunExternalNode(for_node, &varbinder); + compiler::InitScopesPhaseETS::RunExternalNode(for_node, &varbinder); auto block_scope = for_node->Body()->AsBlockStatement()->Scope(); auto loop_scope = for_node->Scope(); @@ -111,7 +111,7 @@ TEST_F(ScopesInitPhaseTest, CreateWhile) auto varbinder = varbinder::VarBinder(Allocator()); auto while_node = NodeGen().CreateWhile(); - compiler::ScopesInitPhaseETS::RunExternalNode(while_node, &varbinder); + compiler::InitScopesPhaseETS::RunExternalNode(while_node, &varbinder); auto while_scope = while_node->Scope(); auto body_scope = while_node->Body()->AsBlockStatement()->Scope(); @@ -124,4 +124,4 @@ TEST_F(ScopesInitPhaseTest, CreateWhile) ASSERT_EQ(body_bindings.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 dc3414ba7c3f6e0a0e902e79482821719d2a0fac..fdfbb06ceaca0d7e07d9ee76dad19aa6976f21bc 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 empty_node; - - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("HasParent"); - bool has_parent = verifier.Verify(&empty_node, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; - - ASSERT_EQ(has_parent, false); - ASSERT_EQ(errors.size(), 1); - ASSERT_EQ(name, "HasParent"); - ASSERT_EQ(error.message, "NULL_PARENT: STR_LITERAL "); + ASTVerifier verifier {Allocator()}; + StringLiteral empty_node; + + const auto check = "NodeHasParent"; + auto checks = ASTVerifier::InvariantSet {}; + checks.insert(check); + const auto [warnings, errors] = verifier.Verify({{"NodeHasParent"}}, {{}}, &empty_node, checks); + bool has_parent = warnings.empty(); + ASSERT_FALSE(has_parent); + 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 empty_node; - - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("HasType"); - bool has_type = verifier.Verify(&empty_node, checks); - const auto &errors = verifier.GetErrors(); - const auto [name, error] = errors[0]; - + ASTVerifier verifier {Allocator()}; + StringLiteral empty_node; + + auto check = "NodeHasType"; + auto checks = ASTVerifier::InvariantSet {}; + checks.insert(check); + const auto [warnings, errors] = verifier.Verify({{"NodeHasType"}}, {{}}, &empty_node, checks); + bool has_type = warnings.empty(); ASSERT_EQ(has_type, 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 empty_node; + ASTVerifier verifier {Allocator()}; + StringLiteral empty_node; - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("HasScope"); - bool has_scope = verifier.Verify(&empty_node, checks); - const auto &errors = verifier.GetErrors(); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("VariableHasScope"); + const auto [warnings, errors] = verifier.Verify({{"VariableHasScope"}}, {{}}, &empty_node, checks); - ASSERT_EQ(has_scope, 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 parent_scope(Allocator(), nullptr); + LocalScope scope(Allocator(), nullptr); + FunctionScope parent_scope(Allocator(), nullptr); scope.SetParent(&parent_scope); - 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 is_ok = verifier.Verify(&ident, checks); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("VariableHasScope"); + const auto [warnings, errors] = verifier.Verify({{"VariableHasScope"}}, {{}}, &ident, checks); - ASSERT_EQ(is_ok, 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 parent_scope(Allocator(), nullptr); + LocalScope scope(Allocator(), nullptr); + FunctionScope parent_scope(Allocator(), nullptr); scope.SetParent(&parent_scope); - scope.AddDecl(Allocator(), &decl, panda::es2panda::ScriptExtension::ETS); + scope.AddDecl(Allocator(), &decl, ScriptExtension::ETS); scope.BindNode(&ident); parent_scope.BindNode(&ident); local.SetScope(&scope); - auto checks = panda::es2panda::compiler::ASTVerifier::CheckSet {Allocator()->Adapter()}; - checks.insert("VerifyScopeNode"); - bool is_ok = verifier.Verify(&ident, checks); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("VariableHasEnclosingScope"); + const auto [warnings, errors] = verifier.Verify({{"VariableHasEnclosingScope"}}, {{}}, &ident, checks); - ASSERT_EQ(is_ok, 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 arithmetic_expression = - panda::es2panda::ir::BinaryExpression(&left, &right, panda::es2panda::lexer::TokenType::PUNCTUATOR_PLUS); + auto left = NumberLiteral(Number {1}); + auto right = NumberLiteral(Number {6}); + auto arithmetic_expression = 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 is_correct = verifier.Verify(arithmetic_expression.AsBinaryExpression(), checks); - ASSERT_EQ(is_correct, true); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("ArithmeticOperationValid"); + const auto [warnings, errors] = + verifier.Verify({{"ArithmeticOperationValid"}}, {{}}, arithmetic_expression.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 arithmetic_expression = - 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 arithmetic_expression = 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 is_correct = verifier.Verify(arithmetic_expression.AsBinaryExpression(), checks); - ASSERT_EQ(is_correct, true); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("ArithmeticOperationValid"); + const auto [warnings, errors] = + verifier.Verify({{"ArithmeticOperationValid"}}, {{}}, arithmetic_expression.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 left_param("1"); + const StringView left_param("1"); constexpr uint32_t RIGHT_PARAM = 1; - auto left = panda::es2panda::ir::StringLiteral(left_param); - auto right = panda::es2panda::ir::NumberLiteral(panda::es2panda::lexer::Number {RIGHT_PARAM}); - auto arithmetic_expression = - panda::es2panda::ir::BinaryExpression(&left, &right, panda::es2panda::lexer::TokenType::PUNCTUATOR_DIVIDE); + auto left = StringLiteral(left_param); + auto right = NumberLiteral(Number {RIGHT_PARAM}); + auto arithmetic_expression = 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 is_correct = verifier.Verify(arithmetic_expression.AsBinaryExpression(), checks); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("ArithmeticOperationValid"); + const auto [warnings, errors] = + verifier.Verify({{"ArithmeticOperationValid"}}, {{}}, arithmetic_expression.AsBinaryExpression(), checks); - ASSERT_EQ(is_correct, 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 arithmetic_expression = - 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 arithmetic_expression = 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 is_correct = verifier.Verify(arithmetic_expression.AsBinaryExpression(), checks); + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("ArithmeticOperationValid"); + const auto [warnings, errors] = + verifier.Verify({{"ArithmeticOperationValid"}}, {{}}, arithmetic_expression.AsBinaryExpression(), checks); - ASSERT_EQ(is_correct, false); + ASSERT_EQ(warnings.size(), 0); +} + +TEST_F(ASTVerifierTest, SequenceExpressionType) +{ + ASTVerifier verifier {Allocator()}; + auto checker = ETSChecker(); + auto *last = Tree(Node(Number {3})); + auto *sequence_expression = Tree(Node( + Nodes(Node(Number {1}), Node(Number {2}), last))); + + last->SetTsType(checker.GlobalIntType()); + sequence_expression->SetTsType(checker.GlobalIntType()); + + auto checks = ASTVerifier::InvariantSet {}; + checks.insert("SequenceExpressionHasLastType"); + const auto [warnings, errors] = + verifier.Verify({{"SequenceExpressionHasLastType"}}, {{}}, sequence_expression, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 is_correct = 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(is_correct, 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 6da53b1a0bbed13429a1f015ea7c33197ee3a60a..cbffadb1fd445630a1b796dc48840e4f111a6dc0 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 union_constituents1(checker.Allocator()->Adapter()); + union_constituents1.emplace_back(checker.GlobalBuiltinETSStringType()); + union_constituents1.emplace_back(checker.CreateETSStringLiteralType("abc")); + + // Create union type, which will be normalized inside creation function + auto *const normalized_type1 = checker.CreateETSUnionType(std::move(union_constituents1)); + ASSERT_NE(normalized_type1, nullptr); + ASSERT_TRUE(normalized_type1->IsETSObjectType()); + ASSERT_EQ(normalized_type1, checker.GlobalBuiltinETSStringType()); + + // Test normalization: "abc" | string | string ==> string + ArenaVector union_constituents2(checker.Allocator()->Adapter()); + union_constituents2.emplace_back(checker.CreateETSStringLiteralType("abc")); + union_constituents2.emplace_back(checker.GlobalBuiltinETSStringType()); + union_constituents2.emplace_back(checker.GlobalBuiltinETSStringType()); + + // Create union type, which will be normalized inside creation function + auto *const normalized_type2 = checker.CreateETSUnionType(std::move(union_constituents2)); + ASSERT_NE(normalized_type2, nullptr); + ASSERT_TRUE(normalized_type2->IsETSObjectType()); + ASSERT_EQ(normalized_type2, checker.GlobalBuiltinETSStringType()); + + // Test normalization: number | "abc" | string | "xy" ==> number | string + ArenaVector union_constituents3(checker.Allocator()->Adapter()); + union_constituents3.emplace_back(checker.GlobalDoubleType()); + union_constituents3.emplace_back(checker.CreateETSStringLiteralType("abc")); + union_constituents3.emplace_back(checker.GlobalBuiltinETSStringType()); + union_constituents3.emplace_back(checker.CreateETSStringLiteralType("xy")); + + // Create union type, which will be normalized inside creation function + auto *const normalized_type3 = checker.CreateETSUnionType(std::move(union_constituents3)); + ASSERT_NE(normalized_type3, nullptr); + ASSERT_TRUE(normalized_type3->IsETSUnionType()); + auto *const union_type = normalized_type3->AsETSUnionType(); + ASSERT_EQ(union_type->ConstituentTypes().size(), SIZE2); + ASSERT_EQ(union_type->ConstituentTypes().at(IDX0), checker.GetGlobalTypesHolder()->GlobalDoubleBuiltinType()); + ASSERT_EQ(union_type->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 ef9399af141efb46040113746838d7ebe48541ea..81bf6ab5277239f5040f02d4e8a8fdf2e36828da 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 gen_std_lib("gen-stdlib", false, "Gen standard library"); panda::PandArg plugins("plugins", "", "Plugins"); panda::PandArg skip_phases("skip-phases", "", "Phases to skip"); + panda::PandArg verifier_warnings("verifier-warnings", "", "Show warnings form verifier"); + panda::PandArg verifier_errors("verifier-errors", "", "Show warnings form verifier"); panda::PandArg dump_before_phases("dump-before-phases", "", "Generate program dump before running phases in the list"); panda::PandArg dump_ets_src_before_phases( @@ -222,6 +224,8 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&gen_std_lib); argparser_->Add(&plugins); argparser_->Add(&skip_phases); + argparser_->Add(&verifier_warnings); + argparser_->Add(&verifier_errors); argparser_->Add(&dump_before_phases); argparser_->Add(&dump_ets_src_before_phases); argparser_->Add(&dump_after_phases); @@ -420,6 +424,8 @@ bool Options::Parse(int argc, const char **argv) compiler_options_.is_ets_module = op_ets_module.GetValue(); compiler_options_.plugins = SplitToStringVector(plugins.GetValue()); compiler_options_.skip_phases = SplitToStringSet(skip_phases.GetValue()); + compiler_options_.verifier_warnings = SplitToStringSet(verifier_warnings.GetValue()); + compiler_options_.verifier_errors = SplitToStringSet(verifier_errors.GetValue()); compiler_options_.dump_before_phases = SplitToStringSet(dump_before_phases.GetValue()); compiler_options_.dump_ets_src_before_phases = SplitToStringSet(dump_ets_src_before_phases.GetValue()); compiler_options_.dump_after_phases = SplitToStringSet(dump_after_phases.GetValue()); diff --git a/ets2panda/varbinder/scope.cpp b/ets2panda/varbinder/scope.cpp index 7d685b6aa3439e9acc1d4260e72e85fd14256729..46c3c1366c19ee242cf4bc99a65e19554a1fa31b 100644 --- a/ets2panda/varbinder/scope.cpp +++ b/ets2panda/varbinder/scope.cpp @@ -744,8 +744,18 @@ Variable *ClassScope::AddBinding(ArenaAllocator *allocator, [[maybe_unused]] Var SetBindingProps(new_decl, &props, is_static); - if (FindLocal(new_decl->Name(), ResolveBindingOptions::ALL) != nullptr) { - return nullptr; + const auto *found_var = FindLocal(new_decl->Name(), ResolveBindingOptions::ALL); + if (found_var != nullptr) { + if (!new_decl->IsLetOrConstDecl()) { + return nullptr; + } + + found_var = FindLocal(new_decl->Name(), + ResolveBindingOptions::ALL ^ (is_static ? ResolveBindingOptions::VARIABLES + : ResolveBindingOptions::STATIC_VARIABLES)); + if (found_var != nullptr) { + return nullptr; + } } auto *var = props.GetTargetScope()->AddBinding(allocator, nullptr, new_decl, extension);