Enable execution of primitive arithmetic bytecode

This commit is contained in:
Konstantin Nazarov 2024-08-13 01:11:23 +01:00
parent 040eb540b1
commit 3a117c9b1f
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
10 changed files with 247 additions and 67 deletions

View file

@ -84,39 +84,60 @@ Result<Value> syntax_unwrap(Value& val) {
return syntax->get_value();
}
Result<Value> Nil::copy() const { return Value(Nil()); }
Result<Value> Nil::copy_value() const { return Value(Nil()); }
Result<Value> Int64::copy() const { return Value(Int64(TRY(_value.copy()))); }
Result<Value> Float::copy() const { return Value(Float(TRY(_value.copy()))); }
Result<Value> Int64::copy_value() const {
return Value(Int64(TRY(_value.copy())));
}
Result<Value> Float::copy_value() const {
return Value(Float(TRY(_value.copy())));
}
Result<Value> Array::copy() const { return Value(Array(TRY(_value.copy()))); }
Result<Value> Array::copy_value() const {
return Value(Array(TRY(_value.copy())));
}
Result<Array> Array::copy() const { return Array(TRY(_value.copy())); }
Result<Value> ByteArray::copy() const {
Result<Value> ByteArray::copy_value() const {
return Value(ByteArray(TRY(_value.copy())));
}
Result<Value> Dict::copy() const { return Value(Dict(TRY(_value.copy()))); }
Result<Value> Dict::copy_value() const {
return Value(Dict(TRY(_value.copy())));
}
Result<Value> String::copy() const { return Value(String(TRY(_value.copy()))); }
Result<Value> String::copy_value() const {
return Value(String(TRY(_value.copy())));
}
Result<Value> Symbol::copy() const { return Value(Symbol(TRY(_value.copy()))); }
Result<Value> Symbol::copy_value() const {
return Value(Symbol(TRY(_value.copy())));
}
Result<Value> Syntax::copy() const { return Value(Syntax(TRY(_value.copy()))); }
Result<Value> Syntax::copy_value() const {
return Value(Syntax(TRY(_value.copy())));
}
Result<Value> Pair::copy() const { return Value(Pair(TRY(_value.copy()))); }
Result<Value> Pair::copy_value() const {
return Value(Pair(TRY(_value.copy())));
}
Result<Value> Bool::copy() const { return Value(Bool(TRY(_value.copy()))); }
Result<Value> Bool::copy_value() const {
return Value(Bool(TRY(_value.copy())));
}
Result<Value> Opcode::copy() const { return Value(Opcode(TRY(_value.copy()))); }
Result<Value> Opcode::copy_value() const {
return Value(Opcode(TRY(_value.copy())));
}
Result<Value> Function::copy() const {
Result<Value> Function::copy_value() const {
return Value(Function(TRY(_value.copy())));
}
Result<Function> Function::copy_function() const {
return Function(TRY(_value.copy()));
}
Result<Function> Function::copy() const { return Function(TRY(_value.copy())); }
Result<Value> Stack::copy() const { return Value(Stack(TRY(_value.copy()))); }
Result<Value> Stack::copy_value() const {
return Value(Stack(TRY(_value.copy())));
}
Result<Value> Stack::get(uint64_t idx) const {
if (idx >= _value->top) return ERROR(KeyError);
@ -163,7 +184,7 @@ Result<Value> Pair::rest() {
}
Result<Function> Function::create(const Value& name, uint64_t arity,
const Value& constants, const Value& code) {
const Array& constants, const Array& code) {
auto pod = TRY(arena_alloc<PodFunction>());
pod->header.tag = Tag::Function;
pod->arity = arity;
@ -178,12 +199,12 @@ Result<Value> Function::name() const {
return Value::create(_value->name.get());
}
Result<Value> Function::code() const {
return Value::create(_value->code.get());
Result<Array> Function::code() const {
return Array::create((PodArray*)_value->code.get());
}
Result<Value> Function::constants() const {
return Value::create(_value->constants.get());
Result<Array> Function::constants() const {
return Array::create((PodArray*)_value->constants.get());
}
Result<Value> reverse(Value& val) {
@ -316,11 +337,45 @@ Result<uint64_t> Dict::find(const Value& key) const {
return left;
}
Result<Value> Object::add(const Object&) const { return ERROR(NotImplemented); }
Result<Value> Object::add(const Int64&) const { return ERROR(NotImplemented); }
Result<Value> Object::sub(const Object&) const { return ERROR(NotImplemented); }
Result<Value> Object::sub_inv(const Int64&) const {
return ERROR(NotImplemented);
}
Result<Value> Object::mul(const Object&) const { return ERROR(NotImplemented); }
Result<Value> Object::mul(const Int64&) const { return ERROR(NotImplemented); }
Result<Value> Object::div(const Object&) const { return ERROR(NotImplemented); }
Result<Value> Object::div_inv(const Int64&) const {
return ERROR(NotImplemented);
}
Result<Value> Int64::add(const Object& rhs) const { return rhs.add(*this); }
Result<Value> Int64::add(const Int64& rhs) const {
return Value(TRY(Int64::create(value() + rhs.value())));
}
Result<Value> Int64::mul(const Object& rhs) const { return rhs.mul(*this); }
Result<Value> Int64::mul(const Int64& rhs) const {
return Value(TRY(Int64::create(value() * rhs.value())));
}
Result<Value> Int64::sub(const Object& rhs) const { return rhs.sub_inv(*this); }
Result<Value> Int64::sub_inv(const Int64& rhs) const {
return Value(TRY(Int64::create(rhs.value() - value())));
}
Result<Value> Int64::div(const Object& rhs) const { return rhs.div_inv(*this); }
Result<Value> Int64::div_inv(const Int64& rhs) const {
return Value(TRY(Int64::create(rhs.value() / value())));
}
Result<short> Int64::cmp(const Float& rhs) const {
return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value);
}
Result<short> Float::cmp(const Int64& rhs) const {
return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value);

View file

@ -26,13 +26,15 @@ class Pair;
class Array;
class ByteArray;
class Writer;
class Opcode;
class Stack;
short cmp_tag(Tag lhs, Tag rhs);
class Object {
public:
virtual Tag tag() const = 0;
virtual Result<Value> copy() const = 0;
virtual Result<Value> copy_value() const = 0;
virtual PodObject* pod() const = 0;
virtual void move(Object*) = 0;
virtual ~Object() = default;
@ -68,6 +70,28 @@ class Object {
virtual Result<short> cmp(const ByteArray&) const {
return cmp_tag(tag(), Tag::ByteArray);
}
virtual Result<short> cmp(const Opcode& rhs) const {
return cmp_tag(tag(), Tag::Opcode);
}
virtual Result<short> cmp(const char* rhs) const {
return ERROR(NotImplemented);
}
virtual Result<short> cmp(const Stack& rhs) const {
return ERROR(NotImplemented);
}
virtual Result<Value> add(const Object&) const;
virtual Result<Value> add(const Int64&) const;
virtual Result<Value> sub(const Object&) const;
virtual Result<Value> sub_inv(const Int64&) const;
virtual Result<Value> mul(const Object&) const;
virtual Result<Value> mul(const Int64&) const;
virtual Result<Value> div(const Object&) const;
virtual Result<Value> div_inv(const Int64&) const;
virtual Result<Value> get(const Value& key) const;
Object() = default;
@ -97,7 +121,8 @@ class Nil : public Object {
return Nil(TRY(MkGcRoot(pod)));
}
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Nil> copy() const;
virtual void move(Object* obj) final { new (obj) Nil(std::move(_value)); }
@ -139,7 +164,8 @@ class Array : public Object {
}
uint64_t size() const { return _value->size; }
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Array> copy() const;
Result<Value> get(uint64_t idx) const;
virtual Result<Value> get(const Value& key) const final;
@ -165,7 +191,7 @@ class Array : public Object {
return Array(TRY(MkGcRoot(pod)));
}
Result<Array> sub(uint64_t start, uint64_t end) {
Result<Array> slice(uint64_t start, uint64_t end) {
if (start > end) return ERROR(IndexOutOfRange);
uint64_t res_size = end - start;
auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
@ -230,7 +256,8 @@ class ByteArray : public Object {
static Result<ByteArray> create(const String& str);
uint64_t size() const { return _value->size; }
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<ByteArray> copy() const;
Result<char> operator[](uint64_t idx) const {
if (idx >= _value->size) return ERROR(IndexOutOfRange);
@ -275,7 +302,7 @@ class ByteArray : public Object {
return ByteArray(TRY(MkGcRoot(pod)));
}
Result<ByteArray> sub(uint64_t start, uint64_t end) {
Result<ByteArray> slice(uint64_t start, uint64_t end) {
if (start > end) return ERROR(IndexOutOfRange);
uint64_t res_size = end - start;
auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
@ -321,7 +348,8 @@ class Dict : public Object {
return Dict(TRY(MkGcRoot(pod)));
}
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Dict> copy() const;
virtual Result<Value> get(const Value& key) const final;
@ -419,7 +447,8 @@ class String : public Object {
}
uint64_t size() const { return _value->size; }
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<String> copy() const;
Result<char32_t> operator[](uint64_t idx) const {
if (idx >= _value->size) return ERROR(IndexOutOfRange);
@ -467,7 +496,7 @@ class String : public Object {
return String(TRY(MkGcRoot(pod)));
}
Result<String> sub(uint64_t start, uint64_t end) {
Result<String> slice(uint64_t start, uint64_t end) {
if (start > end) return ERROR(IndexOutOfRange);
uint64_t res_size = end - start;
auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
@ -561,7 +590,8 @@ class Symbol : public Object {
}
static Result<Symbol> create(String& rhs);
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Symbol> copy() const;
uint64_t size() const { return _value->size; }
@ -595,7 +625,8 @@ class Syntax : public Object {
Result<Value> get_value();
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Syntax> copy() const;
private:
GcRoot<PodSyntax> _value;
@ -621,7 +652,8 @@ class Pair : public Object {
Result<Value> first();
Result<Value> rest();
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Pair> copy() const;
private:
GcRoot<PodPair> _value;
@ -645,6 +677,18 @@ class Int64 : public Object {
}
virtual Result<short> cmp(const Float& rhs) const final;
virtual Result<Value> add(const Object& rhs) const final;
virtual Result<Value> add(const Int64& rhs) const final;
virtual Result<Value> mul(const Object& rhs) const final;
virtual Result<Value> mul(const Int64& rhs) const final;
virtual Result<Value> sub(const Object& rhs) const final;
virtual Result<Value> sub_inv(const Int64& rhs) const final;
virtual Result<Value> div(const Object& rhs) const final;
virtual Result<Value> div_inv(const Int64& rhs) const final;
virtual void move(Object* obj) final { new (obj) Int64(std::move(_value)); }
static Result<Int64> create(PodInt64* obj) {
@ -661,7 +705,8 @@ class Int64 : public Object {
int64_t value() const { return _value->value; }
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Int64> copy() const;
private:
GcRoot<PodInt64> _value;
@ -701,7 +746,8 @@ class Float : public Object {
double value() const { return _value->value; }
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Float> copy() const;
private:
GcRoot<PodFloat> _value;
@ -734,7 +780,8 @@ class Bool : public Object {
bool value() const { return _value->value; }
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Bool> copy() const;
private:
GcRoot<PodBool> _value;
@ -779,7 +826,8 @@ class Opcode : public Object {
OpArg arg3() const { return _value->arg3; }
OpArg arg4() const { return _value->arg4; }
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Opcode> copy() const;
private:
GcRoot<PodOpcode> _value;
@ -812,16 +860,16 @@ class Function : public Object {
}
static Result<Function> create(const Value& name, uint64_t arity,
const Value& constants, const Value& code);
const Array& constants, const Array& code);
uint64_t arity() { return _value->arity; }
Result<Value> name() const;
Result<Value> code() const;
Result<Value> constants() const;
Result<Array> code() const;
Result<Array> constants() const;
virtual Result<Value> copy() const final;
virtual Result<Function> copy_function() const final;
virtual Result<Value> copy_value() const final;
Result<Function> copy() const;
private:
GcRoot<PodFunction> _value;
@ -864,7 +912,8 @@ class Stack : public Object {
return Stack(TRY(MkGcRoot(pod)));
}
virtual Result<Value> copy() const final;
virtual Result<Value> copy_value() const final;
Result<Stack> copy() const;
private:
GcRoot<PodStack> _value;
@ -925,6 +974,22 @@ class Value {
return ((Object*)buf)->cmp(*(Object*)rhs.buf);
}
Result<Value> add(const Value& rhs) const {
return ((Object*)buf)->add(*(Object*)rhs.buf);
}
Result<Value> mul(const Value& rhs) const {
return ((Object*)buf)->mul(*(Object*)rhs.buf);
}
Result<Value> sub(const Value& rhs) const {
return ((Object*)buf)->sub(*(Object*)rhs.buf);
}
Result<Value> div(const Value& rhs) const {
return ((Object*)buf)->div(*(Object*)rhs.buf);
}
Result<Value> get(Value& key) { return ((Object*)buf)->get(key); }
Result<Value> get(int64_t key) {
Value k = TRY(Int64::create(key));
@ -935,7 +1000,7 @@ class Value {
// Result<bool> operator==(Value& rhs) { return TRY(cmp(rhs)) == 0; }
// Result<bool> operator!=(Value& rhs) { return TRY(cmp(rhs)) != 0; }
Result<Value> copy() const { return ((Object*)buf)->copy(); }
Result<Value> copy() const { return ((Object*)buf)->copy_value(); }
private:
uint8_t buf[24];

View file

@ -67,12 +67,10 @@ Result<Value> Compiler::compile(Value& expr) {
TRY(ex.add_opcode(Oc::Ret, {0, (int64_t)ex.reg}));
Value name = TRY(Nil::create());
Value constants = TRY(context.constants.copy());
Value code = TRY(ex.code.copy());
// TRY(debug_print(constants));
// TRY(debug_print(code));
// TRY(debug_print(context.constants));
// TRY(debug_print(ex.code));
auto fun = TRY(Function::create(name, 0, constants, code));
auto fun = TRY(Function::create(name, 0, context.constants, ex.code));
return Value(std::move(fun));
}
@ -110,6 +108,10 @@ Result<Expression> Compiler::compile_primop(Context& context, Symbol& op,
opcode = Oc::Add;
} else if (TRY(op.cmp("*")) == 0) {
opcode = Oc::Mul;
} else if (TRY(op.cmp("-")) == 0) {
opcode = Oc::Sub;
} else if (TRY(op.cmp("/")) == 0) {
opcode = Oc::Div;
} else {
return ERROR(NotImplemented);
}
@ -177,7 +179,7 @@ Result<Expression> Compiler::compile_int64(Context& context, Int64& value) {
Expression ex = TRY(Expression::create());
uint64_t reg = context.alloc_reg();
int64_t c = TRY(context.add_const(TRY(value.copy())));
int64_t c = TRY(context.add_const(TRY(value.copy_value())));
TRY(ex.add_opcode(Oc::Mov, {0, (int64_t)reg}, {1, (int64_t)c}));

View file

@ -296,7 +296,7 @@ Result<Value> Reader::read_symbol() {
size_t end = position_.offset;
String str = TRY(_str.sub(start, end));
String str = TRY(_str.slice(start, end));
if (!is_separator(get()) && !is_eof()) return ERROR(ReadError);

View file

@ -10,7 +10,7 @@
StaticArena<64 * 1024 * 1024> arena;
Result<void> run() {
auto code_str = TRY(String::create("(* (+ 1 2 3) 4)"));
auto code_str = TRY(String::create("(* (+ 1 2 3) (/ 4 2))"));
auto reader = Reader(code_str);
auto parsed = TRY(reader.read_one());
@ -30,6 +30,8 @@ Result<void> run() {
auto res = TRY(vm.run(fun));
TRY(debug_print(res));
return Result<void>();
}

View file

@ -7,7 +7,7 @@ Result<void> VM::setreg(uint64_t idx, const Value& value) {
return Result<void>();
}
Result<Value> VM::getconst(uint64_t idx) { return ERROR(NotImplemented); }
Result<Value> VM::getconst(uint64_t idx) { return _constants.get(idx); }
Result<Value> VM::get(bool is_const, uint64_t idx) {
if (is_const) return getconst(idx);
@ -16,22 +16,71 @@ Result<Value> VM::get(bool is_const, uint64_t idx) {
Result<void> VM::vm_mov(Opcode& oc) {
uint64_t acc = (uint64_t)oc.arg1().arg;
setreg(acc, TRY(Nil::create()));
return ERROR(NotImplemented);
Value val = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg));
setreg(acc, val);
return Result<void>();
}
Result<void> VM::vm_add(Opcode& oc) {
uint64_t acc = (uint64_t)oc.arg1().arg;
Value val1 = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg));
Value val2 = TRY(get(oc.arg3().is_const, (uint64_t)oc.arg3().arg));
Value res = TRY(val1.add(val2));
setreg(acc, res);
return Result<void>();
}
Result<void> VM::vm_mul(Opcode& oc) {
uint64_t acc = (uint64_t)oc.arg1().arg;
Value val1 = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg));
Value val2 = TRY(get(oc.arg3().is_const, (uint64_t)oc.arg3().arg));
Value res = TRY(val1.mul(val2));
setreg(acc, res);
return Result<void>();
}
Result<void> VM::vm_sub(Opcode& oc) {
uint64_t acc = (uint64_t)oc.arg1().arg;
Value val1 = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg));
Value val2 = TRY(get(oc.arg3().is_const, (uint64_t)oc.arg3().arg));
Value res = TRY(val1.sub(val2));
setreg(acc, res);
return Result<void>();
}
Result<void> VM::vm_div(Opcode& oc) {
uint64_t acc = (uint64_t)oc.arg1().arg;
Value val1 = TRY(get(oc.arg2().is_const, (uint64_t)oc.arg2().arg));
Value val2 = TRY(get(oc.arg3().is_const, (uint64_t)oc.arg3().arg));
Value res = TRY(val1.div(val2));
setreg(acc, res);
return Result<void>();
}
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));
auto opcode = TRY(_code.get(_pc));
if (!opcode.is<Opcode>()) return ERROR(TypeMismatch);
Opcode& oc = *opcode.to<Opcode>();
switch (oc.opcode()) {
case Oc::Mov:
TRY(vm_mov(oc));
break;
case Oc::Add:
TRY(vm_add(oc));
break;
case Oc::Mul:
TRY(vm_mul(oc));
break;
case Oc::Sub:
TRY(vm_sub(oc));
break;
case Oc::Div:
TRY(vm_div(oc));
break;
case Oc::Ret:
_res = TRY(getreg((uint64_t)oc.arg1().arg));
return ERROR(EndOfProgram);
default:
return ERROR(NotImplemented);
}
@ -44,16 +93,18 @@ Result<void> VM::step() {
// Result<Value> Int64::copy() const { return Value(Int64(TRY(_value.copy())));
// }
Result<Value> VM::run(const Function& fun) {
_fun = TRY(fun.copy_function());
_fun = TRY(fun.copy());
_pc = 0;
_base = 0;
_code = TRY(fun.code());
_constants = TRY(fun.constants());
while (true) {
auto rc = step();
if (!rc.has_error()) continue;
// TODO: return real value
if (rc.error() == ErrorCode::EndOfProgram) return Value(TRY(Nil::create()));
if (rc.error() == ErrorCode::EndOfProgram) return TRY(_res.copy());
return rc.error();
}

View file

@ -18,6 +18,10 @@ class VM {
Result<void> step();
Result<void> vm_mov(Opcode& oc);
Result<void> vm_add(Opcode& oc);
Result<void> vm_mul(Opcode& oc);
Result<void> vm_sub(Opcode& oc);
Result<void> vm_div(Opcode& oc);
Result<Value> get(bool is_const, uint64_t idx);
Result<Value> getconst(uint64_t idx);
@ -31,4 +35,5 @@ class VM {
Array _constants;
uint64_t _pc;
uint64_t _base;
Value _res;
};

View file

@ -157,7 +157,7 @@ Result<String> Writer::write_syntax(const Syntax& val) {
Result<String> Writer::write_pair(const Pair& val) {
String res = TRY(String::create("("));
Value cur = TRY(val.copy());
Value cur = TRY(val.copy_value());
bool is_first = true;
while (!cur.is<Nil>()) {

View file

@ -34,6 +34,6 @@ Result<String> write_one(const T& value)
requires std::derived_from<T, Object>
{
auto w = Writer();
auto v = DIEX(value.copy());
auto v = DIEX(value.copy_value());
return w.write_one(v);
}

View file

@ -49,7 +49,7 @@ Result<Value> to_value(const Value& val) { return val.copy(); }
template <class T>
requires std::derived_from<T, Object>
Result<Value> to_value(T& val) {
return val.copy();
return val.copy_value();
}
template <class T>