From 0ecd0e167c24bd4bf3010f10f3370c240dda143b Mon Sep 17 00:00:00 2001 From: Artem Udovichenko Date: Tue, 13 Dec 2022 18:14:34 +0300 Subject: [PATCH 1/3] Support launch keyword in ETSparser Signed-off-by: Artem Udovichenko Change-Id: I3dc9ce04ffa9e9398632a5e9788d4699c6d40a27 --- BUILD.gn | 1 + CMakeLists.txt | 1 + checker/ETSchecker.cpp | 5 +++ checker/ETSchecker.h | 1 + checker/ets/typeCreation.cpp | 5 +++ checker/types/globalTypesHolder.cpp | 6 ++++ checker/types/globalTypesHolder.h | 2 ++ compiler/scripts/signatures.yaml | 3 ++ ir/astNodeMapping.h | 1 + ir/ets/etsLaunchExpression.cpp | 54 +++++++++++++++++++++++++++++ ir/ets/etsLaunchExpression.h | 41 ++++++++++++++++++++++ lexer/scripts/keywords.yaml | 4 +++ lexer/token/token.cpp | 2 ++ lexer/token/tokenType.h | 1 + parser/ETSparser.cpp | 19 ++++++++++ parser/ETSparser.h | 1 + 16 files changed, 147 insertions(+) create mode 100644 ir/ets/etsLaunchExpression.cpp create mode 100644 ir/ets/etsLaunchExpression.h diff --git a/BUILD.gn b/BUILD.gn index 231bf13f0..82517265a 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -215,6 +215,7 @@ libes2panda_sources = [ "ir/ts/tsVoidKeyword.cpp", "ir/ets/etsClassLiteral.cpp", "ir/ets/etsFunctionType.cpp", + "ir/ets/etsLaunchExpression.cpp", "ir/ets/etsNewArrayInstanceExpression.cpp", "ir/ets/etsNewClassInstanceExpression.cpp", "ir/ets/etsNewMultiDimArrayInstanceExpression.cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt index 0db70f857..4b2de5d92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,7 @@ set(ES2PANDA_LIB_SRC ir/as/prefixAssertionExpression.cpp ir/ets/etsClassLiteral.cpp ir/ets/etsFunctionType.cpp + ir/ets/etsLaunchExpression.cpp ir/ets/etsNewArrayInstanceExpression.cpp ir/ets/etsNewClassInstanceExpression.cpp ir/ets/etsNewMultiDimArrayInstanceExpression.cpp diff --git a/checker/ETSchecker.cpp b/checker/ETSchecker.cpp index 752bcbe35..999d11a26 100644 --- a/checker/ETSchecker.cpp +++ b/checker/ETSchecker.cpp @@ -236,6 +236,11 @@ ETSObjectType *ETSChecker::GlobalBuiltinEnumType() const return globalBuiltinEnumType_; } +ETSObjectType *ETSChecker::GlobalBuiltinPromiseType() const +{ + return AsETSObjectType(&GlobalTypesHolder::GlobalPromiseBuiltinType); +} + const checker::WrapperDesc &ETSChecker::PrimitiveWrapper() const { return primitiveWrappers_.Wrappers(); diff --git a/checker/ETSchecker.h b/checker/ETSchecker.h index 9f73aed19..db78e8e6c 100644 --- a/checker/ETSchecker.h +++ b/checker/ETSchecker.h @@ -123,6 +123,7 @@ public: ETSObjectType *GlobalBuiltinPanicType() const; ETSObjectType *GlobalStringBuilderBuiltinType() const; ETSObjectType *GlobalBuiltinEnumType() const; + ETSObjectType *GlobalBuiltinPromiseType() const; const checker::WrapperDesc &PrimitiveWrapper() const; diff --git a/checker/ets/typeCreation.cpp b/checker/ets/typeCreation.cpp index 4adfa40e2..3d0045b9e 100644 --- a/checker/ets/typeCreation.cpp +++ b/checker/ets/typeCreation.cpp @@ -205,6 +205,11 @@ ETSObjectType *ETSChecker::CreateETSObjectTypeCheckBuiltins(util::StringView nam return globalBuiltinEnumType_; } globalBuiltinEnumType_ = objType; + } else if (name == compiler::Signatures::BUILTIN_PROMISE_CLASS) { + if (GlobalBuiltinPromiseType() != nullptr) { + return GlobalBuiltinPromiseType(); + } + GetGlobalTypesHolder()->GlobalTypes()[static_cast(GlobalTypeId::ETS_PROMISE_BUILTIN)] = objType; } return objType; diff --git a/checker/types/globalTypesHolder.cpp b/checker/types/globalTypesHolder.cpp index ea93ab12e..240559d9a 100644 --- a/checker/types/globalTypesHolder.cpp +++ b/checker/types/globalTypesHolder.cpp @@ -130,6 +130,7 @@ GlobalTypesHolder::GlobalTypesHolder(ArenaAllocator *allocator) : builtinNameMap builtinNameMappings_.emplace("StringBuilder", GlobalTypeId::ETS_STRING_BUILDER_BUILTIN); builtinNameMappings_.emplace("Type", GlobalTypeId::ETS_TYPE_BUILTIN); builtinNameMappings_.emplace("Types", GlobalTypeId::ETS_TYPES_BUILTIN); + builtinNameMappings_.emplace("Promise", GlobalTypeId::ETS_PROMISE_BUILTIN); } Type *GlobalTypesHolder::GlobalNumberType() @@ -477,6 +478,11 @@ Type *GlobalTypesHolder::GlobalTypesBuiltinType() return globalTypes_.at(static_cast(GlobalTypeId::ETS_TYPES_BUILTIN)); } +Type *GlobalTypesHolder::GlobalPromiseBuiltinType() +{ + return globalTypes_.at(static_cast(GlobalTypeId::ETS_PROMISE_BUILTIN)); +} + void GlobalTypesHolder::InitializeBuiltin(const util::StringView name, Type *type) { const auto typeId = builtinNameMappings_.find(name); diff --git a/checker/types/globalTypesHolder.h b/checker/types/globalTypesHolder.h index 5cd1d3a89..dbd7156ac 100644 --- a/checker/types/globalTypesHolder.h +++ b/checker/types/globalTypesHolder.h @@ -90,6 +90,7 @@ enum class GlobalTypeId { ETS_STRING_BUILDER_BUILTIN, ETS_TYPE_BUILTIN, ETS_TYPES_BUILTIN, + ETS_PROMISE_BUILTIN, COUNT, }; @@ -172,6 +173,7 @@ public: Type *GlobalStringBuilderBuiltinType(); Type *GlobalTypeBuiltinType(); Type *GlobalTypesBuiltinType(); + Type *GlobalPromiseBuiltinType(); void InitializeBuiltin(util::StringView name, Type *type); diff --git a/compiler/scripts/signatures.yaml b/compiler/scripts/signatures.yaml index 58bcf58fb..72871402c 100644 --- a/compiler/scripts/signatures.yaml +++ b/compiler/scripts/signatures.yaml @@ -178,6 +178,9 @@ builtins: - name: Enum package: PKG_STD_CORE ref: BUILTIN_ENUM + - name: Promise + package: PKG_STD_CORE + ref: BUILTIN_PROMISE signatures: - callee: BUILTIN_OBJECT diff --git a/ir/astNodeMapping.h b/ir/astNodeMapping.h index 94f71f92f..8ca2b5881 100644 --- a/ir/astNodeMapping.h +++ b/ir/astNodeMapping.h @@ -86,6 +86,7 @@ _(ETS_TRY_EXPRESSION, ETSTryExpression) \ _(ETS_TYPE_REFERENCE, ETSTypeReference) \ _(ETS_TYPE_REFERENCE_PART, ETSTypeReferencePart) \ + _(ETS_LAUNCH_EXPRESSION, ETSLaunchExpression) \ _(ETS_NEW_ARRAY_INSTANCE_EXPRESSION, ETSNewArrayInstanceExpression) \ _(ETS_NEW_MULTI_DIM_ARRAY_INSTANCE_EXPRESSION, ETSNewMultiDimArrayInstanceExpression) \ _(ETS_NEW_CLASS_INSTANCE_EXPRESSION, ETSNewClassInstanceExpression) \ diff --git a/ir/ets/etsLaunchExpression.cpp b/ir/ets/etsLaunchExpression.cpp new file mode 100644 index 000000000..7f2cec9f4 --- /dev/null +++ b/ir/ets/etsLaunchExpression.cpp @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2021 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 "etsLaunchExpression.h" + +#include "plugins/ecmascript/es2panda/compiler/core/pandagen.h" +#include "plugins/ecmascript/es2panda/compiler/core/ETSGen.h" +#include "plugins/ecmascript/es2panda/checker/ETSchecker.h" +#include "plugins/ecmascript/es2panda/checker/TSchecker.h" +#include "plugins/ecmascript/es2panda/ir/astDump.h" +#include "plugins/ecmascript/es2panda/ir/expressions//callExpression.h" + +namespace panda::es2panda::ir { +void ETSLaunchExpression::Iterate(const NodeTraverser &cb) const +{ + cb(expr_); +} + +void ETSLaunchExpression::Dump(ir::AstDumper *dumper) const +{ + dumper->Add({{"type", "ETSLaunchExpression"}, {"expr", expr_}}); +} + +void ETSLaunchExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} + +void ETSLaunchExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +{ + etsg->Acc().SetType(TsType()); +} + +checker::Type *ETSLaunchExpression::Check([[maybe_unused]] checker::TSChecker *checker) +{ + return nullptr; +} + +checker::Type *ETSLaunchExpression::Check(checker::ETSChecker *checker) +{ + expr_->Check(checker); + SetTsType(checker->GlobalBuiltinPromiseType()); + return TsType(); +} +} // namespace panda::es2panda::ir diff --git a/ir/ets/etsLaunchExpression.h b/ir/ets/etsLaunchExpression.h new file mode 100644 index 000000000..ec5a618ae --- /dev/null +++ b/ir/ets/etsLaunchExpression.h @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2021 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_IR_STATEMENT_LAUNCH_STATEMENT_H +#define ES2PANDA_IR_STATEMENT_LAUNCH_STATEMENT_H + +#include "plugins/ecmascript/es2panda/ir/expression.h" + +namespace panda::es2panda::ir { + +class CallExpression; + +class ETSLaunchExpression : public Expression { +public: + explicit ETSLaunchExpression(CallExpression *expr) : Expression(AstNodeType::ETS_LAUNCH_EXPRESSION), expr_(expr) {} + + void Iterate(const NodeTraverser &cb) const override; + void Dump(ir::AstDumper *dumper) const override; + void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; + checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; + checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + +private: + CallExpression *expr_; +}; +} // namespace panda::es2panda::ir + +#endif diff --git a/lexer/scripts/keywords.yaml b/lexer/scripts/keywords.yaml index 97b395468..4de8f1e35 100644 --- a/lexer/scripts/keywords.yaml +++ b/lexer/scripts/keywords.yaml @@ -282,6 +282,10 @@ keywords: token: KEYW_LET keyword: [as, js, ets, ts] + - name: 'launch' + token: KEYW_LAUNCH + keyword: [ets] + - name: 'long' token: KEYW_LONG keyword: [ets] diff --git a/lexer/token/token.cpp b/lexer/token/token.cpp index 97ea93fd9..4f2c9117c 100644 --- a/lexer/token/token.cpp +++ b/lexer/token/token.cpp @@ -320,6 +320,8 @@ const char *TokenToString(TokenType type) // NOLINT(readability-function-size) return "int"; case TokenType::KEYW_IMPORT: return "import"; + case TokenType::KEYW_LAUNCH: + return "launch"; case TokenType::KEYW_LONG: return "long"; case TokenType::KEYW_NEVER: diff --git a/lexer/token/tokenType.h b/lexer/token/tokenType.h index 167868134..35bb8e3f5 100644 --- a/lexer/token/tokenType.h +++ b/lexer/token/tokenType.h @@ -138,6 +138,7 @@ enum class TokenType { KEYW_IF, KEYW_IMPORT, KEYW_INT, + KEYW_LAUNCH, KEYW_LONG, KEYW_NATIVE, KEYW_NEVER, diff --git a/parser/ETSparser.cpp b/parser/ETSparser.cpp index f9d079cf7..4f3935d85 100644 --- a/parser/ETSparser.cpp +++ b/parser/ETSparser.cpp @@ -61,6 +61,7 @@ #include "plugins/ecmascript/es2panda/ir/statements/panicStatement.h" #include "plugins/ecmascript/es2panda/ir/statements/blockStatement.h" #include "plugins/ecmascript/es2panda/ir/statements/trapStatement.h" +#include "plugins/ecmascript/es2panda/ir/ets/etsLaunchExpression.h" #include "plugins/ecmascript/es2panda/ir/ets/etsTryExpression.h" #include "plugins/ecmascript/es2panda/ir/ets/etsClassLiteral.h" #include "plugins/ecmascript/es2panda/ir/ets/etsPrimitiveType.h" @@ -1109,6 +1110,21 @@ ir::Statement *ETSParser::ParseEnumDeclaration(bool isConst, bool isStatic) return declNode; } +ir::Expression *ETSParser::ParseLaunchExpression(ExpressionParseFlags flags) +{ + lexer::SourcePosition start = Lexer()->GetToken().Start(); + Lexer()->NextToken(); // eat launch + + ir::Expression *callee = ParseLeftHandSideExpression(flags); + if (!callee->IsCallExpression()) { + ThrowSyntaxError("Only call expressions are allowed after 'launch'", callee->Start()); + } + auto *launchExpression = AllocNode(callee->AsCallExpression()); + launchExpression->SetRange({start, callee->End()}); + + return launchExpression; +} + // NOLINTNEXTLINE(google-default-arguments) ir::ClassDefinition *ETSParser::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags) { @@ -2067,6 +2083,9 @@ ir::Expression *ETSParser::ParseUnaryOrPrefixUpdateExpression(ExpressionParseFla case lexer::TokenType::KEYW_TRY: { return ParseTryExpression(flags); } + case lexer::TokenType::KEYW_LAUNCH: { + return ParseLaunchExpression(flags); + } default: { return ParseLeftHandSideExpression(flags); } diff --git a/parser/ETSparser.h b/parser/ETSparser.h index f21971da7..f35623a16 100644 --- a/parser/ETSparser.h +++ b/parser/ETSparser.h @@ -142,6 +142,7 @@ private: ir::ModifierFlags flags = ir::ModifierFlags::NONE) override; // NOLINTNEXTLINE(google-default-arguments) ir::Statement *ParseEnumDeclaration(bool isConst = false, bool isStatic = false) override; + ir::Expression *ParseLaunchExpression(ExpressionParseFlags flags); bool CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor, ArenaVector &properties) override; -- Gitee From 45456b041224a23d780dbb084a781d409ca0cdfe Mon Sep 17 00:00:00 2001 From: Artem Udovichenko Date: Thu, 15 Dec 2022 20:06:18 +0300 Subject: [PATCH 2/3] Generate Closure class Change-Id: I5ccdf0ba4e10d721e939662d79b2a7bb983a086a --- binder/ETSBinder.cpp | 1 + binder/ETSBinder.h | 12 +++++ binder/variable.cpp | 1 + compiler/core/ETSemitter.cpp | 77 ++++++++++++++++++++++++++++++++ compiler/core/ETSemitter.h | 2 + compiler/scripts/signatures.yaml | 3 ++ ir/ets/etsLaunchExpression.cpp | 27 +++++++++-- ir/ets/etsLaunchExpression.h | 18 +++++++- parser/ETSparser.cpp | 13 +++--- 9 files changed, 145 insertions(+), 9 deletions(-) diff --git a/binder/ETSBinder.cpp b/binder/ETSBinder.cpp index 35ae12dc9..2a57aea7b 100644 --- a/binder/ETSBinder.cpp +++ b/binder/ETSBinder.cpp @@ -37,6 +37,7 @@ #include "plugins/ecmascript/es2panda/ir/ets/etsTypeReference.h" #include "plugins/ecmascript/es2panda/ir/ets/etsFunctionType.h" #include "plugins/ecmascript/es2panda/ir/ets/etsScript.h" +#include "plugins/ecmascript/es2panda/ir/ets/etsLaunchExpression.h" #include "plugins/ecmascript/es2panda/ir/ts/tsInterfaceDeclaration.h" #include "plugins/ecmascript/es2panda/ir/ts/tsTypeParameterDeclaration.h" #include "plugins/ecmascript/es2panda/ir/ts/tsTypeParameterInstantiation.h" diff --git a/binder/ETSBinder.h b/binder/ETSBinder.h index bcfb42171..fe8a5049a 100644 --- a/binder/ETSBinder.h +++ b/binder/ETSBinder.h @@ -34,6 +34,7 @@ public: defaultImports_(Allocator()->Adapter()), lambdaObjects_(Allocator()->Adapter()), functionalInterfaces_(Allocator()->Adapter()) + launchExpressions_(allocator->Adapter()) { InitImplicitThisParam(); } @@ -72,6 +73,16 @@ public: return &globalRecordTable_; } + void AddLaunchExpression(ir::ETSLaunchExpression *expr) + { + launchExpressions_.push_back(expr); + } + + const ArenaVector GetLaunchExpressions() const + { + return launchExpressions_; + } + ArenaUnorderedMap &GetExternalRecordTable() { return externalRecordTable_; @@ -163,6 +174,7 @@ private: ArenaVector defaultImports_; ComputedLambdaObjects lambdaObjects_; ArenaVector functionalInterfaces_; + ArenaVector launchExpressions_; ir::Identifier *thisParam_ {}; }; diff --git a/binder/variable.cpp b/binder/variable.cpp index bb7dba273..2bfae46ce 100644 --- a/binder/variable.cpp +++ b/binder/variable.cpp @@ -37,6 +37,7 @@ const util::StringView &Variable::Name() const LocalVariable *LocalVariable::Copy(ArenaAllocator *allocator, Decl *decl) const { auto *var = allocator->New(decl, flags_); + var->tsType_ = tsType_; var->vreg_ = vreg_; return var; } diff --git a/compiler/core/ETSemitter.cpp b/compiler/core/ETSemitter.cpp index c67ae58c4..74b15e77e 100644 --- a/compiler/core/ETSemitter.cpp +++ b/compiler/core/ETSemitter.cpp @@ -15,6 +15,7 @@ #include "ETSemitter.h" +#include "runtime/include/mem/panda_string.h" #include "plugins/ecmascript/es2panda/compiler/core/ETSGen.h" #include "plugins/ecmascript/es2panda/binder/binder.h" #include "plugins/ecmascript/es2panda/binder/ETSBinder.h" @@ -23,6 +24,7 @@ #include "plugins/ecmascript/es2panda/ir/base/classDefinition.h" #include "plugins/ecmascript/es2panda/ir/base/scriptFunction.h" #include "plugins/ecmascript/es2panda/ir/base/classProperty.h" +#include "plugins/ecmascript/es2panda/ir/expressions/callExpression.h" #include "plugins/ecmascript/es2panda/ir/ts/tsEnumDeclaration.h" #include "plugins/ecmascript/es2panda/ir/ts/tsEnumMember.h" #include "plugins/ecmascript/es2panda/ir/ts/tsInterfaceDeclaration.h" @@ -30,6 +32,7 @@ #include "plugins/ecmascript/es2panda/ir/ts/tsTypeParameterDeclaration.h" #include "plugins/ecmascript/es2panda/ir/ts/tsTypeParameter.h" #include "plugins/ecmascript/es2panda/ir/ets/etsTypeReference.h" +#include "plugins/ecmascript/es2panda/ir/ets/etsLaunchExpression.h" #include "plugins/ecmascript/es2panda/ir/typeNode.h" #include "plugins/ecmascript/es2panda/parser/program/program.h" #include "plugins/ecmascript/es2panda/compiler/core/compilerContext.h" @@ -211,6 +214,10 @@ void ETSEmitter::GenAnnotation() GenExternalRecord(recordTable); } + for (const auto *launchExpr : binder->GetLaunchExpressions()) { + GenClosureRecord(launchExpr); + } + const auto *checker = static_cast(Context()->Checker()); for (auto [arrType, signature] : checker->GlobalArrayTypes()) { @@ -365,6 +372,76 @@ void ETSEmitter::GenClassInheritedFields(const checker::ETSObjectType *baseType, } } +void ETSEmitter::GenClosureRecord(const ir::ETSLaunchExpression *expr) +{ + const ir::CallExpression *call = expr->Call(); + std::string className = expr->ClosureClassName(); + auto classRecord = pandasm::Record(className.c_str(), Program()->lang); + classRecord.metadata->SetAccessFlags(ACC_PUBLIC | ACC_FINAL); + classRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, Signatures::BUILTIN_OBJECT); + + std::vector annotations; + GenAnnotationRecord(Signatures::METHOD_ANNOTATION, true); + pandasm::AnnotationData method(Signatures::METHOD_ANNOTATION); + pandasm::AnnotationElement value( + Signatures::ANNOTATION_KEY_VALUE, + std::make_unique(pandasm::ScalarValue::Create( + call->Signature()->Function()->Scope()->InternalName().Mutf8()))); + method.AddElement(std::move(value)); + annotations.push_back(method); + classRecord.metadata->SetAnnotations(std::move(annotations)); + + std::string ctorName = className + "._ctor_"; + auto ctor = pandasm::Function(ctorName.c_str(), EXTENSION); + ctor.params.emplace_back(pandasm::Type(className.c_str(), 0), EXTENSION); + size_t argCount = 1; + for (const ir::Expression *arg : call->Arguments()) { + const checker::Type *type = arg->TsType(); + std::stringstream out; + out << "a" << argCount; + std::string fieldName = out.str(); + out.str(""); + type->ToAssemblerType(out); + ctor.params.emplace_back(pandasm::Type(out.str(), type->Rank()), EXTENSION); + GenField(type, util::StringView(fieldName), nullptr, ACC_PUBLIC, classRecord, false); + ++argCount; + } + ctor.return_type = pandasm::Type(Signatures::PRIMITIVE_VOID, 0); + + auto &super_ctor_call = ctor.ins.emplace_back(); + super_ctor_call.opcode = pandasm::Opcode::CALL_SHORT; + super_ctor_call.regs.resize(2); + super_ctor_call.ids.push_back("std.core.Object.:void;"); + argCount = 1; + for (const ir::Expression *arg : call->Arguments()) { + const checker::Type *type = arg->TsType(); + auto &lda = ctor.ins.emplace_back(); + if (type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + lda.opcode = pandasm::Opcode::LDA; + } else { + lda.opcode = pandasm::Opcode::LDA_OBJ; + } + lda.regs.push_back(argCount); + auto &stobj = ctor.ins.emplace_back(); + if (type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE)) { + stobj.opcode = pandasm::Opcode::STOBJ; + } else { + stobj.opcode = pandasm::Opcode::STOBJ_OBJ; + } + stobj.regs.push_back(0); + std::stringstream out; + out << className << ".a" << argCount; + std::string fieldName = out.str(); + stobj.ids.push_back(fieldName.c_str()); + ++argCount; + } + auto &return_void = ctor.ins.emplace_back(); + return_void.opcode = pandasm::Opcode::RETURN_VOID; + + Program()->record_table.emplace(classRecord.name, std::move(classRecord)); + Program()->function_table.emplace(ctor.name, std::move(ctor)); +} + void ETSEmitter::GenGlobalArrayRecord(checker::ETSArrayType *arrayType, checker::Signature *signature) { std::stringstream ss; diff --git a/compiler/core/ETSemitter.h b/compiler/core/ETSemitter.h index 839a2fda7..ccb8179ca 100644 --- a/compiler/core/ETSemitter.h +++ b/compiler/core/ETSemitter.h @@ -24,6 +24,7 @@ class RecordTable; namespace panda::es2panda::ir { class ClassDefinition; +class ETSLaunchExpression; } // namespace panda::es2panda::ir namespace panda::es2panda::checker { @@ -83,6 +84,7 @@ private: uint32_t accesFlags, pandasm::Record &record, bool external); void GenInterfaceMethodDefinition(const ir::MethodDefinition *methodDef, bool external); void GenClassInheritedFields(const checker::ETSObjectType *baseType, pandasm::Record &classRecord); + void GenClosureRecord(const ir::ETSLaunchExpression *expr); pandasm::AnnotationData GenAnnotationSignature(const ir::ClassDefinition *classDef); pandasm::AnnotationData GenAnnotationEnclosingClass(std::string_view className); pandasm::AnnotationData GenAnnotationEnclosingMethod(const ir::MethodDefinition *methodDef); diff --git a/compiler/scripts/signatures.yaml b/compiler/scripts/signatures.yaml index 72871402c..204fc20a1 100644 --- a/compiler/scripts/signatures.yaml +++ b/compiler/scripts/signatures.yaml @@ -88,6 +88,9 @@ defines: ref: CTOR_PARAM0 - name: param1 ref: CTOR_PARAM1 + - name: ets.annotation.Method + ref: METHOD_ANNOTATION + comment: Method annotation packages: - name: 'std.core' diff --git a/ir/ets/etsLaunchExpression.cpp b/ir/ets/etsLaunchExpression.cpp index 7f2cec9f4..e97d18067 100644 --- a/ir/ets/etsLaunchExpression.cpp +++ b/ir/ets/etsLaunchExpression.cpp @@ -20,9 +20,21 @@ #include "plugins/ecmascript/es2panda/checker/ETSchecker.h" #include "plugins/ecmascript/es2panda/checker/TSchecker.h" #include "plugins/ecmascript/es2panda/ir/astDump.h" -#include "plugins/ecmascript/es2panda/ir/expressions//callExpression.h" +#include "plugins/ecmascript/es2panda/ir/expressions/identifier.h" +#include "plugins/ecmascript/es2panda/ir/expressions/callExpression.h" +#include "plugins/ecmascript/es2panda/ir/base/classDefinition.h" namespace panda::es2panda::ir { +size_t ETSLaunchExpression::closureIndex_ = 0; + +ETSLaunchExpression::ETSLaunchExpression(CallExpression *expr): Expression(AstNodeType::ETS_LAUNCH_EXPRESSION), expr_(expr) +{ + size_t index = closureIndex_++; + std::stringstream out; + out << "_Closure_" << index; + closureClassName_ = out.str(); +} + void ETSLaunchExpression::Iterate(const NodeTraverser &cb) const { cb(expr_); @@ -33,10 +45,19 @@ void ETSLaunchExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSLaunchExpression"}, {"expr", expr_}}); } -void ETSLaunchExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void ETSLaunchExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const +{ +} -void ETSLaunchExpression::Compile([[maybe_unused]] compiler::ETSGen *etsg) const +void ETSLaunchExpression::Compile(compiler::ETSGen *etsg) const { + std::string *ctorName = new std::string(closureClassName_); + *ctorName += "._ctor_"; + auto *checker = const_cast(etsg->Checker()); + auto *sigInfo = checker->Allocator()->New(expr_->Signature()->GetSignatureInfo(), checker->Allocator()); + auto *signature = + checker->Allocator()->New(sigInfo, checker->GlobalVoidType(), util::StringView(*ctorName)); + etsg->InitObject(this, signature, expr_->Arguments()); etsg->Acc().SetType(TsType()); } diff --git a/ir/ets/etsLaunchExpression.h b/ir/ets/etsLaunchExpression.h index ec5a618ae..8c0bec8f6 100644 --- a/ir/ets/etsLaunchExpression.h +++ b/ir/ets/etsLaunchExpression.h @@ -18,13 +18,17 @@ #include "plugins/ecmascript/es2panda/ir/expression.h" +namespace panda::es2panda::checker { +class Signature; +} + namespace panda::es2panda::ir { class CallExpression; class ETSLaunchExpression : public Expression { public: - explicit ETSLaunchExpression(CallExpression *expr) : Expression(AstNodeType::ETS_LAUNCH_EXPRESSION), expr_(expr) {} + explicit ETSLaunchExpression(CallExpression *expr); void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; @@ -33,8 +37,20 @@ public: checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + const CallExpression *Call() const + { + return expr_; + } + + std::string ClosureClassName() const + { + return closureClassName_; + } + private: CallExpression *expr_; + std::string closureClassName_; + static size_t closureIndex_; }; } // namespace panda::es2panda::ir diff --git a/parser/ETSparser.cpp b/parser/ETSparser.cpp index 4f3935d85..e285afbf5 100644 --- a/parser/ETSparser.cpp +++ b/parser/ETSparser.cpp @@ -1115,12 +1115,15 @@ ir::Expression *ETSParser::ParseLaunchExpression(ExpressionParseFlags flags) lexer::SourcePosition start = Lexer()->GetToken().Start(); Lexer()->NextToken(); // eat launch - ir::Expression *callee = ParseLeftHandSideExpression(flags); - if (!callee->IsCallExpression()) { - ThrowSyntaxError("Only call expressions are allowed after 'launch'", callee->Start()); + ir::Expression *expr = ParseLeftHandSideExpression(flags); + if (!expr->IsCallExpression()) { + ThrowSyntaxError("Only call expressions are allowed after 'launch'", expr->Start()); } - auto *launchExpression = AllocNode(callee->AsCallExpression()); - launchExpression->SetRange({start, callee->End()}); + auto call = expr->AsCallExpression(); + auto *launchExpression = AllocNode(call); + launchExpression->SetRange({start, call->End()}); + + static_cast(Binder())->AddLaunchExpression(launchExpression); return launchExpression; } -- Gitee From 26d8af8eb6a32e90599e2b8d64c895ebf9759a91 Mon Sep 17 00:00:00 2001 From: Artem Udovichenko Date: Mon, 19 Dec 2022 13:20:11 +0300 Subject: [PATCH 3/3] Call intrinsic to start coroutine Change-Id: I8c876ff94e0de45ba6dc541c9472dc93168e162d --- compiler/core/ETSGen.h | 11 ++++++++ compiler/core/ETSemitter.cpp | 38 +++++++++++++++++++++++++++ compiler/scripts/signatures.yaml | 9 +++++++ ir/ets/etsLaunchExpression.cpp | 45 ++++++++++++++++++++++++++------ ir/ets/etsLaunchExpression.h | 1 + 5 files changed, 96 insertions(+), 8 deletions(-) diff --git a/compiler/core/ETSGen.h b/compiler/core/ETSGen.h index 87b4db78f..247b30263 100644 --- a/compiler/core/ETSGen.h +++ b/compiler/core/ETSGen.h @@ -226,12 +226,23 @@ public: CallImpl(node, signature, arguments); } + void InitThisObject(const ir::AstNode *node, VReg &obj, checker::Signature *signature, + const ArenaVector &arguments) + { + CallThisImpl(node, obj, signature, arguments); + } + void CallStatic(const ir::AstNode *node, checker::Signature *signature, const ArenaVector &arguments) { CallImpl(node, signature, arguments); } + void CallAccStatic0(const ir::AstNode *node, util::StringView name) + { + Ra().Emit(node, name, VReg::RegStart(), 0); + } + void CallThisStatic(const ir::AstNode *node, VReg &ctor, checker::Signature *signature, const ArenaVector &arguments) { diff --git a/compiler/core/ETSemitter.cpp b/compiler/core/ETSemitter.cpp index 74b15e77e..ace8838bb 100644 --- a/compiler/core/ETSemitter.cpp +++ b/compiler/core/ETSemitter.cpp @@ -25,6 +25,7 @@ #include "plugins/ecmascript/es2panda/ir/base/scriptFunction.h" #include "plugins/ecmascript/es2panda/ir/base/classProperty.h" #include "plugins/ecmascript/es2panda/ir/expressions/callExpression.h" +#include "plugins/ecmascript/es2panda/ir/expressions/memberExpression.h" #include "plugins/ecmascript/es2panda/ir/ts/tsEnumDeclaration.h" #include "plugins/ecmascript/es2panda/ir/ts/tsEnumMember.h" #include "plugins/ecmascript/es2panda/ir/ts/tsInterfaceDeclaration.h" @@ -395,6 +396,30 @@ void ETSEmitter::GenClosureRecord(const ir::ETSLaunchExpression *expr) auto ctor = pandasm::Function(ctorName.c_str(), EXTENSION); ctor.params.emplace_back(pandasm::Type(className.c_str(), 0), EXTENSION); size_t argCount = 1; + // Handle 'this' + bool isStatic = expr->IsStaticCall(); + const checker::Type *thisType = nullptr; + if (call->Callee()->IsIdentifier()) { + if (!isStatic) { + thisType = call->TsType(); + } + } else if (call->Callee()->IsMemberExpression()) { + if (!isStatic) { + thisType = call->Callee()->AsMemberExpression()->Object()->TsType(); + } + } else { + thisType = call->Callee()->TsType(); + } + if (thisType != nullptr) { + std::stringstream out; + out << "a" << argCount; + std::string fieldName = out.str(); + out.str(""); + thisType->ToAssemblerType(out); + ctor.params.emplace_back(pandasm::Type(out.str(), thisType->Rank()), EXTENSION); + GenField(thisType, util::StringView(fieldName), nullptr, ACC_PUBLIC, classRecord, false); + ++argCount; + } for (const ir::Expression *arg : call->Arguments()) { const checker::Type *type = arg->TsType(); std::stringstream out; @@ -413,6 +438,19 @@ void ETSEmitter::GenClosureRecord(const ir::ETSLaunchExpression *expr) super_ctor_call.regs.resize(2); super_ctor_call.ids.push_back("std.core.Object.:void;"); argCount = 1; + if (thisType != nullptr) { + auto &lda = ctor.ins.emplace_back(); + lda.opcode = pandasm::Opcode::LDA_OBJ; + lda.regs.push_back(argCount); + auto &stobj = ctor.ins.emplace_back(); + stobj.opcode = pandasm::Opcode::STOBJ_OBJ; + stobj.regs.push_back(0); + std::stringstream out; + out << className << ".a" << argCount; + std::string fieldName = out.str(); + stobj.ids.push_back(fieldName.c_str()); + ++argCount; + } for (const ir::Expression *arg : call->Arguments()) { const checker::Type *type = arg->TsType(); auto &lda = ctor.ins.emplace_back(); diff --git a/compiler/scripts/signatures.yaml b/compiler/scripts/signatures.yaml index 204fc20a1..455804003 100644 --- a/compiler/scripts/signatures.yaml +++ b/compiler/scripts/signatures.yaml @@ -184,6 +184,9 @@ builtins: - name: Promise package: PKG_STD_CORE ref: BUILTIN_PROMISE + - name: Coroutine + package: PKG_STD_CORE + ref: BUILTIN_COROUTINE signatures: - callee: BUILTIN_OBJECT @@ -371,3 +374,9 @@ signatures: params: [] return_type: PRIMITIVE_DOUBLE ref: BUILTIN_DOUBLE_UNBOXED + + - callee: BUILTIN_COROUTINE + method_name: doLaunch + params: [BUILTIN_OBJECT] + return_type: BUILTIN_PROMISE + ref: BUILTIN_COROUTINE_LAUNCH diff --git a/ir/ets/etsLaunchExpression.cpp b/ir/ets/etsLaunchExpression.cpp index e97d18067..06fb911c2 100644 --- a/ir/ets/etsLaunchExpression.cpp +++ b/ir/ets/etsLaunchExpression.cpp @@ -22,12 +22,13 @@ #include "plugins/ecmascript/es2panda/ir/astDump.h" #include "plugins/ecmascript/es2panda/ir/expressions/identifier.h" #include "plugins/ecmascript/es2panda/ir/expressions/callExpression.h" -#include "plugins/ecmascript/es2panda/ir/base/classDefinition.h" +#include "plugins/ecmascript/es2panda/ir/expressions/memberExpression.h" namespace panda::es2panda::ir { size_t ETSLaunchExpression::closureIndex_ = 0; -ETSLaunchExpression::ETSLaunchExpression(CallExpression *expr): Expression(AstNodeType::ETS_LAUNCH_EXPRESSION), expr_(expr) +ETSLaunchExpression::ETSLaunchExpression(CallExpression *expr) + : Expression(AstNodeType::ETS_LAUNCH_EXPRESSION), expr_(expr) { size_t index = closureIndex_++; std::stringstream out; @@ -45,20 +46,43 @@ void ETSLaunchExpression::Dump(ir::AstDumper *dumper) const dumper->Add({{"type", "ETSLaunchExpression"}, {"expr", expr_}}); } -void ETSLaunchExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const -{ -} +void ETSLaunchExpression::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} void ETSLaunchExpression::Compile(compiler::ETSGen *etsg) const { + compiler::RegScope rs(etsg); + compiler::VReg calleeReg = etsg->AllocReg(); + bool isStatic = expr_->Signature()->HasSignatureFlag(checker::SignatureFlags::STATIC); + if (expr_->Callee()->IsIdentifier()) { + if (!isStatic) { + etsg->LoadThis(expr_); + etsg->StoreAccumulator(this, calleeReg); + } + } else if (expr_->Callee()->IsMemberExpression()) { + if (!isStatic) { + expr_->Callee()->AsMemberExpression()->Object()->Compile(etsg); + etsg->StoreAccumulator(this, calleeReg); + } + } else { + expr_->Callee()->Compile(etsg); + etsg->StoreAccumulator(this, calleeReg); + } + std::string *ctorName = new std::string(closureClassName_); *ctorName += "._ctor_"; auto *checker = const_cast(etsg->Checker()); - auto *sigInfo = checker->Allocator()->New(expr_->Signature()->GetSignatureInfo(), checker->Allocator()); + auto *sigInfo = + checker->Allocator()->New(expr_->Signature()->GetSignatureInfo(), checker->Allocator()); auto *signature = checker->Allocator()->New(sigInfo, checker->GlobalVoidType(), util::StringView(*ctorName)); - etsg->InitObject(this, signature, expr_->Arguments()); - etsg->Acc().SetType(TsType()); + if (isStatic) { + etsg->InitObject(this, signature, expr_->Arguments()); + } else { + etsg->InitThisObject(this, calleeReg, signature, expr_->Arguments()); + } + + etsg->CallAccStatic0(this, compiler::Signatures::BUILTIN_COROUTINE_LAUNCH); + etsg->SetAccumulatorType(TsType()); } checker::Type *ETSLaunchExpression::Check([[maybe_unused]] checker::TSChecker *checker) @@ -72,4 +96,9 @@ checker::Type *ETSLaunchExpression::Check(checker::ETSChecker *checker) SetTsType(checker->GlobalBuiltinPromiseType()); return TsType(); } + +bool ETSLaunchExpression::IsStaticCall() const +{ + return expr_->Signature()->HasSignatureFlag(checker::SignatureFlags::STATIC); +} } // namespace panda::es2panda::ir diff --git a/ir/ets/etsLaunchExpression.h b/ir/ets/etsLaunchExpression.h index 8c0bec8f6..6bbc467fa 100644 --- a/ir/ets/etsLaunchExpression.h +++ b/ir/ets/etsLaunchExpression.h @@ -36,6 +36,7 @@ public: void Compile([[maybe_unused]] compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override; + bool IsStaticCall() const; const CallExpression *Call() const { -- Gitee