From cb3065c34756a70cb6006fc25777ce3e720ff1a8 Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Sun, 13 Apr 2025 18:16:19 +0000
Subject: [PATCH] implement variable contexts, add function body store and parsing

---
 src/ScriptInterpreter.hpp |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/src/ScriptInterpreter.hpp b/src/ScriptInterpreter.hpp
index 5ecc7c3..803ef66 100644
--- a/src/ScriptInterpreter.hpp
+++ b/src/ScriptInterpreter.hpp
@@ -1,7 +1,6 @@
 #ifndef SSCRIPTINTERPRETER_HPP
 #define SSCRIPTINTERPRETER_HPP
 #include <functional>
-#include <map>
 #include <memory>
 #include <string>
 #include <unordered_map>
@@ -18,7 +17,8 @@
 class ScriptInterpreter {
   public:
     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);
+    void executeScript(const std::string & source, const std::string & filename,
+                       const std::string & _namespace = "_default_", bool ignore_tags = false);
 
   private:
     std::unordered_map<std::string, FunctionValidator>             functionValidators;
@@ -29,13 +29,19 @@
     std::unordered_map<std::string, std::vector<Value>>            functionParameters;
     std::unordered_map<std::string, std::string>                   functionBodies;
     std::string                                                    filename;
+    std::string                                                    source;
+    std::string                                                    contextPrefix;
 
     [[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 setVariable(const std::string & name, const Value & value, const std::string & context = "default") {
+    void setVariable(const std::string & name, const Value & value, const std::string & context = "default",
+                     bool exception_if_exists = false) {
+        if (exception_if_exists && variables[context].find(name) != variables[context].end()) {
+            THROW_VARIABLE_REDEFINITION_ERROR(name, value.token);
+        }
         this->variables[context][name] = value;
     }
 
@@ -51,7 +57,8 @@
         throw std::runtime_error("Variable not found: " + name);
     };
 
-    [[nodiscard]] Value getVariable(const Token & token, const std::string & context = "default") const {
+    [[nodiscard]] Value getVariable(const Token & token, const std::string & context = "default",
+                                    const std::string & file = __FILE__, const int & line = __LINE__) const {
         for (auto it = variables.begin(); it != variables.end(); ++it) {
             if (it->first == context) {
                 const auto & innerMap = it->second.find(token.lexeme);
@@ -60,9 +67,47 @@
                 }
             }
         }
-        THROW_UNDEFINED_VARIABLE_ERROR(token.lexeme, token);
+        THROW_UNDEFINED_VARIABLE_ERROR_HELPER(token.lexeme, token, file, line);
     };
 
+    /**
+         * Checks if a variable exists within the specified context.
+         *
+         * @param name The name of the variable to check.
+         * @param context The context in which to search for the variable (defaults to "default").
+         * @param file The source file where the check is performed (for error reporting).
+         * @param line The line number where the check is performed (for error reporting).
+         * @return True if the variable exists in the specified context.
+         * @throws Throws an undefined variable error if the variable is not found.
+         */
+    [[nodiscard]] bool variableExists(const std::string & name, const std::string & context = "default",
+                                      const std::string & file = __FILE__, const int & line = __LINE__) 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 true;
+                }
+            }
+        }
+        THROW_UNDEFINED_VARIABLE_ERROR_HELPER(name, Token(TokenType::Variable, name, name, 0, 0), file, line);
+    }
+
+    /**
+     * Checks if a variable exists within the specified context using a Token.
+     *
+     * @param token The token representing the variable to check.
+     * @param context The context in which to search for the variable (defaults to "default").
+     * @param file The source file where the check is performed (for error reporting).
+     * @param line The line number where the check is performed (for error reporting).
+     * @return True if the variable exists in the specified context.
+     * @throws Throws an undefined variable error if the variable is not found.
+     */
+    [[nodiscard]] bool variableExists(const Token & token, const std::string & context = "default",
+                                      const std::string & file = __FILE__, const int & line = __LINE__) const {
+        return this->variableExists(token.lexeme, context, file, line);
+    }
+
     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);

--
Gitblit v1.9.3