diff --git a/.idea/ctestState.xml b/.idea/ctestState.xml
index 1bbf61b..156f501 100644
--- a/.idea/ctestState.xml
+++ b/.idea/ctestState.xml
@@ -2,9 +2,10 @@
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1f00baf..3e1aaa7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,32 +60,34 @@ FetchContent_MakeAvailable(googletest)
add_library(lib${PROJECT_NAME} SHARED
src/common/overloaded.hh
- src/common/bytearray.hh
- src/common/bytearray.cc
- src/bytecode/bytecode.cc
- src/bytecode/bytecode.hh
- src/bytecode/bytecodeprototype.hh
- src/bytecode/constant.hh
- src/bytecode/bc_exceptions.hh
- src/assembler/lexer.cc
- src/assembler/lexer.hh
- src/assembler/assembler.cc
- src/assembler/assembler.hh
- src/assembler/as_exceptions.hh
- src/instructions/instruction.hh
- src/instructions/instruction.cc
- src/vm/code.cc
- src/vm/code.hh
- src/vm/value.cc
- src/vm/value.hh
- src/vm/stack.cc
- src/vm/stack.hh
- src/vm/vm_exceptions.hh
- src/vm/vm.cc
- src/vm/vm.hh
- src/vm/expr.cc
- src/vm/expr.hh
- src/vm/location.hh
+ src/bytearray/bytearray.hh
+ src/bytearray/bytearray.cc
+ src/bytearray/bytearraybuilder.hh
+ src/bytearray/bytearraybuilder.cc
+ #src/bytecode/bytecode.cc
+ #src/bytecode/bytecode.hh
+ #src/bytecode/bytecodeprototype.hh
+ #src/bytecode/constant.hh
+ #src/bytecode/bc_exceptions.hh
+ #src/assembler/lexer.cc
+ #src/assembler/lexer.hh
+ #src/assembler/assembler.cc
+ #src/assembler/assembler.hh
+ #src/assembler/as_exceptions.hh
+ #src/instructions/instruction.hh
+ #src/instructions/instruction.cc
+ #src/vm/code.cc
+ #src/vm/code.hh
+ #src/vm/value.cc
+ #src/vm/value.hh
+ #src/vm/stack.cc
+ #src/vm/stack.hh
+ #src/vm/vm_exceptions.hh
+ #src/vm/vm.cc
+ #src/vm/vm.hh
+ #src/vm/expr.cc
+ #src/vm/expr.hh
+ #src/vm/location.hh
)
target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings})
@@ -96,6 +98,10 @@ target_compile_options(lib${PROJECT_NAME} PRIVATE ${warnings})
enable_testing()
+add_executable(${PROJECT_NAME}-bytearray-test src/bytearray/tests.cc)
+target_link_libraries(${PROJECT_NAME}-bytearray-test lib${PROJECT_NAME} gtest_main)
+add_test(NAME tyche_bytearray_test COMMAND ${PROJECT_NAME}-bytearray-test)
+
add_executable(${PROJECT_NAME}-bytecode-test src/bytecode/tests.cc)
target_link_libraries(${PROJECT_NAME}-bytecode-test lib${PROJECT_NAME} gtest_main)
add_test(NAME tyche_bytecode_test COMMAND ${PROJECT_NAME}-bytecode-test)
@@ -104,7 +110,9 @@ add_executable(${PROJECT_NAME}-vm-test src/vm/tests.cc)
target_link_libraries(${PROJECT_NAME}-vm-test lib${PROJECT_NAME} gtest_main)
add_test(NAME tyche_vm_test COMMAND ${PROJECT_NAME}-vm-test)
-add_executable(${PROJECT_NAME}-as-test src/assembler/tests.cc)
+add_executable(${PROJECT_NAME}-as-test src/assembler/tests.cc
+ src/bytearray/bytearraybuilder.cc
+ src/bytearray/bytearraybuilder.hh)
target_link_libraries(${PROJECT_NAME}-as-test lib${PROJECT_NAME} gtest_main)
add_test(NAME tyche_as_test COMMAND ${PROJECT_NAME}-as-test)
diff --git a/src/assembler/assembler.cc b/src/assembler/assembler.cc
index f2df9a1..c2c7696 100644
--- a/src/assembler/assembler.cc
+++ b/src/assembler/assembler.cc
@@ -10,7 +10,7 @@ using namespace std::string_literals;
namespace tyche::as {
-ByteArray Assembler::assemble()
+StaticByteArray Assembler::assemble()
{
bc::BytecodePrototype bp;
diff --git a/src/assembler/assembler.hh b/src/assembler/assembler.hh
index eea7acf..f0ee57f 100644
--- a/src/assembler/assembler.hh
+++ b/src/assembler/assembler.hh
@@ -5,7 +5,7 @@
#include
#include "lexer.hh"
-#include "../common/bytearray.hh"
+#include "../bytearray/bytearray.hh"
#include "../bytecode/bytecodeprototype.hh"
namespace tyche::as {
@@ -14,7 +14,7 @@ class Assembler {
public:
explicit Assembler(std::string source) : lexer_(std::move(source) + "\n") {}
- [[nodiscard]] ByteArray assemble();
+ [[nodiscard]] StaticByteArray assemble();
private:
Lexer lexer_;
diff --git a/src/assembler/tests.cc b/src/assembler/tests.cc
index 328c731..fc79443 100644
--- a/src/assembler/tests.cc
+++ b/src/assembler/tests.cc
@@ -47,7 +47,7 @@ TEST(Assember, Assembler)
bp.functions.at(1).code.append_byte((uint8_t) Instruction::PushInt16);
bp.functions.at(1).code.append_int16(5000);
bp.functions.at(1).code.append_byte((uint8_t) Instruction::Return);
- ByteArray expected = Bytecode::generate(bp);
+ StaticByteArray expected = Bytecode::generate(bp);
std::string src = R"(
.const
@@ -64,7 +64,7 @@ TEST(Assember, Assembler)
ret
)";
- ByteArray actual = Assembler(src).assemble();
+ StaticByteArray actual = Assembler(src).assemble();
ASSERT_EQ(expected, actual);
}
diff --git a/src/bytearray/bytearray.cc b/src/bytearray/bytearray.cc
new file mode 100644
index 0000000..a261e70
--- /dev/null
+++ b/src/bytearray/bytearray.cc
@@ -0,0 +1,81 @@
+#include "bytearray.hh"
+
+#include
+#include
+
+namespace tyche {
+
+uint8_t StaticByteArray::get_byte(uint32_t addr) const
+{
+ return data_.at(addr);
+}
+
+uint16_t StaticByteArray::get_uint16(uint32_t addr) const
+{
+ return (uint32_t) get_byte(addr)
+ | (uint32_t) get_byte(addr+1) << 8;
+}
+
+uint32_t StaticByteArray::get_uint32(uint32_t addr) const
+{
+ return (uint32_t) get_byte(addr)
+ | (uint32_t) get_byte(addr+1) << 8
+ | (uint32_t) get_byte(addr+2) << 16
+ | (uint32_t) get_byte(addr+3) << 24;
+}
+
+int8_t StaticByteArray::get_int8(uint32_t addr) const
+{
+ return std::bit_cast(get_byte(addr));
+}
+
+int16_t StaticByteArray::get_int16(uint32_t addr) const
+{
+ return (uint16_t) get_byte(addr)
+ | (uint16_t) get_byte(addr+1) << 8;
+}
+
+int32_t StaticByteArray::get_int32(uint32_t addr) const
+{
+ return std::bit_cast((uint32_t) get_byte(addr)
+ | (uint32_t) get_byte(addr+1) << 8
+ | (uint32_t) get_byte(addr+2) << 16
+ | (uint32_t) get_byte(addr+3) << 24);
+}
+
+float StaticByteArray::get_float(uint32_t addr) const
+{
+ uint32_t bits = (uint32_t) get_byte(addr)
+ | (uint32_t) get_byte(addr+1) << 8
+ | (uint32_t) get_byte(addr+2) << 16
+ | (uint32_t) get_byte(addr+3) << 24;
+ float value;
+ std::memcpy(&value, &bits, 4);
+ return value;
+}
+
+std::pair StaticByteArray::get_string_ptr(uint32_t addr) const
+{
+ return { (const char *) &data_.at(addr), strlen((const char *) &data_.at(addr)) + 1 };
+}
+
+std::string StaticByteArray::hexdump() const
+{
+ auto to_hex = [](uint32_t value, size_t n_chars) -> std::string {
+ char buf[15];
+ snprintf(buf, sizeof buf, "%0*X", (int) n_chars, value);
+ return { buf };
+ };
+
+ std::string out;
+ for (size_t i = 0; i < data_.size(); ++i) {
+ if (i % 16 == 0)
+ out += to_hex(i, 4) + " | ";
+ out += to_hex(data_.at(i), 2) + " ";
+ if (i % 16 == 15)
+ out += "\n";
+ }
+ return out + "\n";
+}
+
+}
\ No newline at end of file
diff --git a/src/bytearray/bytearray.hh b/src/bytearray/bytearray.hh
new file mode 100644
index 0000000..3aee5de
--- /dev/null
+++ b/src/bytearray/bytearray.hh
@@ -0,0 +1,44 @@
+#ifndef TYCHE_BYTEARRAY_HH
+#define TYCHE_BYTEARRAY_HH
+
+#include
+#include
+#include
+#include
+
+namespace tyche {
+
+class StaticByteArray {
+public:
+ explicit StaticByteArray(std::vector const& data) : data_(data) {}
+
+ explicit StaticByteArray(StaticByteArray const& ba) : data_(ba.data()) {}
+
+ // not assignable or moveable
+ StaticByteArray(StaticByteArray&&) = delete;
+ StaticByteArray& operator=(StaticByteArray const&) = delete;
+ StaticByteArray& operator=(StaticByteArray&&) = delete;
+
+ [[nodiscard]] uint8_t get_byte(uint32_t addr) const;
+ [[nodiscard]] uint16_t get_uint16(uint32_t addr) const;
+ [[nodiscard]] uint32_t get_uint32(uint32_t addr) const;
+ [[nodiscard]] int8_t get_int8(uint32_t addr) const;
+ [[nodiscard]] int16_t get_int16(uint32_t addr) const;
+ [[nodiscard]] int32_t get_int32(uint32_t addr) const;
+ [[nodiscard]] float get_float(uint32_t addr) const;
+ [[nodiscard]] std::pair get_string_ptr(uint32_t addr) const;
+
+ [[nodiscard]] std::vector const& data() const { return data_; }
+ [[nodiscard]] size_t size() const { return data_.size(); }
+
+ [[nodiscard]] std::string hexdump() const;
+
+ friend bool operator==(StaticByteArray const& lhs, StaticByteArray const& rhs) { return lhs.data_ == rhs.data_; }
+
+private:
+ const std::vector data_ {};
+};
+
+}
+
+#endif //TYCHE_BYTEARRAY_HH
diff --git a/src/bytearray/bytearraybuilder.cc b/src/bytearray/bytearraybuilder.cc
new file mode 100644
index 0000000..a2bf660
--- /dev/null
+++ b/src/bytearray/bytearraybuilder.cc
@@ -0,0 +1,88 @@
+#include "bytearraybuilder.hh"
+
+namespace tyche {
+
+ByteArrayBuilder& ByteArrayBuilder::set_byte(uint32_t addr, uint8_t byte)
+{
+ if (data_.size() < (addr + 1))
+ data_.resize(addr + 1, 0);
+ data_.at(addr) = byte;
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::set_int8(uint32_t addr, int8_t value)
+{
+ set_byte(addr, (uint8_t) value);
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::set_int16(uint32_t addr, int16_t value)
+{
+ set_byte(addr, (uint8_t) (value));
+ set_byte(addr+1, (uint8_t) (value >> 8));
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::set_int32(uint32_t addr, int32_t value)
+{
+ set_byte(addr, (uint8_t) (value));
+ set_byte(addr+1, (uint8_t) (value >> 8));
+ set_byte(addr+2, (uint8_t) (value >> 16));
+ set_byte(addr+3, (uint8_t) (value >> 24));
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::set_uint16(uint32_t addr, uint16_t value)
+{
+ set_byte(addr, (uint8_t) (value));
+ set_byte(addr+1, (uint8_t) (value >> 8));
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::set_uint32(uint32_t addr, uint32_t value)
+{
+ set_byte(addr, (uint8_t) (value));
+ set_byte(addr+1, (uint8_t) (value >> 8));
+ set_byte(addr+2, (uint8_t) (value >> 16));
+ set_byte(addr+3, (uint8_t) (value >> 24));
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::set_float(uint32_t addr, float value)
+{
+ uint32_t bits;
+ std::memcpy(&bits, &value, 4);
+ set_byte(addr, (uint8_t) (bits));
+ set_byte(addr+1, (uint8_t) (bits >> 8));
+ set_byte(addr+2, (uint8_t) (bits >> 16));
+ set_byte(addr+3, (uint8_t) (bits >> 24));
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::set_string(uint32_t addr, std::string const& str)
+{
+ for (uint8_t c: str)
+ set_byte(addr++, c);
+ set_byte(addr, 0);
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::set_bytearray(uint32_t addr, ByteArrayBuilder const& bytearray)
+{
+ for (uint8_t byte: bytearray.data_)
+ set_byte(addr++, byte);
+ return *this;
+}
+
+ByteArrayBuilder& ByteArrayBuilder::append_bytearray(ByteArrayBuilder const& bytearray)
+{
+ data_.insert(data_.end(), bytearray.data_.begin(), bytearray.data_.end());
+ return *this;
+}
+
+StaticByteArray ByteArrayBuilder::build() const
+{
+ return StaticByteArray(data_);
+}
+
+}
diff --git a/src/bytearray/bytearraybuilder.hh b/src/bytearray/bytearraybuilder.hh
new file mode 100644
index 0000000..b05f4ba
--- /dev/null
+++ b/src/bytearray/bytearraybuilder.hh
@@ -0,0 +1,45 @@
+#ifndef TYCHE_BYTEARRAYBUILDER_HH
+#define TYCHE_BYTEARRAYBUILDER_HH
+
+#include
+#include
+#include
+
+#include "bytearray.hh"
+
+namespace tyche {
+
+class ByteArrayBuilder {
+public:
+ ByteArrayBuilder& set_byte(uint32_t addr, uint8_t byte);
+ ByteArrayBuilder& set_uint16(uint32_t addr, uint16_t value);
+ ByteArrayBuilder& set_uint32(uint32_t addr, uint32_t value);
+ ByteArrayBuilder& set_int8(uint32_t addr, int8_t value);
+ ByteArrayBuilder& set_int16(uint32_t addr, int16_t value);
+ ByteArrayBuilder& set_int32(uint32_t addr, int32_t value);
+ ByteArrayBuilder& set_float(uint32_t addr, float value);
+ ByteArrayBuilder& set_string(uint32_t addr, std::string const& str);
+ ByteArrayBuilder& set_bytearray(uint32_t addr, ByteArrayBuilder const& bytearray);
+
+ ByteArrayBuilder& append_byte(uint8_t byte) { set_byte(data_.size(), byte); return *this; }
+ ByteArrayBuilder& append_uint16(uint16_t value) { set_uint16(data_.size(), value); return *this; }
+ ByteArrayBuilder& append_uint32(uint32_t value) { set_uint32(data_.size(), value); return *this; }
+ ByteArrayBuilder& append_int8(int8_t value) { set_int8(data_.size(), value); return *this; }
+ ByteArrayBuilder& append_int16(int16_t value) { set_int16(data_.size(), value); return *this; }
+ ByteArrayBuilder& append_int32(int32_t value) { set_int32(data_.size(), value); return *this; }
+ ByteArrayBuilder& append_float(float value) { set_float(data_.size(), value); return *this; }
+ ByteArrayBuilder& append_string(std::string const& str) { set_string(data_.size(), str); return *this; }
+ ByteArrayBuilder& append_bytearray(ByteArrayBuilder const& bytearray);
+
+ [[nodiscard]] std::vector const& data() const { return data_; }
+ [[nodiscard]] size_t size() const { return data_.size(); }
+
+ [[nodiscard]] StaticByteArray build() const;
+
+private:
+ std::vector data_ {};
+};
+
+}
+
+#endif //TYCHE_BYTEARRAYBUILDER_HH
diff --git a/src/bytearray/tests.cc b/src/bytearray/tests.cc
new file mode 100644
index 0000000..8ba9bd8
--- /dev/null
+++ b/src/bytearray/tests.cc
@@ -0,0 +1,51 @@
+#include "gtest/gtest.h"
+
+#include
+#include
+
+#include "bytearray.hh"
+#include "bytearraybuilder.hh"
+
+using namespace tyche;
+
+TEST(StaticByteArray, StaticByteArray)
+{
+ auto test = [](std::function const& f, std::vector const& expected) {
+ ByteArrayBuilder ba;
+ f(ba);
+ ASSERT_EQ(ba.data().size(), expected.size());
+ ASSERT_EQ(std::memcmp(ba.data().data(), expected.data(), ba.data().size()), 0);
+ };
+
+#define TESTX(a, ...) test([](ByteArrayBuilder& ba) { a; }, std::vector({ __VA_ARGS__ }));
+
+ TESTX(ba.set_byte(1, 0xab), 0x00, 0xab)
+
+ ByteArrayBuilder ba;
+ { auto b = ba.set_byte(1, 0xab).build(); ASSERT_EQ(b.get_byte(1), 0xab); }
+
+ { auto b = ba.set_int8(1, 12).build(); ASSERT_EQ(b.get_int8(1), 12); }
+ { auto b = ba.set_int8(1, -12).build(); ASSERT_EQ(b.get_int8(1), -12); }
+ { auto b = ba.set_int16(1, 5000).build(); ASSERT_EQ(b.get_int16(1), 5000); }
+ { auto b = ba.set_int32(1, 5000300).build(); ASSERT_EQ(b.get_int32(1), 5000300); }
+ { auto b = ba.set_int32(1, -5000300).build(); ASSERT_EQ(b.get_int32(1), -5000300); }
+
+ { auto b = ba.set_float(1, 3.14).build(); ASSERT_FLOAT_EQ(b.get_float(1), 3.14); }
+ { auto b = ba.set_float(1, -3.14).build(); ASSERT_FLOAT_EQ(b.get_float(1), -3.14); }
+ { auto b = ba.set_float(1, -5000300.1324).build(); ASSERT_FLOAT_EQ(b.get_float(1), -5000300.1324); }
+
+ {
+ auto b = ba.set_string(1, "Hello world!").build();
+ auto str = b.get_string_ptr(1);
+ EXPECT_STREQ(str.first, "Hello world!");
+ ASSERT_EQ(str.second, 13);
+ }
+
+#undef TESTX
+}
+
+int main(int argc, char** argv)
+{
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/src/bytecode/bytecode.cc b/src/bytecode/bytecode.cc
index b8554d1..fe21a6b 100644
--- a/src/bytecode/bytecode.cc
+++ b/src/bytecode/bytecode.cc
@@ -5,29 +5,29 @@
namespace tyche::bc {
-Bytecode::Bytecode(ByteArray ba)
- : byte_array_(std::move(ba))
+Bytecode::Bytecode(StaticByteArray const* ba)
+ : byte_array_(ba)
{
// check file size
- if (byte_array_.size() < (TOC_START + TOC_SZ))
+ if (byte_array_->size() < (TOC_START + TOC_SZ))
throw BytecodeParsingError("Invalid bytecode format (file too short)");
// check magic number and version
- if (byte_array_.get_uint32(0) != MAGIC_NUMBER)
+ if (byte_array_->get_uint32(0) != MAGIC_NUMBER)
throw BytecodeParsingError("Invalid bytecode format (magic number not matching)");
- if (byte_array_.get_uint32(4) != BYTECODE_VERSION)
+ if (byte_array_->get_uint32(4) != BYTECODE_VERSION)
throw BytecodeParsingError("Unexpected bytecode format version");
// load cache
- cache_.constants_idx_addr = byte_array_.get_uint32(TOC_START);
- cache_.n_constants = byte_array_.get_uint16(TOC_START + 4);
- cache_.functions_idx_addr = byte_array_.get_uint32(TOC_START + (1 * TOC_RECORD_SZ));
- cache_.n_functions = byte_array_.get_uint16(TOC_START + (1 * TOC_RECORD_SZ) + 4);
- cache_.constants_start_addr = byte_array_.get_uint32(TOC_START + (2 * TOC_RECORD_SZ));
- uint32_t code_start = byte_array_.get_uint32(TOC_START + (3 * TOC_RECORD_SZ));
+ cache_.constants_idx_addr = byte_array_->get_uint32(TOC_START);
+ cache_.n_constants = byte_array_->get_uint16(TOC_START + 4);
+ cache_.functions_idx_addr = byte_array_->get_uint32(TOC_START + (1 * TOC_RECORD_SZ));
+ cache_.n_functions = byte_array_->get_uint16(TOC_START + (1 * TOC_RECORD_SZ) + 4);
+ cache_.constants_start_addr = byte_array_->get_uint32(TOC_START + (2 * TOC_RECORD_SZ));
+ uint32_t code_start = byte_array_->get_uint32(TOC_START + (3 * TOC_RECORD_SZ));
for (uint32_t i = 0; i < cache_.n_functions; ++i) {
- cache_.function_addr.emplace_back(code_start + byte_array_.get_uint32(cache_.functions_idx_addr + (i * FUNCTION_RECORD_SZ)));
- cache_.function_sz.emplace_back(byte_array_.get_uint32(cache_.functions_idx_addr + (i * FUNCTION_RECORD_SZ) + 8));
+ cache_.function_addr.emplace_back(code_start + byte_array_->get_uint32(cache_.functions_idx_addr + (i * FUNCTION_RECORD_SZ)));
+ cache_.function_sz.emplace_back(byte_array_->get_uint32(cache_.functions_idx_addr + (i * FUNCTION_RECORD_SZ) + 8));
}
}
@@ -43,12 +43,12 @@ uint32_t Bytecode::n_functions() const
ConstantValue Bytecode::get_constant(uint32_t idx) const
{
- uint32_t constant_idx = byte_array_.get_uint32(cache_.constants_idx_addr + (idx * CONST_RECORD_SZ));
- switch ((ConstantType) byte_array_.get_byte(cache_.constants_start_addr + constant_idx)) {
+ uint32_t constant_idx = byte_array_->get_uint32(cache_.constants_idx_addr + (idx * CONST_RECORD_SZ));
+ switch ((ConstantType) byte_array_->get_byte(cache_.constants_start_addr + constant_idx)) {
case CONST_TYPE_FLOAT:
- return byte_array_.get_float(cache_.constants_start_addr + constant_idx + 1);
+ return byte_array_->get_float(cache_.constants_start_addr + constant_idx + 1);
case CONST_TYPE_STRING:
- return byte_array_.get_string_ptr(cache_.constants_start_addr + constant_idx + 1).first;
+ return byte_array_->get_string_ptr(cache_.constants_start_addr + constant_idx + 1).first;
default:
throw BytecodeParsingError("Invalid bytecode format (invalid constant type)");
}
@@ -58,8 +58,8 @@ Bytecode::FunctionDef Bytecode::get_function_def(uint32_t function_id) const
{
uint32_t idx = cache_.functions_idx_addr + (function_id * FUNCTION_RECORD_SZ);
return {
- .n_params = byte_array_.get_uint16(idx + 4),
- .locals = byte_array_.get_uint16(idx + 6),
+ .n_params = byte_array_->get_uint16(idx + 4),
+ .locals = byte_array_->get_uint16(idx + 6),
};
}
@@ -70,34 +70,34 @@ uint32_t Bytecode::get_function_sz(uint32_t function_id) const
uint8_t Bytecode::get_code_byte(uint32_t function_id, uint32_t idx) const
{
- return byte_array_.get_byte(cache_.function_addr.at(function_id) + idx);
+ return byte_array_->get_byte(cache_.function_addr.at(function_id) + idx);
}
int8_t Bytecode::get_code_int8(uint32_t function_id, uint32_t idx) const
{
- return byte_array_.get_int8(cache_.function_addr.at(function_id) + idx);
+ return byte_array_->get_int8(cache_.function_addr.at(function_id) + idx);
}
int16_t Bytecode::get_code_int16(uint32_t function_id, uint32_t idx) const
{
- return byte_array_.get_int16(cache_.function_addr.at(function_id) + idx);
+ return byte_array_->get_int16(cache_.function_addr.at(function_id) + idx);
}
int32_t Bytecode::get_code_int32(uint32_t function_id, uint32_t idx) const
{
- return byte_array_.get_int32(cache_.function_addr.at(function_id) + idx);
+ return byte_array_->get_int32(cache_.function_addr.at(function_id) + idx);
}
-ByteArray Bytecode::generate(BytecodePrototype const& bp)
+StaticByteArray Bytecode::generate(BytecodePrototype const& bp)
{
// header section
- ByteArray header;
+ ByteArrayBuilder header;
header.set_uint32(0, MAGIC_NUMBER);
header.set_byte(4, BYTECODE_VERSION);
// constants
- ByteArray constant_indexes;
- ByteArray raw_constants;
+ ByteArrayBuilder constant_indexes;
+ ByteArrayBuilder raw_constants;
uint32_t idx = 0;
for (auto const& constant: bp.constants) {
@@ -116,8 +116,8 @@ ByteArray Bytecode::generate(BytecodePrototype const& bp)
}
// functions
- ByteArray functions_indexes;
- ByteArray raw_code;
+ ByteArrayBuilder functions_indexes;
+ ByteArrayBuilder raw_code;
uint32_t idx_idx = 0, code_idx = 0;
for (auto const& f: bp.functions) {
@@ -135,7 +135,7 @@ ByteArray Bytecode::generate(BytecodePrototype const& bp)
uint32_t raw_constant_start = function_idx_start + functions_indexes.size();
uint32_t raw_code_start = raw_constant_start + raw_constants.size();
- ByteArray toc;
+ ByteArrayBuilder toc;
if (!bp.constants.empty()) {
toc.set_uint32(SEC_CONST_IDX * TOC_RECORD_SZ, CONST_IDX_START);
toc.set_uint32(SEC_CONST_IDX * TOC_RECORD_SZ + 4, constant_indexes.size() / CONST_RECORD_SZ);
@@ -153,14 +153,14 @@ ByteArray Bytecode::generate(BytecodePrototype const& bp)
// assemble bytecode
//
- ByteArray ba;
+ ByteArrayBuilder ba;
ba.set_bytearray(0, header);
ba.set_bytearray(TOC_START, toc);
ba.set_bytearray(CONST_IDX_START, constant_indexes);
ba.set_bytearray(function_idx_start, functions_indexes);
ba.set_bytearray(raw_constant_start, raw_constants);
ba.set_bytearray(raw_code_start, raw_code);
- return ba;
+ return ba.build();
}
}
\ No newline at end of file
diff --git a/src/bytecode/bytecode.hh b/src/bytecode/bytecode.hh
index 5835ab8..55fd0d1 100644
--- a/src/bytecode/bytecode.hh
+++ b/src/bytecode/bytecode.hh
@@ -1,7 +1,7 @@
#ifndef TYCHE_BYTECODE_HH
#define TYCHE_BYTECODE_HH
-#include "../common/bytearray.hh"
+#include "../bytearray/bytearray.hh"
#include "bytecodeprototype.hh"
#include "constant.hh"
@@ -9,8 +9,7 @@ namespace tyche::bc {
class Bytecode {
public:
- Bytecode() = default;
- explicit Bytecode(ByteArray ba);
+ explicit Bytecode(StaticByteArray const* ba);
[[nodiscard]] uint32_t n_constants() const;
[[nodiscard]] uint32_t n_functions() const;
@@ -28,10 +27,10 @@ public:
// TODO - debugging info
- [[nodiscard]] static ByteArray generate(BytecodePrototype const& bp);
+ [[nodiscard]] static StaticByteArray generate(BytecodePrototype const& bp);
private:
- ByteArray byte_array_; // the actual data
+ StaticByteArray const* byte_array_; // the actual data
static constexpr uint8_t BYTECODE_VERSION = 1;
static constexpr uint32_t MAGIC_NUMBER = 0x74b3c138;
diff --git a/src/bytecode/bytecodeprototype.hh b/src/bytecode/bytecodeprototype.hh
index 908bb2f..562627e 100644
--- a/src/bytecode/bytecodeprototype.hh
+++ b/src/bytecode/bytecodeprototype.hh
@@ -5,17 +5,17 @@
#include
#include
#include
-#include "../common/bytearray.hh"
+#include "../bytearray/bytearraybuilder.hh"
namespace tyche::bc {
struct BytecodePrototype {
struct Function {
- uint16_t n_pars;
- uint16_t n_locals;
- ByteArray code {};
+ uint16_t n_pars;
+ uint16_t n_locals;
+ ByteArrayBuilder code {};
- Function(uint16_t n_pars_, uint16_t n_locals_) : n_pars(n_pars_), n_locals(n_locals_), code(ByteArray {}) {}
+ Function(uint16_t n_pars_, uint16_t n_locals_) : n_pars(n_pars_), n_locals(n_locals_), code(ByteArrayBuilder {}) {}
};
using ConstantValue = std::variant;
diff --git a/src/bytecode/tests.cc b/src/bytecode/tests.cc
index fa02e34..6cae72b 100644
--- a/src/bytecode/tests.cc
+++ b/src/bytecode/tests.cc
@@ -3,43 +3,46 @@
#include
#include
-#include "../common/bytearray.hh"
+#include "../bytearray/bytearray.hh"
+#include "../bytearray/bytearraybuilder.hh"
#include "bytecodeprototype.hh"
#include "bytecode.hh"
using namespace tyche;
using namespace tyche::bc;
-TEST(ByteArray, ByteArray)
+TEST(StaticByteArray, StaticByteArray)
{
- auto test = [](std::function const& f, std::vector const& expected) {
- ByteArray ba;
+ auto test = [](std::function const& f, std::vector const& expected) {
+ ByteArrayBuilder ba;
f(ba);
ASSERT_EQ(ba.data().size(), expected.size());
ASSERT_EQ(std::memcmp(ba.data().data(), expected.data(), ba.data().size()), 0);
};
-#define TESTX(a, ...) test([](ByteArray& ba) { a; }, std::vector({ __VA_ARGS__ }));
+#define TESTX(a, ...) test([](ByteArrayBuilder& ba) { a; }, std::vector({ __VA_ARGS__ }));
TESTX(ba.set_byte(1, 0xab), 0x00, 0xab)
- ByteArray ba;
- ba.set_byte(1, 0xab); ASSERT_EQ(ba.get_byte(1), 0xab);
+ ByteArrayBuilder ba;
+ { auto b = ba.set_byte(1, 0xab).build(); ASSERT_EQ(b.get_byte(1), 0xab); }
- ba.set_int8(1, 12); ASSERT_EQ(ba.get_int8(1), 12);
- ba.set_int8(1, -12); ASSERT_EQ(ba.get_int8(1), -12);
- ba.set_int16(1, 5000); ASSERT_EQ(ba.get_int16(1), 5000);
- ba.set_int32(1, 5000300); ASSERT_EQ(ba.get_int32(1), 5000300);
- ba.set_int32(1, -5000300); ASSERT_EQ(ba.get_int32(1), -5000300);
+ { auto b = ba.set_int8(1, 12).build(); ASSERT_EQ(b.get_int8(1), 12); }
+ { auto b = ba.set_int8(1, -12).build(); ASSERT_EQ(b.get_int8(1), -12); }
+ { auto b = ba.set_int16(1, 5000).build(); ASSERT_EQ(b.get_int16(1), 5000); }
+ { auto b = ba.set_int32(1, 5000300).build(); ASSERT_EQ(b.get_int32(1), 5000300); }
+ { auto b = ba.set_int32(1, -5000300).build(); ASSERT_EQ(b.get_int32(1), -5000300); }
- ba.set_float(1, 3.14); ASSERT_FLOAT_EQ(ba.get_float(1), 3.14);
- ba.set_float(1, -3.14); ASSERT_FLOAT_EQ(ba.get_float(1), -3.14);
- ba.set_float(1, -5000300.1324); ASSERT_FLOAT_EQ(ba.get_float(1), -5000300.1324);
+ { auto b = ba.set_float(1, 3.14).build(); ASSERT_FLOAT_EQ(b.get_float(1), 3.14); }
+ { auto b = ba.set_float(1, -3.14).build(); ASSERT_FLOAT_EQ(b.get_float(1), -3.14); }
+ { auto b = ba.set_float(1, -5000300.1324).build(); ASSERT_FLOAT_EQ(b.get_float(1), -5000300.1324); }
- ba.set_string(1, "Hello world!");
- auto str = ba.get_string_ptr(1);
- EXPECT_STREQ(str.first, "Hello world!");
- ASSERT_EQ(str.second, 13);
+ {
+ auto b = ba.set_string(1, "Hello world!").build();
+ auto str = b.get_string_ptr(1);
+ EXPECT_STREQ(str.first, "Hello world!");
+ ASSERT_EQ(str.second, 13);
+ }
#undef TESTX
}
@@ -76,7 +79,7 @@ TEST(Bytecode, Constants)
CONST_TYPE_STRING, 'H', 'E', 'L', 'L', 'O', 0x00
};
- ByteArray ba = Bytecode::generate(bp);
+ StaticByteArray ba = Bytecode::generate(bp);
ASSERT_EQ(ba.data(), expected);
}
@@ -115,7 +118,7 @@ TEST(Bytecode, Code)
0x68, 42, 0x42,
};
- ByteArray ba = Bytecode::generate(bp);
+ StaticByteArray ba = Bytecode::generate(bp);
ASSERT_EQ(ba.data(), expected);
}
@@ -135,12 +138,12 @@ TEST(Bytecode, Parsing)
auto& ff = bp.functions.emplace_back(2, 1);
ff.code.append_byte(0x42);
- ByteArray ba = Bytecode::generate(bp);
+ StaticByteArray ba = Bytecode::generate(bp);
// print(ba.data());
// read bytecode
- Bytecode bc(std::move(ba));
+ Bytecode bc(&ba);
ASSERT_EQ(bc.n_constants(), 2);
ASSERT_EQ(bc.n_functions(), 2);
diff --git a/src/common/bytearray.cc b/src/common/bytearray.cc
deleted file mode 100644
index cb3e973..0000000
--- a/src/common/bytearray.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-#include "bytearray.hh"
-
-#include
-#include
-
-namespace tyche {
-
-void ByteArray::set_byte(uint32_t addr, uint8_t byte)
-{
- if (data_.size() < (addr + 1))
- data_.resize(addr + 1, 0);
- data_.at(addr) = byte;
-}
-
-void ByteArray::set_int8(uint32_t addr, int8_t value)
-{
- set_byte(addr, (uint8_t) value);
-}
-
-void ByteArray::set_int16(uint32_t addr, int16_t value)
-{
- set_byte(addr, (uint8_t) (value));
- set_byte(addr+1, (uint8_t) (value >> 8));
-}
-
-void ByteArray::set_int32(uint32_t addr, int32_t value)
-{
- set_byte(addr, (uint8_t) (value));
- set_byte(addr+1, (uint8_t) (value >> 8));
- set_byte(addr+2, (uint8_t) (value >> 16));
- set_byte(addr+3, (uint8_t) (value >> 24));
-}
-
-void ByteArray::set_uint16(uint32_t addr, uint16_t value)
-{
- set_byte(addr, (uint8_t) (value));
- set_byte(addr+1, (uint8_t) (value >> 8));
-}
-
-void ByteArray::set_uint32(uint32_t addr, uint32_t value)
-{
- set_byte(addr, (uint8_t) (value));
- set_byte(addr+1, (uint8_t) (value >> 8));
- set_byte(addr+2, (uint8_t) (value >> 16));
- set_byte(addr+3, (uint8_t) (value >> 24));
-}
-
-void ByteArray::set_float(uint32_t addr, float value)
-{
- uint32_t bits;
- std::memcpy(&bits, &value, 4);
- set_byte(addr, (uint8_t) (bits));
- set_byte(addr+1, (uint8_t) (bits >> 8));
- set_byte(addr+2, (uint8_t) (bits >> 16));
- set_byte(addr+3, (uint8_t) (bits >> 24));
-}
-
-void ByteArray::set_string(uint32_t addr, std::string const& str)
-{
- for (uint8_t c: str)
- set_byte(addr++, c);
- set_byte(addr, 0);
-}
-
-void ByteArray::set_bytearray(uint32_t addr, ByteArray const& bytearray)
-{
- for (uint8_t byte: bytearray.data())
- set_byte(addr++, byte);
-}
-
-uint8_t ByteArray::get_byte(uint32_t addr) const
-{
- return data_.at(addr);
-}
-
-uint16_t ByteArray::get_uint16(uint32_t addr) const
-{
- return (uint32_t) get_byte(addr)
- | (uint32_t) get_byte(addr+1) << 8;
-}
-
-uint32_t ByteArray::get_uint32(uint32_t addr) const
-{
- return (uint32_t) get_byte(addr)
- | (uint32_t) get_byte(addr+1) << 8
- | (uint32_t) get_byte(addr+2) << 16
- | (uint32_t) get_byte(addr+3) << 24;
-}
-
-int8_t ByteArray::get_int8(uint32_t addr) const
-{
- return std::bit_cast(get_byte(addr));
-}
-
-int16_t ByteArray::get_int16(uint32_t addr) const
-{
- return (uint16_t) get_byte(addr)
- | (uint16_t) get_byte(addr+1) << 8;
-}
-
-int32_t ByteArray::get_int32(uint32_t addr) const
-{
- return std::bit_cast((uint32_t) get_byte(addr)
- | (uint32_t) get_byte(addr+1) << 8
- | (uint32_t) get_byte(addr+2) << 16
- | (uint32_t) get_byte(addr+3) << 24);
-}
-
-float ByteArray::get_float(uint32_t addr) const
-{
- uint32_t bits = (uint32_t) get_byte(addr)
- | (uint32_t) get_byte(addr+1) << 8
- | (uint32_t) get_byte(addr+2) << 16
- | (uint32_t) get_byte(addr+3) << 24;
- float value;
- std::memcpy(&value, &bits, 4);
- return value;
-}
-
-std::pair ByteArray::get_string_ptr(uint32_t addr) const
-{
- return { (const char *) &data_.at(addr), strlen((const char *) &data_.at(addr)) + 1 };
-}
-
-void ByteArray::append_bytearray(ByteArray const& bytearray)
-{
- data_.insert(data_.end(), bytearray.data().begin(), bytearray.data().end());
-}
-
-std::string ByteArray::hexdump() const
-{
- auto to_hex = [](uint32_t value, size_t n_chars) -> std::string {
- char buf[15];
- snprintf(buf, sizeof buf, "%0*X", (int) n_chars, value);
- return { buf };
- };
-
- std::string out;
- for (size_t i = 0; i < data_.size(); ++i) {
- if (i % 16 == 0)
- out += to_hex(i, 4) + " | ";
- out += to_hex(data_.at(i), 2) + " ";
- if (i % 16 == 15)
- out += "\n";
- }
- return out + "\n";
-}
-
-}
\ No newline at end of file
diff --git a/src/common/bytearray.hh b/src/common/bytearray.hh
deleted file mode 100644
index d3ed12f..0000000
--- a/src/common/bytearray.hh
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef TYCHE_BYTEARRAY_HH
-#define TYCHE_BYTEARRAY_HH
-
-#include
-#include
-#include
-#include
-
-namespace tyche {
-
-class ByteArray {
-public:
- ByteArray() = default;
- explicit ByteArray(std::vector data) : data_(std::move(data)) {}
-
- void set_byte(uint32_t addr, uint8_t byte);
- void set_uint16(uint32_t addr, uint16_t value);
- void set_uint32(uint32_t addr, uint32_t value);
- void set_int8(uint32_t addr, int8_t value);
- void set_int16(uint32_t addr, int16_t value);
- void set_int32(uint32_t addr, int32_t value);
- void set_float(uint32_t addr, float value);
- void set_string(uint32_t addr, std::string const& str);
- void set_bytearray(uint32_t addr, ByteArray const& bytearray);
-
- void append_byte(uint8_t byte) { set_byte(data_.size(), byte); }
- void append_uint16(uint16_t value) { set_uint16(data_.size(), value); }
- void append_uint32(uint32_t value) { set_uint32(data_.size(), value); }
- void append_int8(int8_t value) { set_int8(data_.size(), value); }
- void append_int16(int16_t value) { set_int16(data_.size(), value); }
- void append_int32(int32_t value) { set_int32(data_.size(), value); }
- void append_float(float value) { set_float(data_.size(), value); }
- void append_string(std::string const& str) { set_string(data_.size(), str); }
- void append_bytearray(ByteArray const& bytearray);
-
- [[nodiscard]] uint8_t get_byte(uint32_t addr) const;
- [[nodiscard]] uint16_t get_uint16(uint32_t addr) const;
- [[nodiscard]] uint32_t get_uint32(uint32_t addr) const;
- [[nodiscard]] int8_t get_int8(uint32_t addr) const;
- [[nodiscard]] int16_t get_int16(uint32_t addr) const;
- [[nodiscard]] int32_t get_int32(uint32_t addr) const;
- [[nodiscard]] float get_float(uint32_t addr) const;
- [[nodiscard]] std::pair get_string_ptr(uint32_t addr) const;
-
- [[nodiscard]] std::vector const& data() const { return data_; }
- [[nodiscard]] size_t size() const { return data_.size(); }
-
- [[nodiscard]] std::string hexdump() const;
-
- friend bool operator==(ByteArray const& lhs, ByteArray const& rhs) { return lhs.data_ == rhs.data_; }
-
-private:
- std::vector data_ {};
-};
-
-}
-
-#endif //TYCHE_BYTEARRAY_HH
diff --git a/src/vm/code.cc b/src/vm/code.cc
index 75a98d3..372e2b3 100644
--- a/src/vm/code.cc
+++ b/src/vm/code.cc
@@ -4,9 +4,9 @@
namespace tyche::vm {
-FunctionId Code::import_bytecode(ByteArray incoming)
+FunctionId Code::import_bytecode(StaticByteArray const* incoming)
{
- bc::Bytecode bc(std::move(incoming));
+ bc::Bytecode bc(incoming);
// TODO - adjust function calls, constants
bytecode_ = std::move(bc);
diff --git a/src/vm/code.hh b/src/vm/code.hh
index 6296018..90b4639 100644
--- a/src/vm/code.hh
+++ b/src/vm/code.hh
@@ -17,7 +17,7 @@ struct Operation
class Code {
public:
- FunctionId import_bytecode(ByteArray incoming);
+ FunctionId import_bytecode(StaticByteArray const* incoming);
[[nodiscard]] std::string disassemble() const;