A simple scripting language in C++
Ferenc Szontágh
2025-04-19 558e0191ba5a5b0ab99825de7d7d2219387e559e
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
66
67
68
69
70
71
72
73
74
75
76
#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;
    bool                            isConst_;
 
 
  public:
    // isConst: if true, declares a constant; otherwise a mutable variable
    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, bool isConst = false) :
        StatementNode(file_name, file_line, line_column),
        variableName_(std::move(name)),
        variableType_(type),
        expression_(std::move(expr)),
        ns(ns),
        isConst_(isConst) {}
 
    void interpret(Interpreter & interpreter) const override {
        try {
            Symbols::Value value = expression_->evaluate(interpreter);
            if (Symbols::SymbolContainer::instance()->exists(variableName_)) {
                throw Exception("Variable already declared: " + variableName_, filename_, line_, column_);
            }
            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 a constant or variable symbol
            std::shared_ptr<Symbols::Symbol> variable;
            if (isConst_) {
                variable = Symbols::SymbolFactory::createConstant(variableName_, value, ns);
            } else {
                variable = Symbols::SymbolFactory::createVariable(variableName_, value, ns, variableType_);
            }
            Symbols::SymbolContainer::instance()->add(variable);
        } catch (const Exception &) {
            throw;
        } catch (const std::exception &e) {
            throw Exception(e.what(), filename_, line_, column_);
        }
    }
 
    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