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