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_COMPILER_BASE_JSLREFERENCE_H
17#define ES2PANDA_COMPILER_BASE_JSLREFERENCE_H
18
19#include "varbinder/scope.h"
20#include "ir/irnode.h"
21
22namespace ark::es2panda::ir {
23class AstNode;
24}  // namespace ark::es2panda::ir
25
26namespace ark::es2panda::checker {
27class ETSObjectType;
28}  // namespace ark::es2panda::checker
29
30namespace ark::es2panda::compiler {
31enum class ReferenceKind {
32    MEMBER,
33    PRIVATE,
34    SUPER,
35    VAR_OR_GLOBAL,
36    DESTRUCTURING,
37    LOCAL,
38    STATIC_FIELD,
39    FIELD,
40    CLASS,
41    STATIC_CLASS,
42    METHOD,
43    STATIC_METHOD,
44};
45
46class CodeGen;
47class ETSGen;
48class PandaGen;
49
50class LReference {
51public:
52    ~LReference() = default;
53    NO_COPY_SEMANTIC(LReference);
54    DEFAULT_MOVE_SEMANTIC(LReference);
55
56    ReferenceKind Kind() const
57    {
58        return refKind_;
59    }
60
61    void SetKind(ReferenceKind refKind)
62    {
63        refKind_ = refKind;
64    }
65
66    varbinder::Variable *Variable() const
67    {
68        return res_.variable;
69    }
70
71    const ir::AstNode *Node() const
72    {
73        return node_;
74    }
75
76    varbinder::ConstScopeFindResult &Result()
77    {
78        return res_;
79    }
80
81    const varbinder::ConstScopeFindResult &Result() const
82    {
83        return res_;
84    }
85
86    bool IsDeclaration() const
87    {
88        return isDeclaration_;
89    }
90
91protected:
92    using LReferenceBase =
93        std::tuple<CodeGen *, const ir::AstNode *, ReferenceKind, varbinder::ConstScopeFindResult, bool>;
94    static LReferenceBase CreateBase(CodeGen *cg, const ir::AstNode *node, bool isDeclaration);
95
96    explicit LReference(const ir::AstNode *node, ReferenceKind refKind, varbinder::ConstScopeFindResult res,
97                        bool isDeclaration)
98        : node_(node), refKind_(refKind), res_(res), isDeclaration_(isDeclaration)
99    {
100    }
101
102private:
103    const ir::AstNode *node_;
104    ReferenceKind refKind_;
105    varbinder::ConstScopeFindResult res_;
106    bool isDeclaration_;
107};
108
109class JSLReference : public LReference {
110public:
111    JSLReference(CodeGen *cg, const ir::AstNode *node, ReferenceKind refKind, varbinder::ConstScopeFindResult res,
112                 bool isDeclaration);
113    ~JSLReference() = default;
114    NO_COPY_SEMANTIC(JSLReference);
115    NO_MOVE_SEMANTIC(JSLReference);
116
117    void GetValue() const;
118    void SetValue() const;
119
120    static JSLReference Create(CodeGen *cg, const ir::AstNode *node, bool isDeclaration)
121    {
122        return std::make_from_tuple<JSLReference>(CreateBase(cg, node, isDeclaration));
123    }
124
125private:
126    PandaGen *pg_;
127    VReg obj_;
128    VReg privateCtor_ {};
129    Operand prop_;
130};
131
132class ETSLReference : public LReference {
133public:
134    ETSLReference(CodeGen *cg, const ir::AstNode *node, ReferenceKind refKind, varbinder::ConstScopeFindResult res,
135                  bool isDeclaration);
136    ~ETSLReference() = default;
137    NO_COPY_SEMANTIC(ETSLReference);
138    NO_MOVE_SEMANTIC(ETSLReference);
139
140    void GetValue() const;
141    void SetValue() const;
142
143    static ETSLReference Create(CodeGen *const cg, const ir::AstNode *const node, const bool isDeclaration);
144    static ReferenceKind ResolveReferenceKind(const varbinder::Variable *variable);
145
146private:
147    void SetValueComputed(const ir::MemberExpression *memberExpr) const;
148    void SetValueGetterSetter(const ir::MemberExpression *memberExpr) const;
149
150    ETSGen *etsg_;
151    const checker::Type *staticObjRef_ {};
152    VReg baseReg_ {};
153    VReg propReg_ {};
154};
155}  // namespace ark::es2panda::compiler
156
157#endif
158