diff --git a/es2panda/compiler/base/iterators.cpp b/es2panda/compiler/base/iterators.cpp index 8ba4d12a112babd5be5ced988353548bac097703..47d653b8ee8b1aa983ecb5b73cb67f91726c5ee0 100644 --- a/es2panda/compiler/base/iterators.cpp +++ b/es2panda/compiler/base/iterators.cpp @@ -35,13 +35,11 @@ Iterator::Iterator(PandaGen *pg, const ir::AstNode *node, IteratorType type) pg_->StoreAccumulator(node, iterator_); pg_->LoadObjByName(node_, iterator_, "next"); pg_->StoreAccumulator(node_, method_); - - pg_->ThrowIfNotObject(node_); } void Iterator::GetMethod(util::StringView name) const { - pg_->GetMethod(node_, iterator_, name); + pg_->LoadObjByName(node_, iterator_, name); pg_->StoreAccumulator(node_, method_); } @@ -63,8 +61,8 @@ void Iterator::Next() const pg_->FuncBuilder()->Await(node_); } - pg_->ThrowIfNotObject(node_); pg_->StoreAccumulator(node_, nextResult_); + pg_->ThrowIfNotObject(node_, nextResult_); } void Iterator::Complete() const @@ -80,10 +78,34 @@ void Iterator::Value() const void Iterator::Close(bool abruptCompletion) const { if (type_ == IteratorType::SYNC) { - if (!abruptCompletion) { - pg_->LoadConst(node_, Constant::JS_HOLE); + RegScope rs(pg_); + VReg exception = pg_->AllocReg(); + VReg doneResult = pg_->AllocReg(); + VReg innerResult = pg_->AllocReg(); + Label *noReturn = pg_->AllocLabel(); + + if (abruptCompletion) { + pg_->StoreAccumulator(node_, exception); + } + + pg_->StoreConst(node_, doneResult, Constant::JS_TRUE); + Complete(); + pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, doneResult, noReturn); + + // close iterator + pg_->LoadObjByName(node_, iterator_, "return"); + pg_->StoreAccumulator(node_, method_); + pg_->LoadConst(node_, Constant::JS_UNDEFINED); + pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, method_, noReturn); + CallMethod(); + pg_->StoreAccumulator(node_, innerResult); + pg_->ThrowIfNotObject(node_, innerResult); + + pg_->SetLabel(node_, noReturn); + if (abruptCompletion) { + pg_->LoadAccumulator(node_, exception); + pg_->EmitThrow(node_); } - pg_->CloseIterator(node_, iterator_); return; } @@ -159,7 +181,7 @@ void Iterator::Close(bool abruptCompletion) const // 8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. pg_->LoadAccumulator(node_, innerResult); - pg_->ThrowIfNotObject(node_); + pg_->ThrowIfNotObject(node_, innerResult); } DestructuringIterator::DestructuringIterator(PandaGen *pg, const ir::AstNode *node) diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 17375d9a93e8359e6e7b4374cc5bc0e9888b6ca9..21ca7cf5857db079faeef95de18e6393fb3a4fe1 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -983,7 +983,9 @@ void PandaGen::LoadHomeObject(const ir::AstNode *node) void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name) { auto formalParamCnt = realNode->FormalParamsLength(); - if (realNode->IsAsync()) { + if (realNode->IsMethod()) { + ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); + } else if (realNode->IsAsync()) { if (realNode->IsGenerator()) { // TODO(): async generator } else { @@ -994,8 +996,6 @@ void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction } else if (realNode->IsArrow()) { LoadHomeObject(node); ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); - } else if (realNode->IsMethod()) { - ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); } else { ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); } @@ -1040,15 +1040,6 @@ void PandaGen::ToNumber(const ir::AstNode *node, VReg arg) ra_.Emit(node, arg); } -void PandaGen::GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name) -{ - /** - * TODO - * ra_.Emit(node, name, obj); - * strings_.insert(name); - */ -} - void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj) { ra_.Emit(node, funcObj); @@ -1062,20 +1053,14 @@ void PandaGen::CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj) */ } -void PandaGen::CreateIterResultObject(const ir::AstNode *node, bool done) +void PandaGen::CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done) { - /* - * TODO: create iter result - * ra_.Emit(node, static_cast(done)); - */ + ra_.Emit(node, value, done); } -void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj) +void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj, VReg iterResult) { - /* - * TODO: suspend generator - * ra_.Emit(node, genObj); - */ + ra_.Emit(node, genObj, iterResult); } void PandaGen::SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj) @@ -1117,28 +1102,19 @@ void PandaGen::AsyncFunctionEnter(const ir::AstNode *node) sa_.Emit(node); } -void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj, VReg retVal) { - /* - * TODO: async function await - * ra_.Emit(node, asyncFuncObj); - */ + ra_.Emit(node, asyncFuncObj, retVal); } -void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend) { - /* - * TODO: async function resolve - * ra_.Emit(node, asyncFuncObj); - */ + ra_.Emit(node, asyncFuncObj, value, canSuspend); } -void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend) { - /* - * TODO: async function reject - * ra_.Emit(node, asyncFuncObj); - */ + ra_.Emit(node, asyncFuncObj, value, canSuspend); } void PandaGen::AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj) @@ -1324,12 +1300,9 @@ void PandaGen::StoreArraySpread(const ir::AstNode *node, VReg array, VReg index) ra_.Emit(node, array, index); } -void PandaGen::ThrowIfNotObject(const ir::AstNode *node) +void PandaGen::ThrowIfNotObject(const ir::AstNode *node, VReg obj) { - // TODO: implement this method correctly - RegScope rs(this); - VReg value = AllocReg(); - ra_.Emit(node, value); + ra_.Emit(node, obj); } void PandaGen::ThrowThrowNotExist(const ir::AstNode *node) diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index 67582f92e3112017278889585a03aef2304ed600..6086561b1439b4b4090b7b03b425f9e5a801abb4 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -294,16 +294,15 @@ public: void GetResumeMode(const ir::AstNode *node, VReg genObj); void AsyncFunctionEnter(const ir::AstNode *node); - void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj); - void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj); - void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj); + void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj, VReg retVal); + void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend); + void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend); - void GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name); void GeneratorYield(const ir::AstNode *node, VReg genObj); void GeneratorComplete(const ir::AstNode *node, VReg genObj); void CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj); - void CreateIterResultObject(const ir::AstNode *node, bool done); - void SuspendGenerator(const ir::AstNode *node, VReg genObj); + void CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done); + void SuspendGenerator(const ir::AstNode *node, VReg genObj, VReg iterResult); void SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj); void AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj); @@ -326,7 +325,7 @@ public: void CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx); void StoreArraySpread(const ir::AstNode *node, VReg array, VReg index); - void ThrowIfNotObject(const ir::AstNode *node); + void ThrowIfNotObject(const ir::AstNode *node, VReg obj); void ThrowThrowNotExist(const ir::AstNode *node); void GetIterator(const ir::AstNode *node); void GetAsyncIterator(const ir::AstNode *node); diff --git a/es2panda/compiler/function/asyncFunctionBuilder.cpp b/es2panda/compiler/function/asyncFunctionBuilder.cpp index acbbc790ab449ea78e45f907ad6cc3d527c0c3d5..170db3207315506a56f354e901c50a69a9fe9dc7 100644 --- a/es2panda/compiler/function/asyncFunctionBuilder.cpp +++ b/es2panda/compiler/function/asyncFunctionBuilder.cpp @@ -23,7 +23,15 @@ namespace panda::es2panda::compiler { void AsyncFunctionBuilder::DirectReturn(const ir::AstNode *node) const { - pg_->AsyncFunctionResolve(node, funcObj_); + RegScope rs(pg_); + VReg retVal = pg_->AllocReg(); + VReg canSuspend = pg_->AllocReg(); + + pg_->StoreAccumulator(node, retVal); + pg_->LoadConst(node, Constant::JS_TRUE); + pg_->StoreAccumulator(node, canSuspend); + pg_->AsyncFunctionResolve(node, funcObj_, retVal, canSuspend); + pg_->LoadAccumulator(node, retVal); pg_->EmitReturn(node); } @@ -33,7 +41,7 @@ void AsyncFunctionBuilder::ImplicitReturn(const ir::AstNode *node) const DirectReturn(node); } -void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) { pg_->AsyncFunctionEnter(node); pg_->StoreAccumulator(node, funcObj_); @@ -42,11 +50,16 @@ void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) const void AsyncFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const { + RegScope rs(pg_); const auto &labelSet = catchTable_->LabelSet(); pg_->SetLabel(node, labelSet.TryEnd()); pg_->SetLabel(node, labelSet.CatchBegin()); - pg_->AsyncFunctionReject(node, funcObj_); + VReg exception = pg_->AllocReg(); + VReg canSuspend = pg_->AllocReg(); + pg_->StoreAccumulator(node, exception); + pg_->StoreConst(node, canSuspend, Constant::JS_TRUE); + pg_->AsyncFunctionReject(node, funcObj_, exception, canSuspend); pg_->EmitReturn(node); pg_->SetLabel(node, labelSet.CatchEnd()); } diff --git a/es2panda/compiler/function/asyncFunctionBuilder.h b/es2panda/compiler/function/asyncFunctionBuilder.h index bd7f38a81456a69877e83c58318ab9670dec20ba..68bdd99433f8cf94781f210ba5ca6842d8af09cb 100644 --- a/es2panda/compiler/function/asyncFunctionBuilder.h +++ b/es2panda/compiler/function/asyncFunctionBuilder.h @@ -30,7 +30,7 @@ public: NO_COPY_SEMANTIC(AsyncFunctionBuilder); NO_MOVE_SEMANTIC(AsyncFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override; diff --git a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp index c4360cd87af39409aa8692c5872f7498320848e7..a74eea46df994ebcf77a2c6e04bdbe664a8b0831 100644 --- a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp +++ b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp @@ -20,13 +20,13 @@ #include namespace panda::es2panda::compiler { -void AsyncGeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void AsyncGeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) { VReg callee = FunctionReg(node); pg_->CreateAsyncGeneratorObj(node, callee); pg_->StoreAccumulator(node, funcObj_); - pg_->SuspendGenerator(node, funcObj_); + // pg_->SuspendGenerator(node, funcObj_); TODO implement this part correctly while implementing async generator pg_->SetLabel(node, catchTable_->LabelSet().TryBegin()); } @@ -72,7 +72,7 @@ void AsyncGeneratorFunctionBuilder::Yield(const ir::AstNode *node) pg_->Condition(node, lexer::TokenType::PUNCTUATOR_EQUAL, completionType, notReturnCompletion); // 27.6.3.8.8.b. Let awaited be Await(resumptionValue.[[Value]]). pg_->LoadAccumulator(node, completionValue); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->AsyncFunctionAwait(node, funcObj_, completionValue); SuspendResumeExecution(node, completionType, completionValue); // 27.6.3.8.8.c. If awaited.[[Type]] is throw, return Completion(awaited). diff --git a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h index f492da49d1f4428945821d5f1a4fae51c75c7b91..8ae591a79c41b90324fb45d62f41ed5284df1f29 100644 --- a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h +++ b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h @@ -30,7 +30,7 @@ public: NO_COPY_SEMANTIC(AsyncGeneratorFunctionBuilder); NO_MOVE_SEMANTIC(AsyncGeneratorFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override; diff --git a/es2panda/compiler/function/functionBuilder.cpp b/es2panda/compiler/function/functionBuilder.cpp index eaba22a71aaada4722e54db98adba4d474341bc6..47184ca1f557a1cbed483deb7641eac1ad3da9cb 100644 --- a/es2panda/compiler/function/functionBuilder.cpp +++ b/es2panda/compiler/function/functionBuilder.cpp @@ -68,7 +68,10 @@ void FunctionBuilder::SuspendResumeExecution(const ir::AstNode *node, VReg compl ASSERT(BuilderKind() == BuilderType::ASYNC || BuilderKind() == BuilderType::ASYNC_GENERATOR || BuilderKind() == BuilderType::GENERATOR); - pg_->SuspendGenerator(node, funcObj_); + RegScope rs(pg_); + VReg iterResult = pg_->AllocReg(); + pg_->StoreAccumulator(node, iterResult); + pg_->SuspendGenerator(node, funcObj_, iterResult); resumeGenerator(node, completionType, completionValue); } @@ -103,8 +106,10 @@ void FunctionBuilder::Await(const ir::AstNode *node) RegScope rs(pg_); VReg completionType = pg_->AllocReg(); VReg completionValue = pg_->AllocReg(); + VReg retVal = pg_->AllocReg(); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->StoreAccumulator(node, retVal); + pg_->AsyncFunctionAwait(node, funcObj_, retVal); SuspendResumeExecution(node, completionType, completionValue); HandleCompletion(node, completionType, completionValue); @@ -239,7 +244,7 @@ void FunctionBuilder::YieldStar(const ir::AstNode *node) // ii. If Type(innerResult) is not Object, throw a TypeError exception. // 4. If Type(innerResult) is not Object, throw a TypeError exception. // vi. If Type(innerReturnResult) is not Object, throw a TypeError exception. - pg_->ThrowIfNotObject(node); + pg_->ThrowIfNotObject(node, receivedValue); // iv. Let done be ? IteratorComplete(innerResult). // v. Let done be ? IteratorComplete(innerResult). @@ -264,8 +269,7 @@ void FunctionBuilder::YieldStar(const ir::AstNode *node) pg_->Condition(node, lexer::TokenType::PUNCTUATOR_EQUAL, receivedType, loopStart); // b. Let awaited be Await(resumptionValue.[[Value]]). - pg_->LoadAccumulator(node, receivedValue); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->AsyncFunctionAwait(node, funcObj_, receivedValue); SuspendResumeExecution(node, receivedType, receivedValue); // c. If awaited.[[Type]] is throw, return Completion(awaited). diff --git a/es2panda/compiler/function/functionBuilder.h b/es2panda/compiler/function/functionBuilder.h index 4147c49577a673a71ea7f8ee198bc1e2158443ce..63abf6f78e5cd054a2064fe9340ff85ee66d1f20 100644 --- a/es2panda/compiler/function/functionBuilder.h +++ b/es2panda/compiler/function/functionBuilder.h @@ -49,7 +49,7 @@ public: NO_COPY_SEMANTIC(FunctionBuilder); NO_MOVE_SEMANTIC(FunctionBuilder); - virtual void Prepare([[maybe_unused]] const ir::ScriptFunction *node) const {}; + virtual void Prepare([[maybe_unused]] const ir::ScriptFunction *node) {}; virtual void CleanUp([[maybe_unused]] const ir::ScriptFunction *node) const {}; virtual void DirectReturn(const ir::AstNode *node) const; diff --git a/es2panda/compiler/function/generatorFunctionBuilder.cpp b/es2panda/compiler/function/generatorFunctionBuilder.cpp index a4d71b3fd2dac50aded1c33cabc31d89dac78a15..e302dfe9846fa2b1d6be422225399a35fc3ccc1a 100644 --- a/es2panda/compiler/function/generatorFunctionBuilder.cpp +++ b/es2panda/compiler/function/generatorFunctionBuilder.cpp @@ -21,14 +21,17 @@ namespace panda::es2panda::compiler { -void GeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void GeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) { VReg callee = FunctionReg(node); + VReg completionType = pg_->AllocReg(); + VReg completionValue = pg_->AllocReg(); pg_->CreateGeneratorObj(node, callee); pg_->StoreAccumulator(node, funcObj_); - pg_->SuspendGenerator(node, funcObj_); - pg_->SetLabel(node, catchTable_->LabelSet().TryBegin()); + pg_->LoadConst(node, Constant::JS_UNDEFINED); + SuspendResumeExecution(node, completionType, completionValue); + HandleCompletion(node, completionType, completionValue); } void GeneratorFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const @@ -44,8 +47,6 @@ void GeneratorFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const void GeneratorFunctionBuilder::DirectReturn(const ir::AstNode *node) const { - pg_->GeneratorComplete(node, funcObj_); - pg_->CreateIterResultObject(node, true); pg_->EmitReturn(node); } @@ -58,11 +59,15 @@ void GeneratorFunctionBuilder::ImplicitReturn(const ir::AstNode *node) const void GeneratorFunctionBuilder::Yield(const ir::AstNode *node) { RegScope rs(pg_); + VReg value = pg_->AllocReg(); + VReg done = pg_->AllocReg(); VReg completionType = pg_->AllocReg(); VReg completionValue = pg_->AllocReg(); - pg_->CreateIterResultObject(node, false); - pg_->GeneratorYield(node, funcObj_); + pg_->StoreAccumulator(node, value); + pg_->LoadConst(node, Constant::JS_FALSE); + pg_->StoreAccumulator(node, done); + pg_->CreateIterResultObject(node, value, done); SuspendResumeExecution(node, completionType, completionValue); HandleCompletion(node, completionType, completionValue); diff --git a/es2panda/compiler/function/generatorFunctionBuilder.h b/es2panda/compiler/function/generatorFunctionBuilder.h index a1a12295654cff025fcd0754b8d1cd116074ecff..6b3b96acb38608325ffc00b5426909e807f617db 100644 --- a/es2panda/compiler/function/generatorFunctionBuilder.h +++ b/es2panda/compiler/function/generatorFunctionBuilder.h @@ -44,7 +44,7 @@ public: NO_COPY_SEMANTIC(GeneratorFunctionBuilder); NO_MOVE_SEMANTIC(GeneratorFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override;