add builtins and statics to vm

This commit is contained in:
sfja 2024-12-11 00:18:51 +01:00
parent 916c2376a0
commit 4be4e50b7d
3 changed files with 106 additions and 31 deletions

View File

@ -7,31 +7,42 @@ namespace sliger {
// NOTICE: keep up to date with src/arch.ts
enum class Op : uint32_t {
Nop = 0,
PushNull = 1,
PushInt = 2,
PushBool = 3,
PushString = 4,
PushPtr = 5,
Pop = 6,
LoadLocal = 7,
StoreLocal = 8,
Call = 9,
Return = 10,
Jump = 11,
JumpIfFalse = 12,
Add = 13,
Subtract = 14,
Multiply = 15,
Divide = 16,
Remainder = 17,
Equal = 18,
LessThan = 19,
And = 20,
Or = 21,
Xor = 22,
Not = 23,
SourceMap = 24,
Nop = 0x00,
PushNull = 0x01,
PushInt = 0x02,
PushBool = 0x03,
PushString = 0x04,
PushPtr = 0x05,
Pop = 0x06,
ReserveStatic = 0x07,
LoadStatic = 0x08,
StoreStatic = 0x09,
LoadLocal = 0x0a,
StoreLocal = 0x0b,
Call = 0x0c,
Return = 0x0d,
Jump = 0x0e,
JumpIfTrue = 0x0f,
Builtin = 0x10,
Add = 0x20,
Subtract = 0x21,
Multiply = 0x22,
Divide = 0x23,
Remainder = 0x24,
Equal = 0x25,
LessThan = 0x26,
And = 0x27,
Or = 0x28,
Xor = 0x29,
Not = 0x2a,
SourceMap = 0x30,
};
enum class Builtin : uint32_t {
StringConcat = 0x10,
StringEqual = 0x11,
ArraySet = 0x20,
StructSet = 0x30,
};
}

View File

@ -37,8 +37,8 @@ inline auto maybe_op_to_string(uint32_t value) -> std::string
return "Return";
case Op::Jump:
return "Jump";
case Op::JumpIfFalse:
return "JumpIfFalse";
case Op::JumpIfTrue:
return "JumpIfTrue";
case Op::Add:
return "Add";
case Op::Subtract:
@ -87,8 +87,8 @@ void VM::run_n_instructions(size_t amount)
void VM::run_instruction()
{
std::cout << std::format(" {:>4}: {:<12}{}\n", this->pc,
maybe_op_to_string(this->program[this->pc]), stack_repr_string(4));
/*std::cout << std::format(" {:>4}: {:<12}{}\n", this->pc,*/
/* maybe_op_to_string(this->program[this->pc]), stack_repr_string(4));*/
auto op = eat_op();
switch (op) {
case Op::Nop:
@ -132,7 +132,28 @@ void VM::run_instruction()
this->stack.pop_back();
break;
}
case Op::ReserveStatic: {
assert_program_has(1);
auto value = eat_uint32();
this->statics.reserve(value);
break;
}
case Op::LoadStatic: {
assert_program_has(1);
auto loc = eat_uint32();
auto value = this->statics.at(loc);
stack_push(value);
break;
}
case Op::StoreStatic: {
assert_program_has(1);
auto loc = eat_uint32();
auto value = stack_pop();
this->statics.at(loc) = value;
break;
}
case Op::LoadLocal: {
assert_program_has(1);
auto loc = eat_uint32();
assert_fn_stack_has(loc);
auto value = fn_stack_at(loc);
@ -140,6 +161,7 @@ void VM::run_instruction()
break;
}
case Op::StoreLocal: {
assert_program_has(1);
auto loc = eat_uint32();
assert_fn_stack_has(loc + 1);
auto value = stack_pop();
@ -187,15 +209,21 @@ void VM::run_instruction()
this->pc = addr.as_ptr().value;
break;
}
case Op::JumpIfFalse: {
case Op::JumpIfTrue: {
assert_stack_has(2);
auto addr = stack_pop();
auto cond = stack_pop();
if (!cond.as_bool().value) {
if (cond.as_bool().value) {
this->pc = addr.as_ptr().value;
}
break;
}
case Op::Builtin: {
assert_program_has(1);
auto builtin_id = eat_uint32();
run_builtin(static_cast<Builtin>(builtin_id));
break;
}
case Op::Add: {
assert_stack_has(2);
auto right = stack_pop().as_int().value;
@ -296,3 +324,36 @@ void VM::run_instruction()
}
this->instruction_counter += 1;
}
void VM::run_builtin(Builtin builtin_id)
{
switch (builtin_id) {
case Builtin::StringConcat: {
assert_stack_has(2);
auto right = stack_pop();
auto left = stack_pop();
stack_push(
String(right.as_string().value + left.as_string().value));
break;
}
case Builtin::StringEqual: {
assert_stack_has(2);
auto right = stack_pop();
auto left = stack_pop();
stack_push(Bool(right.as_string().value == left.as_string().value));
break;
}
case Builtin::ArraySet: {
assert_stack_has(2);
std::cerr << std::format("not implemented\n");
std::exit(1);
break;
}
case Builtin::StructSet: {
assert_stack_has(2);
std::cerr << std::format("not implemented\n");
std::exit(1);
break;
}
}
}

View File

@ -191,6 +191,8 @@ public:
}
private:
void run_builtin(Builtin builtin_id);
inline void step() { this->pc += 1; }
inline auto eat_op() -> Op
@ -272,6 +274,7 @@ private:
const uint32_t* program;
size_t program_size;
std::vector<Value> stack;
std::vector<Value> statics;
heap::Heap heap;
SourcePos current_pos = { 0, 1, 1 };
int64_t instruction_counter = 0;