diff --git a/src/main.cc b/src/main.cc index 4664dd5cd..ed864a8bf 100644 --- a/src/main.cc +++ b/src/main.cc @@ -6,6 +6,7 @@ #include #include "zen/config.hpp" +#include "zen/po.hpp" #include "bolt/CST.hpp" #include "bolt/DiagnosticEngine.hpp" @@ -22,7 +23,7 @@ ByteString readFile(std::string Path) { std::ifstream File(Path); ByteString Out; - File.seekg(0, std::ios::end); + File.seekg(0, std::ios::end); Out.reserve(File.tellg()); File.seekg(0, std::ios::beg); @@ -32,35 +33,62 @@ ByteString readFile(std::string Path) { return Out; } -int main(int argc, const char* argv[]) { +namespace po = zen::po; - if (argc < 2) { - fprintf(stderr, "Not enough arguments provided.\n"); - return 1; - } +int main(int Argc, const char* Argv[]) { + + auto Match = po::program("bolt", "The offical compiler for the Bolt programming language") + .flag(po::flag("direct-diagnostics", "Immediately print diagnostics without sorting them first")) // TODO support default values in zen::po + .subcommand( + po::command("check", "Check sources for programming mistakes") + .pos_arg("file", po::some)) + .subcommand( + po::command("eval", "Run sources") + .pos_arg("file", po::some) + .fallback()) + .parse_args(Argc, Argv) + .unwrap(); + + ZEN_ASSERT(Match.has_subcommand()); + + auto DirectDiagnostics = Match.has_flag("direct-diagnostics") && Match.get_flag("direct-diagnostics"); + + std::cerr << DirectDiagnostics << std::endl; + + auto [Name, Submatch] = Match.subcommand(); ConsoleDiagnostics DE; LanguageConfig Config; - auto Text = readFile(argv[1]); - TextFile File { argv[1], Text }; - VectorStream Chars(Text, EOF); - Scanner S(File, Chars); - Punctuator PT(S); - Parser P(File, PT, DE); + std::vector SourceFiles; - auto SF = P.parseSourceFile(); - if (SF == nullptr) { - return 1; + for (auto Filename: Submatch->get_pos_args()) { + + auto Text = readFile(Filename); + TextFile File { Filename, Text }; + VectorStream Chars(Text, EOF); + Scanner S(File, Chars); + Punctuator PT(S); + Parser P(File, PT, DE); + + auto SF = P.parseSourceFile(); + if (SF == nullptr) { + continue; + } + + SF->setParents(); + + SourceFiles.push_back(SF); } - SF->setParents(); - DiagnosticStore DS; - Checker TheChecker { Config, DE }; // TODO set this to DS in production - TheChecker.check(SF); + Checker TheChecker { Config, DirectDiagnostics ? static_cast(DE) : static_cast(DS) }; - auto LT = [](const Diagnostic* L, const Diagnostic* R) { + for (auto SF: SourceFiles) { + TheChecker.check(SF); + } + + auto lessThan = [](const Diagnostic* L, const Diagnostic* R) { auto N1 = L->getNode(); auto N2 = R->getNode(); if (N1 == nullptr && N2 == nullptr) { @@ -74,7 +102,7 @@ int main(int argc, const char* argv[]) { } return N1->getStartLine() < N2->getStartLine() || N1->getStartColumn() < N2->getStartColumn(); }; - std::sort(DS.Diagnostics.begin(), DS.Diagnostics.end(), LT); + std::sort(DS.Diagnostics.begin(), DS.Diagnostics.end(), lessThan); for (auto D: DS.Diagnostics) { DE.printDiagnostic(*D); @@ -84,14 +112,19 @@ int main(int argc, const char* argv[]) { return 1; } - Evaluator E; - Env TheEnv; - TheEnv.add("print", Value::binding([](auto Args) { - ZEN_ASSERT(Args.size() == 1) - std::cerr << Args[0].asString() << "\n"; - return Value::unit(); - })); - E.evaluate(SF, TheEnv); + if (Name == "eval") { + Evaluator E; + Env GlobalEnv; + GlobalEnv.add("print", Value::binding([](auto Args) { + ZEN_ASSERT(Args.size() == 1) + std::cerr << Args[0].asString() << "\n"; + return Value::unit(); + })); + for (auto SF: SourceFiles) { + // TODO add a SourceFile-local env that inherits from GlobalEnv + E.evaluate(SF, GlobalEnv); + } + } return 0; }