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 
21 namespace ark::es2panda::parser {
22 
23 template <ParserStatus STATUS>
24 class SavedStatusContext {
25 public:
SavedStatusContext(ParserContext *ctx)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 
~SavedStatusContext()37     ~SavedStatusContext()
38     {
39         if (savedStatus_ == ParserStatus::NO_OPTS) {
40             ctx_->Status() &= ~savedStatus_;
41         }
42     }
43 
44 private:
45     ParserContext *ctx_;
46     ParserStatus savedStatus_;
47 };
48 
49 class SwitchContext : public SavedStatusContext<ParserStatus::IN_SWITCH> {
50 public:
SwitchContext(ParserContext *ctx)51     explicit SwitchContext(ParserContext *ctx) : SavedStatusContext(ctx) {}
52     NO_COPY_SEMANTIC(SwitchContext);
53     NO_MOVE_SEMANTIC(SwitchContext);
54     ~SwitchContext() = default;
55 };
56 
57 class IterationContext : public SavedStatusContext<ParserStatus::IN_ITERATION> {
58 public:
IterationContext(ParserContext *ctx)59     explicit IterationContext(ParserContext *ctx) : SavedStatusContext(ctx) {}
60 
61     NO_COPY_SEMANTIC(IterationContext);
62     NO_MOVE_SEMANTIC(IterationContext);
63     ~IterationContext() = default;
64 };
65 
66 class FunctionParameterContext : public SavedStatusContext<ParserStatus::FUNCTION_PARAM> {
67 public:
FunctionParameterContext(ParserContext *ctx)68     explicit FunctionParameterContext(ParserContext *ctx) : SavedStatusContext(ctx) {}
69 
70     NO_COPY_SEMANTIC(FunctionParameterContext);
71     NO_MOVE_SEMANTIC(FunctionParameterContext);
72     ~FunctionParameterContext() = default;
73 };
74 
75 class SavedParserContext {
76 public:
77     template <typename... Args>
SavedParserContext(ParserImpl *parser, Args &&...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 
~SavedParserContext()86     ~SavedParserContext()
87     {
88         parser_->context_ = prev_;
89     }
90 
91 private:
92     ParserImpl *parser_;
93     ParserContext prev_;
94 };
95 
96 class SavedClassPrivateContext {
97 public:
SavedClassPrivateContext(ParserImpl *parser)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 
~SavedClassPrivateContext()106     ~SavedClassPrivateContext()
107     {
108         parser_->classPrivateContext_ = prev_;
109     }
110 
111 private:
112     ParserImpl *parser_;
113     ClassPrivateContext prev_;
114 };
115 
116 class FunctionContext : public SavedParserContext {
117 public:
FunctionContext(ParserImpl *parser, ParserStatus newStatus)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 
Flags() const133     ir::ScriptFunctionFlags Flags() const
134     {
135         return flags_;
136     }
137 
IsAsync() const138     bool IsAsync() const
139     {
140         return (flags_ & ir::ScriptFunctionFlags::ASYNC) != 0;
141     }
142 
AddFlag(ir::ScriptFunctionFlags flags)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 
152 private:
153     ir::ScriptFunctionFlags flags_ {ir::ScriptFunctionFlags::NONE};
154 };
155 
156 class ArrowFunctionContext : public FunctionContext {
157 public:
ArrowFunctionContext(ParserImpl *parser, bool isAsync)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 
172 private:
InitialFlags(ParserStatus currentStatus)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