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#include "phase.h"
17#include "checker/checker.h"
18#include "ets/ambientLowering.h"
19#include "lexer/token/sourceLocation.h"
20#include "compiler/lowering/resolveIdentifiers.h"
21#include "compiler/lowering/checkerPhase.h"
22#include "compiler/lowering/ets/constStringToCharLowering.h"
23#include "compiler/lowering/ets/defaultParameterLowering.h"
24#include "compiler/lowering/ets/expandBrackets.h"
25#include "compiler/lowering/ets/recordLowering.h"
26#include "compiler/lowering/ets/topLevelStmts/topLevelStmts.h"
27#include "compiler/lowering/ets/expressionLambdaLowering.h"
28#include "compiler/lowering/ets/boxingForLocals.h"
29#include "compiler/lowering/ets/capturedVariables.h"
30#include "compiler/lowering/ets/lambdaLowering.h"
31#include "compiler/lowering/ets/spreadLowering.h"
32#include "compiler/lowering/ets/interfacePropertyDeclarations.h"
33#include "compiler/lowering/ets/objectIndexAccess.h"
34#include "compiler/lowering/ets/objectIterator.h"
35#include "compiler/lowering/ets/localClassLowering.h"
36#include "compiler/lowering/ets/opAssignment.h"
37#include "compiler/lowering/ets/objectLiteralLowering.h"
38#include "compiler/lowering/ets/interfaceObjectLiteralLowering.h"
39#include "compiler/lowering/ets/optionalLowering.h"
40#include "compiler/lowering/ets/packageImplicitImport.h"
41#include "compiler/lowering/ets/partialExportClassGen.h"
42#include "compiler/lowering/ets/promiseVoid.h"
43#include "compiler/lowering/ets/stringComparison.h"
44#include "compiler/lowering/ets/structLowering.h"
45#include "compiler/lowering/ets/tupleLowering.h"
46#include "compiler/lowering/ets/bigintLowering.h"
47#include "compiler/lowering/ets/unionLowering.h"
48#include "compiler/lowering/ets/stringConstructorLowering.h"
49#include "compiler/lowering/ets/enumLowering.h"
50#include "compiler/lowering/ets/enumPostCheckLowering.h"
51#include "compiler/lowering/ets/genericBridgesLowering.h"
52#include "compiler/lowering/plugin_phase.h"
53#include "compiler/lowering/scopesInit/scopesInitPhase.h"
54#include "public/es2panda_lib.h"
55
56namespace ark::es2panda::compiler {
57
58static CheckerPhase g_checkerPhase;
59static ResolveIdentifiers g_resolveIdentifiers {};
60static AmbientLowering g_ambientLowering;
61static BigIntLowering g_bigintLowering;
62static StringConstructorLowering g_stringConstructorLowering;
63static ConstStringToCharLowering g_constStringToCharLowering;
64static InterfacePropertyDeclarationsPhase g_interfacePropDeclPhase;
65static EnumLoweringPhase g_enumLoweringPhase;
66static EnumPostCheckLoweringPhase g_enumPostCheckLoweringPhase;
67static SpreadConstructionPhase g_spreadConstructionPhase;
68static ExpressionLambdaConstructionPhase g_expressionLambdaConstructionPhase;
69static OpAssignmentLowering g_opAssignmentLowering;
70static BoxingForLocals g_boxingForLocals;
71static CapturedVariables g_capturedVariables {};
72static LambdaConversionPhase g_lambdaConversionPhase;
73static ObjectIndexLowering g_objectIndexLowering;
74static ObjectIteratorLowering g_objectIteratorLowering;
75static ObjectLiteralLowering g_objectLiteralLowering;
76static InterfaceObjectLiteralLowering g_interfaceObjectLiteralLowering;
77static TupleLowering g_tupleLowering;  // Can be only applied after checking phase, and OP_ASSIGNMENT_LOWERING phase
78static UnionLowering g_unionLowering;
79static OptionalLowering g_optionalLowering;
80static ExpandBracketsPhase g_expandBracketsPhase;
81static PromiseVoidInferencePhase g_promiseVoidInferencePhase;
82static RecordLowering g_recordLowering;
83static StructLowering g_structLowering;
84static DefaultParameterLowering g_defaultParameterLowering;
85static TopLevelStatements g_topLevelStatements;
86static LocalClassConstructionPhase g_localClassLowering;
87static StringComparisonLowering g_stringComparisonLowering;
88static PartialExportClassGen g_partialExportClassGen;
89static PackageImplicitImport g_packageImplicitImport;
90static GenericBridgesPhase g_genericBridgesLowering;
91static PluginPhase g_pluginsAfterParse {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse};
92static PluginPhase g_pluginsAfterCheck {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck};
93static PluginPhase g_pluginsAfterLowerings {"plugins-after-lowering", ES2PANDA_STATE_LOWERED,
94                                            &util::Plugin::AfterLowerings};
95// NOLINTBEGIN(fuchsia-statically-constructed-objects)
96static InitScopesPhaseETS g_initScopesPhaseEts;
97static InitScopesPhaseAS g_initScopesPhaseAs;
98static InitScopesPhaseTs g_initScopesPhaseTs;
99static InitScopesPhaseJs g_initScopesPhaseJs;
100// NOLINTEND(fuchsia-statically-constructed-objects)
101
102static void CheckOptionsBeforePhase(const CompilerOptions &options, const parser::Program *program,
103                                    const std::string &name);
104static void CheckOptionsAfterPhase(const CompilerOptions &options, const parser::Program *program,
105                                   const std::string &name);
106
107std::vector<Phase *> GetETSPhaseList()
108{
109    // clang-format off
110    return {
111        &g_pluginsAfterParse,
112        &g_packageImplicitImport,
113        &g_topLevelStatements,
114        &g_defaultParameterLowering,
115        &g_ambientLowering,
116        &g_initScopesPhaseEts,
117        &g_optionalLowering,
118        &g_promiseVoidInferencePhase,
119        &g_structLowering,
120        &g_expressionLambdaConstructionPhase,
121        &g_interfacePropDeclPhase,
122        &g_enumLoweringPhase,
123        &g_resolveIdentifiers,
124        &g_capturedVariables,
125        &g_checkerPhase,        // please DO NOT change order of these two phases: checkerPhase and pluginsAfterCheck
126        &g_pluginsAfterCheck,   // pluginsAfterCheck has to go right after checkerPhase, nothing should be between them
127        &g_enumPostCheckLoweringPhase,
128        &g_spreadConstructionPhase,
129        &g_bigintLowering,
130        &g_opAssignmentLowering,
131        &g_constStringToCharLowering,
132        &g_boxingForLocals,
133        &g_lambdaConversionPhase,
134        &g_recordLowering,
135        &g_objectIndexLowering,
136        &g_objectIteratorLowering,
137        &g_tupleLowering,
138        &g_unionLowering,
139        &g_expandBracketsPhase,
140        &g_localClassLowering,
141        &g_interfaceObjectLiteralLowering,
142        &g_objectLiteralLowering,
143        &g_stringConstructorLowering,
144        &g_stringComparisonLowering,
145        &g_partialExportClassGen,
146        &g_genericBridgesLowering,
147        &g_pluginsAfterLowerings,  // pluginsAfterLowerings has to come at the very end, nothing should go after it
148    };
149    // clang-format on
150}
151
152std::vector<Phase *> GetASPhaseList()
153{
154    return {
155        &g_initScopesPhaseAs,
156        &g_checkerPhase,
157    };
158}
159
160std::vector<Phase *> GetTSPhaseList()
161{
162    return {
163        &g_initScopesPhaseTs,
164        &g_checkerPhase,
165    };
166}
167
168std::vector<Phase *> GetJSPhaseList()
169{
170    return {
171        &g_initScopesPhaseJs,
172        &g_checkerPhase,
173    };
174}
175
176std::vector<Phase *> GetPhaseList(ScriptExtension ext)
177{
178    switch (ext) {
179        case ScriptExtension::ETS:
180            return GetETSPhaseList();
181        case ScriptExtension::AS:
182            return GetASPhaseList();
183        case ScriptExtension::TS:
184            return GetTSPhaseList();
185        case ScriptExtension::JS:
186            return GetJSPhaseList();
187        default:
188            UNREACHABLE();
189    }
190}
191
192bool Phase::Apply(public_lib::Context *ctx, parser::Program *program)
193{
194    const auto &options = ctx->config->options->CompilerOptions();
195    const auto name = std::string {Name()};
196    if (options.skipPhases.count(name) > 0) {
197        return true;
198    }
199
200    CheckOptionsBeforePhase(options, program, name);
201
202#ifndef NDEBUG
203    if (!Precondition(ctx, program)) {
204        ctx->checker->LogTypeError({"Precondition check failed for ", util::StringView {Name()}},
205                                   lexer::SourcePosition {});
206        return false;
207    }
208#endif
209
210    if (!Perform(ctx, program)) {
211        return false;
212    }
213
214    CheckOptionsAfterPhase(options, program, name);
215
216#ifndef NDEBUG
217    if (!Postcondition(ctx, program)) {
218        ctx->checker->LogTypeError({"Postcondition check failed for ", util::StringView {Name()}},
219                                   lexer::SourcePosition {});
220        return false;
221    }
222#endif
223
224    return !ctx->checker->ErrorLogger()->IsAnyError();
225}
226
227static void CheckOptionsBeforePhase(const CompilerOptions &options, const parser::Program *program,
228                                    const std::string &name)
229{
230    if (options.dumpBeforePhases.count(name) > 0) {
231        std::cout << "Before phase " << name << ":" << std::endl;
232        std::cout << program->Dump() << std::endl;
233    }
234
235    if (options.dumpEtsSrcBeforePhases.count(name) > 0) {
236        std::cout << "Before phase " << name << " ets source"
237                  << ":" << std::endl;
238        std::cout << program->Ast()->DumpEtsSrc() << std::endl;
239    }
240}
241
242static void CheckOptionsAfterPhase(const CompilerOptions &options, const parser::Program *program,
243                                   const std::string &name)
244{
245    if (options.dumpAfterPhases.count(name) > 0) {
246        std::cout << "After phase " << name << ":" << std::endl;
247        std::cout << program->Dump() << std::endl;
248    }
249
250    if (options.dumpEtsSrcAfterPhases.count(name) > 0) {
251        std::cout << "After phase " << name << " ets source"
252                  << ":" << std::endl;
253        std::cout << program->Ast()->DumpEtsSrc() << std::endl;
254    }
255}
256
257}  // namespace ark::es2panda::compiler
258