Phasor 3.1.1
Stack VM based Programming Language
Loading...
Searching...
No Matches
Utility.cpp
Go to the documentation of this file.
1#ifndef CMAKE
2#include "VM.hpp"
3#endif
4#include <iostream>
5#include <stdexcept>
6#include <format>
7#include <cassert>
8#include "core/core.h"
9
10namespace Phasor
11{
12
13int VM::run(const Bytecode &bc)
14{
15 m_bytecode = &bc;
16 pc = 0;
17 stack.clear();
18 callStack.clear();
19
20#ifdef TRACING
21 log(std::format("\nVM::{}():\n\n{}\n", __func__, getBytecodeInformation()));
22 flush();
23#endif
24
25 registers.fill(Value());
26 variables.resize(m_bytecode->nextVarIndex);
27
28 while (pc < m_bytecode->instructions.size())
29 {
30 const Instruction &instr = m_bytecode->instructions[pc++];
31#ifdef TRACING
32 log(std::format("\nVM::{}(): RUN (pc={})\n", __func__, pc - 1));
33 flush();
34#endif
35 try
36 {
37 operation(instr.op, instr.operand1, instr.operand2, instr.operand3);
38 }
39 catch (const VM::Halt &)
40 {
41#ifdef TRACING
42 log(std::format("\nVM::{}(): HALT (status={})\n\n{}\n\n", __func__, status, getInformation()));
43 flush();
44#endif
45#ifdef _DEBUG
46 assert(status == 0);
47#endif
48 return status;
49 }
50 catch (const std::exception &e)
51 {
52#ifdef TRACING
53 logerr(std::format("\nVM::{}(): PANIC!\n\n{}\n{}\n\n", __func__, e.what(), getInformation()));
54 flusherr();
55#endif
56 status = 1;
57#ifdef _DEBUG
58 logerr(std::format("{}\n", e.what()));
59 assert(false);
60#endif
61 throw;
62 }
63 }
64 return -1;
65}
66
68{
69#ifdef TRACING
70 log(std::format("VM::{}()\n", __func__));
71 flush();
72#endif
73 importHandler = handler;
74}
75
77#ifdef TRACING
78 log(std::format("VM::{}()\n", __func__));
79 flush();
80#endif
81 for (auto &i : registers) { i = Value(); }
82 for (auto &i : variables) { i = Value(); }
83 flush();
84 flusherr();
85 reset(true, true, true);
86}
87
88void VM::reset(const bool &resetStack, const bool &resetFunctions, const bool &resetVariables)
89{
90#ifdef TRACING
91 log(std::format("VM::{}()\n", __func__));
92 flush();
93#endif
94 if (resetStack)
95 {
96 stack.clear();
97 callStack.clear();
98 }
99 if (resetFunctions)
100 {
101 nativeFunctions.clear();
102 }
103 if (resetVariables)
104 {
105 variables.clear();
106 }
107 pc = 0;
108 m_bytecode = nullptr;
109}
110
112{
113 int callStackTop = callStack.empty() ? -1 : callStack.back();
114 std::string info;
115
116 if (!stack.empty())
117 info = std::format("Stack Top: {:T}\n", peek());
118
119 std::string registersStr;
120 int regCount = 0;
121
122 for (const auto &reg : registers)
123 {
124 if (reg.getType() != ValueType::Null) {
125 registersStr += std::format("R{}: {:T}\n", regCount, reg);
126 }
127 regCount++;
128 }
129
130 info += std::format(
131 "VM INFORMATION:\n{}PC: {}\nCS: {}",
132 registersStr,
133 pc,
134 callStackTop
135 );
136
137 return info;
138}
139
141{
142 std::string info;
143 std::string constants;
144 std::string variables;
145 std::string functions;
146 std::string instructions;
147
148 for (const auto &constant : m_bytecode->constants)
149 {
150 constants += std::format("{:T}\n", constant);
151 }
152 for (const auto &variable : m_bytecode->variables)
153 {
154 variables += std::format("{}\n", variable.first);
155 }
156 for (const auto &function : m_bytecode->functionEntries)
157 {
158 functions += std::format("{}() PC = {}\n", function.first, function.second);
159 }
160#ifdef TRACING
161 for (const auto &instruction : m_bytecode->instructions)
162 {
163 instructions += std::format("{}({}, {}, {})\n", opCodeToString(instruction.op), instruction.operand1,
164 instruction.operand2, instruction.operand3);
165 }
166#endif
167
168 info = std::format("BYTECODE INFORMATION:\n\nConstants: {}\n{}\nVariables: {}\n{}\nFunctions: {}\n{}\nInstructions: {}\n{}",
169 m_bytecode->constants.size(), constants,
170 m_bytecode->variables.size(), variables,
171 m_bytecode->functionEntries.size(), functions,
172 m_bytecode->instructions.size(), instructions);
173 return info;
174}
175
176void VM::log(const Value &msg)
177{
178 std::string s = msg.toString();
179 asm_print_stdout(s.c_str(), (int64_t)s.length());
180}
181
182void VM::logerr(const Value &msg)
183{
184 std::string s = msg.toString();
185 asm_print_stderr(s.c_str(), (int64_t)s.length());
186}
187
189{
190 fflush(stdout);
191}
192
194{
195 fflush(stderr);
196}
197} // namespace Phasor
void asm_print_stdout(const char *s, int64_t len)
Native print function.
Definition IO.c:100
void asm_print_stderr(const char *s, int64_t len)
Native print error function.
Definition IO.c:106
Throws when the HALT opcode is reached.
Definition VM.hpp:75
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
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
std::vector< int > callStack
Call stack for function calls.
Definition VM.hpp:267
std::map< std::string, NativeFunction > nativeFunctions
Native function registry.
Definition VM.hpp:279
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
void flush()
Flush stdout.
Definition Utility.cpp:188
void cleanup()
Clean up the virtual machine.
Definition Utility.cpp:76
size_t pc
Program counter.
Definition VM.hpp:276
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 peek()
Peek at the top value on the stack.
Definition Stack.cpp:38
void flusherr()
Flush stderr.
Definition Utility.cpp:193
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
std::string getInformation()
Get VM information for debugging.
Definition Utility.cpp:111
A value in the Phasor VM.
Definition Value.hpp:67
std::string toString() const
Convert to string for printing.
Definition Value.hpp:415
The Phasor Programming Language and Runtime.
Definition AST.hpp:11
std::string opCodeToString(OpCode op)
Definition map.cpp:126
Complete bytecode structure.
Definition CodeGen.hpp:47
Instruction with up to 5 operands Format: instruction operand1, operand2, operand3 Each instruction u...
Definition CodeGen.hpp:18
int32_t operand1
First operand.
Definition CodeGen.hpp:20
int32_t operand2
Second operand.
Definition CodeGen.hpp:21
int32_t operand3
Third operand.
Definition CodeGen.hpp:22
OpCode op
Operation code.
Definition CodeGen.hpp:19