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 "compiler/core/ASTVerifier.h"
19 #include "compiler/core/compilerContext.h"
20 #include "compiler/lowering/ets/objectIndexAccess.h"
21 #include "lexer/token/sourceLocation.h"
22 #include "compiler/lowering/checkerPhase.h"
23 #include "compiler/lowering/plugin_phase.h"
24 #include "compiler/lowering/scopesInit/scopesInitPhase.h"
25 #include "compiler/lowering/ets/expandBrackets.h"
26 #include "compiler/lowering/ets/generateDeclarations.h"
27 #include "compiler/lowering/ets/lambdaLowering.h"
28 #include "compiler/lowering/ets/interfacePropertyDeclarations.h"
29 #include "compiler/lowering/ets/opAssignment.h"
30 #include "compiler/lowering/ets/tupleLowering.h"
31 #include "compiler/lowering/ets/unionLowering.h"
32 #include "compiler/lowering/ets/structLowering.h"
33 #include "public/es2panda_lib.h"
34 #include "compiler/lowering/ets/promiseVoid.h"
35 #include "utils/json_builder.h"
36
37 namespace panda::es2panda::compiler {
38
39 static CheckerPhase g_checkerPhase;
40
GetTrivialPhaseList()41 std::vector<Phase *> GetTrivialPhaseList()
42 {
43 return std::vector<Phase *> {
44 &g_checkerPhase,
45 };
46 }
47
48 static InterfacePropertyDeclarationsPhase g_interfacePropDeclPhase;
49 static GenerateTsDeclarationsPhase g_generateTsDeclarationsPhase;
50 static LambdaConstructionPhase g_lambdaConstructionPhase;
51 static OpAssignmentLowering g_opAssignmentLowering;
52 static ObjectIndexLowering g_objectIndexLowering;
53 static TupleLowering g_tupleLowering; // Can be only applied after checking phase, and OP_ASSIGNMENT_LOWERING phase
54 static UnionLowering g_unionLowering;
55 static ExpandBracketsPhase g_expandBracketsPhase;
56 static PromiseVoidInferencePhase g_promiseVoidInferencePhase;
57 static StructLowering g_structLowering;
58 static PluginPhase g_pluginsAfterParse {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse};
59 static PluginPhase g_pluginsAfterCheck {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck};
60 static PluginPhase g_pluginsAfterLowerings {"plugins-after-lowering", ES2PANDA_STATE_LOWERED,
61 &util::Plugin::AfterLowerings};
62 // NOLINTBEGIN(fuchsia-statically-constructed-objects)
63 static InitScopesPhaseETS g_initScopesPhaseEts;
64 static InitScopesPhaseAS g_initScopesPhaseAs;
65 static InitScopesPhaseTs g_initScopesPhaseTs;
66 static InitScopesPhaseJs g_initScopesPhaseJs;
67 // NOLINTEND(fuchsia-statically-constructed-objects)
68
GetETSPhaseList()69 std::vector<Phase *> GetETSPhaseList()
70 {
71 return {
72 &g_pluginsAfterParse, &g_initScopesPhaseEts, &g_promiseVoidInferencePhase,
73 &g_structLowering, &g_lambdaConstructionPhase, &g_interfacePropDeclPhase,
74 &g_checkerPhase, &g_pluginsAfterCheck, &g_generateTsDeclarationsPhase,
75 &g_opAssignmentLowering, &g_objectIndexLowering, &g_tupleLowering,
76 &g_unionLowering, &g_expandBracketsPhase, &g_pluginsAfterLowerings,
77 };
78 }
79
GetASPhaseList()80 std::vector<Phase *> GetASPhaseList()
81 {
82 return {
83 &g_initScopesPhaseAs,
84 &g_checkerPhase,
85 };
86 }
87
GetTSPhaseList()88 std::vector<Phase *> GetTSPhaseList()
89 {
90 return {
91 &g_initScopesPhaseTs,
92 &g_checkerPhase,
93 };
94 }
95
GetJSPhaseList()96 std::vector<Phase *> GetJSPhaseList()
97 {
98 return {
99 &g_initScopesPhaseJs,
100 &g_checkerPhase,
101 };
102 }
103
GetPhaseList(ScriptExtension ext)104 std::vector<Phase *> GetPhaseList(ScriptExtension ext)
105 {
106 switch (ext) {
107 case ScriptExtension::ETS:
108 return GetETSPhaseList();
109 case ScriptExtension::AS:
110 return GetASPhaseList();
111 case ScriptExtension::TS:
112 return GetTSPhaseList();
113 case ScriptExtension::JS:
114 return GetJSPhaseList();
115 default:
116 UNREACHABLE();
117 }
118 }
119
Apply(public_lib::Context * ctx,parser::Program * program)120 bool Phase::Apply(public_lib::Context *ctx, parser::Program *program)
121 {
122 const auto *options = ctx->compilerContext->Options();
123 const auto name = std::string {Name()};
124 if (options->skipPhases.count(name) > 0) {
125 return true;
126 }
127
128 CheckOptionsBeforePhase(options, program, name);
129
130 #ifndef NDEBUG
131 if (!Precondition(ctx, program)) {
132 ctx->checker->ThrowTypeError({"Precondition check failed for ", util::StringView {Name()}},
133 lexer::SourcePosition {});
134 }
135 #endif
136
137 if (!Perform(ctx, program)) {
138 return false;
139 }
140
141 CheckOptionsAfterPhase(options, program, name);
142
143 #ifndef NDEBUG
144 if (!Postcondition(ctx, program)) {
145 ctx->checker->ThrowTypeError({"Postcondition check failed for ", util::StringView {Name()}},
146 lexer::SourcePosition {});
147 }
148 #endif
149
150 return true;
151 }
152
CheckOptionsBeforePhase(const CompilerOptions * options,const parser::Program * program,const std::string & name) const153 void Phase::CheckOptionsBeforePhase(const CompilerOptions *options, const parser::Program *program,
154 const std::string &name) const
155 {
156 if (options->dumpAfterPhases.count(name) > 0) {
157 std::cout << "After phase " << name << ":" << std::endl;
158 std::cout << program->Dump() << std::endl;
159 }
160
161 if (options->dumpEtsSrcAfterPhases.count(name) > 0) {
162 std::cout << "After phase " << name << " ets source"
163 << ":" << std::endl;
164 std::cout << program->Ast()->DumpEtsSrc() << std::endl;
165 }
166 }
167
CheckOptionsAfterPhase(const CompilerOptions * options,const parser::Program * program,const std::string & name) const168 void Phase::CheckOptionsAfterPhase(const CompilerOptions *options, const parser::Program *program,
169 const std::string &name) const
170 {
171 if (options->dumpAfterPhases.count(name) > 0) {
172 std::cout << "After phase " << name << ":" << std::endl;
173 std::cout << program->Dump() << std::endl;
174 }
175
176 if (options->dumpEtsSrcAfterPhases.count(name) > 0) {
177 std::cout << "After phase " << name << " ets source"
178 << ":" << std::endl;
179 std::cout << program->Ast()->DumpEtsSrc() << std::endl;
180 }
181 }
182
183 } // namespace panda::es2panda::compiler
184