1 /**
2 * Copyright (c) 2022-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 "options.h"
17
18 #include "utils/pandargs.h"
19
20 #include "arktsconfig.h"
21
22 #include <random>
23 #include <utility>
24
25 #ifdef PANDA_WITH_BYTECODE_OPTIMIZER
26 #include "bytecode_optimizer/bytecodeopt_options.h"
27 #include "compiler/compiler_options.h"
28 #endif
29
30 namespace ark::es2panda::util {
31 template <class T>
RemoveExtension(T const &filename)32 T RemoveExtension(T const &filename)
33 {
34 typename T::size_type const p(filename.find_last_of('.'));
35 return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
36 }
37
38 // Options
39
Options()40 Options::Options() : argparser_(new ark::PandArgParser()) {}
41
~Options()42 Options::~Options()
43 {
44 delete argparser_;
45 }
46
SplitToStringVector(std::string const &str)47 static std::vector<std::string> SplitToStringVector(std::string const &str)
48 {
49 std::vector<std::string> res;
50 std::string_view currStr {str};
51 auto ix = currStr.find(',');
52 while (ix != std::string::npos) {
53 if (ix != 0) {
54 res.emplace_back(currStr.substr(0, ix));
55 }
56 currStr = currStr.substr(ix + 1);
57 ix = currStr.find(',');
58 }
59
60 if (!currStr.empty()) {
61 res.emplace_back(currStr);
62 }
63 return res;
64 }
65
SplitToStringSet(std::string const &str)66 static std::unordered_set<std::string> SplitToStringSet(std::string const &str)
67 {
68 std::vector<std::string> vec = SplitToStringVector(str);
69 std::unordered_set<std::string> res;
70 for (auto &elem : vec) {
71 res.emplace(elem);
72 }
73 return res;
74 }
75
76 // NOLINTNEXTLINE(modernize-avoid-c-arrays, hicpp-avoid-c-arrays)
SplitArgs(int argc, const char *argv[], std::vector<std::string> &es2pandaArgs, std::vector<std::string> &bcoCompilerArgs, std::vector<std::string> &bytecodeoptArgs)77 static void SplitArgs(int argc, const char *argv[], std::vector<std::string> &es2pandaArgs,
78 std::vector<std::string> &bcoCompilerArgs, std::vector<std::string> &bytecodeoptArgs)
79 {
80 constexpr std::string_view COMPILER_PREFIX = "--bco-compiler";
81 constexpr std::string_view OPTIMIZER_PREFIX = "--bco-optimizer";
82
83 enum class OptState { ES2PANDA, JIT_COMPILER, OPTIMIZER };
84 OptState optState = OptState::ES2PANDA;
85
86 std::unordered_map<OptState, std::vector<std::string> *> argsMap = {{OptState::ES2PANDA, &es2pandaArgs},
87 {OptState::JIT_COMPILER, &bcoCompilerArgs},
88 {OptState::OPTIMIZER, &bytecodeoptArgs}};
89
90 for (int i = 1; i < argc; i++) {
91 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
92 const char *argI = argv[i];
93 if (COMPILER_PREFIX == argI) {
94 optState = OptState::JIT_COMPILER;
95 continue;
96 }
97
98 if (OPTIMIZER_PREFIX == argI) {
99 optState = OptState::OPTIMIZER;
100 continue;
101 }
102
103 argsMap[optState]->emplace_back(argI);
104 optState = OptState::ES2PANDA;
105 }
106 }
107
108 template <class T>
ParseComponentArgs(const std::vector<std::string> &args, T &options)109 static bool ParseComponentArgs(const std::vector<std::string> &args, T &options)
110 {
111 ark::PandArgParser parser;
112 options.AddOptions(&parser);
113 if (!parser.Parse(args)) {
114 std::cerr << parser.GetErrorString();
115 std::cerr << parser.GetHelpString();
116 return false;
117 }
118
119 if (auto optionsErr = options.Validate(); optionsErr) {
120 std::cerr << "Error: " << optionsErr.value().GetMessage() << std::endl;
121 return false;
122 }
123
124 return true;
125 }
126
ParseBCOCompilerOptions([[maybe_unused]] const std::vector<std::string> &compilerArgs, [[maybe_unused]] const std::vector<std::string> &bytecodeoptArgs)127 static bool ParseBCOCompilerOptions([[maybe_unused]] const std::vector<std::string> &compilerArgs,
128 [[maybe_unused]] const std::vector<std::string> &bytecodeoptArgs)
129 {
130 #ifdef PANDA_WITH_BYTECODE_OPTIMIZER
131 if (!ParseComponentArgs(compilerArgs, ark::compiler::g_options)) {
132 return false;
133 }
134 if (!ParseComponentArgs(bytecodeoptArgs, ark::bytecodeopt::g_options)) {
135 return false;
136 }
137 #endif
138
139 return true;
140 }
141
ETSWarningsGroupSetter(const ark::PandArg<bool> &option)142 static inline bool ETSWarningsGroupSetter(const ark::PandArg<bool> &option)
143 {
144 return !option.WasSet() || (option.WasSet() && option.GetValue());
145 }
146
SplitPath(std::string_view path)147 static std::tuple<std::string_view, std::string_view, std::string_view> SplitPath(std::string_view path)
148 {
149 std::string_view fileDirectory;
150 std::string_view fileBaseName = path;
151 auto lastDelimPos = fileBaseName.find_last_of(ark::os::file::File::GetPathDelim());
152 if (lastDelimPos != std::string_view::npos) {
153 ++lastDelimPos;
154 fileDirectory = fileBaseName.substr(0, lastDelimPos);
155 fileBaseName = fileBaseName.substr(lastDelimPos);
156 }
157
158 // Save all extensions.
159 std::string_view fileExtensions;
160 auto fileBaseNamePos = fileBaseName.find_first_of('.');
161 if (fileBaseNamePos > 0 && fileBaseNamePos != std::string_view::npos) {
162 fileExtensions = fileBaseName.substr(fileBaseNamePos);
163 fileBaseName = fileBaseName.substr(0, fileBaseNamePos);
164 }
165
166 return {fileDirectory, fileBaseName, fileExtensions};
167 }
168
169 /**
170 * @brief Generate evaluated expression wrapping code.
171 * @param sourceFilePath used for generating a unique package name.
172 * @param input expression source code file stream.
173 * @param output stream for generating expression wrapper.
174 */
GenerateEvaluationWrapper(std::string_view sourceFilePath, std::ifstream &input, std::stringstream &output)175 static void GenerateEvaluationWrapper(std::string_view sourceFilePath, std::ifstream &input, std::stringstream &output)
176 {
177 static constexpr std::string_view EVAL_PREFIX = "eval_";
178 static constexpr std::string_view EVAL_SUFFIX = "_eval";
179
180 auto splittedPath = SplitPath(sourceFilePath);
181 auto fileBaseName = std::get<1>(splittedPath);
182
183 std::random_device rd;
184 std::stringstream ss;
185 ss << EVAL_PREFIX << fileBaseName << '_' << rd() << EVAL_SUFFIX;
186 auto methodName = ss.str();
187
188 output << "package " << methodName << "; class " << methodName << " { private static " << methodName << "() { "
189 << input.rdbuf() << " } }";
190 }
191
192 static auto constexpr DEFAULT_THREAD_COUNT = 0;
193
194 struct AllArgs {
195 // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
196 ark::PandArg<bool> opHelp {"help", false, "Print this message and exit"};
197 ark::PandArg<bool> opVersion {"version", false, "Print message with version and exit"};
198
199 // parser
200 ark::PandArg<std::string> inputExtension {"extension", "",
201 "Parse the input as the given extension (options: js | ts | as | sts)"};
202 ark::PandArg<bool> opModule {"module", false, "Parse the input as module (JS only option)"};
203 ark::PandArg<bool> opParseOnly {"parse-only", false, "Parse the input only"};
204 ark::PandArg<bool> opDumpAst {"dump-ast", false, "Dump the parsed AST"};
205 ark::PandArg<bool> opDumpAstOnlySilent {"dump-ast-only-silent", false,
206 "Dump parsed AST with all dumpers available but don't print to stdout"};
207 ark::PandArg<bool> opDumpCheckedAst {"dump-dynamic-ast", false,
208 "Dump AST with synthetic nodes for dynamic languages"};
209 ark::PandArg<bool> opListFiles {"list-files", false, "Print names of files that are part of compilation"};
210
211 // compiler
212 ark::PandArg<bool> opDumpAssembly {"dump-assembly", false, "Dump pandasm"};
213 ark::PandArg<bool> opDebugInfo {"debug-info", false, "Compile with debug info"};
214 ark::PandArg<bool> opDumpDebugInfo {"dump-debug-info", false, "Dump debug info"};
215 ark::PandArg<int> opOptLevel {"opt-level", 0, "Compiler optimization level (options: 0 | 1 | 2)", 0, MAX_OPT_LEVEL};
216 ark::PandArg<bool> opEtsModule {"ets-module", false, "Compile the input as ets-module"};
217
218 // ETS-warnings
219 ark::PandArg<bool> opEtsEnableAll {"ets-warnings-all", false, "Show performance-related ets-warnings"};
220 ark::PandArg<bool> opEtsWerror {"ets-werror", false, "Treat all enabled performance-related ets-warnings as error"};
221 ark::PandArg<bool> opEtsSubsetWarnings {"ets-subset-warnings", false, "Show ETS-warnings that keep you in subset"};
222 ark::PandArg<bool> opEtsNonsubsetWarnings {"ets-nonsubset-warnings", false,
223 "Show ETS-warnings that do not keep you in subset"};
224 ark::PandArg<bool> opEtsSuggestFinal {"ets-suggest-final", false,
225 "Suggest final keyword warning - ETS non-subset warning"};
226 ark::PandArg<bool> opEtsProhibitTopLevelStatements {"ets-prohibit-top-level-statements", false,
227 "Prohibit top-level statements - ETS subset Warning"};
228 ark::PandArg<bool> opEtsBoostEqualityStatement {"ets-boost-equality-statement", false,
229 "Suggest boosting Equality Statements - ETS Subset Warning"};
230 ark::PandArg<bool> opEtsRemoveAsync {
231 "ets-remove-async", false, "Suggests replacing async functions with coroutines - ETS Non Subset Warnings"};
232 ark::PandArg<bool> opEtsRemoveLambda {"ets-remove-lambda", false,
233 "Suggestions to replace lambda with regular functions - ETS Subset Warning"};
234 ark::PandArg<bool> opEtsImplicitBoxingUnboxing {
235 "ets-implicit-boxing-unboxing", false,
236 "Check if a program contains implicit boxing or unboxing - ETS Subset Warning"};
237
238 ark::PandArg<bool> opDebuggerEvalMode {"debugger-eval-mode", false, "Compile given file in evaluation mode"};
239 ark::PandArg<uint64_t> opDebuggerEvalLine {
240 "debugger-eval-line", 0, "Debugger evaluation mode, line in the source file code where evaluate occurs."};
241 ark::PandArg<std::string> opDebuggerEvalSource {"debugger-eval-source", "",
242 "Debugger evaluation mode, path to evaluation mode source file"};
243 ark::PandArg<std::string> opDebuggerEvalPandaFiles {
244 "debugger-eval-panda-files", "",
245 "Debugger evaluation mode, paths to evaluation mode (.abc) files, must be accessible"};
246
247 ark::PandArg<int> opThreadCount {"thread", DEFAULT_THREAD_COUNT, "Number of worker threads"};
248 ark::PandArg<bool> opSizeStat {"dump-size-stat", false, "Dump size statistics"};
249 ark::PandArg<std::string> outputFile {"output", "", "Compiler binary output (.abc)"};
250 ark::PandArg<std::string> logLevel {"log-level", "error", "Log-level"};
251 ark::PandArg<std::string> stdLib {"stdlib", "", "Path to standard library"};
252 ark::PandArg<bool> genStdLib {"gen-stdlib", false, "Gen standard library"};
253 ark::PandArg<std::string> plugins {"plugins", "", "Plugins"};
254 ark::PandArg<std::string> skipPhases {"skip-phases", "", "Phases to skip"};
255 ark::PandArg<std::string> verifierWarnings {
256 "verifier-warnings", "CheckInfiniteLoopForAll",
257 "Print errors and continue compilation if AST tree is incorrect. "
258 "Possible values: "
259 "NodeHasParentForAll,EveryChildHasValidParentForAll,VariableHasScopeForAll,NodeHasTypeForAll,"
260 "IdentifierHasVariableForAll,ArithmeticOperationValidForAll,SequenceExpressionHasLastTypeForAll, "
261 "CheckInfiniteLoopForAll,"
262 "ForLoopCorrectlyInitializedForAll,VariableHasEnclosingScopeForAll,ModifierAccessValidForAll,"
263 "ImportExportAccessValid,NodeHasSourceRangeForAll,EveryChildInParentRangeForAll,"
264 "ReferenceTypeAnnotationIsNullForAll,VariableNameIdentifierNameSameForAll,CheckAbstractMethodForAll,"
265 "GetterSetterValidationForAll,CheckScopeDeclarationForAll"};
266 ark::PandArg<std::string> verifierErrors {
267 "verifier-errors",
268 "ForLoopCorrectlyInitializedForAll,SequenceExpressionHasLastTypeForAll,NodeHasTypeForAll,NodeHasParentForAll,"
269 "EveryChildHasValidParentForAll,ModifierAccessValidForAll,ArithmeticOperationValidForAll,"
270 "VariableHasScopeForAll,IdentifierHasVariableForAll,VariableHasEnclosingScopeForAll,"
271 "ReferenceTypeAnnotationIsNullForAll,VariableNameIdentifierNameSameForAll,CheckAbstractMethodForAll,"
272 "GetterSetterValidationForAll,CheckScopeDeclarationForAll",
273 "Print errors and stop compilation if AST tree is incorrect. "
274 "Possible values: "
275 "NodeHasParentForAll,EveryChildHasValidParentForAll,VariableHasScopeForAll,NodeHasTypeForAll,"
276 "IdentifierHasVariableForAll,ArithmeticOperationValidForAll,SequenceExpressionHasLastTypeForAll,"
277 "CheckInfiniteLoopForAll,"
278 "ForLoopCorrectlyInitializedForAll,VariableHasEnclosingScopeForAll,ModifierAccessValidForAll,"
279 "ImportExportAccessValid,NodeHasSourceRangeForAll,EveryChildInParentRangeForAll,"
280 "ReferenceTypeAnnotationIsNullForAll,VariableNameIdentifierNameSameForAll,CheckAbstractMethodForAll,"
281 "GetterSetterValidationForAll,CheckScopeDeclarationForAll"};
282 ark::PandArg<bool> verifierAllChecks {
283 "verifier-all-checks", false,
284 "Run verifier checks on every phase, monotonically expanding them on every phase"};
285 ark::PandArg<bool> verifierFullProgram {"verifier-full-program", false,
286 "Analyze full program, including program AST and it's dependencies"};
287 ark::PandArg<std::string> dumpBeforePhases {"dump-before-phases", "",
288 "Generate program dump before running phases in the list"};
289 ark::PandArg<std::string> dumpEtsSrcBeforePhases {
290 "dump-ets-src-before-phases", "", "Generate program dump as ets source code before running phases in the list"};
291 ark::PandArg<std::string> dumpEtsSrcAfterPhases {
292 "dump-ets-src-after-phases", "", "Generate program dump as ets source code after running phases in the list"};
293 ark::PandArg<std::string> dumpAfterPhases {"dump-after-phases", "",
294 "Generate program dump after running phases in the list"};
295 ark::PandArg<bool> opListPhases {"list-phases", false, "Dump list of available phases"};
296
297 // tail arguments
298 ark::PandArg<std::string> inputFile {"input", "", "input file"};
299
300 ark::PandArg<std::string> arktsConfig;
301 // NOLINTEND(misc-non-private-member-variables-in-classes)
302
AllArgsark::es2panda::util::AllArgs303 explicit AllArgs(const char *argv0)
304 : arktsConfig {"arktsconfig", ark::es2panda::JoinPaths(ark::es2panda::ParentPath(argv0), "arktsconfig.json"),
305 "Path to arkts configuration file"}
306 {
307 }
308
ParseInputOutputark::es2panda::util::AllArgs309 bool ParseInputOutput(CompilationMode compilationMode, std::string &errorMsg, std::string &sourceFile,
310 std::string &parserInput, std::string &compilerOutput) const
311 {
312 auto isDebuggerEvalMode = opDebuggerEvalMode.GetValue();
313 if (isDebuggerEvalMode && compilationMode != CompilationMode::SINGLE_FILE) {
314 errorMsg = "Error: When compiling with --debugger-eval-mode single input file must be provided";
315 return false;
316 }
317
318 sourceFile = inputFile.GetValue();
319 if (compilationMode == CompilationMode::SINGLE_FILE) {
320 std::ifstream inputStream(sourceFile.c_str());
321 if (inputStream.fail()) {
322 errorMsg = "Failed to open file: ";
323 errorMsg.append(sourceFile);
324 return false;
325 }
326
327 std::stringstream ss;
328 if (isDebuggerEvalMode) {
329 GenerateEvaluationWrapper(sourceFile, inputStream, ss);
330 } else {
331 ss << inputStream.rdbuf();
332 }
333 parserInput = ss.str();
334 }
335
336 if (!outputFile.GetValue().empty()) {
337 if (compilationMode == CompilationMode::PROJECT) {
338 errorMsg = "Error: When compiling in project mode --output key is not needed";
339 return false;
340 }
341 compilerOutput = outputFile.GetValue();
342 } else {
343 compilerOutput = RemoveExtension(BaseName(sourceFile)).append(".abc");
344 }
345
346 return true;
347 }
348
BindArgsark::es2panda::util::AllArgs349 void BindArgs(ark::PandArgParser &argparser)
350 {
351 argparser.Add(&opHelp);
352 argparser.Add(&opVersion);
353 argparser.Add(&opModule);
354 argparser.Add(&opDumpAst);
355 argparser.Add(&opDumpAstOnlySilent);
356 argparser.Add(&opDumpCheckedAst);
357 argparser.Add(&opParseOnly);
358 argparser.Add(&opDumpAssembly);
359 argparser.Add(&opDebugInfo);
360 argparser.Add(&opDumpDebugInfo);
361
362 argparser.Add(&opOptLevel);
363 argparser.Add(&opEtsModule);
364 argparser.Add(&opThreadCount);
365 argparser.Add(&opSizeStat);
366 argparser.Add(&opListFiles);
367
368 argparser.Add(&inputExtension);
369 argparser.Add(&outputFile);
370 argparser.Add(&logLevel);
371 argparser.Add(&stdLib);
372 argparser.Add(&genStdLib);
373 argparser.Add(&plugins);
374 argparser.Add(&skipPhases);
375 argparser.Add(&verifierAllChecks);
376 argparser.Add(&verifierFullProgram);
377 argparser.Add(&verifierWarnings);
378 argparser.Add(&verifierErrors);
379 argparser.Add(&dumpBeforePhases);
380 argparser.Add(&dumpEtsSrcBeforePhases);
381 argparser.Add(&dumpAfterPhases);
382 argparser.Add(&dumpEtsSrcAfterPhases);
383 argparser.Add(&opListPhases);
384 argparser.Add(&arktsConfig);
385
386 argparser.Add(&opEtsEnableAll);
387 argparser.Add(&opEtsWerror);
388 argparser.Add(&opEtsSubsetWarnings);
389 argparser.Add(&opEtsNonsubsetWarnings);
390
391 // ETS-subset warnings
392 argparser.Add(&opEtsProhibitTopLevelStatements);
393 argparser.Add(&opEtsBoostEqualityStatement);
394 argparser.Add(&opEtsRemoveLambda);
395 argparser.Add(&opEtsImplicitBoxingUnboxing);
396
397 // ETS-non-subset warnings
398 argparser.Add(&opEtsSuggestFinal);
399 argparser.Add(&opEtsRemoveAsync);
400
401 AddDebuggerEvaluationOptions(argparser);
402
403 argparser.PushBackTail(&inputFile);
404 argparser.EnableTail();
405 argparser.EnableRemainder();
406 }
407
InitCompilerOptionsark::es2panda::util::AllArgs408 void InitCompilerOptions(es2panda::CompilerOptions &compilerOptions, CompilationMode compilationMode) const
409 {
410 compilerOptions.dumpAsm = opDumpAssembly.GetValue();
411 compilerOptions.dumpAst = opDumpAst.GetValue();
412 compilerOptions.opDumpAstOnlySilent = opDumpAstOnlySilent.GetValue();
413 compilerOptions.dumpCheckedAst = opDumpCheckedAst.GetValue();
414 compilerOptions.dumpDebugInfo = opDumpDebugInfo.GetValue();
415 compilerOptions.isDebug = opDebugInfo.GetValue();
416 compilerOptions.parseOnly = opParseOnly.GetValue();
417 compilerOptions.stdLib = stdLib.GetValue();
418 compilerOptions.isEtsModule = opEtsModule.GetValue();
419 compilerOptions.plugins = SplitToStringVector(plugins.GetValue());
420 compilerOptions.skipPhases = SplitToStringSet(skipPhases.GetValue());
421 compilerOptions.verifierFullProgram = verifierFullProgram.GetValue();
422 compilerOptions.verifierAllChecks = verifierAllChecks.GetValue();
423 compilerOptions.verifierWarnings = SplitToStringSet(verifierWarnings.GetValue());
424 compilerOptions.verifierErrors = SplitToStringSet(verifierErrors.GetValue());
425 compilerOptions.dumpBeforePhases = SplitToStringSet(dumpBeforePhases.GetValue());
426 compilerOptions.dumpEtsSrcBeforePhases = SplitToStringSet(dumpEtsSrcBeforePhases.GetValue());
427 compilerOptions.dumpAfterPhases = SplitToStringSet(dumpAfterPhases.GetValue());
428 compilerOptions.dumpEtsSrcAfterPhases = SplitToStringSet(dumpEtsSrcAfterPhases.GetValue());
429
430 // ETS-Warnings
431 compilerOptions.etsSubsetWarnings = opEtsSubsetWarnings.GetValue();
432 compilerOptions.etsWerror = opEtsWerror.GetValue();
433 compilerOptions.etsNonsubsetWarnings = opEtsNonsubsetWarnings.GetValue();
434 compilerOptions.etsEnableAll = opEtsEnableAll.GetValue();
435
436 if (compilerOptions.etsEnableAll || compilerOptions.etsSubsetWarnings) {
437 // Adding subset warnings
438 compilerOptions.etsProhibitTopLevelStatements = ETSWarningsGroupSetter(opEtsProhibitTopLevelStatements);
439 compilerOptions.etsBoostEqualityStatement = ETSWarningsGroupSetter(opEtsBoostEqualityStatement);
440 compilerOptions.etsRemoveLambda = ETSWarningsGroupSetter(opEtsRemoveLambda);
441 compilerOptions.etsImplicitBoxingUnboxing = ETSWarningsGroupSetter(opEtsImplicitBoxingUnboxing);
442 }
443
444 if (compilerOptions.etsEnableAll || compilerOptions.etsNonsubsetWarnings) {
445 // Adding non-subset warnings
446 compilerOptions.etsSuggestFinal = ETSWarningsGroupSetter(opEtsSuggestFinal);
447 compilerOptions.etsRemoveAsync = ETSWarningsGroupSetter(opEtsRemoveAsync);
448 }
449
450 if (!compilerOptions.etsEnableAll && !compilerOptions.etsSubsetWarnings &&
451 !compilerOptions.etsNonsubsetWarnings) {
452 // If no warnings groups enabled - check all if enabled
453 compilerOptions.etsSuggestFinal = opEtsSuggestFinal.GetValue();
454 compilerOptions.etsProhibitTopLevelStatements = opEtsProhibitTopLevelStatements.GetValue();
455 compilerOptions.etsBoostEqualityStatement = opEtsBoostEqualityStatement.GetValue();
456 compilerOptions.etsRemoveAsync = opEtsRemoveAsync.GetValue();
457 compilerOptions.etsRemoveLambda = opEtsRemoveLambda.GetValue();
458 compilerOptions.etsImplicitBoxingUnboxing = opEtsImplicitBoxingUnboxing.GetValue();
459 }
460
461 InitDebuggerEvaluationCompilerOptions(compilerOptions);
462
463 // Pushing enabled warnings to warning collection
464 PushingEnabledWarnings(compilerOptions);
465
466 compilerOptions.compilationMode = compilationMode;
467 compilerOptions.arktsConfig = std::make_shared<ark::es2panda::ArkTsConfig>(arktsConfig.GetValue());
468 }
469
470 private:
PushingEnabledWarningsark::es2panda::util::AllArgs471 static void PushingEnabledWarnings(es2panda::CompilerOptions &compilerOptions)
472 {
473 if (compilerOptions.etsSuggestFinal) {
474 compilerOptions.etsWarningCollection.push_back(ETSWarnings::SUGGEST_FINAL);
475 }
476 if (compilerOptions.etsProhibitTopLevelStatements) {
477 compilerOptions.etsWarningCollection.push_back(ETSWarnings::PROHIBIT_TOP_LEVEL_STATEMENTS);
478 }
479 if (compilerOptions.etsBoostEqualityStatement) {
480 compilerOptions.etsWarningCollection.push_back(ETSWarnings::BOOST_EQUALITY_STATEMENT);
481 }
482 if (compilerOptions.etsRemoveAsync) {
483 compilerOptions.etsWarningCollection.push_back(ETSWarnings::REMOVE_ASYNC_FUNCTIONS);
484 }
485 if (compilerOptions.etsRemoveLambda) {
486 compilerOptions.etsWarningCollection.push_back(ETSWarnings::REMOVE_LAMBDA);
487 }
488 if (compilerOptions.etsImplicitBoxingUnboxing) {
489 compilerOptions.etsWarningCollection.push_back(ETSWarnings::IMPLICIT_BOXING_UNBOXING);
490 }
491 if (!compilerOptions.etsWarningCollection.empty()) {
492 compilerOptions.etsHasWarnings = true;
493 }
494 }
495
AddDebuggerEvaluationOptionsark::es2panda::util::AllArgs496 void AddDebuggerEvaluationOptions(ark::PandArgParser &argparser)
497 {
498 argparser.Add(&opDebuggerEvalMode);
499 argparser.Add(&opDebuggerEvalLine);
500 argparser.Add(&opDebuggerEvalSource);
501 argparser.Add(&opDebuggerEvalPandaFiles);
502 }
503
InitDebuggerEvaluationCompilerOptionsark::es2panda::util::AllArgs504 void InitDebuggerEvaluationCompilerOptions(es2panda::CompilerOptions &compilerOptions) const
505 {
506 compilerOptions.debuggerEvalMode = opDebuggerEvalMode.GetValue();
507 if (compilerOptions.debuggerEvalMode) {
508 compilerOptions.debuggerEvalLine = opDebuggerEvalLine.GetValue();
509 compilerOptions.debuggerEvalSource = opDebuggerEvalSource.GetValue();
510 compilerOptions.debuggerEvalPandaFiles = SplitToStringVector(opDebuggerEvalPandaFiles.GetValue());
511 }
512 }
513 };
514
Usage(const ark::PandArgParser &argparser)515 static std::string Usage(const ark::PandArgParser &argparser)
516 {
517 std::stringstream ss;
518
519 ss << argparser.GetErrorString() << std::endl;
520 ss << "Usage: "
521 << "es2panda"
522 << " [OPTIONS] [input file] -- [arguments]" << std::endl;
523 ss << std::endl;
524 ss << "optional arguments:" << std::endl;
525 ss << argparser.GetHelpString() << std::endl;
526
527 ss << std::endl;
528 ss << "--bco-optimizer: Argument directly to bytecode optimizer can be passed after this prefix" << std::endl;
529 ss << "--bco-compiler: Argument directly to jit-compiler inside bytecode optimizer can be passed after this "
530 "prefix"
531 << std::endl;
532
533 return ss.str();
534 }
535
GetVersion()536 static std::string GetVersion()
537 {
538 std::stringstream ss;
539
540 ss << std::endl;
541 ss << " Es2panda Version " << ES2PANDA_VERSION << std::endl;
542
543 #ifndef PANDA_PRODUCT_BUILD
544 #ifdef ES2PANDA_DATE
545 ss << std::endl;
546 ss << " Build date: ";
547 ss << ES2PANDA_DATE;
548 #endif // ES2PANDA_DATE
549 #ifdef ES2PANDA_HASH
550 ss << std::endl;
551 ss << " Last commit hash: ";
552 ss << ES2PANDA_HASH;
553 ss << std::endl;
554 #endif // ES2PANDA_HASH
555 #endif // PANDA_PRODUCT_BUILD
556
557 return ss.str();
558 }
559
Parse(int argc, const char **argv)560 bool Options::Parse(int argc, const char **argv)
561 {
562 std::vector<std::string> es2pandaArgs;
563 std::vector<std::string> bcoCompilerArgs;
564 std::vector<std::string> bytecodeoptArgs;
565
566 SplitArgs(argc, argv, es2pandaArgs, bcoCompilerArgs, bytecodeoptArgs);
567 if (!ParseBCOCompilerOptions(bcoCompilerArgs, bytecodeoptArgs)) {
568 return false;
569 }
570
571 AllArgs allArgs(argv[0]); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
572
573 allArgs.BindArgs(*argparser_);
574 if (!argparser_->Parse(es2pandaArgs) || allArgs.opHelp.GetValue()) {
575 errorMsg_ = Usage(*argparser_);
576 return false;
577 }
578
579 if (allArgs.opVersion.GetValue()) {
580 errorMsg_ = GetVersion();
581 return false;
582 }
583
584 // Determine compilation mode
585 auto compilationMode = DetermineCompilationMode(allArgs.genStdLib, allArgs.inputFile);
586 if (!allArgs.ParseInputOutput(compilationMode, errorMsg_, sourceFile_, parserInput_, compilerOutput_)) {
587 return false;
588 }
589
590 // Determine Extension
591 DetermineExtension(allArgs.inputExtension, allArgs.arktsConfig, compilationMode);
592 if (extension_ == es2panda::ScriptExtension::INVALID) {
593 return false;
594 }
595
596 if (extension_ != es2panda::ScriptExtension::JS && allArgs.opModule.GetValue()) {
597 errorMsg_ = "Error: --module is not supported for this extension.";
598 return false;
599 }
600
601 // Add Option Flags
602 AddOptionFlags(allArgs.opParseOnly, allArgs.opModule, allArgs.opSizeStat);
603
604 if ((allArgs.dumpEtsSrcBeforePhases.GetValue().size() + allArgs.dumpEtsSrcAfterPhases.GetValue().size() > 0) &&
605 extension_ != es2panda::ScriptExtension::ETS) {
606 errorMsg_ = "--dump-ets-src-* option is valid only with ETS extension";
607 return false;
608 }
609
610 DetermineLogLevel(allArgs.logLevel);
611 if (logLevel_ == util::LogLevel::INVALID) {
612 return false;
613 }
614
615 allArgs.InitCompilerOptions(compilerOptions_, compilationMode);
616 // Some additional checks for ETS extension
617 if (!CheckEtsSpecificOptions(compilationMode, allArgs.arktsConfig)) {
618 return false;
619 }
620
621 optLevel_ = allArgs.opOptLevel.GetValue();
622 threadCount_ = allArgs.opThreadCount.GetValue();
623 listFiles_ = allArgs.opListFiles.GetValue();
624 listPhases_ = allArgs.opListPhases.GetValue();
625
626 return true;
627 }
628 } // namespace ark::es2panda::util
629