#ifndef SSCRIPTINTERPRETER_HPP #define SSCRIPTINTERPRETER_HPP #include #include #include #include #include #include "BaseFunction.hpp" #include "Token.hpp" #include "Value.hpp" using FunctionValidator = std::function &, size_t &, const std::unordered_map &)>; using VariableContext = std::unordered_map; class ScriptInterpreter { public: void registerModule(const std::string & name, std::shared_ptr fn); void executeScript(const std::string & source, const std::string & filename, const std::string & _namespace = "_default_", bool ignore_tags = false); private: std::unordered_map functionValidators; std::unordered_map> functionObjects; // store the current script's variables std::unordered_map variables; // store the current script's function arguments std::unordered_map> functionParameters; std::unordered_map functionBodies; std::string filename; std::string source; std::string contextPrefix; [[nodiscard]] std::vector parseFunctionArguments(const std::vector & 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", 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; } [[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 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); if (innerMap != it->second.end()) { return it->second.at(token.lexeme); } } } 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 & tokens, std::size_t & i); void handleVariableReference(const std::vector & tokens, std::size_t & i); static void handleComment(std::size_t & i){ i++;} static void handleSemicolon(std::size_t & i) {i++;}; void handleStringDeclaration(const std::vector & tokens, std::size_t & i); void handleBooleanDeclaration(const std::vector & tokens, std::size_t & i); void handleNumberDeclaration(const std::vector & tokens, std::size_t & i, TokenType type); void handleFunctionDeclaration(const std::vector & tokens, std::size_t & i); }; #endif // SSCRIPTINTERPRETER_HPP