23int main(
int argc,
char** argv)
25 using namespace clipp;
40 auto selected = mode::repl;
51 std::string file, eval_expression;
54 bool format_dry_run =
false;
55 bool format_check =
false;
57 std::vector<std::string> script_args;
62 auto debug_flag = joinable(repeatable(option(
"-d",
"--debug").call([&]{ debug++; })
63 .doc(
"Increase debug level (default: 0)\n")));
64 auto lib_dir_flag = option(
"-L",
"--lib").doc(
"Set the location of the ArkScript standard library. Paths can be delimited by ';'\n")
65 & value(
"lib_dir", libdir);
67 auto import_solver_pass_flag = (
69 | option(
"-fno-importsolver").call([&] { passes &=
~Ark::FeatureImportSolver; })
70 ).doc(
"Toggle on and off the import solver pass");
71 auto macro_proc_pass_flag = (
73 | option(
"-fno-macroprocessor").call([&] { passes &=
~Ark::FeatureMacroProcessor; })
74 ).doc(
"Toggle on and off the macro processor pass");
75 auto optimizer_pass_flag = (
77 | option(
"-fno-optimizer").call([&] { passes &=
~Ark::FeatureASTOptimizer; })
78 ).doc(
"Toggle on and off the optimizer pass");
79 auto ir_optimizer_pass_flag = (
81 | option(
"-fno-iroptimizer").call([&] { passes &=
~Ark::FeatureIROptimizer; })
82 ).doc(
"Toggle on and off the IR optimizer pass");
84 .doc(
"Dump IR to file.ark.ir");
86 const auto run_flags = (
88 debug_flag, lib_dir_flag, import_solver_pass_flag, macro_proc_pass_flag, optimizer_pass_flag, ir_optimizer_pass_flag, ir_dump
92 option(
"-h",
"--help").set(selected, mode::help).doc(
"Display this message")
93 | option(
"-v",
"--version").set(selected, mode::version).doc(
"Display ArkScript version and exit")
94 | option(
"--dev-info").set(selected, mode::dev_info).doc(
"Display development information and exit")
96 required(
"-e",
"--eval").set(selected, mode::eval).doc(
"Evaluate ArkScript expression\n")
97 & 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 | value(
"file", file).set(selected, mode::run)
108 required(
"-f",
"--format").set(selected, mode::format).doc(
"Format the given source file in place")
109 & value(
"file", file)
111 option(
"--dry-run").set(format_dry_run,
true).doc(
"Do not modify the file, only print out the changes")
112 | 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")
118 , required(
"--ast").set(selected, mode::ast).doc(
"Compile the given program and output its AST as JSON to stdout")
119 & value(
"file", file)
122 required(
"-bcr",
"--bytecode-reader").set(selected, mode::bytecode_reader).doc(
"Launch the bytecode reader")
123 & value(
"file", file).doc(
".arkc bytecode file or .ark source file that will be compiled first")
134 & value(
"page", bcr_page)
137 , option(
"-s",
"--slice").doc(
"Select a slice of instructions in the bytecode")
138 & value(
"start", bcr_start)
139 & value(
"end", bcr_end)
143 , any_other(script_args)
147 auto fmt = doc_formatting {}
151 .split_alternatives(
true)
152 .merge_alternative_flags_with_common_prefix(
true)
153 .paragraph_spacing(1)
154 .ignore_newline_chars(
false);
155 const auto man_page = make_man_page(cli,
"arkscript", fmt)
156 .prepend_section(
"DESCRIPTION",
" ArkScript programming language")
158 .append_section(
"LICENSE",
" Mozilla Public License 2.0");
160 if (parse(argc, argv, cli))
164 std::vector<std::filesystem::path> lib_paths;
168 std::ranges::transform(Utils::splitString(libdir,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
169 return std::filesystem::path(path);
174 if (
const char* arkpath = std::getenv(
"ARKSCRIPT_PATH"))
176 std::ranges::transform(Utils::splitString(arkpath,
';'), std::back_inserter(lib_paths), [](
const std::string& path) {
177 return std::filesystem::path(path);
180 else if (Utils::fileExists(
"./lib"))
181 lib_paths.emplace_back(
"lib");
183 fmt::println(
"{}: Couldn't read ARKSCRIPT_PATH environment variable", fmt::styled(
"Warning", fmt::fg(fmt::color::dark_orange)));
189 std::cout << man_page << std::endl;
199 fmt::println(
"{:^34}|{:^8}|{:^10}",
"Type",
"SizeOf",
"AlignOf");
201#define ARK_PRINT_SIZE(type) fmt::println("{:<34}| {:<7}| {:<9}", #type, sizeof(type), alignof(type))
234 if (!state.
doFile(file, passes))
245 if (!state.
doFile(file, passes))
257 if (!state.
doString(eval_expression))
259 std::cerr <<
"Could not evaluate expression\n";
271 fmt::println(
"{}", compiler.
compile());
275 case mode::bytecode_reader:
284 fmt::println(
"Compiling {}...", file);
295 bcr.
display(segment, std::nullopt, std::nullopt, bcr_page);
297 bcr.
display(segment, bcr_start, bcr_end);
299 bcr.
display(segment, bcr_start, bcr_end, bcr_page);
301 catch (
const std::exception& e)
303 std::cerr << e.what() << std::endl;
312 Formatter formatter(file, format_dry_run || format_check);
315 fmt::println(
"{}", formatter.
output());
#define ARK_PRINT_SIZE(type)
constexpr int ArkErrorExitCode
void display(BytecodeSegment segment=BytecodeSegment::All, std::optional< uint16_t > sStart=std::nullopt, std::optional< uint16_t > sEnd=std::nullopt, std::optional< uint16_t > cPage=std::nullopt) const
Display the bytecode opcode in a human friendly way.
std::variant< Number_t, String_t, internal::PageAddr_t, Procedure, internal::Closure, UserType, List_t, std::shared_ptr< Dict_t >, Ref_t > Value_t