From 80995caa32c7a9801a03435a668e4bcbc46e777d Mon Sep 17 00:00:00 2001
From: Mattias Ajander <mattias@ajander.se>
Date: Mon, 31 Mar 2025 19:24:12 +0200
Subject: [PATCH] Improved main file with tokens, ast and debug settings.

---
 include/logging/Logger.h | 13 ++++++
 source/logging/Logger.cc | 13 +++++-
 source/main.cc           | 94 +++++++++++++++++++++++++++++++++++-----
 3 files changed, 107 insertions(+), 13 deletions(-)

diff --git a/include/logging/Logger.h b/include/logging/Logger.h
index 538de3a..2329866 100644
--- a/include/logging/Logger.h
+++ b/include/logging/Logger.h
@@ -55,6 +55,18 @@ public:
      */
     void set_file(const std::string& filePath);
 
+    /**
+     * @brief Gets the current log level
+     * @return LogLevel The current log level
+     */
+    LogLevel get_level() const;
+
+    /**
+     * @brief Sets the log level
+     * @param level The log level to set
+     */
+    void set_level(LogLevel level);
+
     /**
      * @brief Gets the current log file path
      * @return std::string The current log file path
@@ -94,6 +106,7 @@ private:
 
     std::string log_path;   ///< Path to the log file
     std::ofstream log_file; ///< Output stream for the log file
+    LogLevel log_level;     ///< Current log level
 };
 
 /**
diff --git a/source/logging/Logger.cc b/source/logging/Logger.cc
index 9251d90..90f923f 100644
--- a/source/logging/Logger.cc
+++ b/source/logging/Logger.cc
@@ -3,7 +3,7 @@
 namespace funk
 {
 
-Logger::Logger() : log_path("funk.log")
+Logger::Logger() : log_path("funk.log"), log_level(LogLevel::INFO)
 {
     file_open();
 }
@@ -22,6 +22,7 @@ Logger& Logger::instance()
 void Logger::log(LogLevel level, const std::string& message)
 {
     file_open();
+    if (level < log_level) return;
 
     auto now = std::chrono::system_clock::now();
     auto time = std::chrono::system_clock::to_time_t(now);
@@ -60,6 +61,16 @@ std::string Logger::get_file() const
     return log_path;
 }
 
+void Logger::set_level(LogLevel level)
+{
+    log_level = level;
+}
+
+LogLevel Logger::get_level() const
+{
+    return log_level;
+}
+
 void Logger::file_open()
 {
     if (log_file.is_open()) return;
diff --git a/source/main.cc b/source/main.cc
index 4eb5d77..8350180 100644
--- a/source/main.cc
+++ b/source/main.cc
@@ -5,20 +5,31 @@
 
 using namespace funk;
 
+// Command line options
 HashMap<String, String> options{
     {"--help", "Display this help message"},
     {"--log <file>", "Set the log file"},
+    {"--debug", "Enable debug logging"},
+    {"--ast", "Log the AST representation"},
+    {"--tokens", "Log the lexical tokens"},
 };
 
-int main(int argc, char* argv[])
+// Configuration for command line options
+struct Config
 {
-    ArgParser parser(argc, argv);
+    bool debug{false};
+    bool ast{false};
+    bool tokens{false};
+};
 
+// Process command line arguments and set up logging
+bool setup(ArgParser& parser, Config& config)
+{
     // Print help message
-    if (argc == 1 || parser.has_option("--help"))
+    if (parser.has_option("--help"))
     {
         cout << ArgParser::help("funk [options] <file>", options) << "\n";
-        return 0;
+        return false;
     }
 
     // Set log file if specified
@@ -27,27 +38,86 @@ int main(int argc, char* argv[])
         if (!parser.has_value("--log"))
         {
             cerr << "No log file specified!\n";
-            return 1;
+            return false;
         }
-
         logger().set_file(parser.get_option("--log"));
     }
 
+    // Configure logging level
+    if (parser.has_option("--debug"))
+    {
+        config.debug = true;
+        logger().set_level(LogLevel::DEBUG);
+    }
+
     // Check if any files were specified
     if (!parser.has_files())
     {
         cerr << "No files specified!\n";
-        return 1;
+        return false;
     }
 
-    // Lex each file
-    for (const auto& file : parser.get_files())
+    // Set other configuration options
+    config.ast = parser.has_option("--ast");
+    config.tokens = parser.has_option("--tokens");
+
+    return true;
+}
+
+// Process a single file
+void process_file(const String& file, const Config& config)
+{
+    LOG_INFO("Processing file: " + file);
+
+    try
     {
-        Parser parser{Parser::load(file)};
-        Node* result{parser.parse()};
+        LOG_DEBUG("Lexing file...");
+        Lexer lexer{read_file(file), file};
+        Vector<Token> tokens{lexer.tokenize()};
+        LOG_DEBUG("Tokens lexed!");
+
+        if (config.tokens)
+        {
+            LOG_INFO("Tokens:");
+            for (const auto& token : tokens) { LOG_INFO(token); }
+        }
 
-        cout << result->to_s() << " = " << result->evaluate()->to_s() << '\n';
+        LOG_DEBUG("Parsing file...");
+        Parser parser{tokens, file};
+        Node* ast = parser.parse();
+        LOG_DEBUG("File parsed!");
+
+        if (config.ast) { LOG_INFO("AST: " + ast->to_s()); }
+
+        LOG_DEBUG("Evaluating AST...");
+        Node* res{ast->evaluate()};
+        LOG_DEBUG("AST evaluated!");
+        LOG_INFO("Result: " + res->to_s());
+    }
+    catch (const FunkError& e)
+    {
+        LOG_ERROR("Error processing file " + file + ": " + e.what());
+        cerr << "Error: " << e.trace() << '\n';
+    }
+}
+
+int main(int argc, char* argv[])
+{
+    ArgParser parser(argc, argv);
+    Config config;
+
+    // Show help if no arguments provided
+    if (argc == 1)
+    {
+        cout << ArgParser::help("funk [options] <file>", options) << "\n";
+        return 0;
     }
 
+    // Setup and validate arguments
+    if (!setup(parser, config)) { return 1; }
+
+    // Process each file
+    for (const auto& file : parser.get_files()) { process_file(file, config); }
+
     return 0;
 }
-- 
GitLab