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