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 
56 namespace ark::es2panda::compiler {
57 
58 static CheckerPhase g_checkerPhase;
59 static ResolveIdentifiers g_resolveIdentifiers {};
60 static AmbientLowering g_ambientLowering;
61 static BigIntLowering g_bigintLowering;
62 static StringConstructorLowering g_stringConstructorLowering;
63 static ConstStringToCharLowering g_constStringToCharLowering;
64 static InterfacePropertyDeclarationsPhase g_interfacePropDeclPhase;
65 static EnumLoweringPhase g_enumLoweringPhase;
66 static EnumPostCheckLoweringPhase g_enumPostCheckLoweringPhase;
67 static SpreadConstructionPhase g_spreadConstructionPhase;
68 static ExpressionLambdaConstructionPhase g_expressionLambdaConstructionPhase;
69 static OpAssignmentLowering g_opAssignmentLowering;
70 static BoxingForLocals g_boxingForLocals;
71 static CapturedVariables g_capturedVariables {};
72 static LambdaConversionPhase g_lambdaConversionPhase;
73 static ObjectIndexLowering g_objectIndexLowering;
74 static ObjectIteratorLowering g_objectIteratorLowering;
75 static ObjectLiteralLowering g_objectLiteralLowering;
76 static InterfaceObjectLiteralLowering g_interfaceObjectLiteralLowering;
77 static TupleLowering g_tupleLowering;  // Can be only applied after checking phase, and OP_ASSIGNMENT_LOWERING phase
78 static UnionLowering g_unionLowering;
79 static OptionalLowering g_optionalLowering;
80 static ExpandBracketsPhase g_expandBracketsPhase;
81 static PromiseVoidInferencePhase g_promiseVoidInferencePhase;
82 static RecordLowering g_recordLowering;
83 static StructLowering g_structLowering;
84 static DefaultParameterLowering g_defaultParameterLowering;
85 static TopLevelStatements g_topLevelStatements;
86 static LocalClassConstructionPhase g_localClassLowering;
87 static StringComparisonLowering g_stringComparisonLowering;
88 static PartialExportClassGen g_partialExportClassGen;
89 static PackageImplicitImport g_packageImplicitImport;
90 static GenericBridgesPhase g_genericBridgesLowering;
91 static PluginPhase g_pluginsAfterParse {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse};
92 static PluginPhase g_pluginsAfterCheck {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck};
93 static PluginPhase g_pluginsAfterLowerings {"plugins-after-lowering", ES2PANDA_STATE_LOWERED,
94                                             &util::Plugin::AfterLowerings};
95 // NOLINTBEGIN(fuchsia-statically-constructed-objects)
96 static InitScopesPhaseETS g_initScopesPhaseEts;
97 static InitScopesPhaseAS g_initScopesPhaseAs;
98 static InitScopesPhaseTs g_initScopesPhaseTs;
99 static InitScopesPhaseJs g_initScopesPhaseJs;
100 // NOLINTEND(fuchsia-statically-constructed-objects)
101 
102 static void CheckOptionsBeforePhase(const CompilerOptions &options, const parser::Program *program,
103                                     const std::string &name);
104 static void CheckOptionsAfterPhase(const CompilerOptions &options, const parser::Program *program,
105                                    const std::string &name);
106 
GetETSPhaseList()107 std::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 
GetASPhaseList()152 std::vector<Phase *> GetASPhaseList()
153 {
154     return {
155         &g_initScopesPhaseAs,
156         &g_checkerPhase,
157     };
158 }
159 
GetTSPhaseList()160 std::vector<Phase *> GetTSPhaseList()
161 {
162     return {
163         &g_initScopesPhaseTs,
164         &g_checkerPhase,
165     };
166 }
167 
GetJSPhaseList()168 std::vector<Phase *> GetJSPhaseList()
169 {
170     return {
171         &g_initScopesPhaseJs,
172         &g_checkerPhase,
173     };
174 }
175 
GetPhaseList(ScriptExtension ext)176 std::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 
Apply(public_lib::Context *ctx, parser::Program *program)192 bool 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 
CheckOptionsBeforePhase(const CompilerOptions &options, const parser::Program *program, const std::string &name)227 static 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 
CheckOptionsAfterPhase(const CompilerOptions &options, const parser::Program *program, const std::string &name)242 static 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