23int main(
int argc,
char** argv)
25 using namespace clipp;
40 auto selected = mode::repl;
44 constexpr uint16_t max_uint16 = std::numeric_limits<uint16_t>::max();
48 uint16_t bcr_page = max_uint16;
49 uint16_t bcr_start = max_uint16;
50 uint16_t bcr_end = max_uint16;
53 std::string file, eval_expression;
56 bool format_dry_run =
false;
57 bool format_check =
false;
59 std::vector<std::string> wrong, script_args;
64 auto debug_flag = joinable(repeatable(option(
"-d",
"--debug").call([&]{ debug++; })
65 .doc(
"Increase debug level (default: 0)\n")));
66 auto lib_dir_flag = option(
"-L",
"--lib").doc(
"Set the location of the ArkScript standard library. Paths can be delimited by ';'\n")
67 & value(
"lib_dir", libdir);
69 auto import_solver_pass_flag = (
71 | option(
"-fno-importsolver").call([&] { passes &=
~Ark::FeatureImportSolver; })
72 ).doc(
"Toggle on and off the import solver pass");
73 auto macro_proc_pass_flag = (
75 | option(
"-fno-macroprocessor").call([&] { passes &=
~Ark::FeatureMacroProcessor; })
76 ).doc(
"Toggle on and off the macro processor pass");
77 auto optimizer_pass_flag = (
79 | option(
"-fno-optimizer").call([&] { passes &=
~Ark::FeatureASTOptimizer; })
80 ).doc(
"Toggle on and off the optimizer pass");
81 auto ir_optimizer_pass_flag = (
83 | option(
"-fno-iroptimizer").call([&] { passes &=
~Ark::FeatureIROptimizer; })
84 ).doc(
"Toggle on and off the IR optimizer pass");
86 .doc(
"Dump IR to file.ark.ir");
88 const auto compiler_passes_flag = (
90 import_solver_pass_flag, macro_proc_pass_flag, optimizer_pass_flag, ir_optimizer_pass_flag, ir_dump
94 option(
"-h",
"--help").set(selected, mode::help).doc(
"Display this message")
95 | option(
"-v",
"--version").set(selected, mode::version).doc(
"Display ArkScript version and exit")
96 | option(
"--dev-info").set(selected, mode::dev_info).doc(
"Display development information and exit")
98 required(
"-e",
"--eval").set(selected, mode::eval).doc(
"Evaluate ArkScript expression\n")
99 & value(
"expression", eval_expression)
102 required(
"-c",
"--compile").set(selected, mode::compile).doc(
"Compile the given program to bytecode, but do not run")
103 & value(
"file", file)
105 , compiler_passes_flag
108 value(
"file", file).set(selected, mode::run)
112 , compiler_passes_flag
114 , any_other(script_args)
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")
125 required(
"--ast").set(selected, mode::ast).doc(
"Compile the given program and output its AST as JSON to stdout")
126 & 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)
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")
167 .append_section(
"LICENSE",
" Mozilla Public License 2.0");
169 if (parse(argc, argv, cli) && wrong.empty())
173 std::vector<std::filesystem::path> lib_paths;
177 std::ranges::transform(Utils::splitString(libdir,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
178 return std::filesystem::path(path);
183 if (
const char* arkpath = std::getenv(
"ARKSCRIPT_PATH"))
185 std::ranges::transform(Utils::splitString(arkpath,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
186 return std::filesystem::path(path);
189 else if (Utils::fileExists(
"./lib"))
190 lib_paths.emplace_back(
"lib");
192 fmt::println(
"{}: Couldn't read ARKSCRIPT_PATH environment variable", fmt::styled(
"Warning", fmt::fg(fmt::color::dark_orange)));
198 std::cout << man_page << std::endl;
208 "Have been compiled with {}\n\n"
209 "sizeof(Ark::Value) = {}B\n"
210 " sizeof(Value_t) = {}B\n"
211 " sizeof(ValueType) = {}B\n"
212 " sizeof(Ark::Procedure) = {}B\n"
213 " sizeof(Ark::Closure) = {}B\n"
214 " sizeof(Ark::UserType) = {}B\n"
215 "\nVirtual Machine\n"
216 "sizeof(Ark::VM) = {}B\n"
217 " sizeof(Ark::State) = {}B\n"
218 " sizeof(Ark::Scope) = {}B\n"
219 " sizeof(ExecutionContext) = {}B\n"
221 " sizeof(vector<Ark::Value>) = {}B\n"
222 " sizeof(char) = {}B\n"
223 "\nsizeof(Node) = {}B",
238 sizeof(std::vector<Ark::Value>),
255 if (!state.
doFile(file, passes))
267 if (!state.
doFile(file, passes))
279 if (!state.
doString(eval_expression))
281 std::cerr <<
"Could not evaluate expression\n";
293 fmt::println(
"{}", compiler.
compile());
297 case mode::bytecode_reader:
306 fmt::println(
"Compiling {}...", file);
314 if (bcr_page == max_uint16 && bcr_start == max_uint16)
316 else if (bcr_page != max_uint16 && bcr_start == max_uint16)
317 bcr.
display(segment, std::nullopt, std::nullopt, bcr_page);
318 else if (bcr_page == max_uint16 && bcr_start != max_uint16)
319 bcr.
display(segment, bcr_start, bcr_end);
321 bcr.
display(segment, bcr_start, bcr_end, bcr_page);
323 catch (
const std::exception& e)
325 std::cerr << e.what() << std::endl;
334 Formatter formatter(file, format_dry_run || format_check);
337 fmt::println(
"{}", formatter.
output());
345 for (
const auto& arg : wrong)
346 std::cerr <<
"'" << arg.c_str() <<
"' isn't a valid argument\n";
348 std::cout << usage_lines(cli, fmt) << std::endl;
#define ARK_ERROR_EXIT_CODE