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
22namespace ark::es2panda::compiler {
23class JSCompiler;
24class ETSCompiler;
25}  // namespace ark::es2panda::compiler
26
27namespace ark::es2panda::checker {
28class ETSObjectType;
29class ETSAnalyzer;
30}  // namespace ark::es2panda::checker
31
32namespace ark::es2panda::ir {
33
34// NOLINTBEGIN(modernize-avoid-c-arrays)
35inline constexpr char const PREDEFINED_METHOD[] = "The special predefined method '";
36// NOLINTEND(modernize-avoid-c-arrays)
37
38using ENUMBITOPS_OPERATORS;
39
40enum 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
50template <>
51struct enumbitops::IsAllowedType<ark::es2panda::ir::MemberExpressionKind> : std::true_type {
52};
53
54namespace ark::es2panda::ir {
55
56class MemberExpression : public MaybeOptionalExpression {
57    friend class checker::ETSAnalyzer;
58
59private:
60    struct Tag {};
61
62public:
63    MemberExpression() = delete;
64    ~MemberExpression() override = default;
65
66    NO_COPY_OPERATOR(MemberExpression);
67    NO_MOVE_SEMANTIC(MemberExpression);
68
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
204protected:
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
215private:
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