24int main(
int argc,
char** argv)
26 using namespace clipp;
41 auto selected = mode::repl;
52 std::string file, eval_expression;
55 bool format_dry_run =
false;
56 bool format_check =
false;
58 std::vector<std::string> script_args;
63 auto debug_flag = joinable(repeatable(option(
"-d",
"--debug").call([&]{ debug++; })
64 .doc(
"Increase debug level (default: 0)\n")));
65 auto lib_dir_flag = option(
"-L",
"--lib").doc(
"Set the location of the ArkScript standard library. Paths can be delimited by ';'\n")
66 & value(
"lib_dir", libdir);
68 auto import_solver_pass_flag = (
70 | option(
"-fno-importsolver").call([&] { passes &=
~Ark::FeatureImportSolver; })
71 ).doc(
"Toggle on and off the import solver pass");
72 auto macro_proc_pass_flag = (
74 | option(
"-fno-macroprocessor").call([&] { passes &=
~Ark::FeatureMacroProcessor; })
75 ).doc(
"Toggle on and off the macro processor pass");
76 auto optimizer_pass_flag = (
78 | option(
"-fno-optimizer").call([&] { passes &=
~Ark::FeatureASTOptimizer; })
79 ).doc(
"Toggle on and off the optimizer pass");
80 auto ir_optimizer_pass_flag = (
82 | option(
"-fno-iroptimizer").call([&] { passes &=
~Ark::FeatureIROptimizer; })
83 ).doc(
"Toggle on and off the IR optimizer pass");
84 auto vm_debugger_flag = (
86 ).doc(
"Turn on the debugger");
88 .doc(
"Dump IR to file.ark.ir");
90 .doc(
"Disable the bytecode cache creation");
92 const auto run_flags = (
94 debug_flag, lib_dir_flag, import_solver_pass_flag, macro_proc_pass_flag,
96 optimizer_pass_flag, ir_optimizer_pass_flag, vm_debugger_flag, ir_dump,
101 option(
"-h",
"--help").set(selected, mode::help).doc(
"Display this message")
102 | option(
"-v",
"--version").set(selected, mode::version).doc(
"Display ArkScript version and exit")
103 | option(
"--dev-info").set(selected, mode::dev_info).doc(
"Display development information and exit")
105 required(
"-e",
"--eval").set(selected, mode::eval).doc(
"Evaluate ArkScript expression")
106 & value(
"expression", eval_expression)
111 required(
"-c",
"--compile").set(selected, mode::compile).doc(
"Compile the given program to bytecode, but do not run")
112 & value(
"file", file).doc(
"If file is -, it reads code from stdin")
114 | value(
"file", file).set(selected, mode::run)
117 required(
"-f",
"--format").set(selected, mode::format).doc(
"Format the given source file in place")
118 & value(
"file", file)
120 option(
"--dry-run").set(format_dry_run,
true).doc(
"Do not modify the file, only print out the changes")
121 | option(
"--check").set(format_check,
true).doc(
"Check if a file formating is correctly, without modifying it. Return 1 if formating is needed, 0 otherwise")
127 , required(
"--ast").set(selected, mode::ast).doc(
"Compile the given program and output its AST as JSON to stdout")
128 & value(
"file", file)
131 required(
"-bcr",
"--bytecode-reader").set(selected, mode::bytecode_reader).doc(
"Launch the bytecode reader")
132 & value(
"file", file).doc(
".arkc bytecode file or .ark source file that will be compiled first")
143 & value(
"page", bcr_page)
146 , option(
"-s",
"--slice").doc(
"Select a slice of instructions in the bytecode")
147 & value(
"start", bcr_start)
148 & value(
"end", bcr_end)
152 , any_other(script_args)
156 auto fmt = doc_formatting {}
160 .split_alternatives(
true)
161 .merge_alternative_flags_with_common_prefix(
true)
162 .paragraph_spacing(1)
163 .ignore_newline_chars(
false);
164 const auto man_page = make_man_page(cli,
"arkscript", fmt)
165 .prepend_section(
"DESCRIPTION",
" ArkScript programming language")
168 .append_section(
"LICENSE",
" Mozilla Public License 2.0");
170 if (
auto result = parse(argc, argv, cli))
174 std::vector<std::filesystem::path> lib_paths;
178 std::ranges::transform(Utils::splitString(libdir,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
179 return std::filesystem::path(path);
184 if (
const char* arkpath = std::getenv(
"ARKSCRIPT_PATH"))
186 std::ranges::transform(Utils::splitString(arkpath,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
187 return std::filesystem::path(path);
190 else if (Utils::fileExists(
"./lib") && Utils::fileExists(
"./lib/std/Prelude.ark"))
191 lib_paths.emplace_back(
"lib");
193 fmt::println(std::cerr,
"{}: Couldn't read ARKSCRIPT_PATH environment variable", fmt::styled(
"Warning", fmt::fg(fmt::color::dark_orange)));
199 std::cout << man_page << std::endl;
209 fmt::println(
"{:^34}|{:^8}|{:^10}",
"Type",
"SizeOf",
"AlignOf");
211#define ARK_PRINT_SIZE(type) fmt::println("{:<34}| {:<7}| {:<9}", #type, sizeof(type), alignof(type))
244 if (!state.
doFile(file, passes))
257 std::string content(std::istreambuf_iterator<char>(std::cin), {});
258 if (!state.
doString(content, passes))
261 else if (!state.
doFile(file, passes))
273 if (!state.
doString(eval_expression))
275 std::cerr <<
"Could not evaluate expression\n";
287 fmt::println(
"{}", compiler.
compile());
291 case mode::bytecode_reader:
300 fmt::println(
"Compiling {}...", file);
311 bcr.
display(segment, std::nullopt, std::nullopt, bcr_page);
313 bcr.
display(segment, bcr_start, bcr_end);
315 bcr.
display(segment, bcr_start, bcr_end, bcr_page);
317 catch (
const std::exception& e)
319 std::cerr << e.what() << std::endl;
328 Formatter formatter(file, format_dry_run || format_check);
331 fmt::println(
"{}", formatter.
output());
339 std::cerr <<
"Could not parse CLI arguments" << std::endl;
341 auto doc_label = [](
const parameter& p) {
342 if (!p.flags().empty())
343 return p.flags().front();
344 if (!p.label().empty())
346 return doc_string {
"<?>" };
349 std::cout <<
"args -> parameter mapping:\n";
350 for (
const auto& m : result)
352 std::cout <<
"#" << m.index() <<
" " << m.arg() <<
" -> ";
353 if (
const parameter* p = m.param(); p)
355 std::cout << doc_label(*p) <<
" \t";
358 std::cout << (m.bad_repeat() ?
"[bad repeat " :
"[repeat ")
359 << m.repeat() <<
"]";
362 std::cout <<
" [blocked]";
364 std::cout <<
" [conflict]";
368 std::cout <<
" [unmapped]\n";
371 std::cout <<
"missing parameters:\n";
372 for (
const auto& m : result.missing())
374 if (
const parameter* p = m.param(); p)
376 std::cout << doc_label(*p) <<
" \t";
377 std::cout <<
" [missing after " << m.after_index() <<
"]\n";
#define ARK_PRINT_SIZE(type)
constexpr int ArkErrorExitCode