13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "lexenv.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include <binder/variable.h>
193af6ab5fSopenharmony_ci#include <compiler/core/compilerContext.h>
203af6ab5fSopenharmony_ci#include <compiler/core/envScope.h>
213af6ab5fSopenharmony_ci#include <compiler/core/pandagen.h>
223af6ab5fSopenharmony_ci#include <ir/base/classDefinition.h>
233af6ab5fSopenharmony_ci#include <ir/base/scriptFunction.h>
243af6ab5fSopenharmony_ci#include <ir/expressions/identifier.h>
253af6ab5fSopenharmony_ci
263af6ab5fSopenharmony_cinamespace panda::es2panda::compiler {
273af6ab5fSopenharmony_ci
283af6ab5fSopenharmony_ci// Helpers
293af6ab5fSopenharmony_ci
303af6ab5fSopenharmony_cistatic bool CheckTdz(const ir::AstNode *node)
313af6ab5fSopenharmony_ci{
323af6ab5fSopenharmony_ci    return node->IsIdentifier() && node->AsIdentifier()->IsTdz();
333af6ab5fSopenharmony_ci}
343af6ab5fSopenharmony_ci
353af6ab5fSopenharmony_cistatic void CheckConstAssignment(PandaGen *pg, const ir::AstNode *node, binder::Variable *variable)
363af6ab5fSopenharmony_ci{
373af6ab5fSopenharmony_ci    if (!variable->Declaration()->IsConstDecl()) {
383af6ab5fSopenharmony_ci        return;
393af6ab5fSopenharmony_ci    }
403af6ab5fSopenharmony_ci
413af6ab5fSopenharmony_ci    pg->ThrowConstAssignment(node, variable->Name());
423af6ab5fSopenharmony_ci}
433af6ab5fSopenharmony_ci
443af6ab5fSopenharmony_ci// VirtualLoadVar
453af6ab5fSopenharmony_ci
463af6ab5fSopenharmony_cistatic void ExpandLoadLexVar(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result)
473af6ab5fSopenharmony_ci{
483af6ab5fSopenharmony_ci    /**
493af6ab5fSopenharmony_ci     *  Instruction ldsendableclass is generated when use sendable class inside itself, except static initializer.
503af6ab5fSopenharmony_ci     *  Because static initializer is not defined with instruction definesendableclass.
513af6ab5fSopenharmony_ci     */
523af6ab5fSopenharmony_ci    auto decl = result.variable->Declaration();
533af6ab5fSopenharmony_ci    if (decl->IsSendableClassDecl()) {
543af6ab5fSopenharmony_ci        auto classDef = decl->Node()->AsClassDefinition();
553af6ab5fSopenharmony_ci        if (classDef == util::Helpers::GetContainingSendableClass(node) &&
563af6ab5fSopenharmony_ci            !util::Helpers::IsChildScope(classDef->StaticInitializer()->Function()->Scope(), pg->TopScope())) {
573af6ab5fSopenharmony_ci            pg->LoadSendableClass(node, result.lexLevel);
583af6ab5fSopenharmony_ci            return;
593af6ab5fSopenharmony_ci        }
603af6ab5fSopenharmony_ci    }
613af6ab5fSopenharmony_ci
623af6ab5fSopenharmony_ci    auto *local = result.variable->AsLocalVariable();
633af6ab5fSopenharmony_ci    if (local->InSendableEnv()) {
643af6ab5fSopenharmony_ci        pg->LoadSendableVar(node, result.sendableLevel, local->LexIdx());
653af6ab5fSopenharmony_ci    } else {
663af6ab5fSopenharmony_ci        pg->LoadLexicalVar(node, result.lexLevel, local->LexIdx(), result.variable->Name());
673af6ab5fSopenharmony_ci    }
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci    if (decl->IsLetOrConstOrClassDecl()) {
703af6ab5fSopenharmony_ci        pg->ThrowUndefinedIfHole(node, result.variable->Name());
713af6ab5fSopenharmony_ci    }
723af6ab5fSopenharmony_ci}
733af6ab5fSopenharmony_ci
743af6ab5fSopenharmony_cistatic void ExpandLoadNormalVar(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result)
753af6ab5fSopenharmony_ci{
763af6ab5fSopenharmony_ci    auto *local = result.variable->AsLocalVariable();
773af6ab5fSopenharmony_ci
783af6ab5fSopenharmony_ci    if (CheckTdz(node)) {
793af6ab5fSopenharmony_ci        pg->LoadConst(node, Constant::JS_HOLE);
803af6ab5fSopenharmony_ci        pg->ThrowUndefinedIfHole(node, local->Name());
813af6ab5fSopenharmony_ci    } else {
823af6ab5fSopenharmony_ci        pg->LoadAccumulator(node, local->Vreg());
833af6ab5fSopenharmony_ci    }
843af6ab5fSopenharmony_ci}
853af6ab5fSopenharmony_ci
863af6ab5fSopenharmony_civoid VirtualLoadVar::Expand(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result)
873af6ab5fSopenharmony_ci{
883af6ab5fSopenharmony_ci    if (result.variable->LexicalBound()) {
893af6ab5fSopenharmony_ci        ExpandLoadLexVar(pg, node, result);
903af6ab5fSopenharmony_ci    } else {
913af6ab5fSopenharmony_ci        ExpandLoadNormalVar(pg, node, result);
923af6ab5fSopenharmony_ci    }
933af6ab5fSopenharmony_ci}
943af6ab5fSopenharmony_ci
953af6ab5fSopenharmony_ci// VirtualStoreVar
963af6ab5fSopenharmony_ci
973af6ab5fSopenharmony_cistatic void ExpandStoreLexVar(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDecl)
983af6ab5fSopenharmony_ci{
993af6ab5fSopenharmony_ci    binder::LocalVariable *local = result.variable->AsLocalVariable();
1003af6ab5fSopenharmony_ci
1013af6ab5fSopenharmony_ci    const auto *decl = result.variable->Declaration();
1023af6ab5fSopenharmony_ci
1033af6ab5fSopenharmony_ci    if (decl->IsLetOrConstOrClassDecl() && !isDecl) {
1043af6ab5fSopenharmony_ci        RegScope rs(pg);
1053af6ab5fSopenharmony_ci
1063af6ab5fSopenharmony_ci        VReg valueReg = pg->AllocReg();
1073af6ab5fSopenharmony_ci        pg->StoreAccumulator(node, valueReg);
1083af6ab5fSopenharmony_ci
1093af6ab5fSopenharmony_ci        ExpandLoadLexVar(pg, node, result);
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_ci        if (decl->IsConstDecl()) {
1123af6ab5fSopenharmony_ci            pg->ThrowConstAssignment(node, local->Name());
1133af6ab5fSopenharmony_ci        }
1143af6ab5fSopenharmony_ci
1153af6ab5fSopenharmony_ci        pg->LoadAccumulator(node, valueReg);
1163af6ab5fSopenharmony_ci    }
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_ci    if (local->InSendableEnv()) {
1193af6ab5fSopenharmony_ci        pg->StoreSendableVar(node, result.sendableLevel, local->LexIdx());
1203af6ab5fSopenharmony_ci        return;
1213af6ab5fSopenharmony_ci    }
1223af6ab5fSopenharmony_ci    pg->StoreLexicalVar(node, result.lexLevel, local->LexIdx(), local);
1233af6ab5fSopenharmony_ci}
1243af6ab5fSopenharmony_ci
1253af6ab5fSopenharmony_cistatic void ExpandStoreNormalVar(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result,
1263af6ab5fSopenharmony_ci                                 bool isDecl)
1273af6ab5fSopenharmony_ci{
1283af6ab5fSopenharmony_ci    auto *local = result.variable->AsLocalVariable();
1293af6ab5fSopenharmony_ci    VReg localReg = local->Vreg();
1303af6ab5fSopenharmony_ci
1313af6ab5fSopenharmony_ci    if (!isDecl) {
1323af6ab5fSopenharmony_ci        if (CheckTdz(node)) {
1333af6ab5fSopenharmony_ci            pg->LoadConst(node, Constant::JS_HOLE);
1343af6ab5fSopenharmony_ci            pg->ThrowUndefinedIfHole(node, local->Name());
1353af6ab5fSopenharmony_ci        }
1363af6ab5fSopenharmony_ci
1373af6ab5fSopenharmony_ci        CheckConstAssignment(pg, node, local);
1383af6ab5fSopenharmony_ci    }
1393af6ab5fSopenharmony_ci
1403af6ab5fSopenharmony_ci    pg->StoreAccumulator(node, localReg);
1413af6ab5fSopenharmony_ci}
1423af6ab5fSopenharmony_ci
1433af6ab5fSopenharmony_civoid VirtualStoreVar::Expand(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDecl)
1443af6ab5fSopenharmony_ci{
1453af6ab5fSopenharmony_ci    if (result.variable->LexicalBound()) {
1463af6ab5fSopenharmony_ci        ExpandStoreLexVar(pg, node, result, isDecl);
1473af6ab5fSopenharmony_ci    } else {
1483af6ab5fSopenharmony_ci        ExpandStoreNormalVar(pg, node, result, isDecl);
1493af6ab5fSopenharmony_ci    }
1503af6ab5fSopenharmony_ci}
1513af6ab5fSopenharmony_ci
1523af6ab5fSopenharmony_ci}  // namespace panda::es2panda::compiler
153