.
This commit is contained in:
@@ -3,75 +3,8 @@
|
|||||||
|
|
||||||
namespace tyche {
|
namespace tyche {
|
||||||
|
|
||||||
Bytecode::Bytecode(BytecodePrototype const& bp)
|
Bytecode::Bytecode(ByteArray ba)
|
||||||
{
|
: byte_array_(std::move(ba))
|
||||||
// constants
|
|
||||||
std::vector<uint32_t> constant_table;
|
|
||||||
ByteArray constant_array;
|
|
||||||
uint32_t idx = 0;
|
|
||||||
for (auto const& constant: bp.constants) {
|
|
||||||
constant_table.emplace_back(idx);
|
|
||||||
std::visit(overloaded {
|
|
||||||
[&](int32_t i) { constant_array.append_int(i); },
|
|
||||||
[&](float f) { constant_array.append_float(f); },
|
|
||||||
[&](std::string const& s) { constant_array.append_string(s); },
|
|
||||||
}, constant);
|
|
||||||
idx = constant_array.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// function table
|
|
||||||
std::vector<std::pair<FunctionDef, uint32_t>> functions;
|
|
||||||
ByteArray code;
|
|
||||||
for (auto const& f: bp.functions) {
|
|
||||||
functions.emplace_back(std::make_pair(FunctionDef { f.n_pars, f.n_locals }, code.size()));
|
|
||||||
code.append_bytearray(f.code);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// build binary
|
|
||||||
//
|
|
||||||
|
|
||||||
// header
|
|
||||||
byte_array_.set_uint32(0, MAGIC);
|
|
||||||
byte_array_.set_byte(4, VERSION);
|
|
||||||
|
|
||||||
// constants
|
|
||||||
idx = HEADER_SZ + INDEX_SZ;
|
|
||||||
for (auto const& const_idx: constant_table) {
|
|
||||||
byte_array_.set_uint32(idx, const_idx);
|
|
||||||
idx += 4;
|
|
||||||
}
|
|
||||||
byte_array_.append_bytearray(constant_array);
|
|
||||||
|
|
||||||
// constant index
|
|
||||||
if (!constant_table.empty()) {
|
|
||||||
byte_array_.set_uint32(HEADER_SZ, HEADER_SZ + INDEX_SZ);
|
|
||||||
byte_array_.set_uint16(HEADER_SZ + 4, constant_table.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// functions
|
|
||||||
size_t functions_start = idx + (constant_table.size() * 4) + byte_array_.size();
|
|
||||||
idx += functions_start;
|
|
||||||
uint32_t code_idx = 0;
|
|
||||||
for (auto const& f: functions) {
|
|
||||||
byte_array_.set_uint32(idx, code_idx);
|
|
||||||
byte_array_.set_uint16(idx + 4, f.first.n_params);
|
|
||||||
byte_array_.set_uint16(idx + 6, f.first.n_params);
|
|
||||||
idx += 8;
|
|
||||||
code_idx += f.second;
|
|
||||||
}
|
|
||||||
for (auto const& f: bp.functions)
|
|
||||||
byte_array_.append_bytearray(f.code);
|
|
||||||
|
|
||||||
// function index
|
|
||||||
if (!functions.empty()) {
|
|
||||||
byte_array_.set_uint32(HEADER_SZ + 6, functions_start);
|
|
||||||
byte_array_.set_uint16(HEADER_SZ + 6 + 4, functions.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bytecode::Bytecode(std::vector<uint8_t> data)
|
|
||||||
: byte_array_(std::move(data))
|
|
||||||
{
|
{
|
||||||
// check file size
|
// check file size
|
||||||
if (byte_array_.size() < (HEADER_SZ + INDEX_SZ))
|
if (byte_array_.size() < (HEADER_SZ + INDEX_SZ))
|
||||||
@@ -135,4 +68,75 @@ float Bytecode::get_code_float(uint32_t function_id, uint32_t idx) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ByteArray Bytecode::generate(BytecodePrototype const& bp)
|
||||||
|
{
|
||||||
|
ByteArray ba;
|
||||||
|
|
||||||
|
// constants
|
||||||
|
std::vector<uint32_t> constant_table;
|
||||||
|
ByteArray constant_array;
|
||||||
|
uint32_t idx = 0;
|
||||||
|
for (auto const& constant: bp.constants) {
|
||||||
|
constant_table.emplace_back(idx);
|
||||||
|
std::visit(overloaded {
|
||||||
|
[&](int32_t i) { constant_array.append_int(i); },
|
||||||
|
[&](float f) { constant_array.append_float(f); },
|
||||||
|
[&](std::string const& s) { constant_array.append_string(s); },
|
||||||
|
}, constant);
|
||||||
|
idx = constant_array.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// function table
|
||||||
|
std::vector<std::pair<FunctionDef, uint32_t>> functions;
|
||||||
|
ByteArray code;
|
||||||
|
for (auto const& f: bp.functions) {
|
||||||
|
functions.emplace_back(std::make_pair(FunctionDef { f.n_pars, f.n_locals }, code.size()));
|
||||||
|
code.append_bytearray(f.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// build binary
|
||||||
|
//
|
||||||
|
|
||||||
|
// header
|
||||||
|
ba.set_uint32(0, MAGIC);
|
||||||
|
ba.set_byte(4, VERSION);
|
||||||
|
|
||||||
|
// constants
|
||||||
|
idx = HEADER_SZ + INDEX_SZ;
|
||||||
|
for (auto const& const_idx: constant_table) {
|
||||||
|
ba.set_uint32(idx, const_idx);
|
||||||
|
idx += 4;
|
||||||
|
}
|
||||||
|
ba.append_bytearray(constant_array);
|
||||||
|
|
||||||
|
// constant index
|
||||||
|
if (!constant_table.empty()) {
|
||||||
|
ba.set_uint32(HEADER_SZ, HEADER_SZ + INDEX_SZ);
|
||||||
|
ba.set_uint16(HEADER_SZ + 4, constant_table.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// functions
|
||||||
|
size_t functions_start = idx + (constant_table.size() * 4) + ba.size();
|
||||||
|
idx += functions_start;
|
||||||
|
uint32_t code_idx = 0;
|
||||||
|
for (auto const& f: functions) {
|
||||||
|
ba.set_uint32(idx, code_idx);
|
||||||
|
ba.set_uint16(idx + 4, f.first.n_params);
|
||||||
|
ba.set_uint16(idx + 6, f.first.n_params);
|
||||||
|
idx += 8;
|
||||||
|
code_idx += f.second;
|
||||||
|
}
|
||||||
|
for (auto const& f: bp.functions)
|
||||||
|
ba.append_bytearray(f.code);
|
||||||
|
|
||||||
|
// function index
|
||||||
|
if (!functions.empty()) {
|
||||||
|
ba.set_uint32(HEADER_SZ + 6, functions_start);
|
||||||
|
ba.set_uint16(HEADER_SZ + 6 + 4, functions.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ba;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,8 +8,7 @@ namespace tyche {
|
|||||||
|
|
||||||
class Bytecode {
|
class Bytecode {
|
||||||
public:
|
public:
|
||||||
explicit Bytecode(std::vector<uint8_t> data);
|
explicit Bytecode(ByteArray ba);
|
||||||
explicit Bytecode(BytecodePrototype const& bp);
|
|
||||||
|
|
||||||
[[nodiscard]] uint32_t n_constants() const;
|
[[nodiscard]] uint32_t n_constants() const;
|
||||||
[[nodiscard]] uint32_t n_functions() const;
|
[[nodiscard]] uint32_t n_functions() const;
|
||||||
@@ -29,6 +28,8 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] std::vector<uint8_t> const& data() const { return byte_array_.data(); }
|
[[nodiscard]] std::vector<uint8_t> const& data() const { return byte_array_.data(); }
|
||||||
|
|
||||||
|
[[nodiscard]] static ByteArray generate(BytecodePrototype const& bp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ByteArray byte_array_; // the actual data
|
ByteArray byte_array_; // the actual data
|
||||||
|
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ TEST(Bytecode, Constants)
|
|||||||
0x54, 'H', 'E', 'L', 'L', 'O', 0x00
|
0x54, 'H', 'E', 'L', 'L', 'O', 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
Bytecode bc(bp);
|
ByteArray ba = Bytecode::generate(bp);
|
||||||
ASSERT_EQ(bc.data(), expected);
|
ASSERT_EQ(ba.data(), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Bytecode, Code)
|
TEST(Bytecode, Code)
|
||||||
@@ -122,6 +122,11 @@ TEST(Bytecode, Code)
|
|||||||
// code
|
// code
|
||||||
0x68, 0x54, 0x42,
|
0x68, 0x54, 0x42,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
ByteArray ba = Bytecode::generate(bp);
|
||||||
|
ASSERT_EQ(ba.data(), expected);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Bytecode, Parsing)
|
TEST(Bytecode, Parsing)
|
||||||
@@ -141,12 +146,11 @@ TEST(Bytecode, Parsing)
|
|||||||
auto& f2 = bp.functions.emplace_back(2, 1);
|
auto& f2 = bp.functions.emplace_back(2, 1);
|
||||||
f2.code.append_byte(0x42);
|
f2.code.append_byte(0x42);
|
||||||
|
|
||||||
Bytecode bc1(bp);
|
ByteArray ba = Bytecode::generate(bp);
|
||||||
auto data = bc1.data();
|
|
||||||
|
|
||||||
// read bytecode
|
// read bytecode
|
||||||
|
|
||||||
Bytecode bc2(data);
|
Bytecode bc2(std::move(ba));
|
||||||
|
|
||||||
ASSERT_EQ(bc2.n_constants(), 3);
|
ASSERT_EQ(bc2.n_constants(), 3);
|
||||||
ASSERT_EQ(bc2.n_functions(), 2);
|
ASSERT_EQ(bc2.n_functions(), 2);
|
||||||
|
|||||||
Reference in New Issue
Block a user