From 86904d513734134beffc29c6f4012d53a99f25c5 Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Sun, 13 Apr 2025 15:38:34 +0000
Subject: [PATCH] some clean up, added function declaration

---
 src/ScriptInterpreter.hpp |  115 +++++++++++++++++++++++----------------------------------
 1 files changed, 46 insertions(+), 69 deletions(-)

diff --git a/src/ScriptInterpreter.hpp b/src/ScriptInterpreter.hpp
index 2791e02..5ecc7c3 100644
--- a/src/ScriptInterpreter.hpp
+++ b/src/ScriptInterpreter.hpp
@@ -1,6 +1,7 @@
 #ifndef SSCRIPTINTERPRETER_HPP
 #define SSCRIPTINTERPRETER_HPP
 #include <functional>
+#include <map>
 #include <memory>
 #include <string>
 #include <unordered_map>
@@ -10,90 +11,66 @@
 #include "Token.hpp"
 #include "Value.hpp"
 
-using FunctionValidator = std::function<void(const std::vector<Token> &, size_t &)>;
+using FunctionValidator =
+    std::function<void(const std::vector<Token> &, size_t &, const std::unordered_map<std::string, Value> &)>;
+using VariableContext = std::unordered_map<std::string, Value>;
 
 class ScriptInterpreter {
   public:
-    void registerFunction(const std::string & name, std::shared_ptr<BaseFunction> fn);
-    void executeScript(const std::string & source, const std::string & filenaneame, bool debug = false);
-
-    static void throwUnexpectedTokenError(const Token & token, const std::string & expected = "",
-                                          const std::string & file = "", const int & line = 0) {
-        const std::string error_content =
-            "unexpected token: '" + token.lexeme + "' type: " + tokenTypeNames.at(token.type) +
-            (expected.empty() ? "" : ", expected: '" + expected + "'") + " in file: " + token.file + ":" +
-            std::to_string(token.lineNumber) + ":" + std::to_string(token.columnNumber);
-#ifdef DEBUG_BUILD
-        const std::string error_message = file + ":" + std::to_string(line) + "\n" + error_content;
-#else
-        const std::string& error_message = error_content;
-#endif
-        throw std::runtime_error(error_message);
-    };
-
-    static void throwUndefinedVariableError(const std::string & name, const Token & token, const std::string & file,
-                                            const int & line = 0) {
-        const std::string error_content = "undefined variable: '$" + name + "' in file: " + token.file + ":" +
-                                          std::to_string(token.lineNumber) + ":" + std::to_string(token.columnNumber);
-#ifdef DEBUG_BUILD
-        const std::string error_message = file + ":" + std::to_string(line) + "\n" + error_content;
-#else
-        const std::string& error_message = error_content;
-#endif
-        throw std::runtime_error(error_message);
-    }
-
-    static void throwVariableTypeMissmatchError(const std::string & target_variable_name,
-                                                const std::string & target_type,
-                                                const std::string & source_variable_name,
-                                                const std::string & source_type, const Token & token,
-                                                const std::string & file = "", const int & line = 0) {
-        std::string error_content =
-            "variable type missmatch: '$" + target_variable_name + "' declared type: '" + target_type + "'";
-        if (!source_variable_name.empty()) {
-            error_content += " source variable: '" + source_variable_name + "'";
-        }
-        if (!source_type.empty()) {
-            error_content += " assigned type: '" + source_type + "'";
-        }
-
-        error_content += " in file: " + token.file + ":" + std::to_string(token.lineNumber) + ":" +
-                         std::to_string(token.columnNumber);
-#ifdef DEBUG_BUILD
-        const std::string error_message = file + ":" + std::to_string(line) + "\n" + error_content;
-#else
-        const std::string error_message = error_content;
-#endif
-        throw std::runtime_error(error_message);
-    }
-
-    static void throwVariableRedefinitionError(const std::string & name, const Token & token,
-                                               const std::string & file = "", const int line = 0) {
-        const std::string error_content = "variable alread defined: " + name + " in file: " + token.file + ":" +
-                                          std::to_string(token.lineNumber) + ":" + std::to_string(token.columnNumber);
-#ifdef DEBUG_BUILD
-        const std::string error_message = file + ":" + std::to_string(line) + "\n" + error_content;
-#else
-        const std::string& error_message = error_content;
-#endif
-        throw std::runtime_error(error_message);
-    }
+    void registerModule(const std::string & name, std::shared_ptr<BaseFunction> fn);
+    void executeScript(const std::string & source, const std::string & filenaneame, bool ignore_tags = false);
 
   private:
     std::unordered_map<std::string, FunctionValidator>             functionValidators;
     std::unordered_map<std::string, std::shared_ptr<BaseFunction>> functionObjects;
-    std::unordered_map<std::string, Value>                         variables;
+    // store the current script's variables
+    std::unordered_map<std::string, VariableContext>               variables;
+    // store the current script's function arguments
+    std::unordered_map<std::string, std::vector<Value>>            functionParameters;
+    std::unordered_map<std::string, std::string>                   functionBodies;
+    std::string                                                    filename;
 
-    std::vector<Value> parseArguments(const std::vector<Token> & tokens, std::size_t & current_index) const;
-    Value              evaluateExpression(const Token & token) const;
+    [[nodiscard]] std::vector<Value> parseFunctionArguments(const std::vector<Token> & tokens,
+                                                            std::size_t &              index) const;
+    [[nodiscard]] Value              evaluateExpression(const Token & token) const;
+
     // type handlers
-    void expectSemicolon(const std::vector<Token> & tokens, std::size_t & i, const std::string & message) const;
+    void setVariable(const std::string & name, const Value & value, const std::string & context = "default") {
+        this->variables[context][name] = value;
+    }
+
+    [[nodiscard]] Value getVariable(const std::string & name, const std::string & context = "default") const {
+        for (auto it = variables.begin(); it != variables.end(); ++it) {
+            if (it->first == context) {
+                const auto & innerMap = it->second.find(name);
+                if (innerMap != it->second.end()) {
+                    return it->second.at(name);
+                }
+            }
+        }
+        throw std::runtime_error("Variable not found: " + name);
+    };
+
+    [[nodiscard]] Value getVariable(const Token & token, const std::string & context = "default") const {
+        for (auto it = variables.begin(); it != variables.end(); ++it) {
+            if (it->first == context) {
+                const auto & innerMap = it->second.find(token.lexeme);
+                if (innerMap != it->second.end()) {
+                    return it->second.at(token.lexeme);
+                }
+            }
+        }
+        THROW_UNDEFINED_VARIABLE_ERROR(token.lexeme, token);
+    };
+
     void handleFunctionCall(const std::vector<Token> & tokens, std::size_t & i);
     void handleVariableReference(const std::vector<Token> & tokens, std::size_t & i);
     void handleComment(std::size_t & i);
     void handleSemicolon(std::size_t & i);
     void handleStringDeclaration(const std::vector<Token> & tokens, std::size_t & i);
+    void handleBooleanDeclaration(const std::vector<Token> & tokens, std::size_t & i);
     void handleNumberDeclaration(const std::vector<Token> & tokens, std::size_t & i, TokenType type);
+    void handleFunctionDeclaration(const std::vector<Token> & tokens, std::size_t & i);
 };
 
 #endif  // SSCRIPTINTERPRETER_HPP

--
Gitblit v1.9.3