13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2022 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 "lreference.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include <binder/declaration.h>
193af6ab5fSopenharmony_ci#include <compiler/base/destructuring.h>
203af6ab5fSopenharmony_ci#include <compiler/core/pandagen.h>
213af6ab5fSopenharmony_ci#include <ir/base/classDefinition.h>
223af6ab5fSopenharmony_ci#include <ir/base/spreadElement.h>
233af6ab5fSopenharmony_ci#include <ir/expressions/assignmentExpression.h>
243af6ab5fSopenharmony_ci#include <ir/expressions/identifier.h>
253af6ab5fSopenharmony_ci#include <ir/expressions/memberExpression.h>
263af6ab5fSopenharmony_ci#include <ir/statements/variableDeclaration.h>
273af6ab5fSopenharmony_ci#include <ir/statements/variableDeclarator.h>
283af6ab5fSopenharmony_ci#include <ir/ts/tsAsExpression.h>
293af6ab5fSopenharmony_ci#include <ir/ts/tsSatisfiesExpression.h>
303af6ab5fSopenharmony_ci#include <ir/ts/tsTypeAssertion.h>
313af6ab5fSopenharmony_ci#include <ir/ts/tsNonNullExpression.h>
323af6ab5fSopenharmony_ci
333af6ab5fSopenharmony_cinamespace panda::es2panda::compiler {
343af6ab5fSopenharmony_ci
353af6ab5fSopenharmony_ci// LReference
363af6ab5fSopenharmony_ci
373af6ab5fSopenharmony_ciLReference::LReference(const ir::AstNode *node, PandaGen *pg, bool isDeclaration, ReferenceKind refKind,
383af6ab5fSopenharmony_ci                       binder::ScopeFindResult res)
393af6ab5fSopenharmony_ci    : node_(node), pg_(pg), refKind_(refKind), res_(res), isDeclaration_(isDeclaration)
403af6ab5fSopenharmony_ci{
413af6ab5fSopenharmony_ci    if (refKind == ReferenceKind::MEMBER) {
423af6ab5fSopenharmony_ci        obj_ = pg_->AllocReg();
433af6ab5fSopenharmony_ci
443af6ab5fSopenharmony_ci        node_->AsMemberExpression()->CompileObject(pg_, obj_);
453af6ab5fSopenharmony_ci        if (!node_->AsMemberExpression()->AccessPrivateProperty()) {
463af6ab5fSopenharmony_ci            prop_ = node->AsMemberExpression()->CompileKey(pg_);
473af6ab5fSopenharmony_ci        }
483af6ab5fSopenharmony_ci    }
493af6ab5fSopenharmony_ci}
503af6ab5fSopenharmony_ci
513af6ab5fSopenharmony_civoid LReference::GetValue()
523af6ab5fSopenharmony_ci{
533af6ab5fSopenharmony_ci    switch (refKind_) {
543af6ab5fSopenharmony_ci        case ReferenceKind::VAR_OR_GLOBAL: {
553af6ab5fSopenharmony_ci            pg_->LoadVar(node_->AsIdentifier(), res_);
563af6ab5fSopenharmony_ci            break;
573af6ab5fSopenharmony_ci        }
583af6ab5fSopenharmony_ci        case ReferenceKind::MEMBER: {
593af6ab5fSopenharmony_ci            if (node_->AsMemberExpression()->AccessPrivateProperty()) {
603af6ab5fSopenharmony_ci                auto name = node_->AsMemberExpression()->Property()->AsPrivateIdentifier()->Name();
613af6ab5fSopenharmony_ci                auto result = pg_->Scope()->FindPrivateName(name);
623af6ab5fSopenharmony_ci                if (!result.result.isMethod) {
633af6ab5fSopenharmony_ci                    pg_->LoadAccumulator(node_, obj_);
643af6ab5fSopenharmony_ci                    pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.slot);
653af6ab5fSopenharmony_ci                    break;
663af6ab5fSopenharmony_ci                }
673af6ab5fSopenharmony_ci
683af6ab5fSopenharmony_ci                if (result.result.isStatic) {
693af6ab5fSopenharmony_ci                    pg_->LoadLexicalVar(node_, result.lexLevel, result.result.validateMethodSlot);
703af6ab5fSopenharmony_ci                    pg_->Equal(node_, obj_);
713af6ab5fSopenharmony_ci                    pg_->ThrowTypeErrorIfFalse(node_, "Object does not have private property");
723af6ab5fSopenharmony_ci                } else {
733af6ab5fSopenharmony_ci                    pg_->LoadAccumulator(node_, obj_);
743af6ab5fSopenharmony_ci                    pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.validateMethodSlot);
753af6ab5fSopenharmony_ci                }
763af6ab5fSopenharmony_ci                if (result.result.isSetter) {
773af6ab5fSopenharmony_ci                    pg_->ThrowTypeError(node_, "Property is not defined with Getter");
783af6ab5fSopenharmony_ci                }
793af6ab5fSopenharmony_ci                if (result.result.isGetter) {
803af6ab5fSopenharmony_ci                    pg_->LoadAccumulator(node_, obj_);
813af6ab5fSopenharmony_ci                    pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.slot);
823af6ab5fSopenharmony_ci                    break;
833af6ab5fSopenharmony_ci                }
843af6ab5fSopenharmony_ci                pg_->LoadLexicalVar(node_, result.lexLevel, result.result.slot);
853af6ab5fSopenharmony_ci            } else {
863af6ab5fSopenharmony_ci                pg_->LoadObjProperty(node_, obj_, prop_);
873af6ab5fSopenharmony_ci            }
883af6ab5fSopenharmony_ci            break;
893af6ab5fSopenharmony_ci        }
903af6ab5fSopenharmony_ci        default: {
913af6ab5fSopenharmony_ci            UNREACHABLE();
923af6ab5fSopenharmony_ci        }
933af6ab5fSopenharmony_ci    }
943af6ab5fSopenharmony_ci}
953af6ab5fSopenharmony_ci
963af6ab5fSopenharmony_civoid LReference::SetValue()
973af6ab5fSopenharmony_ci{
983af6ab5fSopenharmony_ci    switch (refKind_) {
993af6ab5fSopenharmony_ci        case ReferenceKind::VAR_OR_GLOBAL: {
1003af6ab5fSopenharmony_ci            pg_->StoreVar(node_, res_, isDeclaration_);
1013af6ab5fSopenharmony_ci            break;
1023af6ab5fSopenharmony_ci        }
1033af6ab5fSopenharmony_ci        case ReferenceKind::MEMBER: {
1043af6ab5fSopenharmony_ci            if (node_->AsMemberExpression()->Object()->IsSuperExpression()) {
1053af6ab5fSopenharmony_ci                pg_->StoreSuperProperty(node_, obj_, prop_);
1063af6ab5fSopenharmony_ci            } else if (node_->AsMemberExpression()->AccessPrivateProperty()) {
1073af6ab5fSopenharmony_ci                compiler::RegScope rs(pg_);
1083af6ab5fSopenharmony_ci                VReg valueReg =  pg_->AllocReg();
1093af6ab5fSopenharmony_ci
1103af6ab5fSopenharmony_ci                auto name = node_->AsMemberExpression()->Property()->AsPrivateIdentifier()->Name();
1113af6ab5fSopenharmony_ci                auto result = pg_->Scope()->FindPrivateName(name, true);
1123af6ab5fSopenharmony_ci                if (!result.result.isMethod) {
1133af6ab5fSopenharmony_ci                    pg_->StorePrivateProperty(node_, result.lexLevel, result.result.slot, obj_);
1143af6ab5fSopenharmony_ci                    break;
1153af6ab5fSopenharmony_ci                }
1163af6ab5fSopenharmony_ci                if (!result.result.isSetter) {
1173af6ab5fSopenharmony_ci                    pg_->ThrowTypeError(node_, "Method is not writable");
1183af6ab5fSopenharmony_ci                }
1193af6ab5fSopenharmony_ci                // store value
1203af6ab5fSopenharmony_ci                pg_->StoreAccumulator(node_, valueReg);
1213af6ab5fSopenharmony_ci
1223af6ab5fSopenharmony_ci                if (result.result.isStatic) {
1233af6ab5fSopenharmony_ci                    pg_->LoadLexicalVar(node_, result.lexLevel, result.result.validateMethodSlot);
1243af6ab5fSopenharmony_ci                    pg_->Equal(node_, obj_);
1253af6ab5fSopenharmony_ci                    pg_->ThrowTypeErrorIfFalse(node_, "Object does not have private property");
1263af6ab5fSopenharmony_ci                } else {
1273af6ab5fSopenharmony_ci                    pg_->LoadAccumulator(node_, obj_);
1283af6ab5fSopenharmony_ci                    pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.validateMethodSlot);
1293af6ab5fSopenharmony_ci                }
1303af6ab5fSopenharmony_ci                pg_->LoadAccumulator(node_, valueReg);
1313af6ab5fSopenharmony_ci                pg_->StorePrivateProperty(node_, result.lexLevel, result.result.slot, obj_);
1323af6ab5fSopenharmony_ci            } else {
1333af6ab5fSopenharmony_ci                pg_->StoreObjProperty(node_, obj_, prop_);
1343af6ab5fSopenharmony_ci            }
1353af6ab5fSopenharmony_ci
1363af6ab5fSopenharmony_ci            break;
1373af6ab5fSopenharmony_ci        }
1383af6ab5fSopenharmony_ci        case ReferenceKind::DESTRUCTURING: {
1393af6ab5fSopenharmony_ci            Destructuring::Compile(pg_, node_->AsExpression());
1403af6ab5fSopenharmony_ci            break;
1413af6ab5fSopenharmony_ci        }
1423af6ab5fSopenharmony_ci        default: {
1433af6ab5fSopenharmony_ci            UNREACHABLE();
1443af6ab5fSopenharmony_ci        }
1453af6ab5fSopenharmony_ci    }
1463af6ab5fSopenharmony_ci}
1473af6ab5fSopenharmony_ci
1483af6ab5fSopenharmony_ciReferenceKind LReference::Kind() const
1493af6ab5fSopenharmony_ci{
1503af6ab5fSopenharmony_ci    return refKind_;
1513af6ab5fSopenharmony_ci}
1523af6ab5fSopenharmony_ci
1533af6ab5fSopenharmony_cibinder::Variable *LReference::Variable() const
1543af6ab5fSopenharmony_ci{
1553af6ab5fSopenharmony_ci    return res_.variable;
1563af6ab5fSopenharmony_ci}
1573af6ab5fSopenharmony_ci
1583af6ab5fSopenharmony_ciLReference LReference::CreateLRef(PandaGen *pg, const ir::AstNode *node, bool isDeclaration)
1593af6ab5fSopenharmony_ci{
1603af6ab5fSopenharmony_ci    switch (node->Type()) {
1613af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
1623af6ab5fSopenharmony_ci            const util::StringView &name = node->AsIdentifier()->Name();
1633af6ab5fSopenharmony_ci            binder::ScopeFindResult res = pg->Scope()->Find(name);
1643af6ab5fSopenharmony_ci
1653af6ab5fSopenharmony_ci            return {node, pg, isDeclaration, ReferenceKind::VAR_OR_GLOBAL, res};
1663af6ab5fSopenharmony_ci        }
1673af6ab5fSopenharmony_ci        case ir::AstNodeType::MEMBER_EXPRESSION: {
1683af6ab5fSopenharmony_ci            return {node, pg, false, ReferenceKind::MEMBER, {}};
1693af6ab5fSopenharmony_ci        }
1703af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATION: {
1713af6ab5fSopenharmony_ci            ASSERT(node->AsVariableDeclaration()->Declarators().size() == 1);
1723af6ab5fSopenharmony_ci            return LReference::CreateLRef(pg, node->AsVariableDeclaration()->Declarators()[0]->Id(), true);
1733af6ab5fSopenharmony_ci        }
1743af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATOR: {
1753af6ab5fSopenharmony_ci            return LReference::CreateLRef(pg, node->AsVariableDeclarator()->Id(), true);
1763af6ab5fSopenharmony_ci        }
1773af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_PATTERN:
1783af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_PATTERN:
1793af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_EXPRESSION:
1803af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_EXPRESSION: {
1813af6ab5fSopenharmony_ci            return {node, pg, isDeclaration, ReferenceKind::DESTRUCTURING, {}};
1823af6ab5fSopenharmony_ci        }
1833af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_PATTERN: {
1843af6ab5fSopenharmony_ci            return LReference::CreateLRef(pg, node->AsAssignmentPattern()->Left(), true);
1853af6ab5fSopenharmony_ci        }
1863af6ab5fSopenharmony_ci        case ir::AstNodeType::REST_ELEMENT: {
1873af6ab5fSopenharmony_ci            return LReference::CreateLRef(pg, node->AsRestElement()->Argument(), isDeclaration);
1883af6ab5fSopenharmony_ci        }
1893af6ab5fSopenharmony_ci        case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION: {
1903af6ab5fSopenharmony_ci            // export default [anonymous class decl]
1913af6ab5fSopenharmony_ci            util::StringView name = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME;
1923af6ab5fSopenharmony_ci            binder::ScopeFindResult res = pg->Scope()->Find(name);
1933af6ab5fSopenharmony_ci
1943af6ab5fSopenharmony_ci            return {node, pg, isDeclaration, ReferenceKind::VAR_OR_GLOBAL, res};
1953af6ab5fSopenharmony_ci        }
1963af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_AS_EXPRESSION: {
1973af6ab5fSopenharmony_ci            return LReference::CreateLRef(pg, node->AsTSAsExpression()->Expr(), isDeclaration);
1983af6ab5fSopenharmony_ci        }
1993af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_SATISFIES_EXPRESSION: {
2003af6ab5fSopenharmony_ci            return LReference::CreateLRef(pg, node->AsTSSatisfiesExpression()->Expr(), isDeclaration);
2013af6ab5fSopenharmony_ci        }
2023af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_TYPE_ASSERTION: {
2033af6ab5fSopenharmony_ci            return LReference::CreateLRef(pg, node->AsTSTypeAssertion()->GetExpression(), isDeclaration);
2043af6ab5fSopenharmony_ci        }
2053af6ab5fSopenharmony_ci        case ir::AstNodeType::TS_NON_NULL_EXPRESSION: {
2063af6ab5fSopenharmony_ci            return LReference::CreateLRef(pg, node->AsTSNonNullExpression()->Expr(), isDeclaration);
2073af6ab5fSopenharmony_ci        }
2083af6ab5fSopenharmony_ci        default: {
2093af6ab5fSopenharmony_ci            UNREACHABLE();
2103af6ab5fSopenharmony_ci        }
2113af6ab5fSopenharmony_ci    }
2123af6ab5fSopenharmony_ci}
2133af6ab5fSopenharmony_ci
2143af6ab5fSopenharmony_ci}  // namespace panda::es2panda::compiler
215