1/* 2 * Copyright (c) 2021-2022 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 "lreference.h" 17 18#include <binder/declaration.h> 19#include <compiler/base/destructuring.h> 20#include <compiler/core/pandagen.h> 21#include <ir/base/classDefinition.h> 22#include <ir/base/spreadElement.h> 23#include <ir/expressions/assignmentExpression.h> 24#include <ir/expressions/identifier.h> 25#include <ir/expressions/memberExpression.h> 26#include <ir/statements/variableDeclaration.h> 27#include <ir/statements/variableDeclarator.h> 28#include <ir/ts/tsAsExpression.h> 29#include <ir/ts/tsSatisfiesExpression.h> 30#include <ir/ts/tsTypeAssertion.h> 31#include <ir/ts/tsNonNullExpression.h> 32 33namespace panda::es2panda::compiler { 34 35// LReference 36 37LReference::LReference(const ir::AstNode *node, PandaGen *pg, bool isDeclaration, ReferenceKind refKind, 38 binder::ScopeFindResult res) 39 : node_(node), pg_(pg), refKind_(refKind), res_(res), isDeclaration_(isDeclaration) 40{ 41 if (refKind == ReferenceKind::MEMBER) { 42 obj_ = pg_->AllocReg(); 43 44 node_->AsMemberExpression()->CompileObject(pg_, obj_); 45 if (!node_->AsMemberExpression()->AccessPrivateProperty()) { 46 prop_ = node->AsMemberExpression()->CompileKey(pg_); 47 } 48 } 49} 50 51void LReference::GetValue() 52{ 53 switch (refKind_) { 54 case ReferenceKind::VAR_OR_GLOBAL: { 55 pg_->LoadVar(node_->AsIdentifier(), res_); 56 break; 57 } 58 case ReferenceKind::MEMBER: { 59 if (node_->AsMemberExpression()->AccessPrivateProperty()) { 60 auto name = node_->AsMemberExpression()->Property()->AsPrivateIdentifier()->Name(); 61 auto result = pg_->Scope()->FindPrivateName(name); 62 if (!result.result.isMethod) { 63 pg_->LoadAccumulator(node_, obj_); 64 pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.slot); 65 break; 66 } 67 68 if (result.result.isStatic) { 69 pg_->LoadLexicalVar(node_, result.lexLevel, result.result.validateMethodSlot); 70 pg_->Equal(node_, obj_); 71 pg_->ThrowTypeErrorIfFalse(node_, "Object does not have private property"); 72 } else { 73 pg_->LoadAccumulator(node_, obj_); 74 pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.validateMethodSlot); 75 } 76 if (result.result.isSetter) { 77 pg_->ThrowTypeError(node_, "Property is not defined with Getter"); 78 } 79 if (result.result.isGetter) { 80 pg_->LoadAccumulator(node_, obj_); 81 pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.slot); 82 break; 83 } 84 pg_->LoadLexicalVar(node_, result.lexLevel, result.result.slot); 85 } else { 86 pg_->LoadObjProperty(node_, obj_, prop_); 87 } 88 break; 89 } 90 default: { 91 UNREACHABLE(); 92 } 93 } 94} 95 96void LReference::SetValue() 97{ 98 switch (refKind_) { 99 case ReferenceKind::VAR_OR_GLOBAL: { 100 pg_->StoreVar(node_, res_, isDeclaration_); 101 break; 102 } 103 case ReferenceKind::MEMBER: { 104 if (node_->AsMemberExpression()->Object()->IsSuperExpression()) { 105 pg_->StoreSuperProperty(node_, obj_, prop_); 106 } else if (node_->AsMemberExpression()->AccessPrivateProperty()) { 107 compiler::RegScope rs(pg_); 108 VReg valueReg = pg_->AllocReg(); 109 110 auto name = node_->AsMemberExpression()->Property()->AsPrivateIdentifier()->Name(); 111 auto result = pg_->Scope()->FindPrivateName(name, true); 112 if (!result.result.isMethod) { 113 pg_->StorePrivateProperty(node_, result.lexLevel, result.result.slot, obj_); 114 break; 115 } 116 if (!result.result.isSetter) { 117 pg_->ThrowTypeError(node_, "Method is not writable"); 118 } 119 // store value 120 pg_->StoreAccumulator(node_, valueReg); 121 122 if (result.result.isStatic) { 123 pg_->LoadLexicalVar(node_, result.lexLevel, result.result.validateMethodSlot); 124 pg_->Equal(node_, obj_); 125 pg_->ThrowTypeErrorIfFalse(node_, "Object does not have private property"); 126 } else { 127 pg_->LoadAccumulator(node_, obj_); 128 pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.validateMethodSlot); 129 } 130 pg_->LoadAccumulator(node_, valueReg); 131 pg_->StorePrivateProperty(node_, result.lexLevel, result.result.slot, obj_); 132 } else { 133 pg_->StoreObjProperty(node_, obj_, prop_); 134 } 135 136 break; 137 } 138 case ReferenceKind::DESTRUCTURING: { 139 Destructuring::Compile(pg_, node_->AsExpression()); 140 break; 141 } 142 default: { 143 UNREACHABLE(); 144 } 145 } 146} 147 148ReferenceKind LReference::Kind() const 149{ 150 return refKind_; 151} 152 153binder::Variable *LReference::Variable() const 154{ 155 return res_.variable; 156} 157 158LReference LReference::CreateLRef(PandaGen *pg, const ir::AstNode *node, bool isDeclaration) 159{ 160 switch (node->Type()) { 161 case ir::AstNodeType::IDENTIFIER: { 162 const util::StringView &name = node->AsIdentifier()->Name(); 163 binder::ScopeFindResult res = pg->Scope()->Find(name); 164 165 return {node, pg, isDeclaration, ReferenceKind::VAR_OR_GLOBAL, res}; 166 } 167 case ir::AstNodeType::MEMBER_EXPRESSION: { 168 return {node, pg, false, ReferenceKind::MEMBER, {}}; 169 } 170 case ir::AstNodeType::VARIABLE_DECLARATION: { 171 ASSERT(node->AsVariableDeclaration()->Declarators().size() == 1); 172 return LReference::CreateLRef(pg, node->AsVariableDeclaration()->Declarators()[0]->Id(), true); 173 } 174 case ir::AstNodeType::VARIABLE_DECLARATOR: { 175 return LReference::CreateLRef(pg, node->AsVariableDeclarator()->Id(), true); 176 } 177 case ir::AstNodeType::ARRAY_PATTERN: 178 case ir::AstNodeType::OBJECT_PATTERN: 179 case ir::AstNodeType::ARRAY_EXPRESSION: 180 case ir::AstNodeType::OBJECT_EXPRESSION: { 181 return {node, pg, isDeclaration, ReferenceKind::DESTRUCTURING, {}}; 182 } 183 case ir::AstNodeType::ASSIGNMENT_PATTERN: { 184 return LReference::CreateLRef(pg, node->AsAssignmentPattern()->Left(), true); 185 } 186 case ir::AstNodeType::REST_ELEMENT: { 187 return LReference::CreateLRef(pg, node->AsRestElement()->Argument(), isDeclaration); 188 } 189 case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION: { 190 // export default [anonymous class decl] 191 util::StringView name = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME; 192 binder::ScopeFindResult res = pg->Scope()->Find(name); 193 194 return {node, pg, isDeclaration, ReferenceKind::VAR_OR_GLOBAL, res}; 195 } 196 case ir::AstNodeType::TS_AS_EXPRESSION: { 197 return LReference::CreateLRef(pg, node->AsTSAsExpression()->Expr(), isDeclaration); 198 } 199 case ir::AstNodeType::TS_SATISFIES_EXPRESSION: { 200 return LReference::CreateLRef(pg, node->AsTSSatisfiesExpression()->Expr(), isDeclaration); 201 } 202 case ir::AstNodeType::TS_TYPE_ASSERTION: { 203 return LReference::CreateLRef(pg, node->AsTSTypeAssertion()->GetExpression(), isDeclaration); 204 } 205 case ir::AstNodeType::TS_NON_NULL_EXPRESSION: { 206 return LReference::CreateLRef(pg, node->AsTSNonNullExpression()->Expr(), isDeclaration); 207 } 208 default: { 209 UNREACHABLE(); 210 } 211 } 212} 213 214} // namespace panda::es2panda::compiler 215