Add arrays and boilerplate for the compiler

This commit is contained in:
Konstantin Nazarov 2024-07-30 23:52:23 +01:00
parent 6e662ad6c4
commit 42a5b7da2b
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
11 changed files with 185 additions and 2 deletions

View file

@ -17,6 +17,7 @@ target_sources(vm_lib
src/reader.cpp
src/writer.cpp
src/utf8.cpp
src/compiler.cpp
PUBLIC
FILE_SET HEADERS
@ -32,6 +33,7 @@ target_sources(vm_lib
src/reader.hpp
src/writer.hpp
src/utf8.hpp
src/compiler.hpp
)
add_executable(vli src/vli.cpp)

View file

@ -70,6 +70,8 @@ Result<PodObject*> Arena::gc_pod(PodObject* obj) {
return gc_syntax((PodSyntax*)obj);
case Tag::Pair:
return gc_pair((PodPair*)obj);
case Tag::Array:
return gc_array((PodArray*)obj);
case Tag::ByteArray:
return gc_bytearray((PodByteArray*)obj);
}
@ -141,6 +143,17 @@ Result<PodObject*> Arena::gc_pair(PodPair* obj) {
return nobj;
}
Result<PodObject*> Arena::gc_array(PodArray* obj) {
auto nobj = TRY(alloc<PodArray>(obj->size));
nobj->header.tag = Tag::Array;
nobj->size = obj->size;
for (uint64_t i = 0; i < obj->size; i++) {
PodObject* val = obj->data[i].get(obj);
nobj->data[i] = OffPtr<PodObject>(nobj, TRY(gc_pod(val)));
}
return nobj;
}
Result<PodObject*> Arena::gc_bytearray(PodByteArray* obj) {
auto nobj = TRY(alloc<PodByteArray>(obj->size));
nobj->header.tag = Tag::ByteArray;

View file

@ -151,6 +151,7 @@ class Arena {
Result<PodObject*> gc_symbol(PodSymbol* obj);
Result<PodObject*> gc_syntax(PodSyntax* obj);
Result<PodObject*> gc_pair(PodPair* obj);
Result<PodObject*> gc_array(PodArray* obj);
Result<PodObject*> gc_bytearray(PodByteArray* obj);
void add_root(GcRootList* node) { _gcroot.insert(node); }

View file

@ -21,6 +21,8 @@ Result<Value> Value::create(Arena& arena, PodObject* obj) {
return Value(TRY(Float::create(arena, (PodFloat*)obj)));
case Tag::Bool:
return Value(TRY(Bool::create(arena, (PodBool*)obj)));
case Tag::Array:
return Value(TRY(Array::create(arena, (PodArray*)obj)));
case Tag::ByteArray:
return Value(TRY(ByteArray::create(arena, (PodByteArray*)obj)));
case Tag::String:
@ -82,6 +84,10 @@ Result<Value> Float::copy(Arena& arena) {
return Value(Float(TRY(_value.copy(arena))));
}
Result<Value> Array::copy(Arena& arena) {
return Value(Array(TRY(_value.copy(arena))));
}
Result<Value> ByteArray::copy(Arena& arena) {
return Value(ByteArray(TRY(_value.copy(arena))));
}
@ -150,3 +156,20 @@ Result<void> debug_print(Arena& arena, String& val) {
std::cout << "\n";
return Result<void>();
}
Result<Value> Array::get(Arena& arena, uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
auto val = _value->data[idx].get(pod());
return Value::create(arena, val);
}
Result<Array> Array::append(Arena& arena, Value& rhs) {
uint64_t res_size = size() + 1;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(PodObject*) * size());
pod->data[size()] = OffPtr<PodObject>(pod, rhs.pod());
return Array(TRY(MkGcRoot(pod, arena)));
}

View file

@ -53,6 +53,69 @@ class Nil : public Object {
GcRoot<PodNil> _value;
};
class Array : public Object {
public:
Array() {}
Array(Array&& rhs) : _value(std::move(rhs._value)) {}
Array(GcRoot<PodArray>&& val) : _value(std::move(val)) {}
Array& operator=(Array&& rhs) {
_value = std::move(rhs._value);
return *this;
}
virtual Tag tag() final { return Tag::Array; }
virtual PodObject* pod() final { return _value.get(); }
virtual void move(Object* obj) final { new (obj) Array(std::move(_value)); }
static Result<Array> create(Arena& arena, PodArray* obj) {
return Array(TRY(MkGcRoot(obj, arena)));
}
static Result<Array> create(Arena& arena) {
auto pod = TRY(arena.alloc<PodArray>());
pod->header.tag = Tag::Array;
pod->size = 0;
return Array(TRY(MkGcRoot(pod, arena)));
}
uint64_t size() { return _value->size; }
virtual Result<Value> copy(Arena& arena) final;
Result<Value> get(Arena& arena, uint64_t idx);
Result<Array> append(Arena& arena, Value& rhs);
Result<Array> concat(Arena& arena, Array& rhs) {
uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(PodObject*) * lhs_size);
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size);
return Array(TRY(MkGcRoot(pod, arena)));
}
Result<Array> sub(Arena& arena, uint64_t start, uint64_t end) {
if (start > end) return ErrorCode::IndexOutOfRange;
uint64_t res_size = end - start;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size;
memcpy(pod->data, _value->data + start, sizeof(PodObject*) * res_size);
return Array(TRY(MkGcRoot(pod, arena)));
}
private:
GcRoot<PodArray> _value;
};
class ByteArray : public Object {
public:
ByteArray() {}
@ -64,7 +127,7 @@ class ByteArray : public Object {
return *this;
}
virtual Tag tag() final { return Tag::String; }
virtual Tag tag() final { return Tag::ByteArray; }
virtual PodObject* pod() final { return _value.get(); }
virtual void move(Object* obj) final {

31
src/compiler.cpp Normal file
View file

@ -0,0 +1,31 @@
#include "compiler.hpp"
Result<Value> Compiler::compile(Value& expr) {
auto env = TRY(Array::create(_arena));
auto constants = TRY(Array::create(_arena));
return compile_expr(expr);
}
Result<Value> Compiler::compile_expr(Value& expr) {
return Value(TRY(Nil::create(_arena)));
switch (expr.tag()) {
case Tag::Pair:
return compile_list(*expr.to<Pair>());
case Tag::Nil:
case Tag::Bool:
case Tag::Int64:
case Tag::Float:
case Tag::String:
case Tag::Symbol:
case Tag::Syntax:
case Tag::Array:
case Tag::ByteArray:
return ErrorCode::TypeMismatch;
}
return ErrorCode::TypeMismatch;
}
Result<Value> Compiler::compile_list(Pair& expr) {
return ErrorCode::TypeMismatch;
}

15
src/compiler.hpp Normal file
View file

@ -0,0 +1,15 @@
#pragma once
#include "common.hpp"
class Compiler {
public:
Compiler(Arena& arena) : _arena(arena) {}
Result<Value> compile(Value& expr);
Result<Value> compile_expr(Value& expr);
Result<Value> compile_list(Pair& expr);
private:
Arena& _arena;
};

View file

@ -14,6 +14,7 @@ enum class Tag : uint8_t {
Symbol,
Syntax,
Pair,
Array,
ByteArray,
};
@ -75,6 +76,14 @@ class PodBool final : public PodObject {
bool value;
};
class PodArray final : public PodObject {
public:
PodArray() : PodObject(Tag::Array){};
uint64_t size;
OffPtr<PodObject> data[];
};
class PodByteArray final : public PodObject {
public:
PodByteArray() : PodObject(Tag::ByteArray){};

View file

@ -2,13 +2,14 @@
#include "arena.hpp"
#include "common.hpp"
#include "compiler.hpp"
#include "reader.hpp"
#include "writer.hpp"
StaticArena<64 * 1024 * 1024> arena;
int main() {
auto s = DIEX(String::create(arena, "(1 2 3 \"foo\" (xyz))"));
auto s = DIEX(String::create(arena, "(+ 1 2 3)"));
auto reader = Reader(arena, s);
auto r = DIEX(reader.read_one());
@ -20,5 +21,8 @@ int main() {
DIEX(debug_print(arena, s2));
Compiler c = Compiler(arena);
auto compiled = DIEX(c.compile_expr(r));
return 0;
}

View file

@ -10,6 +10,8 @@ Result<String> Writer::write_one(Value& obj) {
return write_float(*obj.to<Float>());
case Tag::Bool:
return write_bool(*obj.to<Bool>());
case Tag::Array:
return write_array(*obj.to<Array>());
case Tag::ByteArray:
return write_bytearray(*obj.to<ByteArray>());
case Tag::String:
@ -165,3 +167,22 @@ Result<String> Writer::write_pair(Pair& val) {
res = TRY(res.concat(_arena, ")"));
return res;
}
Result<String> Writer::write_array(Array& val) {
String res = TRY(String::create(_arena, "["));
bool is_first = true;
for (uint64_t i = 0; i < val.size(); i++) {
Value cur = TRY(val.get(_arena, i));
if (!is_first) res = TRY(res.concat(_arena, " "));
String first_str = TRY(write_one(cur));
res = TRY(res.concat(_arena, first_str));
is_first = false;
}
res = TRY(res.concat(_arena, "]"));
return res;
}

View file

@ -17,6 +17,7 @@ class Writer {
Result<String> write_pair(Pair& val);
Result<String> write_nil(Nil& val);
Result<String> write_bool(Bool& val);
Result<String> write_array(Array& val);
Result<String> write_bytearray(ByteArray& val);
Result<String> write_symbol(Symbol& val);
Result<String> write_syntax(Syntax& val);