#include #include #include "headers/Yerbacon.hpp" #include #include using namespace std; #include "headers/misc.hpp" #include "headers/arguments.hpp" #include "headers/transpiler/Target.hpp" int main(int argc, char* argv[]) { string target = ".lua"; bool printResult = false, parallel = false, newLines = true; set files; for (signed int i = 1; i < argc; ++i) { const string_view currentArg (argv[i]); if (currentArg == ArgumentShort("printresult")) printResult = true; else if (currentArg == ArgumentAssignable("target")) { const string_view value = ArgumentAssignable::getValueFor(currentArg); if (not value.empty()) (target = '.') += value; else Yerbacon::exit("No target was provided."); } else if (currentArg == Argument("parallel")) parallel = true; else if (currentArg == ArgumentAssignable("newlines")) { const string_view enabled = ArgumentAssignable::getValueFor(currentArg); if (enabled == "off") { newLines = false; } else if (enabled == "on") { newLines = true; } else goto invalid_argument; } else if (currentArg.ends_with(".ybcon")) files.insert(currentArg); else { if (argc == 2) { if (currentArg == Argument("version")) { cout << Yerbacon::getVersion(); } else if (currentArg == Argument("buildInfo")) { cout << Yerbacon::getBuildInfo() ; } else goto invalid_argument; cout << endl; exit(EXIT_SUCCESS); } else invalid_argument: Yerbacon::exit({"\"", currentArg.data(), "\" is not a valid argument."}); } } const auto currentTarget = Target::forName(target, newLines); const auto compile = [&target, ¤tTarget](string_view name) -> string { string transpiledString = currentTarget->transpileWithTree(parseString(getFileContent(name.data()))); name.remove_suffix(6); string outputFile; (outputFile = name).append(target); outputFileContent(outputFile, transpiledString); return transpiledString; }; int8_t exit_code = EXIT_SUCCESS; if (!files.empty()) { vector>>> Units(files.size()); const launch& Policy = not parallel ? launch::deferred : launch::async; transform(files.cbegin(), files.cend(), Units.begin(), [&Policy, &compile](const string_view& fileName){ return async(Policy, [&fileName, &compile]() { pair> resultingPair; try { resultingPair.first = compile(fileName); } catch (const Yerbacon::Exception& error) { unsigned long lastSlash = 0; const unsigned long position1 = fileName.find_last_of('/'); if (cmp_not_equal(position1, string_view::npos)) lastSlash = position1; if constexpr(filesystem::path::preferred_separator != '/') { const unsigned long position2 = fileName.find_last_of(filesystem::path::preferred_separator); if (cmp_not_equal(position2, string_view::npos)) { lastSlash = max(lastSlash, position2); } } resultingPair.first = fileName.substr(lastSlash + 1); resultingPair.second.emplace(error); } return resultingPair; }); }); if (printResult) cout << "~~~~[Yerbacon compilation result]~~~~\n\n"; exit_code = none_of(Units.rbegin(), Units.rend(), [&printResult](future>>& currentFuture) -> bool { const auto&& result = currentFuture.get(); const bool is_exception = result.second.has_value(); if (not is_exception) { if (printResult && !(result.first.empty() || all_of(result.first.begin(), result.first.end(), [](const char& character){ return isspace(character); }))) { cout << result.first << '\n'; } } else { cout << "Compilation of " << result.first << " has failed with the following error:\n" << result.second.value().what() << '\n'; } return is_exception; }) ? EXIT_SUCCESS : EXIT_FAILURE; } else cout << "No valid file provided.\n"; return exit_code; }