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 int64_t value) noexcept :
28 m_type(ValueType::Number), m_value(static_cast<double>(value))
29 {}
30
31 Value::Value(const double value) noexcept :
32 m_type(ValueType::Number), m_value(value)
33 {}
34
35 Value::Value(const String_t& value) noexcept :
36 m_type(ValueType::String), m_value(value)
37 {}
38
39 Value::Value(const char* value) noexcept :
40 m_type(ValueType::String), m_value(std::string(value))
41 {}
42
44 m_type(ValueType::PageAddr), m_value(value)
45 {}
46
47 Value::Value(Procedure&& value) noexcept :
48 m_type(ValueType::CProc), m_value(std::move(value))
49 {}
50
51 Value::Value(List_t&& value) noexcept :
52 m_type(ValueType::List), m_value(std::move(value))
53 {}
54
55 Value::Value(internal::Closure&& value) noexcept :
56 m_type(ValueType::Closure), m_value(std::move(value))
57 {}
58
59 Value::Value(UserType&& value) noexcept :
60 m_type(ValueType::User), m_value(value)
61 {}
62
63 Value::Value(Dict_t&& value) noexcept :
64 m_type(ValueType::Dict), m_value(std::make_shared<Dict_t>(std::move(value)))
65 {}
66
67 Value::Value(Ref_t ref) noexcept :
68 m_type(ValueType::Reference), m_value(ref)
69 {}
70
71 void Value::push_back(const Value& value)
72 {
73 list().emplace_back(value);
74 }
75
76 void Value::push_back(Value&& value)
77 {
78 list().emplace_back(std::move(value));
79 }
80
81 std::string Value::toString(VM& vm, const bool show_as_code) const noexcept
82 {
83 switch (valueType())
84 {
86 return fmt::format("{}", number());
87
89 if (show_as_code)
90 return fmt::format("\"{}\"", string());
91 return string();
92
94 return fmt::format("Function@{}", pageAddr());
95
97 return "CProcedure";
98
99 case ValueType::List:
100 {
101 std::string out = "[";
102 for (auto it = constList().begin(), it_end = constList().end(); it != it_end; ++it)
103 {
104 if (it->valueType() == ValueType::String)
105 out += "\"" + it->toString(vm) + "\"";
106 else
107 out += it->toString(vm);
108 if (it + 1 != it_end)
109 out += " ";
110 }
111 return out + "]";
112 }
113
115 return closure().toString(vm);
116
117 case ValueType::User:
118 return fmt::format("{}", fmt::streamed(usertype()));
119
120 case ValueType::Dict:
121 return dict().toString(vm);
122
123 case ValueType::Nil:
124 return "nil";
125
126 case ValueType::True:
127 return "true";
128
129 case ValueType::False:
130 return "false";
131
133 return "undefined";
134
136 if (reference() != this)
137 return reference()->toString(vm);
138 return "Ref(self)";
139
141 return fmt::format("Instruction@{}", pageAddr());
142
144 return fmt::format("Garbage (expected)");
145
146 default:
147 return "~\\._./~";
148 }
149 }
150
151 bool operator==(const Value& A, const Value& B) noexcept
152 {
153 // values should have the same type
154 if (A.m_type != B.m_type)
155 return false;
156 // all the types >= Nil are Nil itself, True, False, Undefined
157 if (A.typeNum() >= static_cast<uint8_t>(ValueType::Nil))
158 return true;
159
160 if (A.valueType() == ValueType::Dict)
161 return A.dict() == B.dict();
162
163 return A.m_value == B.m_value;
164 }
165
166 bool operator!(const Value& A) noexcept
167 {
168 switch (A.valueType())
169 {
170 case ValueType::List:
171 return A.constList().empty();
172
174 return A.number() == 0.0;
175
177 return A.string().empty();
178
179 case ValueType::Dict:
180 return std::cmp_equal(A.dict().size(), 0);
181
182 case ValueType::User:
183 [[fallthrough]];
184 case ValueType::Nil:
185 [[fallthrough]];
186 case ValueType::False:
187 return true;
188
189 case ValueType::True:
190 [[fallthrough]];
191 default:
192 return false;
193 }
194 }
195}
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:40
std::string String_t
Definition Value.hpp:96
List_t & list()
Definition Value.hpp:172
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:71
std::string toString(VM &vm, bool show_as_code=false) const noexcept
Definition Value.cpp:81
std::vector< Value > List_t
Definition Value.hpp:97
Closure management.
Definition Closure.hpp:36
bool operator==(const Namespace &A, const Namespace &B)
Definition Namespace.hpp:21
uint16_t PageAddr_t
Definition Closure.hpp:27
bool operator!(const Value &A) noexcept
Definition Value.cpp:166
ValueType
Definition Value.hpp:32
@ Garbage
Used to signal a value was used and can/should be collected and removed from the stack.