ArkScript
A small, lisp-inspired, functional scripting language
Value.cpp
Go to the documentation of this file.
4
5#include <fmt/format.h>
6#include <fmt/ostream.h>
7
8namespace Ark
9{
10 Value::Value() noexcept :
11 m_type(ValueType::Undefined)
12 {}
13
14 Value::Value(ValueType type) noexcept :
15 m_type(type)
16 {
17 if (type == ValueType::List)
18 m_value = List_t();
19 else if (type == ValueType::String)
20 m_value = std::string();
21 }
22
23 Value::Value(const int value) noexcept :
24 m_type(ValueType::Number), m_value(static_cast<double>(value))
25 {}
26
27 Value::Value(const double value) noexcept :
28 m_type(ValueType::Number), m_value(value)
29 {}
30
31 Value::Value(const String_t& value) noexcept :
32 m_type(ValueType::String), m_value(value)
33 {}
34
35 Value::Value(const char* value) noexcept :
36 m_type(ValueType::String), m_value(std::string(value))
37 {}
38
40 m_type(ValueType::PageAddr), m_value(value)
41 {}
42
43 Value::Value(Procedure&& value) noexcept :
44 m_type(ValueType::CProc), m_value(std::move(value))
45 {}
46
47 Value::Value(List_t&& value) noexcept :
48 m_type(ValueType::List), m_value(std::move(value))
49 {}
50
51 Value::Value(internal::Closure&& value) noexcept :
52 m_type(ValueType::Closure), m_value(std::move(value))
53 {}
54
55 Value::Value(UserType&& value) noexcept :
56 m_type(ValueType::User), m_value(value)
57 {}
58
59 Value::Value(Dict_t&& value) noexcept :
60 m_type(ValueType::Dict), m_value(std::make_shared<Dict_t>(std::move(value)))
61 {}
62
63 Value::Value(Ref_t ref) noexcept :
64 m_type(ValueType::Reference), m_value(ref)
65 {}
66
67 void Value::push_back(const Value& value)
68 {
69 list().emplace_back(value);
70 }
71
72 void Value::push_back(Value&& value)
73 {
74 list().emplace_back(std::move(value));
75 }
76
77 std::string Value::toString(VM& vm, const bool show_as_code) const noexcept
78 {
79 switch (valueType())
80 {
82 return fmt::format("{}", number());
83
85 if (show_as_code)
86 return fmt::format("\"{}\"", string());
87 return string();
88
90 return fmt::format("Function@{}", pageAddr());
91
93 return "CProcedure";
94
95 case ValueType::List:
96 {
97 std::string out = "[";
98 for (auto it = constList().begin(), it_end = constList().end(); it != it_end; ++it)
99 {
100 if (it->valueType() == ValueType::String)
101 out += "\"" + it->toString(vm) + "\"";
102 else
103 out += it->toString(vm);
104 if (it + 1 != it_end)
105 out += " ";
106 }
107 return out + "]";
108 }
109
111 return closure().toString(vm);
112
113 case ValueType::User:
114 return fmt::format("{}", fmt::streamed(usertype()));
115
116 case ValueType::Dict:
117 return dict().toString(vm);
118
119 case ValueType::Nil:
120 return "nil";
121
122 case ValueType::True:
123 return "true";
124
125 case ValueType::False:
126 return "false";
127
129 return "undefined";
130
132 if (reference() != this)
133 return reference()->toString(vm);
134 return "Ref(self)";
135
137 return fmt::format("Instruction@{}", pageAddr());
138
140 return fmt::format("Garbage (expected)");
141
142 default:
143 return "~\\._./~";
144 }
145 }
146
147 bool operator==(const Value& A, const Value& B) noexcept
148 {
149 // values should have the same type
150 if (A.m_type != B.m_type)
151 return false;
152 // all the types >= Nil are Nil itself, True, False, Undefined
153 if (A.typeNum() >= static_cast<uint8_t>(ValueType::Nil))
154 return true;
155
156 if (A.valueType() == ValueType::Dict)
157 return A.dict() == B.dict();
158
159 return A.m_value == B.m_value;
160 }
161
162 bool operator!(const Value& A) noexcept
163 {
164 switch (A.valueType())
165 {
166 case ValueType::List:
167 return A.constList().empty();
168
170 return A.number() == 0.0;
171
173 return A.string().empty();
174
175 case ValueType::Dict:
176 return std::cmp_equal(A.dict().size(), 0);
177
178 case ValueType::User:
179 [[fallthrough]];
180 case ValueType::Nil:
181 [[fallthrough]];
182 case ValueType::False:
183 return true;
184
185 case ValueType::True:
186 [[fallthrough]];
187 default:
188 return false;
189 }
190 }
191}
Define how dictionaries are handled.
Wrapper object for user-defined functions.
Default value type handled by the virtual machine.
Storage class to hold custom functions.
Definition Procedure.hpp:26
A class to be use C++ objects in ArkScript.
Definition UserType.hpp:48
The ArkScript virtual machine, executing ArkScript bytecode.
Definition VM.hpp:48
std::string String_t
Definition Value.hpp:96
List_t & list()
Definition Value.hpp:171
Value() noexcept
Construct a new Value object.
Definition Value.cpp:10
void push_back(const Value &value)
Add an element to the list held by the value (if the value type is set to list)
Definition Value.cpp:67
std::string toString(VM &vm, bool show_as_code=false) const noexcept
Definition Value.cpp:77
std::vector< Value > List_t
Definition Value.hpp:97
Closure management.
Definition Closure.hpp:35
bool operator==(const Namespace &A, const Namespace &B)
Definition Namespace.hpp:21
uint16_t PageAddr_t
Definition Closure.hpp:26
bool operator!(const Value &A) noexcept
Definition Value.cpp:162
ValueType
Definition Value.hpp:32
@ Garbage
Used to signal a value was used and can/should be collected and removed from the stack.