This commit is contained in:
Andre Wagner
2026-05-01 16:39:49 -05:00
parent bebaed1998
commit 0bc40cc562
9 changed files with 147 additions and 18 deletions

View File

@@ -12,7 +12,7 @@ namespace tyche::as {
class Assembler { class Assembler {
public: public:
explicit Assembler(std::string source) : lexer_(std::move(source)) {} explicit Assembler(std::string source) : lexer_(std::move(source) + "\n") {}
[[nodiscard]] ByteArray assemble(); [[nodiscard]] ByteArray assemble();

View File

@@ -1,18 +1,58 @@
#include "expr.hh" #include "expr.hh"
#include <functional>
#include "vm_exceptions.hh" #include "vm_exceptions.hh"
namespace tyche::vm { namespace tyche::vm {
std::function<Value(Value const&, Value const&)> binary_ops[(size_t) BinaryOperationType::COUNT][(size_t) Type::COUNT][(size_t) Type::COUNT];
static int init_ = []() {
for (size_t i = 0; i < (size_t) BinaryOperationType::COUNT; ++i)
for (size_t j = 0; j < (size_t) Type::COUNT; ++j)
for (size_t k = 0; k < (size_t) Type::COUNT; ++k)
binary_ops[i][j][k] = [&i](Value const& a, Value const& b) -> Value {
throw VMInvalidOperation((BinaryOperationType) i, a.type(), b.type());
};
// TODO - create macro
#define BIN_OP(op, t1, t2) binary_ops[(size_t) BinaryOperationType::op][(size_t) Type::t1][(size_t) Type::t2] = [](Value const& b, Value const& a)
BIN_OP(Sum, Integer, Integer) { return Value::CreateInteger(a.as_integer() + b.as_integer()); };
BIN_OP(Subtraction, Integer, Integer) { return Value::CreateInteger(a.as_integer() - b.as_integer()); };
BIN_OP(Division, Integer, Integer) { return Value::CreateFloat((float) a.as_integer() / (float) b.as_integer()); };
BIN_OP(IntegerDivision, Integer, Integer) { return Value::CreateInteger(a.as_integer() / b.as_integer()); };
BIN_OP(Equality, Integer, Integer) { return Value::CreateIntegerFromBool(a.as_integer() == b.as_integer()); };
BIN_OP(Inequality, Integer, Integer) { return Value::CreateIntegerFromBool(a.as_integer() != b.as_integer()); };
BIN_OP(LessThan, Integer, Integer) { return Value::CreateIntegerFromBool(a.as_integer() < b.as_integer()); };
BIN_OP(LessThanOrEquals, Integer, Integer) { return Value::CreateIntegerFromBool(a.as_integer() <= b.as_integer()); };
BIN_OP(GreaterThan, Integer, Integer) { return Value::CreateIntegerFromBool(a.as_integer() > b.as_integer()); };
BIN_OP(GreaterThanOrEquals, Integer, Integer) { return Value::CreateIntegerFromBool(a.as_integer() >= b.as_integer()); };
BIN_OP(BitwiseAnd, Integer, Integer) { return Value::CreateInteger(a.as_integer() & b.as_integer()); };
BIN_OP(BitwiseOr, Integer, Integer) { return Value::CreateInteger(a.as_integer() | b.as_integer()); };
BIN_OP(BitwiseXor, Integer, Integer) { return Value::CreateInteger(a.as_integer() ^ b.as_integer()); };
#undef BIN_OP
return 0;
}();
Value binary_operation(Value const& a, Value const& b, BinaryOperationType op) Value binary_operation(Value const& a, Value const& b, BinaryOperationType op)
{ {
// TODO - this is temporary code return binary_ops[(size_t) op][(size_t) a.type()][(size_t) b.type()](a, b);
if (a.type() == Type::Integer && b.type() == Type::Integer && op == BinaryOperationType::Sum) {
return Value::CreateInteger(a.as_integer() + b.as_integer());
} else {
throw VMInvalidOperation(op, a.type(), b.type());
}
} }
} }

View File

@@ -4,7 +4,12 @@
namespace tyche::vm { namespace tyche::vm {
enum class BinaryOperationType { Sum }; enum class BinaryOperationType
{
Sum, Subtraction, Multiplication, Division, IntegerDivision, Equality, Inequality, LessThan, LessThanOrEquals,
GreaterThan, GreaterThanOrEquals, BitwiseAnd, BitwiseOr, BitwiseXor,
COUNT
};
Value binary_operation(Value const& a, Value const& b, BinaryOperationType op); Value binary_operation(Value const& a, Value const& b, BinaryOperationType op);

View File

@@ -3,6 +3,7 @@
#include "../bytecode/bytecodeprototype.hh" #include "../bytecode/bytecodeprototype.hh"
#include "../common/bytearray.hh" #include "../common/bytearray.hh"
#include "../bytecode/bytecode.hh" #include "../bytecode/bytecode.hh"
#include "../assembler/assembler.hh"
#include "code.hh" #include "code.hh"
#include "stack.hh" #include "stack.hh"
#include "vm.hh" #include "vm.hh"
@@ -92,6 +93,28 @@ TEST(VM, BasicCode)
ASSERT_EQ(result, 5); ASSERT_EQ(result, 5);
} }
TEST(VM, SumIntegers)
{
ASSERT_EQ(VM().load_bytecode(as::Assembler(R"(
.func 0
pushi 2
pushi 3
sum
ret
)").assemble()).call(0).to_integer(-1), 5);
}
TEST(VM, SubtractIntegers)
{
ASSERT_EQ(VM().load_bytecode(as::Assembler(R"(
.func 0
pushi 2
pushi 3
sub
ret
)").assemble()).call(0).to_integer(-1), -1);
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);

View File

@@ -4,6 +4,21 @@
namespace tyche::vm { namespace tyche::vm {
std::string type_name(Type type)
{
switch (type) {
case Type::Nil: return "nil";
case Type::Integer: return "integer";
case Type::Float: return "float";
case Type::String: return "string";
case Type::Array: return "array";
case Type::Table: return "table";
case Type::Function: return "function";
case Type::NativePointer: return "native pointer";
default: return "???";
}
}
Type Value::type() const Type Value::type() const
{ {
return std::visit(overloaded { return std::visit(overloaded {

View File

@@ -10,9 +10,10 @@ using FunctionId = uint32_t;
enum class Type : uint8_t enum class Type : uint8_t
{ {
Nil = 0, Integer, Float, String, Array, Table, Function, NativePointer, Nil = 0, Integer, Float, String, Array, Table, Function, NativePointer, COUNT
}; };
std::string type_name(Type type);
class Value { class Value {
struct Function { FunctionId f_id; }; struct Function { FunctionId f_id; };
@@ -26,6 +27,8 @@ public:
static Value CreateString(std::string const& str) { return Value(str); } static Value CreateString(std::string const& str) { return Value(str); }
static Value CreateFunctionId(FunctionId f_id) { return Value(Function { f_id }); } static Value CreateFunctionId(FunctionId f_id) { return Value(Function { f_id }); }
static Value CreateIntegerFromBool(bool b) { return CreateInteger(b ? 1 : 0); }
[[nodiscard]] Type type() const; [[nodiscard]] Type type() const;
[[nodiscard]] int32_t as_integer() const { return std::get<int32_t>(value_); } [[nodiscard]] int32_t as_integer() const { return std::get<int32_t>(value_); }

View File

@@ -5,13 +5,14 @@
namespace tyche::vm { namespace tyche::vm {
void VM::load_bytecode(ByteArray const& ba) VM& VM::load_bytecode(ByteArray const& ba)
{ {
FunctionId f_id = code_.import_bytecode(ba); FunctionId f_id = code_.import_bytecode(ba);
stack_.push(Value::CreateFunctionId(f_id)); stack_.push(Value::CreateFunctionId(f_id));
return *this;
} }
void VM::call(size_t n_params) VM& VM::call(size_t n_params)
{ {
// TODO - parameters // TODO - parameters
@@ -24,6 +25,8 @@ void VM::call(size_t n_params)
run_until_return(); run_until_return();
// stack_.pop_fp(); // stack_.pop_fp();
loc_.pop(); loc_.pop();
return *this;
} }
int32_t VM::to_integer(int index) const int32_t VM::to_integer(int index) const
@@ -33,9 +36,10 @@ int32_t VM::to_integer(int index) const
return i.as_integer(); return i.as_integer();
} }
void VM::push_integer(int32_t value) VM& VM::push_integer(int32_t value)
{ {
stack_.push(Value::CreateInteger(value)); stack_.push(Value::CreateInteger(value));
return *this;
} }
void VM::run_until_return() void VM::run_until_return()
@@ -58,6 +62,45 @@ void VM::step()
case Instruction::Sum: case Instruction::Sum:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::Sum)); stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::Sum));
break; break;
case Instruction::Subtract:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::Subtraction));
break;
case Instruction::Multiply:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::Multiplication));
break;
case Instruction::Divide:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::Division));
break;
case Instruction::DivideInt:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::IntegerDivision));
break;
case Instruction::Equals:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::Equality));
break;
case Instruction::NotEquals:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::Inequality));
break;
case Instruction::LessThan:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::LessThan));
break;
case Instruction::LessThanEq:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::LessThanOrEquals));
break;
case Instruction::GreaterThan:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::GreaterThan));
break;
case Instruction::GreaterThanEq:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::GreaterThanOrEquals));
break;
case Instruction::And:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::BitwiseAnd));
break;
case Instruction::Or:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::BitwiseOr));
break;
case Instruction::Xor:
stack_.push(binary_operation(stack_.pop(), stack_.pop(), BinaryOperationType::BitwiseXor));
break;
case Instruction::Return: { case Instruction::Return: {
Value v = stack_.pop(); Value v = stack_.pop();
stack_.pop_fp(); stack_.pop_fp();

View File

@@ -9,13 +9,13 @@ namespace tyche::vm {
class VM { class VM {
public: public:
void load_bytecode(ByteArray const& ba); VM& load_bytecode(ByteArray const& ba);
void call(size_t n_params); VM& call(size_t n_params);
[[nodiscard]] int32_t to_integer(int index) const; [[nodiscard]] int32_t to_integer(int index) const;
void push_integer(int32_t value); VM& push_integer(int32_t value);
[[nodiscard]] std::string debug_stack() const { return stack_.debug(); } [[nodiscard]] std::string debug_stack() const { return stack_.debug(); }

View File

@@ -29,7 +29,7 @@ public:
class VMTypeError : public VMRuntimeError class VMTypeError : public VMRuntimeError
{ {
public: public:
explicit VMTypeError(Type expected, Type found) : VMRuntimeError("Type error") {} // TODO - print types explicit VMTypeError(Type expected, Type found) : VMRuntimeError("Type error (expected " + type_name(expected) + ", found " + type_name(found) + ")") {}
}; };
class VMInvalidOpcode : public VMRuntimeError class VMInvalidOpcode : public VMRuntimeError
@@ -41,7 +41,7 @@ public:
class VMInvalidOperation : public VMRuntimeError class VMInvalidOperation : public VMRuntimeError
{ {
public: public:
explicit VMInvalidOperation(BinaryOperationType op, Type type1, Type type2) : VMRuntimeError("Invalid binary operation") {} // TODO - print types explicit VMInvalidOperation(BinaryOperationType op, Type type1, Type type2) : VMRuntimeError("Invalid binary operation for types " + type_name(type1) + " and " + type_name(type2)) {}
}; };
} }