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