diff --git a/src/arena.cpp b/src/arena.cpp index a8efa56..52860b5 100644 --- a/src/arena.cpp +++ b/src/arena.cpp @@ -83,6 +83,8 @@ Result 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 Arena::gc_function(PodFunction* obj) { return nobj; } +Result Arena::gc_stack(PodStack* obj) { + auto nobj = TRY(alloc(sizeof(OffPtr) * 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; diff --git a/src/arena.hpp b/src/arena.hpp index 449a843..c67f4c3 100644 --- a/src/arena.hpp +++ b/src/arena.hpp @@ -156,6 +156,7 @@ class Arena { Result gc_dict(PodDict* obj); Result gc_opcode(PodOpcode* obj); Result gc_function(PodFunction* obj); + Result gc_stack(PodStack* obj); void add_root(GcRootList* node) { _gcroot.insert(node); } diff --git a/src/common.cpp b/src/common.cpp index 053d28f..3e0720a 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -40,6 +40,8 @@ Result 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 Opcode::copy() const { return Value(Opcode(TRY(_value.copy()))); } Result Function::copy() const { return Value(Function(TRY(_value.copy()))); } +Result Function::copy_function() const { + return Function(TRY(_value.copy())); +} + +Result Stack::copy() const { return Value(Stack(TRY(_value.copy()))); } + +Result Stack::get(uint64_t idx) const { + if (idx >= _value->top) return ERROR(KeyError); + + return Value::create(_value->data[idx].get()); +} + +Result 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(); +} + +Result 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(); +} Result Pair::create(Value& first, Value& rest) { auto pod = TRY(arena_alloc()); diff --git a/src/common.hpp b/src/common.hpp index 60d6d32..5a8b43f 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -791,6 +791,11 @@ class Function : public Object { Function(Function&& rhs) : _value(std::move(rhs._value)) {} Function(GcRoot&& 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 cmp(const Object& rhs) const final { @@ -816,11 +821,55 @@ class Function : public Object { Result constants() const; virtual Result copy() const final; + virtual Result copy_function() const final; private: GcRoot _value; }; +class Stack : public Object { + public: + Stack() {} + Stack(Stack&& rhs) : _value(std::move(rhs._value)) {} + Stack(GcRoot&& val) : _value(std::move(val)) {} + + virtual Tag tag() const final { return Tag::Stack; } + virtual PodObject* pod() const final { return _value.get(); } + virtual Result cmp(const Object& rhs) const final { + return -TRY(rhs.cmp(*this)); + } + virtual Result cmp(const Stack& rhs) const final { return 0; } + + virtual void move(Object* obj) final { new (obj) Stack(std::move(_value)); } + + static Result create(PodStack* obj) { + return Stack(TRY(MkGcRoot(obj))); + } + + using Object::get; + Result get(uint64_t idx) const; + Result set(uint64_t idx, const Value& val); + Result settop(uint64_t idx); + + static Result create(uint64_t size) { + auto pod = TRY(arena_alloc(sizeof(OffPtr) * 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 copy() const final; + + private: + GcRoot _value; +}; + // note: this class doesn't perform proper destruction of objects in some cases class Value { public: diff --git a/src/compiler.cpp b/src/compiler.cpp index 7c29f87..427cc6b 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -93,6 +93,7 @@ Result 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); diff --git a/src/error.hpp b/src/error.hpp index 085dc6a..b8601b8 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -12,6 +12,7 @@ enum class ErrorCode { InvalidSymbol, MalformedList, KeyError, + EndOfProgram, }; void seterr(const char* err); diff --git a/src/pod.hpp b/src/pod.hpp index 5d01def..c9f0257 100644 --- a/src/pod.hpp +++ b/src/pod.hpp @@ -20,6 +20,7 @@ enum class Tag : uint8_t { Dict, Opcode, Function, + Stack, }; template @@ -166,6 +167,15 @@ class PodFunction final : public PodObject { OffPtr code; }; +class PodStack final : public PodObject { + public: + PodStack() : PodObject(Tag::Stack){}; + + uint64_t size; + uint64_t top; + OffPtr data[]; +}; + template class Ptr { public: diff --git a/src/vli.cpp b/src/vli.cpp index e8ced42..d79e30d 100644 --- a/src/vli.cpp +++ b/src/vli.cpp @@ -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 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(); } diff --git a/src/vm.cpp b/src/vm.cpp index e69de29..84ac922 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -0,0 +1,61 @@ +#include "vm.hpp" + +Result VM::getreg(uint64_t idx) { return _stack.get(_base + idx); } + +Result VM::setreg(uint64_t idx, const Value& value) { + TRY(_stack.set(_base + idx, value)); + return Result(); +} + +Result VM::getconst(uint64_t idx) { return ERROR(NotImplemented); } + +Result VM::get(bool is_const, uint64_t idx) { + if (is_const) return getconst(idx); + return getreg(idx); +} + +Result VM::vm_mov(Opcode& oc) { + uint64_t acc = (uint64_t)oc.arg1().arg; + setreg(acc, TRY(Nil::create())); + return ERROR(NotImplemented); +} + +Result VM::step() { + auto code = TRY(_fun.code()); + if (!code.is()) return ERROR(TypeMismatch); + Array& code_arr = *code.to(); + + auto opcode = TRY(code_arr.get(_pc)); + if (!opcode.is()) return ERROR(TypeMismatch); + Opcode& oc = *opcode.to(); + + switch (oc.opcode()) { + case Oc::Mov: + TRY(vm_mov(oc)); + default: + return ERROR(NotImplemented); + } + + _pc++; + + return Result(); +} + +// Result Int64::copy() const { return Value(Int64(TRY(_value.copy()))); +// } +Result 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); +} diff --git a/src/vm.hpp b/src/vm.hpp index e69de29..e1b8e89 100644 --- a/src/vm.hpp +++ b/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 create() { + auto stack = TRY(Stack::create(16 * 1024)); + return VM(std::move(stack)); + } + + Result run(const Function& fun); + + Result step(); + Result vm_mov(Opcode& oc); + + Result get(bool is_const, uint64_t idx); + Result getconst(uint64_t idx); + Result getreg(uint64_t idx); + Result setreg(uint64_t idx, const Value& value); + + private: + Stack _stack; + Function _fun; + Array _code; + Array _constants; + uint64_t _pc; + uint64_t _base; +}; diff --git a/src/writer.cpp b/src/writer.cpp index edafe0b..5a6a5f4 100644 --- a/src/writer.cpp +++ b/src/writer.cpp @@ -31,6 +31,8 @@ Result Writer::write_one(const Value& obj) { return write_opcode(*obj.to()); case Tag::Function: return write_function(*obj.to()); + case Tag::Stack: + return write_stack(*obj.to()); }; return String(); } @@ -291,6 +293,10 @@ Result Writer::write_function(const Function& val) { return res; } +Result Writer::write_stack(const Stack& val) { + return TRY(String::create("#")); +} + Result write_one(const Value& value) { auto w = Writer(); return w.write_one(value); diff --git a/src/writer.hpp b/src/writer.hpp index 4888473..40996e5 100644 --- a/src/writer.hpp +++ b/src/writer.hpp @@ -24,6 +24,7 @@ class Writer { Result write_syntax(const Syntax& val); Result write_opcode(const Opcode& val); Result write_function(const Function& val); + Result write_stack(const Stack& val); }; Result write_one(const Value& value);