-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbrainfuckvm.h
102 lines (92 loc) · 2.03 KB
/
brainfuckvm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#ifndef H_BRAINFUCKVM
#define H_BRAINFUCKVM
#include <iostream>
#include "registermanager.h"
#include "parser.h"
#include "jit.h"
namespace Brainfuck {
template <typename T>
class BrainfuckVM {
public:
constexpr BrainfuckVM(std::ostream &ostream, std::istream &istream, bool jit) noexcept : regs(ostream, istream), jit(jit) {}
void doAction(char a, int times = 1) noexcept {
#ifdef DEBUG
std::cout << "Doing action " << a << std::endl;
#endif
regs.doAction(a, times);
}
constexpr void run(std::string_view str, ErrorCallback cb) noexcept {
parser.setString(str);
parser.parse(cb);
auto& inst = parser.getInstructions();
if (jit) {
runJIT(inst);
}
else {
runVM(inst);
}
}
RegisterManager<T> getRegisterManager() const noexcept {
return regs;
}
friend std::ostream& operator<<(std::ostream &os, BrainfuckVM const &vm) noexcept {
auto regs = vm.getRegisterManager();
os << regs;
return os;
}
private:
constexpr void runJIT(std::vector<Instruction> const &inst) noexcept {
Jit jit;
jit.init();
for (auto const &i : inst) {
if (i.a == '>') {
jit.shiftRight(i.repeat);
}
else if (i.a == '<') {
jit.shiftLeft(i.repeat);
}
else if (i.a == '+') {
jit.inc(i.repeat);
}
else if (i.a == '-') {
jit.dec(i.repeat);
}
else if (i.a == '.') {
jit.doPrint();
}
else if (i.a == ',') {
jit.doRead();
}
else if (i.a == '[') {
jit.loopStart();
}
else if (i.a == ']') {
jit.loopEnd();
}
}
jit.endFunction();
jit.execute(true);
}
void runVM(std::vector<Instruction> const &inst) noexcept {
size_t size{inst.size()};
for (size_t i = 0; i < size; ++i) {
char c = inst[i].a;
if (c == '[' && regs.getVectorCell() == 0) {
i = inst[i].val;
continue;
}
else if (c == ']' && regs.getVectorCell() != 0) {
i = inst[i].val;
continue;
}
else {
doAction(c, inst[i].repeat);
}
}
}
bool jit;
Parser parser;
RegisterManager<T> regs;
};
}
#endif