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::FeatureASTOptimiser; })
79 ).doc(
"Toggle on and off the optimizer pass");
80 auto ir_inliner_pass_flag = (
82 | option(
"-fno-irinliner").call([&] { passes &=
~Ark::FeatureIRInliner; })
83 ).doc(
"Toggle on and off the IR inliner pass");
84 auto ir_optimizer_pass_flag = (
86 | option(
"-fno-iroptimizer").call([&] { passes &=
~Ark::FeatureIROptimiser; })
87 ).doc(
"Toggle on and off the IR optimizer pass");
88 auto vm_debugger_flag = (
90 ).doc(
"Turn on the debugger");
92 .doc(
"Dump IR to file.ark.ir");
94 .doc(
"Disable the bytecode cache creation");
96 const auto run_flags = (
98 debug_flag, lib_dir_flag, import_solver_pass_flag, macro_proc_pass_flag,
100 optimizer_pass_flag, ir_inliner_pass_flag, ir_optimizer_pass_flag,
102 vm_debugger_flag, ir_dump,
107 option(
"-h",
"--help").set(selected, mode::help).doc(
"Display this message")
108 | option(
"-v",
"--version").set(selected, mode::version).doc(
"Display ArkScript version and exit")
109 | option(
"--dev-info").set(selected, mode::dev_info).doc(
"Display development information and exit")
111 required(
"-e",
"--eval").set(selected, mode::eval).doc(
"Evaluate ArkScript expression")
112 & value(
"expression", eval_expression)
117 required(
"-c",
"--compile").set(selected, mode::compile).doc(
"Compile the given program to bytecode, but do not run")
118 & value(
"file", file).doc(
"If file is -, it reads code from stdin")
120 | value(
"file", file).set(selected, mode::run)
123 required(
"-f",
"--format").set(selected, mode::format).doc(
"Format the given source file in place")
124 & value(
"file", file)
126 option(
"--dry-run").set(format_dry_run,
true).doc(
"Do not modify the file, only print out the changes")
127 | 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")
133 , required(
"--ast").set(selected, mode::ast).doc(
"Compile the given program and output its AST as JSON to stdout")
134 & value(
"file", file)
137 required(
"-bcr",
"--bytecode-reader").set(selected, mode::bytecode_reader).doc(
"Launch the bytecode reader")
138 & value(
"file", file).doc(
".arkc bytecode file or .ark source file that will be compiled first")
149 & value(
"page", bcr_page)
152 , option(
"-s",
"--slice").doc(
"Select a slice of instructions in the bytecode")
153 & value(
"start", bcr_start)
154 & value(
"end", bcr_end)
158 , any_other(script_args)
162 auto fmt = doc_formatting {}
166 .split_alternatives(
true)
167 .merge_alternative_flags_with_common_prefix(
true)
168 .paragraph_spacing(1)
169 .ignore_newline_chars(
false);
170 const auto man_page = make_man_page(cli,
"arkscript", fmt)
171 .prepend_section(
"DESCRIPTION",
" ArkScript programming language")
174 .append_section(
"LICENSE",
" Mozilla Public License 2.0");
176 if (
auto result = parse(argc, argv, cli))
180 std::vector<std::filesystem::path> lib_paths;
184 std::ranges::transform(Utils::splitString(libdir,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
185 return std::filesystem::path(path);
190 if (
const char* arkpath = std::getenv(
"ARKSCRIPT_PATH"))
192 std::ranges::transform(Utils::splitString(arkpath,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
193 return std::filesystem::path(path);
196 else if (Utils::fileExists(
"./lib") && Utils::fileExists(
"./lib/std/Prelude.ark"))
197 lib_paths.emplace_back(
"lib");
198 else if (!DefaultLibFolder.empty() && Utils::fileExists(std::string(DefaultLibFolder) +
"/std/Prelude.ark"))
199 lib_paths.emplace_back(DefaultLibFolder);
201 fmt::println(std::cerr,
"{}: Couldn't read ARKSCRIPT_PATH environment variable", fmt::styled(
"Warning", fmt::fg(fmt::color::dark_orange)));
207 std::cout << man_page << std::endl;
217 fmt::println(
"{:^34}|{:^8}|{:^10}",
"Type",
"SizeOf",
"AlignOf");
219#define ARK_PRINT_SIZE(type) fmt::println("{:<34}| {:<7}| {:<9}", #type, sizeof(type), alignof(type))
252 if (!state.
doFile(file, passes))
265 std::string content(std::istreambuf_iterator<char>(std::cin), {});
266 if (!state.
doString(content, passes))
269 else if (!state.
doFile(file, passes))
281 if (!state.
doString(eval_expression))
283 std::cerr <<
"Could not evaluate expression\n";
295 fmt::println(
"{}", compiler.
compile());
299 case mode::bytecode_reader:
308 fmt::println(
"Compiling {}...", file);
319 bcr.
display(segment, std::nullopt, std::nullopt, bcr_page);
321 bcr.
display(segment, bcr_start, bcr_end);
323 bcr.
display(segment, bcr_start, bcr_end, bcr_page);
325 catch (
const std::exception& e)
327 std::cerr << e.what() << std::endl;
336 Formatter formatter(file, format_dry_run || format_check);
339 fmt::println(
"{}", formatter.
output());
347 std::cerr <<
"Could not parse CLI arguments" << std::endl;
349 auto doc_label = [](
const parameter& p) {
350 if (!p.flags().empty())
351 return p.flags().front();
352 if (!p.label().empty())
354 return doc_string {
"<?>" };
357 std::cout <<
"args -> parameter mapping:\n";
358 for (
const auto& m : result)
360 std::cout <<
"#" << m.index() <<
" " << m.arg() <<
" -> ";
361 if (
const parameter* p = m.param(); p)
363 std::cout << doc_label(*p) <<
" \t";
366 std::cout << (m.bad_repeat() ?
"[bad repeat " :
"[repeat ")
367 << m.repeat() <<
"]";
370 std::cout <<
" [blocked]";
372 std::cout <<
" [conflict]";
376 std::cout <<
" [unmapped]\n";
379 std::cout <<
"missing parameters:\n";
380 for (
const auto& m : result.missing())
382 if (
const parameter* p = m.param(); p)
384 std::cout << doc_label(*p) <<
" \t";
385 std::cout <<
" [missing after " << m.after_index() <<
"]\n";
#define ARK_PRINT_SIZE(type)
constexpr int ArkErrorExitCode