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