Add arrays and boilerplate for the compiler
This commit is contained in:
parent
6e662ad6c4
commit
42a5b7da2b
11 changed files with 185 additions and 2 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
@ -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
31
src/compiler.cpp
Normal 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
15
src/compiler.hpp
Normal 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;
|
||||
};
|
|
@ -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){};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue