diff --git a/checker/ETSchecker.h b/checker/ETSchecker.h index 36f271d1606fb56f6c99b1abf297f02d08a50b26..992e8c1871737a497a0aa3940494fb08785f92d3 100644 --- a/checker/ETSchecker.h +++ b/checker/ETSchecker.h @@ -344,7 +344,7 @@ public: GlobalTypesHolder *globalTypes); private: - void CreateTypeForTypeParameters(ETSObjectType *type, ir::TSTypeParameterDeclaration *typeParams); + void CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration *typeParams); ETSObjectType *CheckException(checker::Type *type, lexer::SourcePosition pos, ETSObjectType *expected, std::string_view msg); ETSObjectType *CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *declNode, ETSObjectFlags flags); diff --git a/checker/ets/function.cpp b/checker/ets/function.cpp index ae9b0f3766148e4373f730520b30901d032d4036..552bdadbfb1a724e7c30a04342ddf24b17f00537 100644 --- a/checker/ets/function.cpp +++ b/checker/ets/function.cpp @@ -202,6 +202,10 @@ checker::ETSFunctionType *ETSChecker::BuildFunctionSignature(ir::ScriptFunction thisVar->SetTsType(Context().ContainingClass()); } + if (func->TypeParams() != nullptr) { + CreateTypeForTypeParameters(func->TypeParams()); + } + for (auto *it : func->Params()) { if (it->IsRestElement()) { auto *restParam = it->AsRestElement(); diff --git a/checker/ets/helpers.cpp b/checker/ets/helpers.cpp index 2ab32e5d2262c9d91aba651b1431a5c5a3d24ec9..ff7534f293e957813a33959cefbebacf50c5c084 100644 --- a/checker/ets/helpers.cpp +++ b/checker/ets/helpers.cpp @@ -311,7 +311,7 @@ Type *ETSChecker::ResolveIdentifier(ir::Identifier *ident) break; } - if (!resolvedType->IsETSObjectType() && !resolvedType->IsETSArrayType()) { + if (!resolvedType->IsETSObjectType() && !resolvedType->IsETSArrayType() && !resolvedType->IsETSTypeReference()) { resolved = nullptr; } diff --git a/checker/ets/object.cpp b/checker/ets/object.cpp index a8a18208d41ba0f8ca8d72c9c44041e887ff5cfc..a54f640942109c89d4791c8cd382261b6bc058a8 100644 --- a/checker/ets/object.cpp +++ b/checker/ets/object.cpp @@ -164,11 +164,8 @@ void ETSChecker::SetTypeParameterType(ir::TSTypeParameter *typeParam, Type *asse var->SetTsType(typeParamType); } -void ETSChecker::CreateTypeForTypeParameters(ETSObjectType *type, ir::TSTypeParameterDeclaration *typeParams) +void ETSChecker::CreateTypeForTypeParameters(ir::TSTypeParameterDeclaration *typeParams) { - if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS)) { - return; - } checker::ScopeContext scopeCtx(this, typeParams->Scope()); @@ -194,20 +191,30 @@ void ETSChecker::CreateTypeForTypeParameters(ETSObjectType *type, ir::TSTypePara SetTypeParameterType(param, paramType); } - - type->AddObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS); } void ETSChecker::CreateTypeForInterfaceTypeParameters(ETSObjectType *type) { + if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS)) { + return; + } + ir::TSTypeParameterDeclaration *typeParams = type->GetDeclNode()->AsTSInterfaceDeclaration()->TypeParams(); - CreateTypeForTypeParameters(type, typeParams); + CreateTypeForTypeParameters(typeParams); + + type->AddObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS); } void ETSChecker::CreateTypeForClassTypeParameters(ETSObjectType *type) { + if (type->HasObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS)) { + return; + } + ir::TSTypeParameterDeclaration *typeParams = type->GetDeclNode()->AsClassDefinition()->TypeParams(); - CreateTypeForTypeParameters(type, typeParams); + CreateTypeForTypeParameters(typeParams); + + type->AddObjectFlag(ETSObjectFlags::RESOLVED_TYPE_PARAMS); } ETSObjectType *ETSChecker::BuildInterfaceProperties(ir::TSInterfaceDeclaration *interfaceDecl) diff --git a/compiler/core/ETSGen.cpp b/compiler/core/ETSGen.cpp index 305570a35cde4ea6e28b7123e5e69f2aadd7f1a8..4a8b301f2c0b06d95c0ae72873575aa77e73d91e 100644 --- a/compiler/core/ETSGen.cpp +++ b/compiler/core/ETSGen.cpp @@ -1318,6 +1318,9 @@ void ETSGen::LoadArrayLength(const ir::AstNode *node, VReg arrayReg) void ETSGen::LoadArrayElement(const ir::AstNode *node, VReg objectReg) { auto *elementType = GetVRegType(objectReg)->AsETSArrayType()->ElementType(); + if (elementType->IsETSTypeReference()) { + elementType = Checker()->GlobalETSObjectType(); + } switch (checker::ETSChecker::ETSType(elementType)) { case checker::TypeFlag::ETS_BOOLEAN: @@ -1366,6 +1369,9 @@ void ETSGen::LoadArrayElement(const ir::AstNode *node, VReg objectReg) void ETSGen::StoreArrayElement(const ir::AstNode *node, VReg objectReg, VReg index) { auto *elementType = GetVRegType(objectReg)->AsETSArrayType()->ElementType(); + if (elementType->IsETSTypeReference()) { + elementType = Checker()->GlobalETSObjectType(); + } switch (checker::ETSChecker::ETSType(elementType)) { case checker::TypeFlag::ETS_BOOLEAN: diff --git a/compiler/core/ETSemitter.cpp b/compiler/core/ETSemitter.cpp index 9d80cc4cb739136f364afc43387b9e259a3c5e8f..db37eeced459b8f2d5af350e12dfbea9257caa85 100644 --- a/compiler/core/ETSemitter.cpp +++ b/compiler/core/ETSemitter.cpp @@ -455,9 +455,7 @@ void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool extern if (classDef->IsAbstract()) { accessFlags |= ACC_ABSTRACT; - } - - if (!classDef->IsOpen()) { + } else if (!classDef->IsOpen()) { accessFlags |= ACC_FINAL; } @@ -495,7 +493,7 @@ void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool extern std::vector annotations; if (classDef->TypeParams() != nullptr) { - annotations.emplace_back(GenAnnotationSignature(classDef)); + //annotations.emplace_back(GenAnnotationSignature(classDef)); } const ir::AstNode *parent = classDef->Parent(); diff --git a/ir/base/scriptFunction.h b/ir/base/scriptFunction.h index 1fb954d1a7be56344199d034db61bbb03e10d560..5582dc4da92c2497e85926a4312f0c015a18aea3 100644 --- a/ir/base/scriptFunction.h +++ b/ir/base/scriptFunction.h @@ -96,6 +96,11 @@ public: return typeParams_; } + TSTypeParameterDeclaration *TypeParams() + { + return typeParams_; + } + const AstNode *Body() const { return body_; diff --git a/ir/ets/etsNewClassInstanceExpression.cpp b/ir/ets/etsNewClassInstanceExpression.cpp index 7e80b1268f289a7132dfab7dc7b74a4c0e138cb3..b6eb97a50d92494c9b01df4b46153594fff44adf 100644 --- a/ir/ets/etsNewClassInstanceExpression.cpp +++ b/ir/ets/etsNewClassInstanceExpression.cpp @@ -62,6 +62,10 @@ checker::Type *ETSNewClassInstanceExpression::Check([[maybe_unused]] checker::ET { checker::Type *calleeType = typeReference_->Check(checker); + if (calleeType->IsETSTypeReference()) { + calleeType = checker->GlobalETSObjectType(); + } + if (!calleeType->IsETSObjectType()) { checker->ThrowTypeError("This expression is not constructible.", Start()); } diff --git a/ir/expressions/memberExpression.cpp b/ir/expressions/memberExpression.cpp index 63035683a83f4a572dd9b28939aa9046e5087594..a12d1ad7bbf1817f5a372fb44e16a870b679a1ea 100644 --- a/ir/expressions/memberExpression.cpp +++ b/ir/expressions/memberExpression.cpp @@ -239,7 +239,7 @@ checker::Type *MemberExpression::Check(checker::ETSChecker *checker) checker::Type *baseType = object_->Check(checker); - if (!baseType->IsETSObjectType()) { + if (!baseType->IsETSObjectType() && !baseType->IsETSTypeReference()) { if (baseType->IsETSArrayType() && property_->AsIdentifier()->Name().Is("length")) { SetTsType(checker->GlobalIntType()); return TsType(); @@ -248,7 +248,12 @@ checker::Type *MemberExpression::Check(checker::ETSChecker *checker) checker->ThrowTypeError({"Cannot access property of non-object type"}, object_->Start()); } - objType_ = baseType->AsETSObjectType(); + if (baseType->IsETSTypeReference()) { + objType_ = checker->GlobalETSObjectType(); + } else { + objType_ = baseType->AsETSObjectType(); + } + propVar_ = checker->ResolveMemberReference(this, objType_); checker->ValidatePropertyAccess(propVar_, objType_, property_->Start()); SetTsType(checker->GetTypeOfVariable(propVar_)); diff --git a/ir/statements/returnStatement.cpp b/ir/statements/returnStatement.cpp index 4ef5420fa4eef27b6eac5fc44c72bdcab694ec65..065f7901c78a7c9486934116de78b8c3581a66ec 100644 --- a/ir/statements/returnStatement.cpp +++ b/ir/statements/returnStatement.cpp @@ -146,6 +146,15 @@ checker::Type *ReturnStatement::Check(checker::ETSChecker *checker) ASSERT(argument_); checker::Type *returnType = argument_->Check(checker); + + if (funcReturnType->IsETSTypeReference()) { + funcReturnType = checker->GlobalETSObjectType(); + } + + if (returnType->IsETSTypeReference()) { + returnType = checker->GlobalETSObjectType(); + } + checker::AssignmentContext( checker->Relation(), argument_, returnType, funcReturnType, argument_->Start(), {"Return statements return type is not compatible with the containing functions return type"}, diff --git a/parser/ETSparser.cpp b/parser/ETSparser.cpp index 98bc8cf0ae47c67ade776ddfd46cf42858565cd4..2d8ef9c21646e03758213e2a48bfb5722a323bea 100644 --- a/parser/ETSparser.cpp +++ b/parser/ETSparser.cpp @@ -336,8 +336,6 @@ ArenaVector ETSParser::ParseTopLevelStatements(ArenaVectorNextToken(); auto *memberName = ExpectIdentifier(); - - ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS, false); auto classCtx = binder::LexicalScope::Enter(Binder(), GetProgram()->GlobalClassScope()); auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers); @@ -540,8 +538,10 @@ ir::ModifierFlags ETSParser::ParseClassModifiers() std::tuple ETSParser::ParseClassImplementsElement() { - TypeAnnotationParsingOptions options = - TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE; + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR | + TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE | + TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE | + TypeAnnotationParsingOptions::ALLOW_WILDCARD; return {ParseTypeReference(&options), nullptr}; } @@ -550,8 +550,10 @@ ir::Expression *ETSParser::ParseSuperClassReference() if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) { Lexer()->NextToken(); - TypeAnnotationParsingOptions options = - TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE; + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR | + TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE | + TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE | + TypeAnnotationParsingOptions::ALLOW_WILDCARD; return ParseTypeReference(&options); } @@ -560,8 +562,10 @@ ir::Expression *ETSParser::ParseSuperClassReference() ir::TypeNode *ETSParser::ParseInterfaceExtendsElement() { - TypeAnnotationParsingOptions options = - TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE; + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR | + TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE | + TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE | + TypeAnnotationParsingOptions::ALLOW_WILDCARD; return ParseTypeReference(&options); } @@ -879,7 +883,8 @@ ir::AstNode *ETSParser::ParseClassElement([[maybe_unused]] const ArenaVectorLookahead(); if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC && nextCp != lexer::LEX_CHAR_EQUALS && - nextCp != lexer::LEX_CHAR_COLON && nextCp != lexer::LEX_CHAR_LEFT_PAREN) { + nextCp != lexer::LEX_CHAR_COLON && nextCp != lexer::LEX_CHAR_LEFT_PAREN && + nextCp != lexer::LEX_CHAR_LESS_THAN) { Lexer()->NextToken(); memberModifiers |= ir::ModifierFlags::STATIC; seenStatic = true; @@ -2256,8 +2261,9 @@ bool ETSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, i Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); } - TypeAnnotationParsingOptions options = - TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE; + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE | + TypeAnnotationParsingOptions::ALLOW_WILDCARD | + TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE; ir::TSTypeParameterInstantiation *typeParams = ParseTypeParameterInstantiation(&options); if (typeParams == nullptr) { @@ -2271,7 +2277,7 @@ bool ETSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, i if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { if (!ignoreCallExpression) { - *returnExpression = ParseCallExpression(*returnExpression, false); + *returnExpression = ParseCallExpression(*returnExpression, false, false); (*returnExpression)->AsCallExpression()->SetTypeParams(typeParams); return false; } @@ -2317,7 +2323,7 @@ ir::Expression *ETSParser::ParsePostPrimaryExpression(ir::Expression *primaryExp break; } - returnExpression = ParseCallExpression(returnExpression, false); + returnExpression = ParseCallExpression(returnExpression, false, false); continue; } default: { @@ -2353,7 +2359,9 @@ ir::Expression *ETSParser::ParseNewExpression() TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; ir::TypeNode *typeReference = ParseBaseTypeReference(&options); if (typeReference == nullptr) { - options |= TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE; + options |= TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE | + TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE | + TypeAnnotationParsingOptions::ALLOW_WILDCARD; typeReference = ParseTypeReference(&options); } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { ThrowSyntaxError("Invalid { after base types."); @@ -2488,6 +2496,7 @@ ir::TSTypeParameter *ETSParser::ParseTypeParameter([[maybe_unused]] TypeAnnotati Lexer()->NextToken(); TypeAnnotationParsingOptions newOptions = TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_INTERSECTION | + TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE | TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE; constraint = ParseTypeAnnotation(&newOptions); } diff --git a/parser/expressionParser.cpp b/parser/expressionParser.cpp index e83ccde230bb314e7cb02a774c8501986cf1d383..a96a127d4cf0f879a9c00387aeca58e97423d370 100644 --- a/parser/expressionParser.cpp +++ b/parser/expressionParser.cpp @@ -1177,7 +1177,7 @@ ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left) return rightExpr; } -ir::CallExpression *ParserImpl::ParseCallExpression(ir::Expression *callee, bool isOptionalChain) +ir::CallExpression *ParserImpl::ParseCallExpression(ir::Expression *callee, bool isOptionalChain, bool handleEval) { ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); bool trailingComma {}; @@ -1207,7 +1207,7 @@ ir::CallExpression *ParserImpl::ParseCallExpression(ir::Expression *callee, bool ir::CallExpression *callExpr {}; - if (!isOptionalChain && callee->IsIdentifier() && callee->AsIdentifier()->Name().Is("eval")) { + if (!isOptionalChain && handleEval && callee->IsIdentifier() && callee->AsIdentifier()->Name().Is("eval")) { auto parserStatus = static_cast(context_.Status() | ParserStatus::DIRECT_EVAL); callExpr = AllocNode(callee, std::move(arguments), nullptr, isOptionalChain, parserStatus); diff --git a/parser/parserImpl.h b/parser/parserImpl.h index e2044a76ebb3a807590e617041188574e23e15ef..f9db2c426673f767f925f3db05d18e9f26392e9b 100644 --- a/parser/parserImpl.h +++ b/parser/parserImpl.h @@ -304,7 +304,8 @@ protected: ir::ArrowFunctionExpression *ParseArrowFunctionExpression(ir::Expression *expr, ir::TSTypeParameterDeclaration *typeParamDecl, ir::TypeNode *returnTypeAnnotation, bool isAsync); - ir::CallExpression *ParseCallExpression(ir::Expression *callee, bool isOptionalChain = false); + ir::CallExpression *ParseCallExpression(ir::Expression *callee, bool isOptionalChain = false, + bool handleEval = true); ir::TemplateLiteral *ParseTemplateLiteral(); ir::Expression *ParseLeftHandSideExpression(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); void ParseNameSpaceImport(ArenaVector *specifiers); @@ -383,6 +384,7 @@ protected: ParserStatus newStatus = ParserStatus::NO_OPTS); ir::ClassDeclaration *ParseClassDeclaration(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags = ir::ModifierFlags::NONE); + FunctionSignature ParseFunctionSignature(ParserStatus status); [[nodiscard]] virtual std::unique_ptr InitLexer(const std::string_view &fileName, const std::string_view &source); @@ -486,7 +488,6 @@ protected: virtual std::tuple ParseFunctionBody( const ArenaVector ¶ms, ParserStatus newStatus, ParserStatus contextStatus, binder::FunctionScope *funcScope); - virtual FunctionSignature ParseFunctionSignature(ParserStatus status); virtual ir::AstNode *ParseImportDefaultSpecifier(ArenaVector *specifiers); virtual ir::Statement *ParseExportDeclaration(StatementParsingFlags flags); diff --git a/test/parser/ets/generic_function-expected.txt b/test/parser/ets/generic_function-expected.txt index 5df0a47e6da0d77ad23265d92a405a81ca198563..42c0f584309872e0fe243380d1c031a567274718 100644 --- a/test/parser/ets/generic_function-expected.txt +++ b/test/parser/ets/generic_function-expected.txt @@ -1 +1,902 @@ -SyntaxError: Unexpected token, expected: '('. [generic_function.ets:20:17] +{ + "type": "Program", + "statements": [ + { + "type": "TSInterfaceDeclaration", + "body": { + "type": "TSInterfaceBody", + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "localeCompare", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 3 + }, + "end": { + "line": 17, + "column": 16 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "localeCompare", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 3 + }, + "end": { + "line": 17, + "column": 16 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "Identifier", + "name": "other", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 24 + }, + "end": { + "line": 17, + "column": 30 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 24 + }, + "end": { + "line": 17, + "column": 31 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 24 + }, + "end": { + "line": 17, + "column": 31 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 17 + }, + "end": { + "line": 17, + "column": 31 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 36 + } + } + }, + "declare": true, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 36 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 36 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 3 + }, + "end": { + "line": 17, + "column": 36 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 23 + }, + "end": { + "line": 18, + "column": 2 + } + } + }, + "id": { + "type": "Identifier", + "name": "Comparable2", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 16, + "column": 22 + } + } + }, + "extends": [], + "loc": { + "start": { + "line": 16, + "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": "compare", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "compare", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 10 + }, + "end": { + "line": 20, + "column": 17 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [ + { + "type": "Identifier", + "name": "x", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 44 + }, + "end": { + "line": 20, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 44 + }, + "end": { + "line": 20, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 44 + }, + "end": { + "line": 20, + "column": 46 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 41 + }, + "end": { + "line": 20, + "column": 46 + } + } + }, + { + "type": "Identifier", + "name": "y", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 50 + }, + "end": { + "line": 20, + "column": 51 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 50 + }, + "end": { + "line": 20, + "column": 52 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 50 + }, + "end": { + "line": 20, + "column": 52 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 47 + }, + "end": { + "line": 20, + "column": 52 + } + } + } + ], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 20, + "column": 54 + }, + "end": { + "line": 20, + "column": 57 + } + } + }, + "typeParameters": { + "type": "TSTypeParameterDeclaration", + "params": [ + { + "type": "TSTypeParameter", + "name": { + "type": "Identifier", + "name": "T", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 19 + } + } + }, + "constraint": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Comparable2", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 28 + }, + "end": { + "line": 20, + "column": 39 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 28 + }, + "end": { + "line": 20, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 28 + }, + "end": { + "line": 20, + "column": 40 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 18 + }, + "end": { + "line": 20, + "column": 40 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 20, + "column": 40 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "Identifier", + "name": "x", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 7 + }, + "end": { + "line": 21, + "column": 8 + } + } + }, + "right": { + "type": "NullLiteral", + "value": null, + "loc": { + "start": { + "line": 21, + "column": 12 + }, + "end": { + "line": 21, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 7 + }, + "end": { + "line": 21, + "column": 16 + } + } + }, + "consequent": { + "type": "ReturnStatement", + "argument": { + "type": "ConditionalExpression", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "Identifier", + "name": "y", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 25 + }, + "end": { + "line": 21, + "column": 26 + } + } + }, + "right": { + "type": "NullLiteral", + "value": null, + "loc": { + "start": { + "line": 21, + "column": 30 + }, + "end": { + "line": 21, + "column": 34 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 25 + }, + "end": { + "line": 21, + "column": 34 + } + } + }, + "consequent": { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 21, + "column": 37 + }, + "end": { + "line": 21, + "column": 38 + } + } + }, + "alternate": { + "type": "UnaryExpression", + "operator": "-", + "prefix": true, + "argument": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 21, + "column": 42 + }, + "end": { + "line": 21, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 41 + }, + "end": { + "line": 21, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 25 + }, + "end": { + "line": 21, + "column": 43 + } + } + }, + "loc": { + "start": { + "line": 21, + "column": 18 + }, + "end": { + "line": 21, + "column": 44 + } + } + }, + "alternate": null, + "loc": { + "start": { + "line": 21, + "column": 3 + }, + "end": { + "line": 21, + "column": 44 + } + } + }, + { + "type": "IfStatement", + "test": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "Identifier", + "name": "y", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 7 + }, + "end": { + "line": 22, + "column": 8 + } + } + }, + "right": { + "type": "NullLiteral", + "value": null, + "loc": { + "start": { + "line": 22, + "column": 12 + }, + "end": { + "line": 22, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 7 + }, + "end": { + "line": 22, + "column": 16 + } + } + }, + "consequent": { + "type": "ReturnStatement", + "argument": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 22, + "column": 25 + }, + "end": { + "line": 22, + "column": 26 + } + } + }, + "loc": { + "start": { + "line": 22, + "column": 18 + }, + "end": { + "line": 22, + "column": 27 + } + } + }, + "alternate": null, + "loc": { + "start": { + "line": 22, + "column": 3 + }, + "end": { + "line": 22, + "column": 27 + } + } + }, + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "x", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 10 + }, + "end": { + "line": 23, + "column": 11 + } + } + }, + "property": { + "type": "Identifier", + "name": "localeCompare", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 12 + }, + "end": { + "line": 23, + "column": 25 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 10 + }, + "end": { + "line": 23, + "column": 25 + } + } + }, + "arguments": [ + { + "type": "Identifier", + "name": "y", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 26 + }, + "end": { + "line": 23, + "column": 27 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 23, + "column": 10 + }, + "end": { + "line": 23, + "column": 28 + } + } + }, + "loc": { + "start": { + "line": 23, + "column": 3 + }, + "end": { + "line": 23, + "column": 29 + } + } + } + ], + "loc": { + "start": { + "line": 20, + "column": 58 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 20, + "column": 17 + }, + "end": { + "line": 24, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 24, + "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": 25, + "column": 1 + } + } +} +TypeError: Extends constraint must be an object [generic_function.ets:20:28] diff --git a/test/parser/ets/generic_function.ets b/test/parser/ets/generic_function.ets index d2c097d70f19faec2542fdf6e4c53c17d7cea4f2..3f7aebabb1cf3eb7510f44001b193fe9f935d003 100644 --- a/test/parser/ets/generic_function.ets +++ b/test/parser/ets/generic_function.ets @@ -13,11 +13,11 @@ * limitations under the License. */ -interface Comparable { +interface Comparable2 { localeCompare(other: Object): int; } -function compare(x: T, y: T): int { +function compare(x: T, y: T): int { if (x == null) return y == null ? 0 : -1; if (y == null) return 1; return x.localeCompare(y); diff --git a/test/parser/ets/type_variance4-expected.txt b/test/parser/ets/type_variance4-expected.txt index 8b99676727c3edfad5cb39c157167c7593cf4ee2..3976c5fe606fcbdde680befc517e49c372b19143 100644 --- a/test/parser/ets/type_variance4-expected.txt +++ b/test/parser/ets/type_variance4-expected.txt @@ -1 +1 @@ -SyntaxError: Unexpected token, expected: '('. [type_variance4.ets:18:12] +SyntaxError: Variance modifier is not allowed here. [type_variance4.ets:18:13] diff --git a/test/runtime/ets/generic-function.ets b/test/runtime/ets/generic-function.ets new file mode 100644 index 0000000000000000000000000000000000000000..9be4ad1216ea86fa33e810864cccedf901e6d12a --- /dev/null +++ b/test/runtime/ets/generic-function.ets @@ -0,0 +1,28 @@ +class cls extends Object { + override toString() : String { + return "cls"; + } +} + +function foo(item : T) : String { + let str = item.toString(); + return str; +} + +function bar() : T { + // crash + // let x : T; + return new T(); +} + +function main() : void { +/* TypeError: No matching call signature + foo(10); + foo(new Int(20)); + foo(new cls()); +*/ + bar(); + bar(); + bar(); + bar(); +} diff --git a/test/runtime/ets/generic-set.ets b/test/runtime/ets/generic-set.ets new file mode 100644 index 0000000000000000000000000000000000000000..642957de5eed116f4d23c86a8673eddec2d2b366 --- /dev/null +++ b/test/runtime/ets/generic-set.ets @@ -0,0 +1,81 @@ +interface MyStack { + getTop() : Item; + pop() : Item; + push(item : Item) : void; + isEmpty() : boolean; + size() : int; +} + +class MyArrayStack implements MyStack { + + private container : Item[]; + private top : int = -1; + private const DEFAULT_SIZE : int = 100; + + constructor() { + container = new Item[DEFAULT_SIZE]; + top = -1; + } + + constructor(size: int) { + container = new Item[size]; + } + + override getTop() : Item { + if (top == -1) { + return null; + } + return container[top]; + } + + override pop() : Item { + if (top == -1) { + return null; + } + return container[top--]; + } + + override push(item : Item) : void { + container[++top] = item; + } + + override isEmpty() : boolean { + return (top == -1); + } + + override size() : int { + return (top + 1); + } +} + +function main() : void { + let stack1 : MyArrayStack; + stack1 = new MyArrayStack(); + assert(stack1.isEmpty() == true); + assert(stack1.size() == 0); + + stack1.push(new Int(10)); + assert(stack1.isEmpty() == false); + assert(stack1.size() == 1); + assert(stack1.getTop() == 10); + + stack1.push(new Int(20)); + stack1.push(new Int(30)); + assert(stack1.isEmpty() == false); + assert(stack1.size() == 3); + assert(stack1.getTop() == 30); + + assert(stack1.pop() == 30); + assert(stack1.size() == 2); + assert(stack1.pop() == 20); + assert(stack1.size() == 1); + assert(stack1.pop() == 10); + assert(stack1.size() == 0); + assert(stack1.isEmpty() == true); + + assert(stack1.getTop() == null); + assert(stack1.pop() == null); + assert(stack1.size() == 0); + assert(stack1.isEmpty() == true); + +}