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 "hoisting.h" 17 18#include "ir/base/scriptFunction.h" 19#include "varbinder/scope.h" 20#include "compiler/core/pandagen.h" 21 22namespace ark::es2panda::compiler { 23static void HoistVar(PandaGen *pg, varbinder::Variable *var, const varbinder::VarDecl *decl) 24{ 25 auto *scope = pg->Scope(); 26 27 if (scope->IsGlobalScope()) { 28 pg->LoadConst(decl->Node(), Constant::JS_UNDEFINED); 29 pg->StoreGlobalVar(decl->Node(), decl->Name()); 30 return; 31 } 32 33 varbinder::ConstScopeFindResult result(decl->Name(), scope, 0, var); 34 35 pg->LoadConst(decl->Node(), Constant::JS_UNDEFINED); 36 pg->StoreAccToLexEnv(decl->Node(), result, true); 37} 38 39static void HoistFunction(PandaGen *pg, varbinder::Variable *var, const varbinder::FunctionDecl *decl) 40{ 41 const ir::ScriptFunction *scriptFunction = decl->Node()->AsScriptFunction(); 42 auto *scope = pg->Scope(); 43 44 const auto &internalName = scriptFunction->Scope()->InternalName(); 45 46 if (scope->IsGlobalScope()) { 47 pg->DefineFunction(decl->Node(), scriptFunction, internalName); 48 pg->StoreGlobalVar(decl->Node(), var->Declaration()->Name()); 49 return; 50 } 51 52 ASSERT(scope->IsFunctionScope() || scope->IsCatchScope() || scope->IsLocalScope() || scope->IsModuleScope()); 53 varbinder::ConstScopeFindResult result(decl->Name(), scope, 0, var); 54 55 pg->DefineFunction(decl->Node(), scriptFunction, internalName); 56 pg->StoreAccToLexEnv(decl->Node(), result, true); 57} 58 59void Hoisting::Hoist(PandaGen *pg) 60{ 61 const auto *scope = pg->Scope(); 62 63 for (const auto &[_, var] : scope->Bindings()) { 64 (void)_; 65 if (!var->HasFlag(varbinder::VariableFlags::HOIST)) { 66 continue; 67 } 68 69 const auto *decl = var->Declaration(); 70 71 if (decl->IsVarDecl()) { 72 HoistVar(pg, var, decl->AsVarDecl()); 73 } else { 74 ASSERT(decl->IsFunctionDecl()); 75 HoistFunction(pg, var, decl->AsFunctionDecl()); 76 } 77 } 78} 79} // namespace ark::es2panda::compiler 80