1/* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "expressionLambdaLowering.h" 17#include "checker/ETSchecker.h" 18 19namespace ark::es2panda::compiler { 20static ir::AstNode *ConvertExpression(checker::ETSChecker *const checker, ir::ArrowFunctionExpression *const arrow) 21{ 22 auto *const function = arrow->Function(); 23 auto *const scope = function->Scope(); 24 auto *const expr = function->Body()->AsExpression(); 25 26 ArenaVector<ir::Statement *> statements(checker->Allocator()->Adapter()); 27 28 if ((function->ReturnTypeAnnotation() != nullptr && function->ReturnTypeAnnotation()->IsETSPrimitiveType() && 29 function->ReturnTypeAnnotation()->AsETSPrimitiveType()->GetPrimitiveType() == ir::PrimitiveType::VOID)) { 30 statements.emplace_back(checker->AllocNode<ir::ExpressionStatement>(expr)); 31 } else { 32 statements.emplace_back(checker->AllocNode<ir::ReturnStatement>(expr)); 33 function->AddFlag(ir::ScriptFunctionFlags::HAS_RETURN); 34 } 35 36 auto *const block = checker->AllocNode<ir::BlockStatement>(checker->Allocator(), std::move(statements)); 37 38 block->SetScope(scope); 39 block->SetParent(function); 40 41 function->SetBody(block); 42 43 return arrow; 44} 45 46using AstNodePtr = ir::AstNode *; 47 48bool ExpressionLambdaConstructionPhase::Perform(public_lib::Context *ctx, parser::Program *program) 49{ 50 for (auto &[_, ext_programs] : program->ExternalSources()) { 51 (void)_; 52 for (auto *extProg : ext_programs) { 53 Perform(ctx, extProg); 54 } 55 } 56 57 checker::ETSChecker *const checker = ctx->checker->AsETSChecker(); 58 59 program->Ast()->TransformChildrenRecursively( 60 [checker](ir::AstNode *const node) -> AstNodePtr { 61 if (node->IsArrowFunctionExpression() && 62 node->AsArrowFunctionExpression()->Function()->Body()->IsExpression()) { 63 return ConvertExpression(checker, node->AsArrowFunctionExpression()); 64 } 65 66 return node; 67 }, 68 Name()); 69 70 return true; 71} 72 73bool ExpressionLambdaConstructionPhase::Postcondition(public_lib::Context *ctx, const parser::Program *program) 74{ 75 for (auto &[_, ext_programs] : program->ExternalSources()) { 76 (void)_; 77 for (auto *extProg : ext_programs) { 78 if (!Postcondition(ctx, extProg)) { 79 return false; 80 } 81 } 82 } 83 84 return !program->Ast()->IsAnyChild([](const ir::AstNode *node) { 85 return node->IsArrowFunctionExpression() && 86 node->AsArrowFunctionExpression()->Function()->Body()->IsExpression(); 87 }); 88} 89 90} // namespace ark::es2panda::compiler 91