ArkScript
A small, fast, functional and scripting language for video games
Value.hpp
Go to the documentation of this file.
1/**
2 * @file Value.hpp
3 * @author Alexandre Plateau ([email protected])
4 * @brief Default value type handled by the virtual machine
5 * @date 2024-04-20
6 *
7 * @copyright Copyright (c) 2020-2025
8 *
9 */
10
11#ifndef ARK_VM_VALUE_HPP
12#define ARK_VM_VALUE_HPP
13
14#include <vector>
15#include <variant>
16#include <string>
17#include <cinttypes>
18#include <array>
19
22#include <Ark/Platform.hpp>
23
24namespace Ark
25{
26 class VM;
27 class BytecodeReader;
28
29 // Order is important because we are doing some optimizations to check ranges
30 // of types based on their integer values.
31 enum class ValueType
32 {
33 List = 0,
34 Number = 1,
35 String = 2,
36 PageAddr = 3,
37 CProc = 4,
38 Closure = 5,
39 User = 6,
40
41 Nil = 7,
42 True = 8,
43 False = 9,
44 Undefined = 10,
45 Reference = 11,
46 InstPtr = 12,
47
48 Any = 99 ///< Used only for typechecking
49 };
50
51 constexpr std::array types_to_str = {
52 "List", "Number", "String", "Function",
53 "CProc", "Closure", "UserType", "Nil",
54 "Bool", "Bool", "Undefined", "Reference",
55 "InstPtr"
56 };
57
59 {
60 public:
61 using ProcType = Value (*)(std::vector<Value>&, VM*);
62 using Iterator = std::vector<Value>::iterator;
63
64 using Value_t = std::variant<
65 double, // 8 bytes
66 std::string, // 32 bytes
67 internal::PageAddr_t, // 2 bytes
68 ProcType, // 8 bytes
69 internal::Closure, // 24 bytes
70 UserType, // 24 bytes
71 std::vector<Value>, // 24 bytes
72 Value* // 8 bytes
73 >; // +8 bytes overhead
74 // total 40 bytes
75
76 /**
77 * @brief Construct a new Value object
78 *
79 */
80 Value() noexcept;
81
82 /**
83 * @brief Construct a new Value object
84 *
85 * @param type the value type which is going to be held
86 */
87 explicit Value(ValueType type) noexcept;
88
89 /**
90 * @brief Construct a new Value object
91 * @details Use at your own risks. Asking for a value type N and putting a non-matching value
92 * will result in errors at runtime.
93 *
94 * @tparam T
95 * @param type value type wanted
96 * @param value value needed
97 */
98 template <typename T>
99 Value(const ValueType type, T&& value) noexcept :
100 m_type(type), m_value(value)
101 {}
102
103 explicit Value(int value) noexcept;
104 explicit Value(double value) noexcept;
105 explicit Value(const std::string& value) noexcept;
106 explicit Value(internal::PageAddr_t value) noexcept;
107 explicit Value(ProcType value) noexcept;
108 explicit Value(std::vector<Value>&& value) noexcept;
109 explicit Value(internal::Closure&& value) noexcept;
110 explicit Value(UserType&& value) noexcept;
111 explicit Value(Value* ref) noexcept;
112
113 [[nodiscard]] ValueType valueType() const noexcept { return m_type; }
114 [[nodiscard]] bool isFunction() const noexcept
115 {
116 return m_type == ValueType::PageAddr || m_type == ValueType::Closure || m_type == ValueType::CProc ||
117 (m_type == ValueType::Reference && reference()->isFunction());
118 }
119 [[nodiscard]] bool isIndexable() const noexcept
120 {
121 return m_type == ValueType::List || m_type == ValueType::String;
122 }
123
124 [[nodiscard]] double number() const { return std::get<double>(m_value); }
125 [[nodiscard]] const std::string& string() const { return std::get<std::string>(m_value); }
126 [[nodiscard]] const std::vector<Value>& constList() const { return std::get<std::vector<Value>>(m_value); }
127 [[nodiscard]] const UserType& usertype() const { return std::get<UserType>(m_value); }
128 [[nodiscard]] std::vector<Value>& list() { return std::get<std::vector<Value>>(m_value); }
129 [[nodiscard]] std::string& stringRef() { return std::get<std::string>(m_value); }
130 [[nodiscard]] UserType& usertypeRef() { return std::get<UserType>(m_value); }
131 [[nodiscard]] Value* reference() const { return std::get<Value*>(m_value); }
132
133 /**
134 * @brief Add an element to the list held by the value (if the value type is set to list)
135 *
136 * @param value
137 */
138 void push_back(const Value& value);
139
140 /**
141 * @brief Add an element to the list held by the value (if the value type is set to list)
142 *
143 * @param value
144 */
145 void push_back(Value&& value);
146
147 std::string toString(VM& vm) const noexcept;
148
149 friend ARK_API_INLINE bool operator==(const Value& A, const Value& B) noexcept;
150 friend ARK_API_INLINE bool operator<(const Value& A, const Value& B) noexcept;
151 friend ARK_API_INLINE bool operator!(const Value& A) noexcept;
152
153 friend class Ark::VM;
155
156 private:
159
160 [[nodiscard]] constexpr uint8_t typeNum() const noexcept { return static_cast<uint8_t>(m_type); }
161
162 [[nodiscard]] internal::PageAddr_t pageAddr() const { return std::get<internal::PageAddr_t>(m_value); }
163 [[nodiscard]] const ProcType& proc() const { return std::get<ProcType>(m_value); }
164 [[nodiscard]] const internal::Closure& closure() const { return std::get<internal::Closure>(m_value); }
165 [[nodiscard]] internal::Closure& refClosure() { return std::get<internal::Closure>(m_value); }
166 };
167
168 inline bool operator==(const Value& A, const Value& B) noexcept
169 {
170 // values should have the same type
171 if (A.m_type != B.m_type)
172 return false;
173 // all the types >= Nil are Nil itself, True, False, Undefined
174 if (A.typeNum() >= static_cast<uint8_t>(ValueType::Nil))
175 return true;
176
177 return A.m_value == B.m_value;
178 }
179
180 inline bool operator<(const Value& A, const Value& B) noexcept
181 {
182 if (A.m_type != B.m_type)
183 return (A.typeNum() - B.typeNum()) < 0;
184 return A.m_value < B.m_value;
185 }
186
187 inline bool operator!=(const Value& A, const Value& B) noexcept
188 {
189 return !(A == B);
190 }
191
192 inline bool operator!(const Value& A) noexcept
193 {
194 switch (A.valueType())
195 {
196 case ValueType::List:
197 return A.constList().empty();
198
200 return A.number() == 0.0;
201
203 return A.string().empty();
204
205 case ValueType::User:
206 [[fallthrough]];
207 case ValueType::Nil:
208 [[fallthrough]];
209 case ValueType::False:
210 return true;
211
212 case ValueType::True:
213 return false;
214
215 default:
216 return false;
217 }
218 }
219}
220
221#endif
Subtype of the value type, handling closures.
#define ARK_API
Definition Module.hpp:28
ArkScript configuration macros.
#define ARK_API_INLINE
Definition Platform.hpp:50
Subtype of the value, capable of handling any C++ type.
This class is just a helper to.
A class to be use C++ objects in ArkScript.
Definition UserType.hpp:47
The ArkScript virtual machine, executing ArkScript bytecode.
Definition VM.hpp:45
const std::vector< Value > & constList() const
Definition Value.hpp:126
std::vector< Value > & list()
Definition Value.hpp:128
internal::Closure & refClosure()
Definition Value.hpp:165
const ProcType & proc() const
Definition Value.hpp:163
Value * reference() const
Definition Value.hpp:131
const internal::Closure & closure() const
Definition Value.hpp:164
double number() const
Definition Value.hpp:124
bool isFunction() const noexcept
Definition Value.hpp:114
Value(*)(std::vector< Value > &, VM *) ProcType
Definition Value.hpp:61
std::vector< Value >::iterator Iterator
Definition Value.hpp:62
ValueType valueType() const noexcept
Definition Value.hpp:113
const std::string & string() const
Definition Value.hpp:125
constexpr uint8_t typeNum() const noexcept
Definition Value.hpp:160
std::variant< double, std::string, internal::PageAddr_t, ProcType, internal::Closure, UserType, std::vector< Value >, Value * > Value_t
Definition Value.hpp:64
const UserType & usertype() const
Definition Value.hpp:127
ValueType m_type
Definition Value.hpp:157
bool isIndexable() const noexcept
Definition Value.hpp:119
Value_t m_value
Definition Value.hpp:158
internal::PageAddr_t pageAddr() const
Definition Value.hpp:162
UserType & usertypeRef()
Definition Value.hpp:130
std::string & stringRef()
Definition Value.hpp:129
Closure management.
Definition Closure.hpp:36
bool operator<(const Namespace &, const Namespace &)
Definition Namespace.hpp:27
bool operator==(const Namespace &A, const Namespace &B)
Definition Namespace.hpp:21
uint16_t PageAddr_t
Definition Closure.hpp:27
constexpr std::array types_to_str
Definition Value.hpp:51
const auto False
ArkScript False value.
Definition VM.hpp:386
bool operator!(const Value &A) noexcept
Definition Value.hpp:192
const auto Nil
ArkScript Nil value.
Definition VM.hpp:384
ValueType
Definition Value.hpp:32
@ Any
Used only for typechecking.
const auto True
ArkScript True value.
Definition VM.hpp:388
bool operator!=(const Value &A, const Value &B) noexcept
Definition Value.hpp:187