1/**
2 * Copyright (c) 2021 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_CORE_DYNAMIC_CONTEXT_H
17#define ES2PANDA_COMPILER_CORE_DYNAMIC_CONTEXT_H
18
19#include <util/ustring.h>
20#include <ir/irnode.h>
21#include <compiler/core/labelTarget.h>
22#include <compiler/base/iterators.h>
23
24namespace panda::es2panda::ir {
25class TryStatement;
26class ForOfStatement;
27class LabelledStatement;
28}  // namespace panda::es2panda::ir
29
30namespace panda::es2panda::compiler {
31class PandaGen;
32class VariableEnvScope;
33class CatchTable;
34class TryLabelSet;
35
36enum class DynamicContextType { NONE, LABEL, LEX_ENV, ITERATOR, TRY };
37
38class DynamicContext {
39public:
40    NO_COPY_SEMANTIC(DynamicContext);
41    NO_MOVE_SEMANTIC(DynamicContext);
42    virtual ~DynamicContext();
43
44    void *operator new(size_t) = delete;
45    void *operator new[](size_t) = delete;
46
47    virtual void AbortContext([[maybe_unused]] ControlFlowChange cfc,
48                              [[maybe_unused]] const util::StringView &targetLabel) {};
49
50    virtual bool HasTryCatch() const
51    {
52        return false;
53    }
54
55    virtual bool HasFinalizer() const
56    {
57        return HasTryCatch();
58    }
59
60    virtual DynamicContextType Type() const = 0;
61
62    DynamicContext *Prev()
63    {
64        return prev_;
65    }
66
67    const DynamicContext *Prev() const
68    {
69        return prev_;
70    }
71
72    const LabelTarget &Target() const
73    {
74        return target_;
75    }
76
77protected:
78    explicit DynamicContext(PandaGen *pg, LabelTarget target);
79
80    PandaGen *pg_;
81    LabelTarget target_;
82    DynamicContext *prev_ {};
83};
84
85class LabelContext : public DynamicContext {
86public:
87    explicit LabelContext(PandaGen *pg, LabelTarget target) : DynamicContext(pg, target) {}
88    explicit LabelContext(PandaGen *pg, const ir::LabelledStatement *labelledStmt);
89    NO_COPY_SEMANTIC(LabelContext);
90    NO_MOVE_SEMANTIC(LabelContext);
91    ~LabelContext();
92
93    DynamicContextType Type() const override
94    {
95        return DynamicContextType::LABEL;
96    }
97
98private:
99    Label *label_ {};
100    const ir::LabelledStatement *labelledStmt_ {};
101};
102
103class LexEnvContext : public DynamicContext {
104public:
105    explicit LexEnvContext(VariableEnvScope *envScope, PandaGen *pg, LabelTarget target);
106    NO_COPY_SEMANTIC(LexEnvContext);
107    NO_MOVE_SEMANTIC(LexEnvContext);
108    ~LexEnvContext();
109
110    DynamicContextType Type() const override
111    {
112        return DynamicContextType::LEX_ENV;
113    }
114
115    bool HasTryCatch() const override;
116    void AbortContext([[maybe_unused]] ControlFlowChange cfc,
117                      [[maybe_unused]] const util::StringView &targetLabel) override;
118
119private:
120    VariableEnvScope *envScope_;
121    CatchTable *catchTable_ {};
122};
123
124class IteratorContext : public DynamicContext {
125public:
126    explicit IteratorContext(PandaGen *pg, const Iterator &iterator, LabelTarget target);
127    NO_COPY_SEMANTIC(IteratorContext);
128    NO_MOVE_SEMANTIC(IteratorContext);
129    ~IteratorContext();
130
131    DynamicContextType Type() const override
132    {
133        return DynamicContextType::ITERATOR;
134    }
135
136    const Iterator &GetIterator() const
137    {
138        return iterator_;
139    }
140
141    bool HasTryCatch() const override
142    {
143        return true;
144    }
145
146    void AbortContext([[maybe_unused]] ControlFlowChange cfc,
147                      [[maybe_unused]] const util::StringView &targetLabel) override;
148
149private:
150    const Iterator &iterator_;
151    CatchTable *catchTable_;
152};
153
154class DestructuringIteratorContext : public DynamicContext {
155public:
156    explicit DestructuringIteratorContext(PandaGen *pg, const DestructuringIterator &iterator);
157    NO_COPY_SEMANTIC(DestructuringIteratorContext);
158    NO_MOVE_SEMANTIC(DestructuringIteratorContext);
159    ~DestructuringIteratorContext() override;
160
161    DynamicContextType Type() const override
162    {
163        return DynamicContextType::ITERATOR;
164    }
165
166    const DestructuringIterator &GetIterator() const
167    {
168        return iterator_;
169    }
170
171    bool HasTryCatch() const override
172    {
173        return true;
174    }
175
176    void AbortContext(ControlFlowChange cfc, const util::StringView &targetLabel) override;
177
178private:
179    const DestructuringIterator &iterator_;
180    CatchTable *catchTable_;
181};
182
183class TryContext : public DynamicContext {
184public:
185    explicit TryContext(PandaGen *pg, const ir::TryStatement *tryStmt, bool hasFinalizer = true)
186        : DynamicContext(pg, {}), tryStmt_(tryStmt), hasFinalizer_(hasFinalizer)
187    {
188        InitCatchTable();
189        InitFinalizer();
190    }
191
192    explicit TryContext(PandaGen *pg) : DynamicContext(pg, {})
193    {
194        InitCatchTable();
195    }
196
197    NO_COPY_SEMANTIC(TryContext);
198    NO_MOVE_SEMANTIC(TryContext);
199    ~TryContext() = default;
200
201    DynamicContextType Type() const override
202    {
203        return DynamicContextType::TRY;
204    }
205
206    bool HasTryCatch() const override
207    {
208        return true;
209    }
210
211    VReg FinalizerRun() const
212    {
213        return finalizerRun_;
214    }
215
216    CatchTable *GetCatchTable() const
217    {
218        return catchTable_;
219    }
220
221    const TryLabelSet &LabelSet() const;
222    bool HasFinalizer() const override;
223    void InitFinalizer();
224    void EmitFinalizer();
225
226    void AbortContext([[maybe_unused]] ControlFlowChange cfc,
227                      [[maybe_unused]] const util::StringView &targetLabel) override;
228
229private:
230    void InitCatchTable();
231
232    const ir::TryStatement *tryStmt_ {};
233    CatchTable *catchTable_ {};
234    VReg finalizerRun_ {};
235    bool hasFinalizer_ {};
236    bool inFinalizer_ {};
237};
238}  // namespace panda::es2panda::compiler
239
240#endif
241