Phasor 3.1.1
Stack VM based Programming Language
Loading...
Searching...
No Matches
VM.hpp
Go to the documentation of this file.
1#pragma once
3#include <Value.hpp>
4#include <vector>
5#include <filesystem>
6#include <functional>
7#include <map>
8#include <array>
9#include <ranges>
10#include "core/core.h"
11#include <iostream>
12#include <stdexcept>
13#include <platform.h>
14#ifndef SANDBOXED
15 #include "../FFI/ffi.hpp"
16#endif
17
18#ifdef TRACING
19#include <format>
20#include "../../ISA/map.hpp"
21#endif
22
24namespace Phasor
25{
26
29class VM
30{
31 public:
32 explicit VM()
33 {
34#ifdef TRACING
35 log(std::format("VM::{}(): normal instance created {:#x}\n", __func__, (uintptr_t)this));
36 flush();
37#endif
38 }
39 explicit VM(const Bytecode &bytecode)
40 {
41#ifdef TRACING
42 log(std::format("VM::{}(): fast instance created {:#x}\n", __func__, (uintptr_t)this));
43 flush();
44#endif
45 run(bytecode);
46 }
47 explicit VM(const OpCode &op, const int &operand1 = 0, const int &operand2 = 0, const int &operand3 = 0,
48 const int &operand4 = 0, const int &operand5 = 0)
49 {
50#ifdef TRACING
51 log(std::format("VM::{}(): operation instance created {:#x}\n", __func__, (uintptr_t)this));
52 flush();
53#endif
54 operation(op, operand1, operand2, operand3, operand4, operand5);
55
56 }
58 {
59 cleanup();
60#ifdef TRACING
61 log(std::format("VM::{}(): deconstructed {:#x}\n", __func__, (uintptr_t)this));
62 flush();
63#endif
64 }
65
66 inline void initFFI(const std::filesystem::path &path) {
67#ifndef SANDBOXED
68 ffi = std::make_unique<FFI>(path, this);
69#endif
70 }
71
74 class Halt : public std::exception
75 {
76 public:
77 const char *what() const noexcept override
78 {
79 return "";
80 }
81 };
82
85 int run(const Bytecode &bytecode);
86
88 using NativeFunction = std::function<Value(const std::vector<Value> &args, VM *vm)>;
89
91 void registerNativeFunction(const std::string &name, NativeFunction fn);
92
93 using ImportHandler = std::function<void(const std::filesystem::path &path)>;
95 void setImportHandler(const ImportHandler &handler);
96
98 void freeVariable(size_t index);
99
103 size_t addVariable(const Value &value);
104
108 void setVariable(size_t index, const Value &value);
109
111 Value getVariable(size_t index);
112
114 size_t getVariableCount();
115
119 void setRegister(uint8_t index, const Value &value);
120
123 void freeRegister(uint8_t index);
124
128 Value getRegister(uint8_t index);
129
132 size_t getRegisterCount();
133
170
171 #define REGISTER1 VM::Register::r0
172 #define REGISTER2 VM::Register::r1
173 #define REGISTER3 VM::Register::r2
174
175#ifdef _WIN32
177 inline Value __fastcall operation(const OpCode &op, const int &operand1 = 0, const int &operand2 = 0,
178 const int &operand3 = 0, const int &operand4 = 0, const int &operand5 = 0);
179#else
181 inline Value operation(const OpCode &op, const int &operand1 = 0, const int &operand2 = 0, const int &operand3 = 0,
182 const int &operand4 = 0, const int &operand5 = 0);
183#endif
185 void push(const Value &value);
186
188 Value pop();
189
191 Value peek();
192
194 void cleanup();
195
197 void reset(const bool &resetStack = true, const bool &resetFunctions = true, const bool &resetVariables = true);
198
200 std::string getInformation();
201
203 std::string getBytecodeInformation();
204
206 void log(const Value &msg);
207
209 void logerr(const Value &msg);
210
212 void flush();
213
215 void flusherr();
216
218 inline void setStatus(int newStatus) { status = newStatus; }
219
227 template <typename... Args> inline Value regRun(OpCode opcode, Args &&...args)
228 {
229 int regIndex = 0;
230 (setRegister(regIndex++, std::forward<Args>(args)), ...);
231 return operation(opcode);
232 }
233
241 template <typename... Args> inline Value stackRun(OpCode opcode, Args&&... args) {
242 Value arr[] = {Value(std::forward<Args>(args))...};
243 for (Value& v : arr | std::views::reverse)
244 push(v);
245 operation(opcode);
246 return pop();
247 }
248
249 private:
250#ifndef SANDBOXED
252 std::unique_ptr<FFI> ffi;
253#endif
255 int status = 0;
256
259
261 std::array<Value, MAX_REGISTERS> registers;
262
264 std::vector<Value> stack;
265
267 std::vector<int> callStack;
268
270 std::vector<Value> variables;
271
274
276 size_t pc = 0;
277
279 std::map<std::string, NativeFunction> nativeFunctions;
280};
281} // namespace Phasor
282
283#define OPS_ARE_INCLUDED
284#include "Operations.cc.inl"
Expanded opcode set for Phasor VM.
Throws when the HALT opcode is reached.
Definition VM.hpp:75
const char * what() const noexcept override
Definition VM.hpp:77
ImportHandler importHandler
Import handler for loading modules.
Definition VM.hpp:258
std::vector< Value > variables
Variable storage indexed by variable index.
Definition VM.hpp:270
std::function< Value(const std::vector< Value > &args, VM *vm)> NativeFunction
Native function signature.
Definition VM.hpp:88
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:67
std::function< void(const std::filesystem::path &path)> ImportHandler
Definition VM.hpp:93
void logerr(const Value &msg)
Log a Value to stderr.
Definition Utility.cpp:182
std::vector< Value > stack
Stack for function calls.
Definition VM.hpp:264
const Bytecode * m_bytecode
Bytecode to execute.
Definition VM.hpp:273
VM(const Bytecode &bytecode)
Definition VM.hpp:39
std::vector< int > callStack
Call stack for function calls.
Definition VM.hpp:267
Value getVariable(size_t index)
Get a variable from the VM.
Definition Variables.cpp:43
VM(const OpCode &op, const int &operand1=0, const int &operand2=0, const int &operand3=0, const int &operand4=0, const int &operand5=0)
Definition VM.hpp:47
std::map< std::string, NativeFunction > nativeFunctions
Native function registry.
Definition VM.hpp:279
void registerNativeFunction(const std::string &name, NativeFunction fn)
Register a native function.
Definition Native.cpp:5
Value getRegister(uint8_t index)
Get a register value.
Definition Register.cpp:26
void setStatus(int newStatus)
Set VM exit code.
Definition VM.hpp:218
size_t getVariableCount()
Get the number of variables in the VM.
Definition Variables.cpp:60
std::string getBytecodeInformation()
Get bytecode information for debugging.
Definition Utility.cpp:140
void log(const Value &msg)
Log a Value to stdout.
Definition Utility.cpp:176
std::array< Value, MAX_REGISTERS > registers
Virtual registers for register-based operations (v2.0).
Definition VM.hpp:261
size_t addVariable(const Value &value)
Add a variable to the VM.
Definition Variables.cpp:8
~VM()
Definition VM.hpp:57
void flush()
Flush stdout.
Definition Utility.cpp:188
void cleanup()
Clean up the virtual machine.
Definition Utility.cpp:76
Register
Enum for registers.
Definition VM.hpp:136
size_t pc
Program counter.
Definition VM.hpp:276
void push(const Value &value)
Push a value onto the stack.
Definition Stack.cpp:8
void setVariable(size_t index, const Value &value)
Set a variable in the VM.
Definition Variables.cpp:30
void initFFI(const std::filesystem::path &path)
Definition VM.hpp:66
void setRegister(uint8_t index, const Value &value)
Set a register value.
Definition Register.cpp:8
Value stackRun(OpCode opcode, Args &&... args)
Run an opcode with values pushed to the stack.
Definition VM.hpp:241
void freeRegister(uint8_t index)
Free a register (reset to null).
Definition Register.cpp:17
std::unique_ptr< FFI > ffi
FFI.
Definition VM.hpp:252
int status
Exit code.
Definition VM.hpp:255
Value operation(const OpCode &op, const int &operand1=0, const int &operand2=0, const int &operand3=0, const int &operand4=0, const int &operand5=0)
Execute a single operation.
Value regRun(OpCode opcode, Args &&...args)
Run an opcode with arguments pre-loaded into registers.
Definition VM.hpp:227
Value peek()
Peek at the top value on the stack.
Definition Stack.cpp:38
void flusherr()
Flush stderr.
Definition Utility.cpp:193
size_t getRegisterCount()
Get the total number of registers.
Definition Register.cpp:35
int run(const Bytecode &bytecode)
Run the virtual machine Exits -1 on uncaught exception.
Definition Utility.cpp:13
void reset(const bool &resetStack=true, const bool &resetFunctions=true, const bool &resetVariables=true)
Reset the virtual machine.
Definition Utility.cpp:88
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:111
A value in the Phasor VM.
Definition Value.hpp:67
The Phasor Programming Language and Runtime.
Definition AST.hpp:11
OpCode
Definition ISA.hpp:12
Complete bytecode structure.
Definition CodeGen.hpp:47