ArkScript
A small, fast, functional and scripting language for video games
VM.hpp
Go to the documentation of this file.
1
/**
2
* @file VM.hpp
3
* @author Alexandre Plateau (
[email protected]
)
4
* @brief The ArkScript virtual machine
5
* @version 2.0
6
* @date 2020-10-27
7
*
8
* @copyright Copyright (c) 2020-2024
9
*
10
*/
11
12
#ifndef ARK_VM_VM_HPP
13
#define ARK_VM_VM_HPP
14
15
#include <array>
16
#include <vector>
17
#include <string>
18
#include <cassert>
19
#include <utility>
20
#include <cinttypes>
21
#include <unordered_map>
22
#include <algorithm>
23
#include <fmt/core.h>
24
25
#include <
Ark/Compiler/Instructions.hpp
>
26
#include <
Ark/VM/Value.hpp
>
27
#include <
Ark/VM/State.hpp
>
28
#include <
Ark/VM/ErrorKind.hpp
>
29
#include <
Ark/VM/ExecutionContext.hpp
>
30
#include <
Ark/Builtins/Builtins.hpp
>
31
#include <
Ark/Platform.hpp
>
32
#include <
Ark/VM/Plugin.hpp
>
33
#include <
Ark/VM/Future.hpp
>
34
35
namespace
Ark
36
{
37
using namespace
std::string_literals;
38
39
/**
40
* @brief The ArkScript virtual machine, executing ArkScript bytecode
41
*
42
*/
43
class
ARK_API
VM
final
44
{
45
public
:
46
/**
47
* @brief Construct a new vm t object
48
*
49
* @param state a reference to an ArkScript state, which can be reused for multiple VMs
50
*/
51
explicit
VM
(
State
& state)
noexcept
;
52
53
/**
54
* @brief Run the bytecode held in the state
55
*
56
* @param fail_with_exception throw if true, display a stacktrace if false
57
* @return int the exit code (default to 0 if no error)
58
*/
59
int
run(
bool
fail_with_exception =
false
);
60
61
/**
62
* @brief Retrieve a value from the virtual machine, given its symbol name
63
*
64
* @param name the name of the variable to retrieve
65
* @return Value&
66
*/
67
Value
& operator[](
const
std::string& name)
noexcept
;
68
69
/**
70
* @brief Call a function from ArkScript, by giving it arguments
71
*
72
* @tparam Args
73
* @param name the function name in the ArkScript code
74
* @param args C++ argument list, converted to internal representation
75
* @return Value
76
*/
77
template
<
typename
... Args>
78
Value
call(
const
std::string& name, Args&&... args);
79
80
// ================================================
81
// function calling from plugins
82
// ================================================
83
84
/**
85
* @brief Resolving a function call (called by plugins and builtins)
86
*
87
* @tparam Args
88
* @param val the ArkScript function object
89
* @param args C++ argument list
90
* @return Value
91
*/
92
template
<
typename
... Args>
93
[[deprecated(
"Use resolve(ExecutionContext*, vector<Value>&) instead"
)]]
Value
resolve(
const
Value
* val, Args&&... args);
94
95
/**
96
* @brief Resolves a function call (called by plugins and builtins)
97
*
98
* @param context the execution context to use
99
* @param n the function and its arguments
100
* @return Value
101
*/
102
inline
Value
resolve
(
internal::ExecutionContext
* context, std::vector<Value>& n);
103
104
/**
105
* @brief Ask the VM to exit with a given exit code
106
*
107
* @param code an exit code
108
*/
109
void
exit(
int
code)
noexcept
;
110
111
/**
112
* @brief Create an execution context and returns it
113
* @details This method is thread-safe VM wise.
114
*
115
* @return internal::ExecutionContext*
116
*/
117
internal::ExecutionContext
* createAndGetContext();
118
119
/**
120
* @brief Free a given execution context
121
* @details This method is thread-safe VM wise.
122
*
123
* @param ec
124
*/
125
void
deleteContext(
internal::ExecutionContext
* ec);
126
127
/**
128
* @brief Create a Future object from a function and its arguments and return a managed pointer to it
129
* @details This method is thread-safe VM wise.
130
*
131
* @param args
132
* @return internal::Future*
133
*/
134
internal::Future
* createFuture(std::vector<Value>& args);
135
136
/**
137
* @brief Free a given future
138
* @details This method is thread-safe VM wise.
139
*
140
* @param f
141
*/
142
void
deleteFuture(
internal::Future
* f);
143
144
/**
145
* @brief Used by the REPL to force reload all the plugins and their bound methods
146
*
147
* @return true on success
148
* @return false if one or more plugins couldn't be reloaded
149
*/
150
[[nodiscard]]
bool
forceReloadPlugins()
const
;
151
152
friend
class
Value
;
153
friend
class
internal::Closure
;
154
friend
class
Repl
;
155
156
private
:
157
State
&
m_state
;
158
std::vector<std::unique_ptr<internal::ExecutionContext>>
m_execution_contexts
;
159
int
m_exit_code
;
///< VM exit code, defaults to 0. Can be changed through `sys:exit`
160
bool
m_running
;
161
std::mutex
m_mutex
;
162
std::vector<std::shared_ptr<internal::SharedLibrary>>
m_shared_lib_objects
;
163
std::vector<std::unique_ptr<internal::Future>>
m_futures
;
///< Storing the promises while we are resolving them
164
165
// a little trick for operator[] and for pop
166
Value
m_no_value = internal::Builtins::nil;
167
Value
m_undefined_value
;
168
169
/**
170
* @brief Run ArkScript bytecode inside a try catch to retrieve all the exceptions and display a stack trace if needed
171
*
172
* @param context
173
* @param untilFrameCount the frame count we need to reach before stopping the VM
174
* @param fail_with_exception throw if true, display a stacktrace if false
175
* @return int the exit code
176
*/
177
int
safeRun(
internal::ExecutionContext
& context, std::size_t untilFrameCount = 0,
bool
fail_with_exception =
false
);
178
179
/**
180
* @brief Initialize the VM according to the parameters
181
*
182
*/
183
void
init() noexcept;
184
185
// ================================================
186
// instruction helpers
187
// ================================================
188
189
inline
Value
* loadSymbol(uint16_t
id
, internal::
ExecutionContext
& context);
190
inline
Value
* loadConstAsPtr(uint16_t
id
) const;
191
inline
void
store(uint16_t
id
, const
Value
* val, internal::
ExecutionContext
& context);
192
inline
void
setVal(uint16_t
id
, const
Value
* val, internal::
ExecutionContext
& context);
193
194
// ================================================
195
// stack related
196
// ================================================
197
198
/**
199
* @brief Pop a value from the stack
200
*
201
* @param context
202
* @return Value*
203
*/
204
inline
Value
* pop(internal::
ExecutionContext
& context);
205
206
/**
207
* @brief Push a value on the stack
208
*
209
* @param value
210
* @param context
211
*/
212
inline
void
push(const
Value
& value, internal::
ExecutionContext
& context);
213
214
/**
215
* @brief Push a value on the stack
216
*
217
* @param value
218
* @param context
219
*/
220
inline
void
push(
Value
&& value, internal::
ExecutionContext
& context);
221
222
/**
223
* @brief Push a value on the stack as a reference
224
*
225
* @param valptr
226
* @param context
227
*/
228
inline
void
push(
Value
* valptr, internal::
ExecutionContext
& context);
229
230
/**
231
* @brief Pop a value from the stack and resolve it if possible, then return it
232
*
233
* @param context
234
* @return Value*
235
*/
236
inline
Value
* popAndResolveAsPtr(internal::
ExecutionContext
& context);
237
238
/**
239
* @brief Move stack values around and invert them
240
* @details values: 1, 2, 3, _, _
241
* wanted: pp, ip, 3, 2, 1
242
* positions: 0, 1, 2, 3, 4
243
*
244
* @param argc number of arguments to swap around
245
* @param context
246
*/
247
inline
void
swapStackForFunCall(uint16_t argc, internal::
ExecutionContext
& context);
248
249
// ================================================
250
// locals related
251
// ================================================
252
253
/**
254
* @brief Find the nearest variable of a given id
255
*
256
* @param id the id to find
257
* @param context
258
* @return Value*
259
*/
260
inline
Value
* findNearestVariable(uint16_t
id
, internal::
ExecutionContext
& context) noexcept;
261
262
/**
263
* @brief Destroy the current frame and get back to the previous one, resuming execution
264
*
265
* Doing the job nobody wants to do: cleaning after everyone has finished to play.
266
* This is a sort of primitive garbage collector
267
*
268
* @param context
269
*/
270
inline
void
returnFromFuncCall(internal::
ExecutionContext
& context);
271
272
/**
273
* @brief Load a plugin from a constant id
274
*
275
* @param id Id of the constant
276
* @param context
277
*/
278
void
loadPlugin(uint16_t
id
, internal::
ExecutionContext
& context);
279
280
// ================================================
281
// error handling
282
// ================================================
283
284
/**
285
* @brief Find the nearest variable id with a given value
286
*
287
* Only used to display the call stack traceback
288
*
289
* @param value the value to search for
290
* @param context
291
* @return uint16_t
292
*/
293
uint16_t findNearestVariableIdWithValue(const
Value
& value, internal::
ExecutionContext
& context) const noexcept;
294
295
/**
296
* @brief Throw a VM error message
297
*
298
* @param kind type of VM error
299
* @param message
300
*/
301
static
void
throwVMError(internal::
ErrorKind
kind, const std::
string
& message);
302
303
/**
304
* @brief Display a backtrace when the VM encounter an exception
305
*
306
* @param context
307
*/
308
void
backtrace(internal::
ExecutionContext
& context) noexcept;
309
310
/**
311
* @brief Function called when the CALL instruction is met in the bytecode
312
*
313
* @param context
314
* @param argc number of arguments already sent
315
*/
316
inline
void
call(internal::
ExecutionContext
& context, uint16_t argc);
317
318
/**
319
* @brief Builtin called when the CALL_BUILTIN instruction is met in the bytecode
320
*
321
* @param context
322
* @param builtin the builtin to call
323
* @param argc number of arguments already sent
324
*/
325
inline
void
callBuiltin(internal::
ExecutionContext
& context, const
Value
& builtin, uint16_t argc);
326
};
327
328
#include "VM.inl"
329
330
/// ArkScript Nil value
331
const
auto
Nil
=
Value
(ValueType::Nil);
332
/// ArkScript False value
333
const
auto
False
=
Value
(ValueType::False);
334
/// ArkScript True value
335
const
auto
True
=
Value
(ValueType::True);
336
}
337
338
#endif
Builtins.hpp
Host the declaration of all the ArkScript builtins.
ErrorKind.hpp
ExecutionContext.hpp
Keeping track of the internal data needed by the VM.
Future.hpp
Instructions.hpp
The different instructions used by the compiler and virtual machine.
ARK_API
#define ARK_API
Definition
Module.hpp:28
Platform.hpp
ArkScript configuration macros.
Plugin.hpp
Loads .dll/.so/.dynlib files.
State.hpp
State used by the virtual machine: it loads the bytecode, can compile it if needed,...
Value.hpp
Ark::Repl
Definition
Repl.hpp:26
Ark::State
Ark state to handle the dirty job of loading and compiling ArkScript code.
Definition
State.hpp:32
Ark::VM
The ArkScript virtual machine, executing ArkScript bytecode.
Definition
VM.hpp:44
Ark::VM::m_futures
std::vector< std::unique_ptr< internal::Future > > m_futures
Storing the promises while we are resolving them.
Definition
VM.hpp:163
Ark::VM::m_exit_code
int m_exit_code
VM exit code, defaults to 0. Can be changed through sys:exit
Definition
VM.hpp:159
Ark::VM::m_shared_lib_objects
std::vector< std::shared_ptr< internal::SharedLibrary > > m_shared_lib_objects
Definition
VM.hpp:162
Ark::VM::m_execution_contexts
std::vector< std::unique_ptr< internal::ExecutionContext > > m_execution_contexts
Definition
VM.hpp:158
Ark::VM::resolve
Value resolve(internal::ExecutionContext *context, std::vector< Value > &n)
Resolves a function call (called by plugins and builtins)
Definition
VM.hpp:91
Ark::VM::m_mutex
std::mutex m_mutex
Definition
VM.hpp:161
Ark::VM::m_running
bool m_running
Definition
VM.hpp:160
Ark::VM::m_undefined_value
Value m_undefined_value
Definition
VM.hpp:167
Ark::VM::m_state
State & m_state
Definition
VM.hpp:157
Ark::Value
Definition
Value.hpp:60
Ark::internal::Closure
Closure management.
Definition
Closure.hpp:37
Ark::internal::Future
Definition
Future.hpp:24
Ark::internal::ErrorKind
ErrorKind
Definition
ErrorKind.hpp:10
Ark
Definition
Builtins.hpp:21
Ark::False
const auto False
ArkScript False value.
Definition
VM.hpp:333
Ark::Nil
const auto Nil
ArkScript Nil value.
Definition
VM.hpp:331
Ark::True
const auto True
ArkScript True value.
Definition
VM.hpp:335
Ark::internal::ExecutionContext
Definition
ExecutionContext.hpp:31
include
Ark
VM
VM.hpp
Generated on Wed Jan 15 2025 19:51:44 for ArkScript by
1.12.0