Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
VM.hpp
Go to the documentation of this file.
1#pragma once
3#ifndef CMAKE_PCH
4#include <Value.hpp>
5#endif
6#include <vector>
7#include <filesystem>
8#include <functional>
9#include <map>
10#include <array>
11#include <ranges>
12#include "core/core.h"
13#include <iostream>
14#include <phsint.hpp>
15#include <stdexcept>
16#include <memory_resource>
17#ifdef TRACING
18#include <format>
19#include "../../ISA/map.hpp"
20#endif
21#include <platform.h>
22#include <version.h>
23#ifndef SANDBOXED
24#include "../FFI/ffi.hpp"
25#endif
26
27#define BAD_STATUS -1
28
30namespace Phasor
31{
32
35class VM
36{
37 public:
38 VM();
39 VM(const Bytecode &bytecode);
40 VM(const OpCode &op, const int &operand1 = 0, const int &operand2 = 0, const int &operand3 = 0);
41 ~VM();
42
44 void initFFI(const std::filesystem::path &path);
45
47 std::string getVersion();
48
51 class Halt : public std::exception
52 {
53 public:
54 const char *what() const noexcept override
55 {
56 return "";
57 }
58 };
59
62 int run(const Bytecode &bytecode, const size_t startPC = 0);
63
65 Value runFunction(const std::string &name, const Bytecode &bytecode, const bool &argsInit = false);
66
68 using NativeFunction = std::function<Value(const std::vector<Value> &args, VM *vm)>;
69
71 void registerNativeFunction(const std::string &name, NativeFunction fn);
72
73 using ImportHandler = std::function<void(const std::filesystem::path &path)>;
75 void setImportHandler(const ImportHandler &handler);
76
78 void freeVariable(size_t index);
79
81 void freeVariableByName(const std::string &name);
82
86 size_t addVariable(const Value &value);
87
91 void setVariable(size_t index, const Value &value);
92
94 Value getVariable(size_t index);
95
97 size_t getVariableCount();
98
102 void setRegister(u8 index, const Value &value);
103
106 void freeRegister(u8 index);
107
111 Value getRegister(u8 index);
112
115 size_t getRegisterCount();
116
153
154#define REGISTER1 VM::Register::r0
155#define REGISTER2 VM::Register::r1
156#define REGISTER3 VM::Register::r2
157
158#ifdef _WIN32
160 Value __fastcall operation(const OpCode &op, const int &operand1 = 0, const int &operand2 = 0,
161 const int &operand3 = 0);
162#else
164 Value operation(const OpCode &op, const int &operand1 = 0, const int &operand2 = 0, const int &operand3 = 0);
165#endif
167 void push(const Value &value);
168
170 Value pop();
171
173 Value peek();
174
176 void cleanup();
177
179 void reset(const bool &resetStack = true, const bool &resetFunctions = true, const bool &resetVariables = true);
180
182 std::string getInformation();
183
185 std::string getBytecodeInformation();
186
188 void log(const Value &msg);
189
191 void logerr(const Value &msg);
192
194 void flush();
195
197 void flusherr();
198
200 void setStatus(int newStatus);
201 void resetStatus();
202 int getStatus();
203 bool isErrorStatus();
204
212 template <typename... Args> inline Value regRun(OpCode opcode, Args &&...args)
213 {
214 int regIndex = 0;
215 (setRegister(regIndex++, std::forward<Args>(args)), ...);
216 operation(opcode);
217 return getRegister(REGISTER1);
218 }
219
227 template <typename... Args> inline Value stackRun(OpCode opcode, Args &&...args)
228 {
229 Value arr[] = {Value(std::forward<Args>(args))...};
230 for (Value &v : arr | std::views::reverse)
231 push(v);
232 operation(opcode);
233 return pop();
234 }
235
236 private:
238 static Value native_array_literal(const std::vector<Value> &args, VM *vm);
239 static Value native_get_elem(const std::vector<Value> &args, VM *vm);
240 static Value native_set_elem(const std::vector<Value> &args, VM *vm);
241
242 void setup(const Bytecode &bc, const size_t initialPC);
243 void evalLoop();
244
245 bool isDirectCall = false;
246
247#ifndef SANDBOXED
249 std::unique_ptr<FFI> ffi;
250#endif
252 int status = 0;
253
255 bool isError = false;
256
259
261 std::array<Value, MAX_REGISTERS> registers;
262
264 std::pmr::monotonic_buffer_resource stack_pool;
265 std::pmr::vector<Value> stack;
266
268 std::vector<int> callStack;
269
271 std::vector<Value> variables;
272
275
277 size_t pc = 0;
278
280 std::map<std::string, NativeFunction> nativeFunctions;
281};
282} // namespace Phasor
#define msg
#define REGISTER1
Definition VM.hpp:154
Expanded opcode set for Phasor VM.
Throws when the HALT opcode is reached.
Definition VM.hpp:52
const char * what() const noexcept override
Definition VM.hpp:54
Virtual Machine.
Definition VM.hpp:36
std::array< Value, MAX_REGISTERS > registers
Virtual registers for register-based operations (v2.0).
Definition VM.hpp:261
ImportHandler importHandler
Import handler for loading modules.
Definition VM.hpp:258
Value operation(const OpCode &op, const int &operand1=0, const int &operand2=0, const int &operand3=0)
Execute a single operation.
std::vector< Value > variables
Variable storage indexed by variable index, or simply: the managed heap.
Definition VM.hpp:271
std::function< Value(const std::vector< Value > &args, VM *vm)> NativeFunction
Native function signature.
Definition VM.hpp:68
Value pop()
Pop a value from the stack.
Definition Stack.cpp:17
void setImportHandler(const ImportHandler &handler)
Set the import handler for importing modules.
Definition Utility.cpp:163
VM()
Definition VM.cpp:8
Value getRegister(u8 index)
Get a register value.
Definition Register.cpp:27
std::function< void(const std::filesystem::path &path)> ImportHandler
Definition VM.hpp:73
void logerr(const Value &msg)
Log a Value to stderr.
Definition Utility.cpp:285
void freeRegister(u8 index)
Free a register (reset to null).
Definition Register.cpp:18
void registerArrayFunctions()
Definition Array.cpp:7
std::string getVersion()
Get Phasor VM version.
Definition Utility.cpp:35
void evalLoop()
Definition Operations.cpp:9
std::unique_ptr< FFI > ffi
FFI.
Definition VM.hpp:249
bool isDirectCall
is a direct call to a function
Definition VM.hpp:245
Value getVariable(size_t index)
Get a variable from the VM.
Definition Variables.cpp:58
void registerNativeFunction(const std::string &name, NativeFunction fn)
Register a native function.
Definition Native.cpp:5
static Value native_array_literal(const std::vector< Value > &args, VM *vm)
Definition Array.cpp:14
void setStatus(int newStatus)
Set VM exit code.
Definition Utility.cpp:39
bool isErrorStatus()
Definition Utility.cpp:51
static Value native_set_elem(const std::vector< Value > &args, VM *vm)
Definition Array.cpp:35
void freeVariableByName(const std::string &name)
Free a variable by name in the VM.
Definition Variables.cpp:30
size_t getVariableCount()
Get the number of variables in the VM.
Definition Variables.cpp:75
std::vector< int > callStack
Call stack for function calls.
Definition VM.hpp:268
std::string getBytecodeInformation()
Get bytecode information for debugging.
Definition Utility.cpp:244
Register
Enum for registers.
Definition VM.hpp:119
void log(const Value &msg)
Log a Value to stdout.
Definition Utility.cpp:279
size_t addVariable(const Value &value)
Add a variable to the VM.
Definition Variables.cpp:8
int getStatus()
Definition Utility.cpp:47
~VM()
Definition VM.cpp:37
void flush()
Flush stdout.
Definition Utility.cpp:291
std::pmr::vector< Value > stack
Definition VM.hpp:265
bool isError
Is status an error code.
Definition VM.hpp:255
void cleanup()
Clean up the virtual machine.
Definition Utility.cpp:172
size_t pc
Program counter.
Definition VM.hpp:277
void push(const Value &value)
Push a value onto the stack.
Definition Stack.cpp:8
Value stackRun(OpCode opcode, Args &&...args)
Run an opcode with values pushed to the stack.
Definition VM.hpp:227
void resetStatus()
Definition Utility.cpp:43
void setVariable(size_t index, const Value &value)
Set a variable in the VM.
Definition Variables.cpp:45
int run(const Bytecode &bytecode, const size_t startPC=0)
Run the virtual machine Exits -1 on uncaught exception.
Definition Utility.cpp:80
void initFFI(const std::filesystem::path &path)
Initialize the FFI plugins.
Definition Utility.cpp:56
std::map< std::string, NativeFunction > nativeFunctions
Native function registry.
Definition VM.hpp:280
void setRegister(u8 index, const Value &value)
Set a register value.
Definition Register.cpp:9
const Bytecode * m_bytecode
Bytecode to execute.
Definition VM.hpp:274
void setup(const Bytecode &bc, const size_t initialPC)
Definition Utility.cpp:63
std::pmr::monotonic_buffer_resource stack_pool
Stack.
Definition VM.hpp:264
int status
Exit code.
Definition VM.hpp:252
Value regRun(OpCode opcode, Args &&...args)
Run an opcode with arguments pre-loaded into registers.
Definition VM.hpp:212
Value peek()
Peek at the top value on the stack.
Definition Stack.cpp:38
void flusherr()
Flush stderr.
Definition Utility.cpp:296
size_t getRegisterCount()
Get the total number of registers.
Definition Register.cpp:36
Value runFunction(const std::string &name, const Bytecode &bytecode, const bool &argsInit=false)
Run a function from bytecode on the virtual machine.
Definition Utility.cpp:136
static Value native_get_elem(const std::vector< Value > &args, VM *vm)
Definition Array.cpp:19
void reset(const bool &resetStack=true, const bool &resetFunctions=true, const bool &resetVariables=true)
Reset the virtual machine.
Definition Utility.cpp:191
void freeVariable(size_t index)
Free a variable in the VM.
Definition Variables.cpp:18
std::string getInformation()
Get VM information for debugging.
Definition Utility.cpp:217
A value in the Phasor VM.
Definition Value.hpp:59
The Phasor Programming Language and Runtime.
Definition AST.hpp:13
uint8_t u8
Definition phsint.hpp:9
OpCode
Definition ISA.hpp:12
Complete bytecode structure.
Definition CodeGen.hpp:50