18inline bool isDebuggerAttached()
20 return IsDebuggerPresent() == TRUE;
24#include <sys/ptrace.h>
25inline bool isDebuggerAttached()
27 return ptrace(PTRACE_TRACEME, 0, 1, 0) == -1;
37 return PHASOR_VERSION_STRING;
59 ffi = std::make_unique<FFI>(path,
this);
85 log(std::format(
"\nVM::{}():\n\n", __func__));
90 using clock = std::chrono::high_resolution_clock;
91 auto start = clock::now();
102 auto end = clock::now();
103 auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
104 log(std::format(
"VM::{}(): Duration of bytecode execution: {}us\n\n", __func__, us));
112 if (isDebuggerAttached())
117#if defined(TRACING) || defined(_DEBUG)
118 catch (
const std::exception &e)
120 catch (
const std::exception &)
124 logerr(std::format(
"\nVM::{}(): UNCAUGHT EXCEPTION!\n\n{}\n{}\n\n", __func__, e.what(),
getInformation()));
129 logerr(std::format(
"{}\n", e.what()));
141 if (!argsInit)
push(0);
151 reset(
true,
false,
true);
154 throw std::runtime_error(
"Function call was not properly handled!");
157 throw std::runtime_error(
"Function did not return properly!");
166 log(std::format(
"VM::{}()\n", __func__));
175 log(std::format(
"VM::{}()\n", __func__));
188 reset(
true,
true,
true);
191void VM::reset(
const bool &resetStack,
const bool &resetFunctions,
const bool &resetVariables)
194 log(std::format(
"VM::{}()\n", __func__));
224 info = std::format(
"Stack Top: {:T}\n",
peek());
227 std::string registersStr;
234 registersStr += std::format(
"R{}: {:T}\n", regCount, reg);
239 info += std::format(
"VM INFORMATION:\n{}PC: {}\nCS: {}", registersStr,
pc, callStackTop);
247 std::string constants;
249 std::string functions;
250 std::string instructions;
252 for (
const auto &constant :
m_bytecode->constants)
254 constants += std::format(
"{:T}\n", constant);
256 for (
const auto &variable :
m_bytecode->variables)
258 variables += std::format(
"{}\n", variable.first);
260 for (
const auto &function :
m_bytecode->functionEntries)
262 functions += std::format(
"{}() PC = {}\n", function.first, function.second);
265 for (
const auto &instruction :
m_bytecode->instructions)
267 instructions += std::format(
"{}({}, {}, {})\n",
opCodeToString(instruction.op), instruction.operand1,
268 instruction.operand2, instruction.operand3);
273 "BYTECODE INFORMATION:\n\nConstants: {}\n{}\nVariables: {}\n{}\nFunctions: {}\n{}\nInstructions: {}\n{}",
281 std::string
s =
msg.toString();
287 std::string
s =
msg.toString();
void c_print_stderr(const char *s, int64_t len)
Native print error function.
void c_print_stdout(const char *s, int64_t len)
Native print function.
Throws when the HALT opcode is reached.
std::array< Value, MAX_REGISTERS > registers
Virtual registers for register-based operations (v2.0).
ImportHandler importHandler
Import handler for loading modules.
std::vector< Value > variables
Variable storage indexed by variable index, or simply: the managed heap.
Value pop()
Pop a value from the stack.
void setImportHandler(const ImportHandler &handler)
Set the import handler for importing modules.
std::function< void(const std::filesystem::path &path)> ImportHandler
void logerr(const Value &msg)
Log a Value to stderr.
void registerArrayFunctions()
std::string getVersion()
Get Phasor VM version.
std::unique_ptr< FFI > ffi
FFI.
bool isDirectCall
is a direct call to a function
void setStatus(int newStatus)
Set VM exit code.
std::vector< int > callStack
Call stack for function calls.
std::string getBytecodeInformation()
Get bytecode information for debugging.
void log(const Value &msg)
Log a Value to stdout.
void flush()
Flush stdout.
std::pmr::vector< Value > stack
bool isError
Is status an error code.
void cleanup()
Clean up the virtual machine.
size_t pc
Program counter.
void push(const Value &value)
Push a value onto the stack.
int run(const Bytecode &bytecode, const size_t startPC=0)
Run the virtual machine Exits -1 on uncaught exception.
void initFFI(const std::filesystem::path &path)
Initialize the FFI plugins.
std::map< std::string, NativeFunction > nativeFunctions
Native function registry.
const Bytecode * m_bytecode
Bytecode to execute.
void setup(const Bytecode &bc, const size_t initialPC)
std::pmr::monotonic_buffer_resource stack_pool
Stack.
Value peek()
Peek at the top value on the stack.
void flusherr()
Flush stderr.
Value runFunction(const std::string &name, const Bytecode &bytecode, const bool &argsInit=false)
Run a function from bytecode on the virtual machine.
void reset(const bool &resetStack=true, const bool &resetFunctions=true, const bool &resetVariables=true)
Reset the virtual machine.
std::string getInformation()
Get VM information for debugging.
A value in the Phasor VM.
bool isInt() const noexcept
i64 asInt() const noexcept
Get the value as an integer.
The Phasor Programming Language and Runtime.
std::string opCodeToString(OpCode op)
Complete bytecode structure.
std::unordered_map< std::string, int > functionEntries
Function name -> instruction index mapping.