• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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