17int main(
int argc,
char** argv)
19 using namespace clipp;
34 auto selected = mode::repl;
38 constexpr uint16_t max_uint16 = std::numeric_limits<uint16_t>::max();
42 uint16_t bcr_page = max_uint16;
43 uint16_t bcr_start = max_uint16;
44 uint16_t bcr_end = max_uint16;
47 std::string file, eval_expression;
50 bool format_dry_run =
false;
51 bool format_check =
false;
53 std::vector<std::string> wrong, script_args;
58 auto debug_flag = joinable(repeatable(option(
"-d",
"--debug").call([&]{ debug++; })
59 .doc(
"Increase debug level (default: 0)\n")));
60 auto lib_dir_flag = option(
"-L",
"--lib").doc(
"Set the location of the ArkScript standard library. Paths can be delimited by ';'\n")
61 & value(
"lib_dir", libdir);
63 auto import_solver_pass_flag = (
65 | option(
"-fno-importsolver").call([&] { passes &=
~Ark::FeatureImportSolver; })
66 ).doc(
"Toggle on and off the import solver pass");
67 auto macro_proc_pass_flag = (
69 | option(
"-fno-macroprocessor").call([&] { passes &=
~Ark::FeatureMacroProcessor; })
70 ).doc(
"Toggle on and off the macro processor pass");
71 auto optimizer_pass_flag = (
73 | option(
"-fno-optimizer").call([&] { passes &=
~Ark::FeatureASTOptimizer; })
74 ).doc(
"Toggle on and off the optimizer pass");
75 auto ir_optimizer_pass_flag = (
77 | option(
"-fno-iroptimizer").call([&] { passes &=
~Ark::FeatureIROptimizer; })
78 ).doc(
"Toggle on and off the IR optimizer pass");
80 .doc(
"Dump IR to file.ark.ir");
82 const auto compiler_passes_flag = (
84 import_solver_pass_flag, macro_proc_pass_flag, optimizer_pass_flag, ir_optimizer_pass_flag, ir_dump
88 option(
"-h",
"--help").set(selected, mode::help).doc(
"Display this message")
89 | option(
"-v",
"--version").set(selected, mode::version).doc(
"Display ArkScript version and exit")
90 | option(
"--dev-info").set(selected, mode::dev_info).doc(
"Display development information and exit")
92 required(
"-e",
"--eval").set(selected, mode::eval).doc(
"Evaluate ArkScript expression\n")
93 & value(
"expression", eval_expression)
96 required(
"-c",
"--compile").set(selected, mode::compile).doc(
"Compile the given program to bytecode, but do not run")
99 , compiler_passes_flag
102 value(
"file", file).set(selected, mode::run)
106 , compiler_passes_flag
108 , any_other(script_args)
111 required(
"-f",
"--format").set(selected, mode::format).doc(
"Format the given source file in place")
112 & value(
"file", file)
114 option(
"--dry-run").set(format_dry_run,
true).doc(
"Do not modify the file, only print out the changes")
115 | 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")
119 required(
"--ast").set(selected, mode::ast).doc(
"Compile the given program and output its AST as JSON to stdout")
120 & value(
"file", file)
125 required(
"-bcr",
"--bytecode-reader").set(selected, mode::bytecode_reader).doc(
"Launch the bytecode reader")
126 & value(
"file", file).doc(
"If file isn't a bytecode file, the cached compiled will be loaded ; if there are none, it will be compiled first")
137 & value(
"page", bcr_page)
140 , option(
"-s",
"--slice").doc(
"Select a slice of instructions in the bytecode")
141 & value(
"start", bcr_start)
142 & value(
"end", bcr_end)
150 auto fmt = doc_formatting {}
154 .split_alternatives(
true)
155 .merge_alternative_flags_with_common_prefix(
true)
156 .paragraph_spacing(1)
157 .ignore_newline_chars(
false);
158 const auto man_page = make_man_page(cli,
"arkscript", fmt)
159 .prepend_section(
"DESCRIPTION",
" ArkScript programming language")
161 .append_section(
"LICENSE",
" Mozilla Public License 2.0");
163 if (parse(argc, argv, cli) && wrong.empty())
167 std::vector<std::filesystem::path> lib_paths;
171 std::ranges::transform(Utils::splitString(libdir,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
172 return std::filesystem::path(path);
177 if (
const char* arkpath = std::getenv(
"ARKSCRIPT_PATH"))
179 std::ranges::transform(Utils::splitString(arkpath,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
180 return std::filesystem::path(path);
183 else if (Utils::fileExists(
"./lib"))
184 lib_paths.emplace_back(
"lib");
186 fmt::println(
"{}: Couldn't read ARKSCRIPT_PATH environment variable", fmt::styled(
"Warning", fmt::fg(fmt::color::dark_orange)));
192 std::cout << man_page << std::endl;
202 "Have been compiled with {}\n\n"
203 "sizeof(Ark::Value) = {}B\n"
204 " sizeof(Value_t) = {}B\n"
205 " sizeof(ValueType) = {}B\n"
206 " sizeof(ProcType) = {}B\n"
207 " sizeof(Ark::Closure) = {}B\n"
208 " sizeof(Ark::UserType) = {}B\n"
209 "\nVirtual Machine\n"
210 "sizeof(Ark::VM) = {}B\n"
211 " sizeof(Ark::State) = {}B\n"
212 " sizeof(Ark::Scope) = {}B\n"
213 " sizeof(ExecutionContext) = {}B\n"
215 " sizeof(vector<Ark::Value>) = {}B\n"
216 " sizeof(char) = {}B\n"
217 "\nsizeof(Node) = {}B",
232 sizeof(std::vector<Ark::Value>),
249 if (!state.
doFile(file, passes))
261 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:
298 if (bcr_page == max_uint16 && bcr_start == max_uint16)
300 else if (bcr_page != max_uint16 && bcr_start == max_uint16)
301 bcr.
display(segment, std::nullopt, std::nullopt, bcr_page);
302 else if (bcr_page == max_uint16 && bcr_start != max_uint16)
303 bcr.
display(segment, bcr_start, bcr_end);
305 bcr.
display(segment, bcr_start, bcr_end, bcr_page);
307 catch (
const std::exception& e)
309 std::cerr << e.what() << std::endl;
318 Formatter formatter(file, format_dry_run || format_check);
321 fmt::println(
"{}", formatter.
output());
329 for (
const auto& arg : wrong)
330 std::cerr <<
"'" << arg.c_str() <<
"' isn't a valid argument\n";
332 std::cout << usage_lines(cli, fmt) << std::endl;
int main(int argc, char **argv)