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 PARSER_STATUS_CONTEXT_H
17#define PARSER_STATUS_CONTEXT_H
18
19#include "parserImpl.h"
20
21namespace ark::es2panda::parser {
22
23template <ParserStatus STATUS>
24class SavedStatusContext {
25public:
26    explicit SavedStatusContext(ParserContext *ctx)
27        // NOLINTNEXTLINE(readability-magic-numbers)
28        : ctx_(ctx), savedStatus_(static_cast<ParserStatus>(ctx->Status() & STATUS))
29    {
30        // NOLINTNEXTLINE(readability-magic-numbers)
31        ctx->Status() |= STATUS;
32    }
33
34    NO_COPY_SEMANTIC(SavedStatusContext);
35    NO_MOVE_SEMANTIC(SavedStatusContext);
36
37    ~SavedStatusContext()
38    {
39        if (savedStatus_ == ParserStatus::NO_OPTS) {
40            ctx_->Status() &= ~savedStatus_;
41        }
42    }
43
44private:
45    ParserContext *ctx_;
46    ParserStatus savedStatus_;
47};
48
49class SwitchContext : public SavedStatusContext<ParserStatus::IN_SWITCH> {
50public:
51    explicit SwitchContext(ParserContext *ctx) : SavedStatusContext(ctx) {}
52    NO_COPY_SEMANTIC(SwitchContext);
53    NO_MOVE_SEMANTIC(SwitchContext);
54    ~SwitchContext() = default;
55};
56
57class IterationContext : public SavedStatusContext<ParserStatus::IN_ITERATION> {
58public:
59    explicit IterationContext(ParserContext *ctx) : SavedStatusContext(ctx) {}
60
61    NO_COPY_SEMANTIC(IterationContext);
62    NO_MOVE_SEMANTIC(IterationContext);
63    ~IterationContext() = default;
64};
65
66class FunctionParameterContext : public SavedStatusContext<ParserStatus::FUNCTION_PARAM> {
67public:
68    explicit FunctionParameterContext(ParserContext *ctx) : SavedStatusContext(ctx) {}
69
70    NO_COPY_SEMANTIC(FunctionParameterContext);
71    NO_MOVE_SEMANTIC(FunctionParameterContext);
72    ~FunctionParameterContext() = default;
73};
74
75class SavedParserContext {
76public:
77    template <typename... Args>
78    explicit SavedParserContext(ParserImpl *parser, Args &&...args) : parser_(parser), prev_(parser->context_)
79    {
80        parser_->context_ = ParserContext(&prev_, std::forward<Args>(args)...);
81    }
82
83    NO_COPY_SEMANTIC(SavedParserContext);
84    DEFAULT_MOVE_SEMANTIC(SavedParserContext);
85
86    ~SavedParserContext()
87    {
88        parser_->context_ = prev_;
89    }
90
91private:
92    ParserImpl *parser_;
93    ParserContext prev_;
94};
95
96class SavedClassPrivateContext {
97public:
98    explicit SavedClassPrivateContext(ParserImpl *parser) : parser_(parser), prev_(parser->classPrivateContext_)
99    {
100        parser_->classPrivateContext_ = ClassPrivateContext(&prev_);
101    }
102
103    NO_COPY_SEMANTIC(SavedClassPrivateContext);
104    DEFAULT_MOVE_SEMANTIC(SavedClassPrivateContext);
105
106    ~SavedClassPrivateContext()
107    {
108        parser_->classPrivateContext_ = prev_;
109    }
110
111private:
112    ParserImpl *parser_;
113    ClassPrivateContext prev_;
114};
115
116class FunctionContext : public SavedParserContext {
117public:
118    explicit FunctionContext(ParserImpl *parser, ParserStatus newStatus) : SavedParserContext(parser, newStatus)
119    {
120        if ((newStatus & ParserStatus::GENERATOR_FUNCTION) != 0) {
121            flags_ |= ir::ScriptFunctionFlags::GENERATOR;
122        }
123
124        if ((newStatus & ParserStatus::ASYNC_FUNCTION) != 0) {
125            flags_ |= ir::ScriptFunctionFlags::ASYNC;
126        }
127
128        if ((newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) != 0) {
129            flags_ |= ir::ScriptFunctionFlags::CONSTRUCTOR;
130        }
131    }
132
133    ir::ScriptFunctionFlags Flags() const
134    {
135        return flags_;
136    }
137
138    bool IsAsync() const
139    {
140        return (flags_ & ir::ScriptFunctionFlags::ASYNC) != 0;
141    }
142
143    void AddFlag(ir::ScriptFunctionFlags flags)
144    {
145        flags_ |= flags;
146    }
147
148    NO_COPY_SEMANTIC(FunctionContext);
149    NO_MOVE_SEMANTIC(FunctionContext);
150    ~FunctionContext() = default;
151
152private:
153    ir::ScriptFunctionFlags flags_ {ir::ScriptFunctionFlags::NONE};
154};
155
156class ArrowFunctionContext : public FunctionContext {
157public:
158    explicit ArrowFunctionContext(ParserImpl *parser, bool isAsync)
159        : FunctionContext(parser, InitialFlags(parser->context_.Status()))
160    {
161        if (isAsync) {
162            AddFlag(ir::ScriptFunctionFlags::ASYNC);
163        }
164
165        AddFlag(ir::ScriptFunctionFlags::ARROW);
166    }
167
168    NO_COPY_SEMANTIC(ArrowFunctionContext);
169    NO_MOVE_SEMANTIC(ArrowFunctionContext);
170    ~ArrowFunctionContext() = default;
171
172private:
173    static ParserStatus InitialFlags(ParserStatus currentStatus)
174    {
175        return ParserStatus::FUNCTION | ParserStatus::ARROW_FUNCTION |
176               static_cast<ParserStatus>(currentStatus & (ParserStatus::ALLOW_SUPER | ParserStatus::ALLOW_SUPER_CALL));
177    }
178};
179}  // namespace ark::es2panda::parser
180#endif
181