1 /** 2 * Copyright (c) 2021-2025 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 #ifndef ES2PANDA_IR_EXPRESSION_MEMBER_EXPRESSION_H 17 #define ES2PANDA_IR_EXPRESSION_MEMBER_EXPRESSION_H 18 19 #include "checker/checkerContext.h" 20 #include "checker/types/ets/etsObjectType.h" 21 #include "ir/expression.h" 22 23 namespace ark::es2panda::compiler { 24 class JSCompiler; 25 class ETSCompiler; 26 } // namespace ark::es2panda::compiler 27 28 namespace ark::es2panda::checker { 29 class ETSObjectType; 30 class ETSAnalyzer; 31 } // namespace ark::es2panda::checker 32 33 namespace ark::es2panda::ir { 34 35 // NOLINTBEGIN(modernize-avoid-c-arrays) 36 inline constexpr char const PREDEFINED_METHOD[] = "The special predefined method '"; 37 // NOLINTEND(modernize-avoid-c-arrays) 38 39 using ENUMBITOPS_OPERATORS; 40 41 enum class MemberExpressionKind : uint32_t { 42 NONE = 0, 43 ELEMENT_ACCESS = 1U << 0U, 44 PROPERTY_ACCESS = 1U << 1U, 45 GETTER = 1U << 2U, 46 SETTER = 1U << 3U, 47 EXTENSION_ACCESSOR = 1U << 4U, 48 }; 49 50 } // namespace ark::es2panda::ir 51 52 template <> 53 struct enumbitops::IsAllowedType<ark::es2panda::ir::MemberExpressionKind> : std::true_type { 54 }; 55 56 namespace ark::es2panda::ir { 57 58 class MemberExpression : public MaybeOptionalExpression { 59 friend class checker::ETSAnalyzer; 60 61 private: 62 struct Tag {}; 63 64 public: 65 MemberExpression() = delete; 66 ~MemberExpression() override = default; 67 68 MemberExpression &operator=(const MemberExpression &) = delete; 69 NO_MOVE_SEMANTIC(MemberExpression); 70 71 explicit MemberExpression(Expression *object, Expression *property, MemberExpressionKind kind, bool computed, 72 bool optional) 73 : MaybeOptionalExpression(AstNodeType::MEMBER_EXPRESSION, optional), 74 object_(object), 75 property_(property), 76 kind_(kind), 77 computed_(computed) 78 { 79 } 80 81 explicit MemberExpression(Tag tag, MemberExpression const &other, ArenaAllocator *allocator); 82 83 // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields 84 friend class compiler::JSCompiler; 85 friend class compiler::ETSCompiler; 86 87 [[nodiscard]] Expression *Object() noexcept 88 { 89 return object_; 90 } 91 92 [[nodiscard]] const Expression *Object() const noexcept 93 { 94 return object_; 95 } 96 97 void SetObject(Expression *object) noexcept 98 { 99 object_ = object; 100 object_->SetParent(this); 101 } 102 103 void SetProperty(Expression *prop) noexcept 104 { 105 property_ = prop; 106 property_->SetParent(this); 107 } 108 109 [[nodiscard]] Expression *Property() noexcept 110 { 111 return property_; 112 } 113 114 [[nodiscard]] const Expression *Property() const noexcept 115 { 116 return property_; 117 } 118 119 [[nodiscard]] varbinder::LocalVariable *PropVar() noexcept 120 { 121 if (Kind() == MemberExpressionKind::ELEMENT_ACCESS) { 122 return nullptr; 123 } 124 return Property()->Variable() != nullptr ? Property()->Variable()->AsLocalVariable() : nullptr; 125 } 126 127 [[nodiscard]] const varbinder::LocalVariable *PropVar() const noexcept 128 { 129 if (Kind() == MemberExpressionKind::ELEMENT_ACCESS) { 130 return nullptr; 131 } 132 return Property()->Variable() != nullptr ? Property()->Variable()->AsLocalVariable() : nullptr; 133 } 134 135 [[nodiscard]] bool IsComputed() const noexcept 136 { 137 return computed_; 138 } 139 140 [[nodiscard]] MemberExpressionKind Kind() const noexcept 141 { 142 return kind_; 143 } 144 145 void AddMemberKind(MemberExpressionKind kind) noexcept 146 { 147 kind_ |= kind; 148 } 149 150 [[nodiscard]] bool HasMemberKind(MemberExpressionKind kind) const noexcept 151 { 152 return (kind_ & kind) != 0; 153 } 154 155 void RemoveMemberKind(MemberExpressionKind const kind) noexcept 156 { 157 kind_ &= ~kind; 158 } 159 160 [[nodiscard]] checker::ETSObjectType *ObjType() const noexcept 161 { 162 return objType_; 163 } 164 165 [[nodiscard]] checker::ETSFunctionType *ExtensionAccessorType() const 166 { 167 return extensionAccessorType_; 168 } 169 170 void SetExtensionAccessorType(checker::ETSFunctionType *eAccessorType) 171 { 172 ES2PANDA_ASSERT(HasMemberKind(ir::MemberExpressionKind::EXTENSION_ACCESSOR)); 173 extensionAccessorType_ = eAccessorType; 174 } 175 176 void SetPropVar(varbinder::LocalVariable *propVar) noexcept 177 { 178 ES2PANDA_ASSERT(Property()); 179 Property()->SetVariable(propVar); 180 } 181 182 void SetObjectType(checker::ETSObjectType *objType) noexcept 183 { 184 objType_ = objType; 185 } 186 187 [[nodiscard]] bool IsIgnoreBox() const noexcept 188 { 189 return ignoreBox_; 190 } 191 192 void SetIgnoreBox() noexcept 193 { 194 ignoreBox_ = true; 195 } 196 197 [[nodiscard]] checker::Type *UncheckedType() const noexcept 198 { 199 return uncheckedType_; 200 } 201 202 [[nodiscard]] bool IsPrivateReference() const noexcept; 203 204 [[nodiscard]] MemberExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; 205 std::optional<std::size_t> GetTupleIndexValue() const; 206 checker::Type *GetTypeOfTupleElement(checker::ETSChecker *checker, checker::Type *baseType); 207 208 void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; 209 void Iterate(const NodeTraverser &cb) const override; 210 void Dump(ir::AstDumper *dumper) const override; 211 void Dump(ir::SrcDumper *dumper) const override; 212 void Compile(compiler::PandaGen *pg) const override; 213 void Compile(compiler::ETSGen *etsg) const override; 214 void CompileToReg(compiler::PandaGen *pg, compiler::VReg objReg) const; 215 void CompileToRegs(compiler::PandaGen *pg, compiler::VReg object, compiler::VReg property) const; 216 checker::Type *Check(checker::TSChecker *checker) override; 217 checker::VerifiedType Check(checker::ETSChecker *checker) override; 218 219 std::string ToString() const override; 220 221 void Accept(ASTVisitorT *v) override 222 { 223 v->Accept(this); 224 } 225 226 void CleanUp() override 227 { 228 AstNode::CleanUp(); 229 uncheckedType_ = nullptr; 230 objType_ = nullptr; 231 extensionAccessorType_ = nullptr; 232 } 233 234 protected: 235 MemberExpression(MemberExpression const &other) : MaybeOptionalExpression(other) 236 { 237 kind_ = other.kind_; 238 computed_ = other.computed_; 239 ignoreBox_ = other.ignoreBox_; 240 // Note! Probably, we need to do 'Instantiate(...)' but we haven't access to 'Relation()' here... 241 uncheckedType_ = other.uncheckedType_; 242 objType_ = other.objType_; 243 } 244 245 private: 246 std::pair<checker::Type *, varbinder::LocalVariable *> ResolveObjectMember(checker::ETSChecker *checker) const; 247 checker::Type *AdjustType(checker::ETSChecker *checker, checker::Type *type); 248 checker::Type *SetAndAdjustType(checker::ETSChecker *checker, checker::ETSObjectType *objectType); 249 checker::Type *CheckComputed(checker::ETSChecker *checker, checker::Type *baseType); 250 checker::Type *CheckUnionMember(checker::ETSChecker *checker, checker::Type *baseType); 251 checker::Type *TraverseUnionMember(checker::ETSChecker *checker, checker::ETSUnionType *unionType); 252 253 bool CheckArrayIndexValue(checker::ETSChecker *checker) const; 254 checker::Type *CheckIndexAccessMethod(checker::ETSChecker *checker); 255 checker::Type *ResolveReturnTypeFromSignature(checker::ETSChecker *checker, bool isSetter, 256 ArenaVector<ir::Expression *> &arguments, 257 ArenaVector<checker::Signature *> &signatures, 258 std::string_view const methodName); 259 260 void LoadRhs(compiler::PandaGen *pg) const; 261 262 Expression *object_ = nullptr; 263 Expression *property_ = nullptr; 264 MemberExpressionKind kind_; 265 bool computed_; 266 bool ignoreBox_ {false}; 267 checker::Type *uncheckedType_ {}; 268 checker::ETSObjectType *objType_ {}; 269 checker::ETSFunctionType *extensionAccessorType_ {}; 270 }; 271 } // namespace ark::es2panda::ir 272 273 #endif 274