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