A simple scripting language in C++
Ferenc Szontágh
2025-04-18 9a186053a690f2216b43355549c8aa7e2959583c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#ifndef INTERPRETER_DEFINE_VARIABLE_STATEMENT_NODE_HPP
#define INTERPRETER_DEFINE_VARIABLE_STATEMENT_NODE_HPP
 
#include <memory>
#include <string>
#include <utility>
 
#include "ExpressionNode.hpp"
#include "Interpreter.hpp"
#include "Interpreter/StatementNode.hpp"
// Include for unified runtime Exception
#include "Interpreter/Interpreter.hpp"
#include "Symbols/SymbolContainer.hpp"
#include "Symbols/SymbolFactory.hpp"
 
namespace Interpreter {
 
class DeclareVariableStatementNode : public StatementNode {
    std::string                     variableName_;
    Symbols::Variables::Type        variableType_;
    std::unique_ptr<ExpressionNode> expression_;
    std::string                     ns;
 
 
  public:
    DeclareVariableStatementNode(std::string name, const std::string & ns, Symbols::Variables::Type type,
                                 std::unique_ptr<ExpressionNode> expr, const std::string & file_name, int file_line,
                                 size_t line_column) :
        StatementNode(file_name, file_line, line_column),
        variableName_(std::move(name)),
        variableType_(type),
        expression_(std::move(expr)),
        ns(ns) {}
 
    void interpret(Interpreter & interpreter) const override {
        // Evaluate the expression and enforce declared type matches actual value type
        Symbols::Value value = expression_->evaluate(interpreter);
        // Check for duplicate declaration
        if (Symbols::SymbolContainer::instance()->exists(variableName_)) {
            throw Exception("Variable already declared: " + variableName_, filename_, line_, column_);
        }
        // Enforce type correctness: the evaluated value must match the declared type
        if (value.getType() != variableType_) {
            using namespace Symbols::Variables;
            std::string expected = TypeToString(variableType_);
            std::string actual   = TypeToString(value.getType());
            throw Exception(
                "Type mismatch for variable '" + variableName_ +
                "': expected '" + expected + "' but got '" + actual + "'",
                filename_, line_, column_);
        }
        // Create and add the variable symbol
        const auto variable = Symbols::SymbolFactory::createVariable(variableName_, value, ns, variableType_);
        Symbols::SymbolContainer::instance()->add(variable);
    }
 
    std::string toString() const override {
        return std::string("variable name: " + variableName_ +
                           " type: " + Symbols::Variables::TypeToString(variableType_));
    }
};
 
}  // namespace Interpreter
 
#endif  // INTERPRETER_DEFINE_VARIABLE_STATEMENT_NODE_HPP