A simple scripting language in C++
Ferenc Szontágh
2025-04-15 3895272a7f238c9aef0b584bd3b10b900445245d
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
77
#ifndef SYMBOL_VALUE_HPP
#define SYMBOL_VALUE_HPP
 
#include <iostream>
#include <stdexcept>
#include <string>
#include <variant>
 
namespace Symbols {
 
class Value {
  public:
    using Variant = std::variant<int, double, float, std::string, bool>;
 
    Value() = default;
 
    Value(int v) : value_(v) {}
 
    Value(double v) : value_(v) {}
 
    Value(float v) : value_(v) {}
 
    Value(const std::string & v) : value_(v) {}
 
    Value(const char * v) : value_(std::string(v)) {}
 
    Value(bool v) : value_(v) {}
 
    const Variant & get() const { return value_; }
 
    Variant & get() { return value_; }
 
    template <typename T> T get() const { return std::get<T>(value_); }
 
    // operator+
    friend Value operator+(const Value & lhs, const Value & rhs) {
        return std::visit(
            [](auto && a, auto && b) -> Value {
                using A = std::decay_t<decltype(a)>;
                using B = std::decay_t<decltype(b)>;
                if constexpr ((std::is_arithmetic_v<A> && std::is_arithmetic_v<B>) ) {
                    return Value{ a + b };
                } else {
                    throw std::runtime_error("Invalid types for operator+");
                }
            },
            lhs.value_, rhs.value_);
    }
 
    // operator==
    friend bool operator==(const Value & lhs, const Value & rhs) { return lhs.value_ == rhs.value_; }
 
    // to_string helper (needed for string + int, etc.)
    static std::string to_string(const Variant & v) {
        return std::visit(
            [](auto && val) -> std::string {
                using T = std::decay_t<decltype(val)>;
                if constexpr (std::is_same_v<T, bool>) {
                    return val ? "true" : "false";
                } else if constexpr (std::is_same_v<T, std::string>) {
                    return val;
                } else {
                    return std::to_string(val);
                }
            },
            v);
    }
 
    static std::string to_string(const Value & val) { return to_string(val.value_); }
 
  private:
    Variant value_;
};
 
}  // namespace Symbols
 
#endif  // SYMBOL_VALUE_HPP