-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbytecode.h
153 lines (114 loc) · 4.19 KB
/
bytecode.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Fn Bytecode is the intermediate representation of Fn programs.
// It is generated by the code generator and executed by the
// virtual machine.
#pragma once
#include <cstdint> // uintXX_t
#include <vector> // std::vector
#include <array> // std::array
#include <initializer_list> // std::initializer_list
#include <functional> // std::hash<std::string>
#include "src/number.h"
namespace fn { namespace bytecode {
// The smallest unit of instruction.
// (Note that instructions are at least this size,
// but are usually more.)
typedef char CodeByte;
// The first byte of any instruction is an OpCode.
// It tells the VM the operation to perform.
typedef CodeByte OpCode;
#define FN_OP_FALSE (fn::bytecode::OpCode)(0)
#define FN_OP_TRUE (fn::bytecode::OpCode)(1)
#define FN_OP_AND (fn::bytecode::OpCode)(2)
#define FN_OP_OR (fn::bytecode::OpCode)(3)
#define FN_OP_NOT (fn::bytecode::OpCode)(4)
#define FN_OP_NUMBER (fn::bytecode::OpCode)(10)
#define FN_OP_MULTIPLY (fn::bytecode::OpCode)(11)
#define FN_OP_DIVIDE (fn::bytecode::OpCode)(12)
#define FN_OP_ADD (fn::bytecode::OpCode)(13)
#define FN_OP_SUBTRACT (fn::bytecode::OpCode)(14)
#define FN_OP_DEF (fn::bytecode::OpCode)(20)
#define FN_OP_CALL (fn::bytecode::OpCode)(21)
#define FN_OP_RETURN_LAST (fn::bytecode::OpCode)(22)
#define FN_OP_STRING (fn::bytecode::OpCode)(30)
#define FN_OP_EQ (fn::bytecode::OpCode)(40)
#define FN_OP_NAME (fn::bytecode::OpCode)(50)
#define FN_OP_LOAD (fn::bytecode::OpCode)(51)
#define FN_OP_FALSE_JUMP (fn::bytecode::OpCode)(60)
#define FN_OP_NEW_FRAME (fn::bytecode::OpCode)(70)
#define FN_OP_COMPRESS (fn::bytecode::OpCode)(71)
#define FN_OP_EXPAND (fn::bytecode::OpCode)(72)
// Instruction references are given by this type.
// TODO: Expand to 32-bit.
typedef CodeByte InstructionIndex;
#define INSTRUCTION_INDEX_BYTES (1)
#define MAX_INSTRUCTIONS (UINT8_MAX)
// Names are given by hashes.
typedef CodeByte NameHash;
#define NAME_HASH_BYTES (1)
// Type for specifying the number of arguments in a function.
// If you ever need more than 255, try something else.
typedef CodeByte NumArgs;
#define NUM_ARGS_BYTES (1)
NameHash hashName(std::string name);
// A CodeBlob is a contiguous list of CodeBytes.
class CodeBlob {
private:
std::vector<CodeByte> bytes;
public:
CodeBlob() {
this->bytes = std::vector<CodeByte>{};
}
CodeBlob(std::initializer_list<CodeByte> bytes) {
this->bytes = std::vector<CodeByte>(bytes);
}
// Special constructor taking a list of CodeBlobs.
// Stores the concatenation of all given CodeBlobs.
CodeBlob(std::initializer_list<CodeBlob> blobs) : CodeBlob() {
for (auto argBlob : blobs) {
this->append(argBlob);
}
}
// Create a CodeBlob from an array.
template<size_t S>
CodeBlob(std::array<CodeByte, S> bytes) {
this->bytes = std::vector<CodeByte>(bytes.begin(), bytes.end());
}
// Copies one blob to the end of another.
void append(CodeBlob blob) {
this->bytes.reserve(blob.size());
this->bytes.insert(this->bytes.end(), blob.bytes.begin(), blob.bytes.end());
}
void append(CodeByte byte) {
this->bytes.push_back(byte);
}
// Use asBytes() and size() to work with the bytes directly
// as a C-array.
CodeByte* asBytes() { return this->bytes.data(); }
size_t size() const { return this->bytes.size(); }
};
// Instruction Generators
CodeBlob iFalse();
CodeBlob iTrue();
CodeBlob iAnd();
CodeBlob iOr();
CodeBlob iNot();
CodeBlob iNumber(Number number);
CodeBlob iNumber(Coefficient coefficient, Exponent exponent);
CodeBlob iMultiply();
CodeBlob iDivide();
CodeBlob iAdd();
CodeBlob iSubtract();
CodeBlob iDefHeader(InstructionIndex length, std::vector<std::string> argList);
CodeBlob iDefHeader(InstructionIndex length, std::vector<NameHash> argList);
CodeBlob iCall();
CodeBlob iReturnLast();
CodeBlob iEq();
CodeBlob iName(std::string name);
CodeBlob iName(NameHash hash);
CodeBlob iLoad(std::string name);
CodeBlob iLoad(NameHash hash);
CodeBlob iJumpIfLastFalse(InstructionIndex jump);
CodeBlob iNewFrame();
CodeBlob iCompress();
CodeBlob iExpand();
}}