Implement reading and writing from stack
This commit is contained in:
parent
fd507f6fcd
commit
040eb540b1
12 changed files with 219 additions and 0 deletions
|
@ -83,6 +83,8 @@ Result<PodObject*> Arena::gc_pod(PodObject* obj) {
|
|||
return gc_opcode((PodOpcode*)obj);
|
||||
case Tag::Function:
|
||||
return gc_function((PodFunction*)obj);
|
||||
case Tag::Stack:
|
||||
return gc_stack((PodStack*)obj);
|
||||
}
|
||||
|
||||
return ERROR(TypeMismatch);
|
||||
|
@ -205,6 +207,21 @@ Result<PodObject*> Arena::gc_function(PodFunction* obj) {
|
|||
return nobj;
|
||||
}
|
||||
|
||||
Result<PodObject*> Arena::gc_stack(PodStack* obj) {
|
||||
auto nobj = TRY(alloc<PodStack>(sizeof(OffPtr<PodObject>) * obj->size));
|
||||
nobj->header.tag = Tag::Stack;
|
||||
nobj->size = obj->size;
|
||||
nobj->top = obj->top;
|
||||
for (uint64_t i = 0; i < obj->top; i++) {
|
||||
PodObject* val = obj->data[i].get();
|
||||
nobj->data[i] = TRY(gc_pod(val));
|
||||
}
|
||||
for (uint64_t i = obj->top; i < obj->size; i++) {
|
||||
nobj->data[i] = 0;
|
||||
}
|
||||
return nobj;
|
||||
}
|
||||
|
||||
Arena& get_arena() {
|
||||
if (current_arena == 0) die("Arena not set\n");
|
||||
return *current_arena;
|
||||
|
|
|
@ -156,6 +156,7 @@ class Arena {
|
|||
Result<PodObject*> gc_dict(PodDict* obj);
|
||||
Result<PodObject*> gc_opcode(PodOpcode* obj);
|
||||
Result<PodObject*> gc_function(PodFunction* obj);
|
||||
Result<PodObject*> gc_stack(PodStack* obj);
|
||||
|
||||
void add_root(GcRootList* node) { _gcroot.insert(node); }
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ Result<Value> Value::create(PodObject* obj) {
|
|||
return Value(TRY(Opcode::create((PodOpcode*)obj)));
|
||||
case Tag::Function:
|
||||
return Value(TRY(Function::create((PodFunction*)obj)));
|
||||
case Tag::Stack:
|
||||
return Value(TRY(Stack::create((PodStack*)obj)));
|
||||
};
|
||||
return Value();
|
||||
}
|
||||
|
@ -110,6 +112,37 @@ Result<Value> Opcode::copy() const { return Value(Opcode(TRY(_value.copy()))); }
|
|||
Result<Value> Function::copy() const {
|
||||
return Value(Function(TRY(_value.copy())));
|
||||
}
|
||||
Result<Function> Function::copy_function() const {
|
||||
return Function(TRY(_value.copy()));
|
||||
}
|
||||
|
||||
Result<Value> Stack::copy() const { return Value(Stack(TRY(_value.copy()))); }
|
||||
|
||||
Result<Value> Stack::get(uint64_t idx) const {
|
||||
if (idx >= _value->top) return ERROR(KeyError);
|
||||
|
||||
return Value::create(_value->data[idx].get());
|
||||
}
|
||||
|
||||
Result<void> Stack::set(uint64_t idx, const Value& val) {
|
||||
if (idx >= _value->size) return ERROR(KeyError);
|
||||
|
||||
if (idx >= _value->top) {
|
||||
_value->top = idx + 1;
|
||||
}
|
||||
|
||||
_value->data[idx] = val.pod();
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<void> Stack::settop(uint64_t idx) {
|
||||
uint64_t top = _value->top;
|
||||
for (uint64_t i = std::min(top, idx); i < std::max(top, idx); i++) {
|
||||
_value->data[i] = 0;
|
||||
}
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<Pair> Pair::create(Value& first, Value& rest) {
|
||||
auto pod = TRY(arena_alloc<PodPair>());
|
||||
|
|
|
@ -791,6 +791,11 @@ class Function : public Object {
|
|||
Function(Function&& rhs) : _value(std::move(rhs._value)) {}
|
||||
Function(GcRoot<PodFunction>&& val) : _value(std::move(val)) {}
|
||||
|
||||
Function& operator=(Function&& rhs) {
|
||||
_value = std::move(rhs._value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual Tag tag() const final { return Tag::Function; }
|
||||
virtual PodObject* pod() const final { return _value.get(); }
|
||||
virtual Result<short> cmp(const Object& rhs) const final {
|
||||
|
@ -816,11 +821,55 @@ class Function : public Object {
|
|||
Result<Value> constants() const;
|
||||
|
||||
virtual Result<Value> copy() const final;
|
||||
virtual Result<Function> copy_function() const final;
|
||||
|
||||
private:
|
||||
GcRoot<PodFunction> _value;
|
||||
};
|
||||
|
||||
class Stack : public Object {
|
||||
public:
|
||||
Stack() {}
|
||||
Stack(Stack&& rhs) : _value(std::move(rhs._value)) {}
|
||||
Stack(GcRoot<PodStack>&& val) : _value(std::move(val)) {}
|
||||
|
||||
virtual Tag tag() const final { return Tag::Stack; }
|
||||
virtual PodObject* pod() const final { return _value.get(); }
|
||||
virtual Result<short> cmp(const Object& rhs) const final {
|
||||
return -TRY(rhs.cmp(*this));
|
||||
}
|
||||
virtual Result<short> cmp(const Stack& rhs) const final { return 0; }
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Stack(std::move(_value)); }
|
||||
|
||||
static Result<Stack> create(PodStack* obj) {
|
||||
return Stack(TRY(MkGcRoot(obj)));
|
||||
}
|
||||
|
||||
using Object::get;
|
||||
Result<Value> get(uint64_t idx) const;
|
||||
Result<void> set(uint64_t idx, const Value& val);
|
||||
Result<void> settop(uint64_t idx);
|
||||
|
||||
static Result<Stack> create(uint64_t size) {
|
||||
auto pod = TRY(arena_alloc<PodStack>(sizeof(OffPtr<PodObject>) * size));
|
||||
pod->header.tag = Tag::Stack;
|
||||
|
||||
pod->size = size;
|
||||
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
pod->data[i] = 0;
|
||||
}
|
||||
|
||||
return Stack(TRY(MkGcRoot(pod)));
|
||||
}
|
||||
|
||||
virtual Result<Value> copy() const final;
|
||||
|
||||
private:
|
||||
GcRoot<PodStack> _value;
|
||||
};
|
||||
|
||||
// note: this class doesn't perform proper destruction of objects in some cases
|
||||
class Value {
|
||||
public:
|
||||
|
|
|
@ -93,6 +93,7 @@ Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
|
|||
case Tag::Dict:
|
||||
case Tag::Opcode:
|
||||
case Tag::Function:
|
||||
case Tag::Stack:
|
||||
return ERROR(TypeMismatch);
|
||||
}
|
||||
return ERROR(TypeMismatch);
|
||||
|
|
|
@ -12,6 +12,7 @@ enum class ErrorCode {
|
|||
InvalidSymbol,
|
||||
MalformedList,
|
||||
KeyError,
|
||||
EndOfProgram,
|
||||
};
|
||||
|
||||
void seterr(const char* err);
|
||||
|
|
10
src/pod.hpp
10
src/pod.hpp
|
@ -20,6 +20,7 @@ enum class Tag : uint8_t {
|
|||
Dict,
|
||||
Opcode,
|
||||
Function,
|
||||
Stack,
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -166,6 +167,15 @@ class PodFunction final : public PodObject {
|
|||
OffPtr<PodObject> code;
|
||||
};
|
||||
|
||||
class PodStack final : public PodObject {
|
||||
public:
|
||||
PodStack() : PodObject(Tag::Stack){};
|
||||
|
||||
uint64_t size;
|
||||
uint64_t top;
|
||||
OffPtr<PodObject> data[];
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Ptr {
|
||||
public:
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "common.hpp"
|
||||
#include "compiler.hpp"
|
||||
#include "reader.hpp"
|
||||
#include "vm.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
StaticArena<64 * 1024 * 1024> arena;
|
||||
|
@ -25,6 +26,10 @@ Result<void> run() {
|
|||
TRY(debug_print(TRY(fun.constants())));
|
||||
TRY(debug_print(TRY(fun.code())));
|
||||
|
||||
auto vm = TRY(VM::create());
|
||||
|
||||
auto res = TRY(vm.run(fun));
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
|
|
61
src/vm.cpp
61
src/vm.cpp
|
@ -0,0 +1,61 @@
|
|||
#include "vm.hpp"
|
||||
|
||||
Result<Value> VM::getreg(uint64_t idx) { return _stack.get(_base + idx); }
|
||||
|
||||
Result<void> VM::setreg(uint64_t idx, const Value& value) {
|
||||
TRY(_stack.set(_base + idx, value));
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
Result<Value> VM::getconst(uint64_t idx) { return ERROR(NotImplemented); }
|
||||
|
||||
Result<Value> VM::get(bool is_const, uint64_t idx) {
|
||||
if (is_const) return getconst(idx);
|
||||
return getreg(idx);
|
||||
}
|
||||
|
||||
Result<void> VM::vm_mov(Opcode& oc) {
|
||||
uint64_t acc = (uint64_t)oc.arg1().arg;
|
||||
setreg(acc, TRY(Nil::create()));
|
||||
return ERROR(NotImplemented);
|
||||
}
|
||||
|
||||
Result<void> VM::step() {
|
||||
auto code = TRY(_fun.code());
|
||||
if (!code.is<Array>()) return ERROR(TypeMismatch);
|
||||
Array& code_arr = *code.to<Array>();
|
||||
|
||||
auto opcode = TRY(code_arr.get(_pc));
|
||||
if (!opcode.is<Opcode>()) return ERROR(TypeMismatch);
|
||||
Opcode& oc = *opcode.to<Opcode>();
|
||||
|
||||
switch (oc.opcode()) {
|
||||
case Oc::Mov:
|
||||
TRY(vm_mov(oc));
|
||||
default:
|
||||
return ERROR(NotImplemented);
|
||||
}
|
||||
|
||||
_pc++;
|
||||
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
// Result<Value> Int64::copy() const { return Value(Int64(TRY(_value.copy())));
|
||||
// }
|
||||
Result<Value> VM::run(const Function& fun) {
|
||||
_fun = TRY(fun.copy_function());
|
||||
_pc = 0;
|
||||
_base = 0;
|
||||
|
||||
while (true) {
|
||||
auto rc = step();
|
||||
if (!rc.has_error()) continue;
|
||||
|
||||
// TODO: return real value
|
||||
if (rc.error() == ErrorCode::EndOfProgram) return Value(TRY(Nil::create()));
|
||||
|
||||
return rc.error();
|
||||
}
|
||||
return ERROR(NotImplemented);
|
||||
}
|
34
src/vm.hpp
34
src/vm.hpp
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
class VM {
|
||||
public:
|
||||
VM() {}
|
||||
VM(Stack&& stack) : _stack(std::move(stack)) {}
|
||||
VM(VM&& vm) : _stack(std::move(vm._stack)) {}
|
||||
VM(const VM&) = delete;
|
||||
|
||||
static Result<VM> create() {
|
||||
auto stack = TRY(Stack::create(16 * 1024));
|
||||
return VM(std::move(stack));
|
||||
}
|
||||
|
||||
Result<Value> run(const Function& fun);
|
||||
|
||||
Result<void> step();
|
||||
Result<void> vm_mov(Opcode& oc);
|
||||
|
||||
Result<Value> get(bool is_const, uint64_t idx);
|
||||
Result<Value> getconst(uint64_t idx);
|
||||
Result<Value> getreg(uint64_t idx);
|
||||
Result<void> setreg(uint64_t idx, const Value& value);
|
||||
|
||||
private:
|
||||
Stack _stack;
|
||||
Function _fun;
|
||||
Array _code;
|
||||
Array _constants;
|
||||
uint64_t _pc;
|
||||
uint64_t _base;
|
||||
};
|
|
@ -31,6 +31,8 @@ Result<String> Writer::write_one(const Value& obj) {
|
|||
return write_opcode(*obj.to<Opcode>());
|
||||
case Tag::Function:
|
||||
return write_function(*obj.to<Function>());
|
||||
case Tag::Stack:
|
||||
return write_stack(*obj.to<Stack>());
|
||||
};
|
||||
return String();
|
||||
}
|
||||
|
@ -291,6 +293,10 @@ Result<String> Writer::write_function(const Function& val) {
|
|||
return res;
|
||||
}
|
||||
|
||||
Result<String> Writer::write_stack(const Stack& val) {
|
||||
return TRY(String::create("#<stack>"));
|
||||
}
|
||||
|
||||
Result<String> write_one(const Value& value) {
|
||||
auto w = Writer();
|
||||
return w.write_one(value);
|
||||
|
|
|
@ -24,6 +24,7 @@ class Writer {
|
|||
Result<String> write_syntax(const Syntax& val);
|
||||
Result<String> write_opcode(const Opcode& val);
|
||||
Result<String> write_function(const Function& val);
|
||||
Result<String> write_stack(const Stack& val);
|
||||
};
|
||||
|
||||
Result<String> write_one(const Value& value);
|
||||
|
|
Loading…
Reference in a new issue