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 "lexenv.h" 17 18#include "varbinder/variable.h" 19#include "compiler/core/envScope.h" 20#include "compiler/core/pandagen.h" 21#include "compiler/core/moduleContext.h" 22#include "ir/expressions/identifier.h" 23 24namespace ark::es2panda::compiler { 25// Helpers 26 27static bool CheckTdz(const ir::AstNode *node) 28{ 29 return node->IsIdentifier() && node->AsIdentifier()->IsTdz(); 30} 31 32static void CheckConstAssignment(PandaGen *pg, const ir::AstNode *node, varbinder::Variable *variable) 33{ 34 if (!variable->Declaration()->IsConstDecl()) { 35 return; 36 } 37 38 pg->ThrowConstAssignment(node, variable->Name()); 39} 40 41// VirtualLoadVar 42 43static void ExpandLoadLexVar(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result) 44{ 45 if (result.variable->Declaration()->IsVarDecl()) { 46 pg->LoadLexicalVar(node, result.lexLevel, result.variable->AsLocalVariable()->LexIdx()); 47 } else { 48 pg->LoadLexical(node, result.name, result.lexLevel, result.variable->AsLocalVariable()->LexIdx()); 49 } 50} 51 52static void ExpandLoadNormalVar(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result) 53{ 54 auto *local = result.variable->AsLocalVariable(); 55 56 if (CheckTdz(node)) { 57 pg->ThrowTdz(node, local->Name()); 58 } else { 59 pg->LoadAccumulator(node, local->Vreg()); 60 } 61} 62 63void VirtualLoadVar::Expand(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result) 64{ 65 if (result.variable->LexicalBound()) { 66 ExpandLoadLexVar(pg, node, result); 67 } else { 68 ExpandLoadNormalVar(pg, node, result); 69 } 70} 71 72// VirtualStoreVar 73 74static void StoreLocalExport(PandaGen *pg, const ir::AstNode *node, varbinder::Variable *variable) 75{ 76 if (!variable->HasFlag(varbinder::VariableFlags::LOCAL_EXPORT) || !pg->Scope()->IsModuleScope()) { 77 return; 78 } 79 80 auto range = pg->Scope()->AsModuleScope()->LocalExports().equal_range(variable); 81 82 for (auto it = range.first; it != range.second; ++it) { 83 if (it->second != "default") { 84 pg->StoreModuleVar(node, it->second); 85 } 86 } 87} 88 89static void ExpandStoreLexVar(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result, 90 bool isDecl) 91{ 92 varbinder::LocalVariable *local = result.variable->AsLocalVariable(); 93 94 const auto *decl = result.variable->Declaration(); 95 96 if (decl->IsLetOrConstDecl() && !isDecl) { 97 if (decl->IsConstDecl()) { 98 pg->ThrowConstAssignment(node, local->Name()); 99 } 100 101 pg->StoreLexical(node, result.name, result.lexLevel, local->LexIdx()); 102 } else { 103 pg->StoreLexicalVar(node, result.lexLevel, local->LexIdx()); 104 } 105 106 StoreLocalExport(pg, node, local); 107} 108 109static void ExpandStoreNormalVar(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result, 110 bool isDecl) 111{ 112 auto *local = result.variable->AsLocalVariable(); 113 VReg localReg = local->Vreg(); 114 115 if (!isDecl) { 116 if (CheckTdz(node)) { 117 pg->ThrowTdz(node, local->Name()); 118 } 119 120 CheckConstAssignment(pg, node, local); 121 } 122 123 pg->StoreAccumulator(node, localReg); 124 StoreLocalExport(pg, node, local); 125} 126 127void VirtualStoreVar::Expand(PandaGen *pg, const ir::AstNode *node, const varbinder::ConstScopeFindResult &result, 128 bool isDecl) 129{ 130 if (result.variable->LexicalBound()) { 131 ExpandStoreLexVar(pg, node, result, isDecl); 132 } else { 133 ExpandStoreNormalVar(pg, node, result, isDecl); 134 } 135} 136} // namespace ark::es2panda::compiler 137