diff --git a/BUILD.gn b/BUILD.gn index 231bf13f01a0b239bf922d2164e30df4397b0e6a..82517265a4a9ebd77a88e1d39d08d64886eb8ff5 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 0db70f8571451d26537313764baf8ff16a5a3bd2..4b2de5d92064df1ee8e04730ed5a77caf73fa2a2 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/binder/ETSBinder.cpp b/binder/ETSBinder.cpp index 35ae12dc90b61ac6a359e41309183743925f786e..2a57aea7b43beb1ac08990f8fbea99ffb15c5d0a 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 bcfb4217172eda4c4c660e3a806e17c214266f0e..fe8a5049ad737a71df16125174a9606899f11742 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 bb7dba2736eceb23d18409572a0bc998775b3b8d..2bfae46ceb1d3d29d42879e8741e7130425d1d03 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/checker/ETSchecker.cpp b/checker/ETSchecker.cpp index 752bcbe351fc2f1d31461874eb7db1a2c524f0ea..999d11a26af00d5c61f3d888ab894b485e38da44 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 9f73aed1988be78381c2020d9b79a08e70e5713c..db78e8e6c9e9e97e368316056c46f47e12da46d4 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 4adfa40e2cdd15fc5151d055714285751717598f..3d0045b9ecd192b349ad1d5ccb4cb001657a3972 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 ea93ab12ea80dcdfcee6c26887a0622b686fe880..240559d9a4d1a30e367695794a976d6eb6c45c5e 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 5cd1d3a8930fcd5f356c5670a3ca71719f401b33..dbd7156acc1380597ab8fab4c4be75769846962d 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/core/ETSGen.h b/compiler/core/ETSGen.h index 87b4db78f45c6f7d87974968629ba40a431848fa..247b30263eaff2bf9d8f2fbd99a2b6d50be04a71 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 c67ae58c44bbe31ab32188b6205dfef1c7a353b8..ace8838bb21862ecd1e07ff78bb952d9577fb6a8 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,8 @@ #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/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" @@ -30,6 +33,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 +215,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 +373,113 @@ 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; + // 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; + 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; + 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(); + 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 839a2fda7eb5a95286bc4c4d0c5033c3890e68bd..ccb8179cad16a2944e9a860b957bd5dd43001e7a 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 58bcf58fbe4ec6f7e836ac4e1b34b2fd0bdce0ba..4558040031dca6eadf3ce7022d7ec067b3802385 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' @@ -178,6 +181,12 @@ builtins: - name: Enum package: PKG_STD_CORE ref: BUILTIN_ENUM + - name: Promise + package: PKG_STD_CORE + ref: BUILTIN_PROMISE + - name: Coroutine + package: PKG_STD_CORE + ref: BUILTIN_COROUTINE signatures: - callee: BUILTIN_OBJECT @@ -365,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/astNodeMapping.h b/ir/astNodeMapping.h index 94f71f92ff84f3bf760fea6ff6028a43ad7ca19b..8ca2b58818fffdb558977db89d168b36a46b6f93 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 0000000000000000000000000000000000000000..06fb911c2da7e71a3596b1df9578a53aba9be348 --- /dev/null +++ b/ir/ets/etsLaunchExpression.cpp @@ -0,0 +1,104 @@ +/** + * 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/identifier.h" +#include "plugins/ecmascript/es2panda/ir/expressions/callExpression.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) +{ + size_t index = closureIndex_++; + std::stringstream out; + out << "_Closure_" << index; + closureClassName_ = out.str(); +} + +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(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 *signature = + checker->Allocator()->New(sigInfo, checker->GlobalVoidType(), util::StringView(*ctorName)); + 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) +{ + return nullptr; +} + +checker::Type *ETSLaunchExpression::Check(checker::ETSChecker *checker) +{ + expr_->Check(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 new file mode 100644 index 0000000000000000000000000000000000000000..6bbc467fa8e494feee6e58f302d4bad760b4adc1 --- /dev/null +++ b/ir/ets/etsLaunchExpression.h @@ -0,0 +1,58 @@ +/** + * 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::checker { +class Signature; +} + +namespace panda::es2panda::ir { + +class CallExpression; + +class ETSLaunchExpression : public Expression { +public: + explicit ETSLaunchExpression(CallExpression *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; + bool IsStaticCall() const; + + 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 + +#endif diff --git a/lexer/scripts/keywords.yaml b/lexer/scripts/keywords.yaml index 97b395468e974dba611409a0e3af98d4517616ed..4de8f1e356381023e770b636bdd2caedcbb379f9 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 97ea93fd9ca1c779ad4e84d4a05d72af2c5b7208..4f2c9117c6e0d16486310651ed44b05b7dec829c 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 167868134860264f2b1dd15aecff212d27630471..35bb8e3f5026e94db46a1be2140e4bf5f443799f 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 f9d079cf743c94e2815b256ef4c58e2e2601dc69..e285afbf5add4660bea438756636d41966750b4a 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,24 @@ 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 *expr = ParseLeftHandSideExpression(flags); + if (!expr->IsCallExpression()) { + ThrowSyntaxError("Only call expressions are allowed after 'launch'", expr->Start()); + } + auto call = expr->AsCallExpression(); + auto *launchExpression = AllocNode(call); + launchExpression->SetRange({start, call->End()}); + + static_cast(Binder())->AddLaunchExpression(launchExpression); + + return launchExpression; +} + // NOLINTNEXTLINE(google-default-arguments) ir::ClassDefinition *ETSParser::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags) { @@ -2067,6 +2086,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 f21971da77f215fc925f6d63c623f3c11f615b69..f35623a169cf773bd90ef8194b81bf3052d26e3f 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;