Stop passing arena explicitly

This commit is contained in:
Konstantin Nazarov 2024-08-09 23:45:06 +01:00
parent b40f835bfb
commit 4c7b44ff01
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
15 changed files with 409 additions and 464 deletions

View file

@ -1,7 +1,10 @@
#include "arena.hpp" #include "arena.hpp"
#include "die.hpp"
#include "error.hpp" #include "error.hpp"
static Arena* current_arena = 0;
GcRootBase::GcRootBase(PodObject* ptr, GcRootList* node) GcRootBase::GcRootBase(PodObject* ptr, GcRootList* node)
: _ptr(ptr), _node(node) {} : _ptr(ptr), _node(node) {}
@ -175,3 +178,11 @@ Result<PodObject*> Arena::gc_dict(PodDict* obj) {
return nobj; return nobj;
// return ErrorCode::NotImplemented; // return ErrorCode::NotImplemented;
} }
Arena& get_arena() {
if (current_arena == 0) die("Arena not set\n");
return *current_arena;
}
void set_arena(Arena& arena) { current_arena = &arena; }
Result<void> arena_gc() { return get_arena().gc(); }

View file

@ -13,6 +13,9 @@
class Arena; class Arena;
class GcRootList; class GcRootList;
Arena& get_arena();
void set_arena(Arena& arena);
class GcRootBase { class GcRootBase {
public: public:
friend class Arena; friend class Arena;
@ -38,10 +41,8 @@ class GcRoot : public GcRootBase {
GcRoot(GcRoot&& rhs); GcRoot(GcRoot&& rhs);
GcRoot& operator=(GcRoot&& rhs); GcRoot& operator=(GcRoot&& rhs);
static Result<GcRoot<T>> create(T* ptr, Arena& arena); static Result<GcRoot<T>> create(T* ptr);
Result<GcRoot<T>> copy(Arena& arena) const { Result<GcRoot<T>> copy() const { return GcRoot<T>::create((T*)_ptr); }
return GcRoot<T>::create((T*)_ptr, arena);
}
T* get() { return (T*)_ptr; } T* get() { return (T*)_ptr; }
T& operator*() { return *(T*)_ptr; } T& operator*() { return *(T*)_ptr; }
@ -50,8 +51,8 @@ class GcRoot : public GcRootBase {
template <class T> template <class T>
requires std::derived_from<T, PodObject> requires std::derived_from<T, PodObject>
Result<GcRoot<T>> MkGcRoot(T* ptr, Arena& arena) { Result<GcRoot<T>> MkGcRoot(T* ptr) {
return GcRoot<T>::create(ptr, arena); return GcRoot<T>::create(ptr);
} }
class GcRootList { class GcRootList {
@ -184,17 +185,24 @@ class StaticArenaHeap : public ArenaHeap {
template <uint64_t size> template <uint64_t size>
class StaticArena : public Arena { class StaticArena : public Arena {
public: public:
StaticArena() : Arena(&_heaps[0], &_heaps[1]) {} StaticArena() : Arena(&_heaps[0], &_heaps[1]) { set_arena(*this); }
private: private:
StaticArenaHeap<(size - sizeof(Arena)) / 2> _heaps[2]; StaticArenaHeap<(size - sizeof(Arena)) / 2> _heaps[2];
}; };
template <class T>
Result<T*> arena_alloc(uint64_t extra = 0) {
return get_arena().alloc<T>(extra);
}
Result<void> arena_gc();
template <class T> template <class T>
requires std::derived_from<T, PodObject> requires std::derived_from<T, PodObject>
Result<GcRoot<T>> GcRoot<T>::create(T* ptr, Arena& arena) { Result<GcRoot<T>> GcRoot<T>::create(T* ptr) {
auto lst = TRY(arena.alloc<GcRootList>()); auto lst = TRY(arena_alloc<GcRootList>());
arena.add_root(lst); get_arena().add_root(lst);
return std::move(GcRoot<T>(ptr, lst)); return std::move(GcRoot<T>(ptr, lst));
} }

View file

@ -8,56 +8,56 @@
Syntax::Syntax(String filename, String modulename, Value expression) {} Syntax::Syntax(String filename, String modulename, Value expression) {}
Result<Value> Syntax::get_value(Arena& arena) { Result<Value> Syntax::get_value() {
return Value::create(arena, _value->expression.get()); return Value::create(_value->expression.get());
} }
Result<Value> Value::create(Arena& arena, PodObject* obj) { Result<Value> Value::create(PodObject* obj) {
switch (obj->header.tag) { switch (obj->header.tag) {
case Tag::Nil: case Tag::Nil:
return Value(TRY(Nil::create(arena, (PodNil*)obj))); return Value(TRY(Nil::create((PodNil*)obj)));
case Tag::Int64: case Tag::Int64:
return Value(TRY(Int64::create(arena, (PodInt64*)obj))); return Value(TRY(Int64::create((PodInt64*)obj)));
case Tag::Float: case Tag::Float:
return Value(TRY(Float::create(arena, (PodFloat*)obj))); return Value(TRY(Float::create((PodFloat*)obj)));
case Tag::Bool: case Tag::Bool:
return Value(TRY(Bool::create(arena, (PodBool*)obj))); return Value(TRY(Bool::create((PodBool*)obj)));
case Tag::Array: case Tag::Array:
return Value(TRY(Array::create(arena, (PodArray*)obj))); return Value(TRY(Array::create((PodArray*)obj)));
case Tag::ByteArray: case Tag::ByteArray:
return Value(TRY(ByteArray::create(arena, (PodByteArray*)obj))); return Value(TRY(ByteArray::create((PodByteArray*)obj)));
case Tag::Dict: case Tag::Dict:
return Value(TRY(Dict::create(arena, (PodDict*)obj))); return Value(TRY(Dict::create((PodDict*)obj)));
case Tag::String: case Tag::String:
return Value(TRY(String::create(arena, (PodString*)obj))); return Value(TRY(String::create((PodString*)obj)));
case Tag::Symbol: case Tag::Symbol:
return Value(TRY(Symbol::create(arena, (PodSymbol*)obj))); return Value(TRY(Symbol::create((PodSymbol*)obj)));
case Tag::Syntax: case Tag::Syntax:
return Value(TRY(Syntax::create(arena, (PodSyntax*)obj))); return Value(TRY(Syntax::create((PodSyntax*)obj)));
case Tag::Pair: case Tag::Pair:
return Value(TRY(Pair::create(arena, (PodPair*)obj))); return Value(TRY(Pair::create((PodPair*)obj)));
}; };
return Value(); return Value();
} }
Result<Symbol> Symbol::create(Arena& arena, String& rhs) { Result<Symbol> Symbol::create(String& rhs) {
uint64_t rhs_size = rhs.size(); uint64_t rhs_size = rhs.size();
uint64_t res_size = rhs_size; uint64_t res_size = rhs_size;
auto pod = TRY(arena.alloc<PodSymbol>(res_size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodSymbol>(res_size * sizeof(char32_t)));
pod->header.tag = Tag::Symbol; pod->header.tag = Tag::Symbol;
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, rhs._value->data, sizeof(char32_t) * rhs_size); memcpy(pod->data, rhs._value->data, sizeof(char32_t) * rhs_size);
return Symbol(TRY(MkGcRoot(pod, arena))); return Symbol(TRY(MkGcRoot(pod)));
} }
Result<ByteArray> ByteArray::create(Arena& arena, String& str) { Result<ByteArray> ByteArray::create(String& str) {
uint64_t size = 0; uint64_t size = 0;
for (uint64_t i = 0; i < str.size(); i++) { for (uint64_t i = 0; i < str.size(); i++) {
size += utf8_codepoint_size(TRY(str[i])); size += utf8_codepoint_size(TRY(str[i]));
} }
auto pod = TRY(arena.alloc<PodByteArray>(size * sizeof(char))); auto pod = TRY(arena_alloc<PodByteArray>(size * sizeof(char)));
pod->header.tag = Tag::ByteArray; pod->header.tag = Tag::ByteArray;
pod->size = size; pod->size = size;
@ -68,94 +68,76 @@ Result<ByteArray> ByteArray::create(Arena& arena, String& str) {
res = utf8_write_codepoint(res, codepoint); res = utf8_write_codepoint(res, codepoint);
} }
return ByteArray(TRY(MkGcRoot(pod, arena))); return ByteArray(TRY(MkGcRoot(pod)));
} }
Result<Value> syntax_unwrap(Arena& arena, Value& val) { Result<Value> syntax_unwrap(Value& val) {
Syntax* syntax = val.to<Syntax>(); Syntax* syntax = val.to<Syntax>();
if (syntax == 0) return val.copy(arena); if (syntax == 0) return val.copy();
return syntax->get_value(arena); return syntax->get_value();
} }
Result<Value> Nil::copy(Arena& arena) const { return Value(Nil()); } Result<Value> Nil::copy() const { return Value(Nil()); }
Result<Value> Int64::copy(Arena& arena) const { Result<Value> Int64::copy() const { return Value(Int64(TRY(_value.copy()))); }
return Value(Int64(TRY(_value.copy(arena)))); Result<Value> Float::copy() const { return Value(Float(TRY(_value.copy()))); }
}
Result<Value> Float::copy(Arena& arena) const { Result<Value> Array::copy() const { return Value(Array(TRY(_value.copy()))); }
return Value(Float(TRY(_value.copy(arena))));
Result<Value> ByteArray::copy() const {
return Value(ByteArray(TRY(_value.copy())));
} }
Result<Value> Array::copy(Arena& arena) const { Result<Value> Dict::copy() const { return Value(Dict(TRY(_value.copy()))); }
return Value(Array(TRY(_value.copy(arena))));
}
Result<Value> ByteArray::copy(Arena& arena) const { Result<Value> String::copy() const { return Value(String(TRY(_value.copy()))); }
return Value(ByteArray(TRY(_value.copy(arena))));
}
Result<Value> Dict::copy(Arena& arena) const { Result<Value> Symbol::copy() const { return Value(Symbol(TRY(_value.copy()))); }
return Value(Dict(TRY(_value.copy(arena))));
}
Result<Value> String::copy(Arena& arena) const { Result<Value> Syntax::copy() const { return Value(Syntax(TRY(_value.copy()))); }
return Value(String(TRY(_value.copy(arena))));
}
Result<Value> Symbol::copy(Arena& arena) const { Result<Value> Pair::copy() const { return Value(Pair(TRY(_value.copy()))); }
return Value(Symbol(TRY(_value.copy(arena))));
}
Result<Value> Syntax::copy(Arena& arena) const { Result<Value> Bool::copy() const { return Value(Bool(TRY(_value.copy()))); }
return Value(Syntax(TRY(_value.copy(arena))));
}
Result<Value> Pair::copy(Arena& arena) const { Result<Pair> Pair::create(Value& first, Value& rest) {
return Value(Pair(TRY(_value.copy(arena)))); auto pod = TRY(arena_alloc<PodPair>());
}
Result<Value> Bool::copy(Arena& arena) const {
return Value(Bool(TRY(_value.copy(arena))));
}
Result<Pair> Pair::create(Arena& arena, Value& first, Value& rest) {
auto pod = TRY(arena.alloc<PodPair>());
pod->header.tag = Tag::Pair; pod->header.tag = Tag::Pair;
pod->first = first.pod(); pod->first = first.pod();
pod->rest = rest.pod(); pod->rest = rest.pod();
return Pair(TRY(MkGcRoot(pod, arena))); return Pair(TRY(MkGcRoot(pod)));
} }
Result<Value> Pair::first(Arena& arena) { Result<Value> Pair::first() {
auto val = _value->first.get(); auto val = _value->first.get();
return Value::create(arena, val); return Value::create(val);
} }
Result<Value> Pair::rest(Arena& arena) { Result<Value> Pair::rest() {
auto val = _value->rest.get(); auto val = _value->rest.get();
return Value::create(arena, val); return Value::create(val);
} }
Result<Value> reverse(Arena& arena, Value& val) { Result<Value> reverse(Value& val) {
if (!val.is<Pair>()) return ErrorCode::TypeMismatch; if (!val.is<Pair>()) return ErrorCode::TypeMismatch;
auto res = Value(TRY(Nil::create(arena))); auto res = Value(TRY(Nil::create()));
auto cur = TRY(val.copy(arena)); auto cur = TRY(val.copy());
while (!cur.is<Nil>()) { while (!cur.is<Nil>()) {
if (!cur.is<Pair>()) return ErrorCode::TypeMismatch; if (!cur.is<Pair>()) return ErrorCode::TypeMismatch;
Pair& pair = *cur.to<Pair>(); Pair& pair = *cur.to<Pair>();
Value first = TRY(pair.first(arena)); Value first = TRY(pair.first());
cur = TRY(pair.rest(arena)); cur = TRY(pair.rest());
res = TRY(Pair::create(arena, first, res)); res = TRY(Pair::create(first, res));
} }
return res; return res;
} }
Result<void> debug_print(Arena& arena, String& val) { Result<void> debug_print(String& val) {
auto ba = TRY(ByteArray::create(arena, val)); auto ba = TRY(ByteArray::create(val));
for (uint64_t i = 0; i < ba.size(); i++) { for (uint64_t i = 0; i < ba.size(); i++) {
std::cout << TRY(ba[i]); std::cout << TRY(ba[i]);
@ -164,27 +146,27 @@ Result<void> debug_print(Arena& arena, String& val) {
return Result<void>(); return Result<void>();
} }
Result<void> debug_print(Arena& arena, Value& val) { Result<void> debug_print(Value& val) {
auto w = Writer(arena); auto w = Writer();
auto s = TRY(w.write_one(val)); auto s = TRY(w.write_one(val));
return debug_print(arena, s); return debug_print(s);
} }
Result<Value> Array::get(Arena& arena, uint64_t idx) { Result<Value> Array::get(uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange; if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
auto val = _value->data[idx].get(); auto val = _value->data[idx].get();
return Value::create(arena, val); return Value::create(val);
} }
Result<Value> Array::get(Arena& arena, Value& key) { Result<Value> Array::get(Value& key) {
if (!key.is<Int64>()) return ErrorCode::TypeMismatch; if (!key.is<Int64>()) return ErrorCode::TypeMismatch;
return get(arena, key.to<Int64>()->value()); return get(key.to<Int64>()->value());
} }
Result<Array> Array::append(Arena& arena, Value& rhs) { Result<Array> Array::append(Value& rhs) {
uint64_t res_size = size() + 1; uint64_t res_size = size() + 1;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(OffPtr<PodObject>))); auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(OffPtr<PodObject>)));
pod->header.tag = Tag::Array; pod->header.tag = Tag::Array;
pod->size = res_size; pod->size = res_size;
for (uint64_t i = 0; i < size(); i++) { for (uint64_t i = 0; i < size(); i++) {
@ -192,7 +174,7 @@ Result<Array> Array::append(Arena& arena, Value& rhs) {
} }
pod->data[size()] = rhs.pod(); pod->data[size()] = rhs.pod();
return Array(TRY(MkGcRoot(pod, arena))); return Array(TRY(MkGcRoot(pod)));
} }
short cmp_tag(Tag lhs, Tag rhs) { short cmp_tag(Tag lhs, Tag rhs) {
@ -201,29 +183,29 @@ short cmp_tag(Tag lhs, Tag rhs) {
return 0; return 0;
} }
Result<Value> Dict::get(Arena& arena, Value& key) { Result<Value> Dict::get(Value& key) {
auto pos = TRY(find(arena, key)); auto pos = TRY(find(key));
if (pos > size()) return ErrorCode::KeyError; if (pos > size()) return ErrorCode::KeyError;
auto k = TRY(Value::create(arena, _value->data[pos * 2].get())); auto k = TRY(Value::create(_value->data[pos * 2].get()));
if (TRY(k.cmp(arena, key)) != 0) { if (TRY(k.cmp(key)) != 0) {
return ErrorCode::KeyError; return ErrorCode::KeyError;
} }
return TRY(Value::create(arena, _value->data[pos * 2 + 1].get())); return TRY(Value::create(_value->data[pos * 2 + 1].get()));
} }
Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) { Result<Dict> Dict::insert(Value& key, Value& value) {
auto pos = TRY(find(arena, key)); auto pos = TRY(find(key));
auto s = size(); auto s = size();
if (pos >= s) { if (pos >= s) {
s += 1; s += 1;
} else { } else {
auto k = TRY(Value::create(arena, _value->data[pos * 2].get())); auto k = TRY(Value::create(_value->data[pos * 2].get()));
if (TRY(k.cmp(arena, key)) != 0) s += 1; if (TRY(k.cmp(key)) != 0) s += 1;
} }
auto pod = TRY(arena.alloc<PodDict>(2 * s * sizeof(OffPtr<PodObject>))); auto pod = TRY(arena_alloc<PodDict>(2 * s * sizeof(OffPtr<PodObject>)));
pod->header.tag = Tag::Dict; pod->header.tag = Tag::Dict;
pod->size = s; pod->size = s;
@ -243,16 +225,16 @@ Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) {
} }
} }
return Dict(TRY(MkGcRoot(pod, arena))); return Dict(TRY(MkGcRoot(pod)));
} }
Result<uint64_t> Dict::find(Arena& arena, Value& key) { Result<uint64_t> Dict::find(Value& key) {
uint64_t left = 0; uint64_t left = 0;
uint64_t right = size(); uint64_t right = size();
uint64_t pos = (left + right) / 2; uint64_t pos = (left + right) / 2;
while (left < right) { while (left < right) {
auto v = TRY(Value::create(arena, _value->data[pos * 2].get())); auto v = TRY(Value::create(_value->data[pos * 2].get()));
auto c = TRY(v.cmp(arena, key)); auto c = TRY(v.cmp(key));
if (c == 0) { if (c == 0) {
return pos; return pos;
} }
@ -267,17 +249,17 @@ Result<uint64_t> Dict::find(Arena& arena, Value& key) {
return left; return left;
} }
Result<short> Int64::cmp(Arena&, Float& rhs) { Result<short> Int64::cmp(Float& rhs) {
return (_value->value > rhs._value->value) - return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value); (_value->value < rhs._value->value);
} }
Result<short> Float::cmp(Arena&, Int64& rhs) { Result<short> Float::cmp(Int64& rhs) {
return (_value->value > rhs._value->value) - return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value); (_value->value < rhs._value->value);
} }
Result<short> Dict::cmp(Arena& arena, Dict& rhs) { Result<short> Dict::cmp(Dict& rhs) {
auto lsize = size() * 2; auto lsize = size() * 2;
auto rsize = rhs.size() * 2; auto rsize = rhs.size() * 2;
uint64_t i = 0; uint64_t i = 0;
@ -288,9 +270,9 @@ Result<short> Dict::cmp(Arena& arena, Dict& rhs) {
short cmp = short(i == lsize) - short(j == rsize); short cmp = short(i == lsize) - short(j == rsize);
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
Value lc = TRY(Value::create(arena, _value->data[i].get())); Value lc = TRY(Value::create(_value->data[i].get()));
Value rc = TRY(Value::create(arena, rhs._value->data[j].get())); Value rc = TRY(Value::create(rhs._value->data[j].get()));
cmp = TRY(lc.cmp(arena, rc)); cmp = TRY(lc.cmp(rc));
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
i++; i++;
j++; j++;
@ -298,6 +280,4 @@ Result<short> Dict::cmp(Arena& arena, Dict& rhs) {
return 0; return 0;
} }
Result<Value> Object::get(Arena& arena, Value& key) { Result<Value> Object::get(Value& key) { return ErrorCode::TypeMismatch; }
return ErrorCode::TypeMismatch;
}

View file

@ -31,37 +31,25 @@ short cmp_tag(Tag lhs, Tag rhs);
class Object { class Object {
public: public:
virtual Tag tag() = 0; virtual Tag tag() = 0;
virtual Result<Value> copy(Arena& arena) const = 0; virtual Result<Value> copy() const = 0;
virtual PodObject* pod() = 0; virtual PodObject* pod() = 0;
virtual void move(Object*) = 0; virtual void move(Object*) = 0;
virtual ~Object() = default; virtual ~Object() = default;
virtual Result<short> cmp(Arena&, Object&) = 0; virtual Result<short> cmp(Object&) = 0;
virtual Result<short> cmp(Arena&, Nil&) { return cmp_tag(tag(), Tag::Nil); } virtual Result<short> cmp(Nil&) { return cmp_tag(tag(), Tag::Nil); }
virtual Result<short> cmp(Arena&, Int64&) { virtual Result<short> cmp(Int64&) { return cmp_tag(tag(), Tag::Int64); }
return cmp_tag(tag(), Tag::Int64); virtual Result<short> cmp(Float&) { return cmp_tag(tag(), Tag::Float); }
} virtual Result<short> cmp(Bool&) { return cmp_tag(tag(), Tag::Bool); }
virtual Result<short> cmp(Arena&, Float&) { virtual Result<short> cmp(String&) { return cmp_tag(tag(), Tag::String); }
return cmp_tag(tag(), Tag::Float); virtual Result<short> cmp(Symbol&) { return cmp_tag(tag(), Tag::Symbol); }
} virtual Result<short> cmp(Syntax&) { return cmp_tag(tag(), Tag::Syntax); }
virtual Result<short> cmp(Arena&, Bool&) { return cmp_tag(tag(), Tag::Bool); } virtual Result<short> cmp(Pair&) { return cmp_tag(tag(), Tag::Pair); }
virtual Result<short> cmp(Arena&, String&) { virtual Result<short> cmp(Array&) { return cmp_tag(tag(), Tag::Array); }
return cmp_tag(tag(), Tag::String); virtual Result<short> cmp(ByteArray&) {
}
virtual Result<short> cmp(Arena&, Symbol&) {
return cmp_tag(tag(), Tag::Symbol);
}
virtual Result<short> cmp(Arena&, Syntax&) {
return cmp_tag(tag(), Tag::Syntax);
}
virtual Result<short> cmp(Arena&, Pair&) { return cmp_tag(tag(), Tag::Pair); }
virtual Result<short> cmp(Arena&, Array&) {
return cmp_tag(tag(), Tag::Array);
}
virtual Result<short> cmp(Arena&, ByteArray&) {
return cmp_tag(tag(), Tag::ByteArray); return cmp_tag(tag(), Tag::ByteArray);
} }
virtual Result<Value> get(Arena& arena, Value& key); virtual Result<Value> get(Value& key);
Object() = default; Object() = default;
Object(const Object&) = delete; Object(const Object&) = delete;
@ -76,23 +64,19 @@ class Nil : public Object {
virtual Tag tag() final { return Tag::Nil; } virtual Tag tag() final { return Tag::Nil; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Nil& rhs) final { return 0; }
}
virtual Result<short> cmp(Arena&, Nil& rhs) final { return 0; }
static Result<Nil> create(Arena& arena, PodNil* obj) { static Result<Nil> create(PodNil* obj) { return Nil(TRY(MkGcRoot(obj))); }
return Nil(TRY(MkGcRoot(obj, arena)));
}
static Result<Nil> create(Arena& arena) { static Result<Nil> create() {
auto pod = TRY(arena.alloc<PodNil>()); auto pod = TRY(arena_alloc<PodNil>());
pod->header.tag = Tag::Nil; pod->header.tag = Tag::Nil;
return Nil(TRY(MkGcRoot(pod, arena))); return Nil(TRY(MkGcRoot(pod)));
} }
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
virtual void move(Object* obj) final { new (obj) Nil(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Nil(std::move(_value)); }
@ -113,42 +97,40 @@ class Array : public Object {
virtual Tag tag() final { return Tag::Array; } virtual Tag tag() final { return Tag::Array; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Array& rhs) final { return 0; }
}
virtual Result<short> cmp(Arena&, Array& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Array(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Array(std::move(_value)); }
static Result<Array> create(Arena& arena, PodArray* obj) { static Result<Array> create(PodArray* obj) {
return Array(TRY(MkGcRoot(obj, arena))); return Array(TRY(MkGcRoot(obj)));
} }
static Result<Array> create(Arena& arena) { static Result<Array> create() {
auto pod = TRY(arena.alloc<PodArray>()); auto pod = TRY(arena_alloc<PodArray>());
pod->header.tag = Tag::Array; pod->header.tag = Tag::Array;
pod->size = 0; pod->size = 0;
return Array(TRY(MkGcRoot(pod, arena))); return Array(TRY(MkGcRoot(pod)));
} }
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
Result<Value> get(Arena& arena, uint64_t idx); Result<Value> get(uint64_t idx);
virtual Result<Value> get(Arena& arena, Value& key) final; virtual Result<Value> get(Value& key) final;
Result<Array> append(Arena& arena, Value& rhs); Result<Array> append(Value& rhs);
template <class V> template <class V>
Result<Array> append(Arena& arena, const V& value); Result<Array> append(const V& value);
Result<Array> concat(Arena& arena, Array& rhs) { Result<Array> concat(Array& rhs) {
uint64_t rhs_size = rhs.size(); uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*))); auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size; pod->size = res_size;
for (uint64_t i = 0; i < size(); i++) { for (uint64_t i = 0; i < size(); i++) {
pod->data[i] = _value->data[i]; pod->data[i] = _value->data[i];
@ -157,19 +139,19 @@ class Array : public Object {
pod->data[i] = rhs._value->data[i]; pod->data[i] = rhs._value->data[i];
} }
return Array(TRY(MkGcRoot(pod, arena))); return Array(TRY(MkGcRoot(pod)));
} }
Result<Array> sub(Arena& arena, uint64_t start, uint64_t end) { Result<Array> sub(uint64_t start, uint64_t end) {
if (start > end) return ErrorCode::IndexOutOfRange; if (start > end) return ErrorCode::IndexOutOfRange;
uint64_t res_size = end - start; uint64_t res_size = end - start;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*))); auto pod = TRY(arena_alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size; pod->size = res_size;
for (uint64_t i = 0; i < end - start; i++) { for (uint64_t i = 0; i < end - start; i++) {
pod->data[i] = _value->data[start + i]; pod->data[i] = _value->data[start + i];
} }
return Array(TRY(MkGcRoot(pod, arena))); return Array(TRY(MkGcRoot(pod)));
} }
private: private:
@ -189,95 +171,93 @@ class ByteArray : public Object {
virtual Tag tag() final { return Tag::ByteArray; } virtual Tag tag() final { return Tag::ByteArray; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(ByteArray& rhs) final { return 0; }
}
virtual Result<short> cmp(Arena&, ByteArray& rhs) final { return 0; }
virtual void move(Object* obj) final { virtual void move(Object* obj) final {
new (obj) ByteArray(std::move(_value)); new (obj) ByteArray(std::move(_value));
} }
static Result<ByteArray> create(Arena& arena, PodByteArray* obj) { static Result<ByteArray> create(PodByteArray* obj) {
return ByteArray(TRY(MkGcRoot(obj, arena))); return ByteArray(TRY(MkGcRoot(obj)));
} }
static Result<ByteArray> create(Arena& arena, char* chars, int64_t size) { static Result<ByteArray> create(char* chars, int64_t size) {
auto pod = TRY(arena.alloc<PodByteArray>(size * sizeof(char))); auto pod = TRY(arena_alloc<PodByteArray>(size * sizeof(char)));
pod->header.tag = Tag::ByteArray; pod->header.tag = Tag::ByteArray;
memcpy(pod->data, chars, size * sizeof(char32_t)); memcpy(pod->data, chars, size * sizeof(char32_t));
pod->size = size; pod->size = size;
return ByteArray(TRY(MkGcRoot(pod, arena))); return ByteArray(TRY(MkGcRoot(pod)));
} }
static Result<ByteArray> create(Arena& arena, const char* str) { static Result<ByteArray> create(const char* str) {
uint64_t size = strlen(str); uint64_t size = strlen(str);
auto pod = TRY(arena.alloc<PodByteArray>(size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodByteArray>(size * sizeof(char32_t)));
pod->header.tag = Tag::ByteArray; pod->header.tag = Tag::ByteArray;
memcpy(pod->data, str, size); memcpy(pod->data, str, size);
pod->size = size; pod->size = size;
return ByteArray(TRY(MkGcRoot(pod, arena))); return ByteArray(TRY(MkGcRoot(pod)));
} }
static Result<ByteArray> create(Arena& arena, String& str); static Result<ByteArray> create(String& str);
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
Result<char> operator[](uint64_t idx) { Result<char> operator[](uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange; if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
return _value->data[idx]; return _value->data[idx];
} }
Result<ByteArray> concat(Arena& arena, const char* rhs) { Result<ByteArray> concat(const char* rhs) {
uint64_t rhs_size = strlen(rhs); uint64_t rhs_size = strlen(rhs);
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodByteArray>(res_size * sizeof(char))); auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char) * lhs_size); memcpy(pod->data, _value->data, sizeof(char) * lhs_size);
memcpy(pod->data, rhs + lhs_size, sizeof(char) * rhs_size); memcpy(pod->data, rhs + lhs_size, sizeof(char) * rhs_size);
return ByteArray(TRY(MkGcRoot(pod, arena))); return ByteArray(TRY(MkGcRoot(pod)));
} }
Result<ByteArray> concat(Arena& arena, const char* rhs, uint64_t rhs_size) { Result<ByteArray> concat(const char* rhs, uint64_t rhs_size) {
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodByteArray>(res_size * sizeof(char))); auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char) * lhs_size); memcpy(pod->data, _value->data, sizeof(char) * lhs_size);
memcpy(pod->data, rhs + lhs_size, sizeof(char) * rhs_size); memcpy(pod->data, rhs + lhs_size, sizeof(char) * rhs_size);
return ByteArray(TRY(MkGcRoot(pod, arena))); return ByteArray(TRY(MkGcRoot(pod)));
} }
Result<ByteArray> concat(Arena& arena, ByteArray& rhs) { Result<ByteArray> concat(ByteArray& rhs) {
uint64_t rhs_size = rhs.size(); uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodByteArray>(res_size * sizeof(char))); auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char) * lhs_size); memcpy(pod->data, _value->data, sizeof(char) * lhs_size);
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size); memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size);
return ByteArray(TRY(MkGcRoot(pod, arena))); return ByteArray(TRY(MkGcRoot(pod)));
} }
Result<ByteArray> sub(Arena& arena, uint64_t start, uint64_t end) { Result<ByteArray> sub(uint64_t start, uint64_t end) {
if (start > end) return ErrorCode::IndexOutOfRange; if (start > end) return ErrorCode::IndexOutOfRange;
uint64_t res_size = end - start; uint64_t res_size = end - start;
auto pod = TRY(arena.alloc<PodByteArray>(res_size * sizeof(char))); auto pod = TRY(arena_alloc<PodByteArray>(res_size * sizeof(char)));
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data + start, sizeof(char) * res_size); memcpy(pod->data, _value->data + start, sizeof(char) * res_size);
return ByteArray(TRY(MkGcRoot(pod, arena))); return ByteArray(TRY(MkGcRoot(pod)));
} }
private: private:
@ -298,41 +278,37 @@ class Dict : public Object {
virtual Tag tag() final { return Tag::Dict; } virtual Tag tag() final { return Tag::Dict; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Dict& rhs) final;
}
virtual Result<short> cmp(Arena&, Dict& rhs) final;
virtual void move(Object* obj) final { new (obj) Dict(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Dict(std::move(_value)); }
static Result<Dict> create(Arena& arena, PodDict* obj) { static Result<Dict> create(PodDict* obj) { return Dict(TRY(MkGcRoot(obj))); }
return Dict(TRY(MkGcRoot(obj, arena)));
}
static Result<Dict> create(Arena& arena) { static Result<Dict> create() {
auto pod = TRY(arena.alloc<PodDict>()); auto pod = TRY(arena_alloc<PodDict>());
pod->header.tag = Tag::Dict; pod->header.tag = Tag::Dict;
pod->size = 0; pod->size = 0;
return Dict(TRY(MkGcRoot(pod, arena))); return Dict(TRY(MkGcRoot(pod)));
} }
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
virtual Result<Value> get(Arena& arena, Value& key) final; virtual Result<Value> get(Value& key) final;
Result<Dict> insert(Arena& arena, Value& key, Value& value); Result<Dict> insert(Value& key, Value& value);
template <class K, class V> template <class K, class V>
Result<Dict> insert(Arena& arena, const K& key, const V& value); Result<Dict> insert(const K& key, const V& value);
Result<Dict> concat(Arena& arena, Dict& rhs) { Result<Dict> concat(Dict& rhs) {
uint64_t rhs_size = rhs.size(); uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodDict>(2 * res_size * sizeof(PodObject*))); auto pod = TRY(arena_alloc<PodDict>(2 * res_size * sizeof(PodObject*)));
pod->size = res_size; pod->size = res_size;
for (uint64_t i = 0; i < 2 * size(); i++) { for (uint64_t i = 0; i < 2 * size(); i++) {
@ -342,11 +318,11 @@ class Dict : public Object {
pod->data[i] = rhs._value->data[i]; pod->data[i] = rhs._value->data[i];
} }
return Dict(TRY(MkGcRoot(pod, arena))); return Dict(TRY(MkGcRoot(pod)));
} }
private: private:
Result<uint64_t> find(Arena& arena, Value& key); Result<uint64_t> find(Value& key);
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
GcRoot<PodDict> _value; GcRoot<PodDict> _value;
@ -365,10 +341,8 @@ class String : public Object {
virtual Tag tag() final { return Tag::String; } virtual Tag tag() final { return Tag::String; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(String& rhs) final {
}
virtual Result<short> cmp(Arena&, String& rhs) final {
auto lsize = size(); auto lsize = size();
auto rsize = rhs.size(); auto rsize = rhs.size();
uint64_t i = 0; uint64_t i = 0;
@ -391,88 +365,88 @@ class String : public Object {
virtual void move(Object* obj) final { new (obj) String(std::move(_value)); } virtual void move(Object* obj) final { new (obj) String(std::move(_value)); }
static Result<String> create(Arena& arena, PodString* obj) { static Result<String> create(PodString* obj) {
return String(TRY(MkGcRoot(obj, arena))); return String(TRY(MkGcRoot(obj)));
} }
static Result<String> create(Arena& arena, char32_t* chars, int64_t size) { static Result<String> create(char32_t* chars, int64_t size) {
auto pod = TRY(arena.alloc<PodString>(size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodString>(size * sizeof(char32_t)));
pod->header.tag = Tag::String; pod->header.tag = Tag::String;
memcpy(pod->data, chars, size * sizeof(char32_t)); memcpy(pod->data, chars, size * sizeof(char32_t));
pod->size = size; pod->size = size;
return String(TRY(MkGcRoot(pod, arena))); return String(TRY(MkGcRoot(pod)));
} }
static Result<String> create(Arena& arena, const char* str) { static Result<String> create(const char* str) {
uint64_t size = strlen(str); uint64_t size = strlen(str);
auto pod = TRY(arena.alloc<PodString>(size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodString>(size * sizeof(char32_t)));
pod->header.tag = Tag::String; pod->header.tag = Tag::String;
for (uint64_t i = 0; i < size; i++) pod->data[i] = str[i]; for (uint64_t i = 0; i < size; i++) pod->data[i] = str[i];
pod->size = size; pod->size = size;
return String(TRY(MkGcRoot(pod, arena))); return String(TRY(MkGcRoot(pod)));
} }
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
Result<char32_t> operator[](uint64_t idx) { Result<char32_t> operator[](uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange; if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
return _value->data[idx]; return _value->data[idx];
} }
Result<String> concat(Arena& arena, const char* rhs) { Result<String> concat(const char* rhs) {
uint64_t rhs_size = strlen(rhs); uint64_t rhs_size = strlen(rhs);
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodString>(res_size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
pod->header.tag = Tag::String; pod->header.tag = Tag::String;
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size); memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size);
for (uint64_t i = 0; i < rhs_size; i++) pod->data[lhs_size + i] = rhs[i]; for (uint64_t i = 0; i < rhs_size; i++) pod->data[lhs_size + i] = rhs[i];
return String(TRY(MkGcRoot(pod, arena))); return String(TRY(MkGcRoot(pod)));
} }
Result<String> concat(Arena& arena, const char32_t* rhs, uint64_t rhs_size) { Result<String> concat(const char32_t* rhs, uint64_t rhs_size) {
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodString>(res_size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
pod->header.tag = Tag::String; pod->header.tag = Tag::String;
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size); memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size);
for (uint64_t i = 0; i < rhs_size; i++) pod->data[lhs_size + i] = rhs[i]; for (uint64_t i = 0; i < rhs_size; i++) pod->data[lhs_size + i] = rhs[i];
return String(TRY(MkGcRoot(pod, arena))); return String(TRY(MkGcRoot(pod)));
} }
Result<String> concat(Arena& arena, String& rhs) { Result<String> concat(String& rhs) {
uint64_t rhs_size = rhs.size(); uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodString>(res_size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
pod->header.tag = Tag::String; pod->header.tag = Tag::String;
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size); memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size);
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char32_t) * rhs_size); memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char32_t) * rhs_size);
return String(TRY(MkGcRoot(pod, arena))); return String(TRY(MkGcRoot(pod)));
} }
Result<String> sub(Arena& arena, uint64_t start, uint64_t end) { Result<String> sub(uint64_t start, uint64_t end) {
if (start > end) return ErrorCode::IndexOutOfRange; if (start > end) return ErrorCode::IndexOutOfRange;
uint64_t res_size = end - start; uint64_t res_size = end - start;
auto pod = TRY(arena.alloc<PodString>(res_size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodString>(res_size * sizeof(char32_t)));
pod->header.tag = Tag::String; pod->header.tag = Tag::String;
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data + start, sizeof(char32_t) * res_size); memcpy(pod->data, _value->data + start, sizeof(char32_t) * res_size);
return String(TRY(MkGcRoot(pod, arena))); return String(TRY(MkGcRoot(pod)));
} }
friend class Symbol; friend class Symbol;
@ -488,10 +462,8 @@ class Symbol : public Object {
Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {} Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Symbol; } virtual Tag tag() final { return Tag::Symbol; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Symbol& rhs) final {
}
virtual Result<short> cmp(Arena&, Symbol& rhs) final {
auto lsize = size(); auto lsize = size();
auto rsize = rhs.size(); auto rsize = rhs.size();
uint64_t i = 0; uint64_t i = 0;
@ -513,32 +485,32 @@ class Symbol : public Object {
} }
virtual void move(Object* obj) final { new (obj) Symbol(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Symbol(std::move(_value)); }
static Result<Symbol> create(Arena& arena, PodSymbol* obj) { static Result<Symbol> create(PodSymbol* obj) {
return Symbol(TRY(MkGcRoot(obj, arena))); return Symbol(TRY(MkGcRoot(obj)));
} }
static Result<Symbol> create(Arena& arena, char32_t* chars, int64_t size) { static Result<Symbol> create(char32_t* chars, int64_t size) {
auto pod = TRY(arena.alloc<PodSymbol>(size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodSymbol>(size * sizeof(char32_t)));
pod->header.tag = Tag::Symbol; pod->header.tag = Tag::Symbol;
memcpy(pod->data, chars, size * sizeof(char32_t)); memcpy(pod->data, chars, size * sizeof(char32_t));
return Symbol(TRY(MkGcRoot(pod, arena))); return Symbol(TRY(MkGcRoot(pod)));
} }
static Result<Symbol> create(Arena& arena, const char* str) { static Result<Symbol> create(const char* str) {
uint64_t size = strlen(str); uint64_t size = strlen(str);
auto pod = TRY(arena.alloc<PodSymbol>(size * sizeof(char32_t))); auto pod = TRY(arena_alloc<PodSymbol>(size * sizeof(char32_t)));
pod->header.tag = Tag::Symbol; pod->header.tag = Tag::Symbol;
for (uint64_t i = 0; i < size; i++) pod->data[i] = str[i]; for (uint64_t i = 0; i < size; i++) pod->data[i] = str[i];
pod->size = size; pod->size = size;
return Symbol(TRY(MkGcRoot(pod, arena))); return Symbol(TRY(MkGcRoot(pod)));
} }
static Result<Symbol> create(Arena& arena, String& rhs); static Result<Symbol> create(String& rhs);
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
@ -559,20 +531,18 @@ class Syntax : public Object {
Syntax(String filename, String modulename, Value expression); Syntax(String filename, String modulename, Value expression);
virtual Tag tag() final { return Tag::Syntax; } virtual Tag tag() final { return Tag::Syntax; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Syntax& rhs) final { return 0; }
}
virtual Result<short> cmp(Arena&, Syntax& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Syntax(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Syntax(std::move(_value)); }
static Result<Syntax> create(Arena& arena, PodSyntax* obj) { static Result<Syntax> create(PodSyntax* obj) {
return Syntax(TRY(MkGcRoot(obj, arena))); return Syntax(TRY(MkGcRoot(obj)));
} }
Result<Value> get_value(Arena& arena); Result<Value> get_value();
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
private: private:
GcRoot<PodSyntax> _value; GcRoot<PodSyntax> _value;
@ -585,22 +555,18 @@ class Pair : public Object {
Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {} Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Pair; } virtual Tag tag() final { return Tag::Pair; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Pair& rhs) final { return 0; }
}
virtual Result<short> cmp(Arena&, Pair& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Pair(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Pair(std::move(_value)); }
static Result<Pair> create(Arena& arena, PodPair* obj) { static Result<Pair> create(PodPair* obj) { return Pair(TRY(MkGcRoot(obj))); }
return Pair(TRY(MkGcRoot(obj, arena))); static Result<Pair> create(Value& first, Value& rest);
}
static Result<Pair> create(Arena& arena, Value& first, Value& rest);
Result<Value> first(Arena& arena); Result<Value> first();
Result<Value> rest(Arena& arena); Result<Value> rest();
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
private: private:
GcRoot<PodPair> _value; GcRoot<PodPair> _value;
@ -615,32 +581,30 @@ class Int64 : public Object {
Int64(GcRoot<PodInt64>&& val) : _value(std::move(val)) {} Int64(GcRoot<PodInt64>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Int64; } virtual Tag tag() final { return Tag::Int64; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Int64& rhs) final {
}
virtual Result<short> cmp(Arena&, Int64& rhs) final {
return (_value->value > rhs._value->value) - return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value); (_value->value < rhs._value->value);
} }
virtual Result<short> cmp(Arena&, Float& rhs) final; virtual Result<short> cmp(Float& rhs) final;
virtual void move(Object* obj) final { new (obj) Int64(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Int64(std::move(_value)); }
static Result<Int64> create(Arena& arena, PodInt64* obj) { static Result<Int64> create(PodInt64* obj) {
return Int64(TRY(MkGcRoot(obj, arena))); return Int64(TRY(MkGcRoot(obj)));
} }
static Result<Int64> create(Arena& arena, double val) { static Result<Int64> create(double val) {
auto pod = TRY(arena.alloc<PodInt64>()); auto pod = TRY(arena_alloc<PodInt64>());
pod->header.tag = Tag::Int64; pod->header.tag = Tag::Int64;
pod->value = val; pod->value = val;
return Int64(TRY(MkGcRoot(pod, arena))); return Int64(TRY(MkGcRoot(pod)));
} }
int64_t value() { return _value->value; } int64_t value() { return _value->value; }
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
private: private:
GcRoot<PodInt64> _value; GcRoot<PodInt64> _value;
@ -655,32 +619,30 @@ class Float : public Object {
Float(GcRoot<PodFloat>&& val) : _value(std::move(val)) {} Float(GcRoot<PodFloat>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Float; } virtual Tag tag() final { return Tag::Float; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Float& rhs) final {
}
virtual Result<short> cmp(Arena&, Float& rhs) final {
return (_value->value > rhs._value->value) - return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value); (_value->value < rhs._value->value);
} }
virtual Result<short> cmp(Arena&, Int64& rhs) final; virtual Result<short> cmp(Int64& rhs) final;
virtual void move(Object* obj) final { new (obj) Float(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Float(std::move(_value)); }
static Result<Float> create(Arena& arena, PodFloat* obj) { static Result<Float> create(PodFloat* obj) {
return Float(TRY(MkGcRoot(obj, arena))); return Float(TRY(MkGcRoot(obj)));
} }
static Result<Float> create(Arena& arena, double val) { static Result<Float> create(double val) {
auto pod = TRY(arena.alloc<PodFloat>()); auto pod = TRY(arena_alloc<PodFloat>());
pod->header.tag = Tag::Float; pod->header.tag = Tag::Float;
pod->value = val; pod->value = val;
return Float(TRY(MkGcRoot(pod, arena))); return Float(TRY(MkGcRoot(pod)));
} }
double value() { return _value->value; } double value() { return _value->value; }
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
private: private:
GcRoot<PodFloat> _value; GcRoot<PodFloat> _value;
@ -694,28 +656,24 @@ class Bool : public Object {
virtual Tag tag() final { return Tag::Bool; } virtual Tag tag() final { return Tag::Bool; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Arena& arena, Object& rhs) final { virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
return -TRY(rhs.cmp(arena, *this)); virtual Result<short> cmp(Bool& rhs) final { return 0; }
}
virtual Result<short> cmp(Arena&, Bool& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Bool(std::move(_value)); } virtual void move(Object* obj) final { new (obj) Bool(std::move(_value)); }
static Result<Bool> create(Arena& arena, PodBool* obj) { static Result<Bool> create(PodBool* obj) { return Bool(TRY(MkGcRoot(obj))); }
return Bool(TRY(MkGcRoot(obj, arena)));
}
static Result<Bool> create(Arena& arena, bool val) { static Result<Bool> create(bool val) {
auto pod = TRY(arena.alloc<PodBool>()); auto pod = TRY(arena_alloc<PodBool>());
pod->header.tag = Tag::Bool; pod->header.tag = Tag::Bool;
pod->value = val; pod->value = val;
return Bool(TRY(MkGcRoot(pod, arena))); return Bool(TRY(MkGcRoot(pod)));
} }
bool value() { return _value->value; } bool value() { return _value->value; }
virtual Result<Value> copy(Arena& arena) const final; virtual Result<Value> copy() const final;
private: private:
GcRoot<PodBool> _value; GcRoot<PodBool> _value;
@ -746,14 +704,14 @@ class Value {
return *this; return *this;
} }
static Result<Value> create(Arena& arena, PodObject* obj); static Result<Value> create(PodObject* obj);
static Result<Value> create(Arena& arena, const int64_t& value) { static Result<Value> create(const int64_t& value) {
return Value(TRY(Int64::create(arena, value))); return Value(TRY(Int64::create(value)));
} }
static Result<Value> create(Arena& arena, const char* value) { static Result<Value> create(const char* value) {
return Value(TRY(String::create(arena, value))); return Value(TRY(String::create(value)));
} }
template <class T> template <class T>
@ -772,23 +730,21 @@ class Value {
Object& operator*() { return *(Object*)(buf); } Object& operator*() { return *(Object*)(buf); }
Object* operator->() { return (Object*)(buf); } Object* operator->() { return (Object*)(buf); }
Result<short> cmp(Arena& arena, Value& rhs) { Result<short> cmp(Value& rhs) {
return ((Object*)buf)->cmp(arena, *(Object*)rhs.buf); return ((Object*)buf)->cmp(*(Object*)rhs.buf);
} }
Result<Value> get(Arena& arena, Value& key) { Result<Value> get(Value& key) { return ((Object*)buf)->get(key); }
return ((Object*)buf)->get(arena, key); Result<Value> get(int64_t key) {
} Value k = TRY(Int64::create(key));
Result<Value> get(Arena& arena, int64_t key) { return ((Object*)buf)->get(k);
Value k = TRY(Int64::create(arena, key));
return ((Object*)buf)->get(arena, k);
} }
// TODO: cmp() probably doesn't need arena parameter // TODO: cmp() probably doesn't need arena parameter
// Result<bool> operator==(Value& rhs) { return TRY(cmp(rhs)) == 0; } // Result<bool> operator==(Value& rhs) { return TRY(cmp(rhs)) == 0; }
// Result<bool> operator!=(Value& rhs) { return TRY(cmp(rhs)) != 0; } // Result<bool> operator!=(Value& rhs) { return TRY(cmp(rhs)) != 0; }
Result<Value> copy(Arena& arena) const { return ((Object*)buf)->copy(arena); } Result<Value> copy() const { return ((Object*)buf)->copy(); }
private: private:
uint8_t buf[24]; uint8_t buf[24];
@ -796,21 +752,21 @@ class Value {
Result<Value> syntax_unwrap(Value& val); Result<Value> syntax_unwrap(Value& val);
Result<Value> reverse(Arena& arena, Value& val); Result<Value> reverse(Value& val);
Result<void> debug_print(Arena& arena, String& val); Result<void> debug_print(String& val);
Result<void> debug_print(Arena& arena, Value& val); Result<void> debug_print(Value& val);
template <class K, class V> template <class K, class V>
Result<Dict> Dict::insert(Arena& arena, const K& key, const V& value) { Result<Dict> Dict::insert(const K& key, const V& value) {
Value k = TRY(Value::create(arena, key)); Value k = TRY(Value::create(key));
Value v = TRY(Value::create(arena, value)); Value v = TRY(Value::create(value));
return insert(arena, k, v); return insert(k, v);
} }
template <class V> template <class V>
Result<Array> Array::append(Arena& arena, const V& value) { Result<Array> Array::append(const V& value) {
Value v = TRY(Value::create(arena, value)); Value v = TRY(Value::create(value));
return append(arena, v); return append(v);
} }

View file

@ -8,9 +8,9 @@ struct Context {
maxreg(0), maxreg(0),
maxconst(0) {} maxconst(0) {}
static Result<Context> create(Arena& arena) { static Result<Context> create() {
auto env = TRY(Nil::create(arena)); auto env = TRY(Nil::create());
auto constants = TRY(Array::create(arena)); auto constants = TRY(Array::create());
return Context(std::move(env), std::move(constants)); return Context(std::move(env), std::move(constants));
} }
@ -27,7 +27,7 @@ bool is_primitive_op(Symbol& sym) {
} }
Result<Value> Compiler::compile(Value& expr) { Result<Value> Compiler::compile(Value& expr) {
auto context = TRY(Context::create(_arena)); auto context = TRY(Context::create());
TRY(compile_expr(context, expr)); TRY(compile_expr(context, expr));
return ErrorCode::NotImplemented; return ErrorCode::NotImplemented;
@ -52,7 +52,7 @@ Result<Expression> Compiler::compile_expr(Context& context, Value& expr) {
} }
Result<Expression> Compiler::compile_list(Context& context, Pair& expr) { Result<Expression> Compiler::compile_list(Context& context, Pair& expr) {
auto first = TRY(expr.first(_arena)); auto first = TRY(expr.first());
if (first.is<Symbol>()) { if (first.is<Symbol>()) {
Symbol& sym = *first.to<Symbol>(); Symbol& sym = *first.to<Symbol>();

View file

@ -13,12 +13,9 @@ struct Expression {
class Compiler { class Compiler {
public: public:
Compiler(Arena& arena) : _arena(arena) {} Compiler() {}
Result<Value> compile(Value& expr); Result<Value> compile(Value& expr);
Result<Expression> compile_expr(Context& context, Value& expr); Result<Expression> compile_expr(Context& context, Value& expr);
Result<Expression> compile_list(Context& context, Pair& expr); Result<Expression> compile_list(Context& context, Pair& expr);
private:
Arena& _arena;
}; };

View file

@ -73,16 +73,16 @@ Result<Value> Reader::read_one() {
} }
Result<Value> Reader::read_multiple() { Result<Value> Reader::read_multiple() {
Value res = TRY(Nil::create(_arena)); Value res = TRY(Nil::create());
while (1) { while (1) {
forward_whitespace(); forward_whitespace();
if (is_eof()) { if (is_eof()) {
return reverse(_arena, res); return reverse(res);
} }
auto val = TRY(read_one()); auto val = TRY(read_one());
res = Value(TRY(Pair::create(_arena, val, res))); res = Value(TRY(Pair::create(val, res)));
} }
return ErrorCode::ReadError; return ErrorCode::ReadError;
@ -93,7 +93,7 @@ Result<Value> Reader::read_list() {
forward(); forward();
Value res = TRY(Nil::create(_arena)); Value res = TRY(Nil::create());
while (1) { while (1) {
forward_whitespace(); forward_whitespace();
@ -104,12 +104,12 @@ Result<Value> Reader::read_list() {
if (match(')')) { if (match(')')) {
forward(); forward();
return reverse(_arena, res); return reverse(res);
} }
auto val = TRY(read_one()); auto val = TRY(read_one());
res = Value(TRY(Pair::create(_arena, val, res))); res = Value(TRY(Pair::create(val, res)));
} }
return ErrorCode::ReadError; return ErrorCode::ReadError;
@ -120,7 +120,7 @@ Result<Value> Reader::read_dict() {
forward(); forward();
auto res = TRY(Dict::create(_arena)); auto res = TRY(Dict::create());
while (1) { while (1) {
forward_whitespace(); forward_whitespace();
@ -137,7 +137,7 @@ Result<Value> Reader::read_dict() {
auto val1 = TRY(read_one()); auto val1 = TRY(read_one());
auto val2 = TRY(read_one()); auto val2 = TRY(read_one());
res = TRY(res.insert(_arena, val1, val2)); res = TRY(res.insert(val1, val2));
} }
return ErrorCode::ReadError; return ErrorCode::ReadError;
@ -146,12 +146,12 @@ Result<Value> Reader::read_bool() {
if (match("true")) { if (match("true")) {
forward(4); forward(4);
if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError;
return Value(TRY(Bool::create(_arena, true))); return Value(TRY(Bool::create(true)));
} }
if (match("false")) { if (match("false")) {
forward(5); forward(5);
if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError;
return Value(TRY(Bool::create(_arena, false))); return Value(TRY(Bool::create(false)));
} }
return ErrorCode::ReadError; return ErrorCode::ReadError;
@ -175,13 +175,13 @@ Result<Value> Reader::read_string() {
forward(); forward();
String result = TRY(String::create(_arena, "")); String result = TRY(String::create(""));
for (size_t i = 0; i < position_.offset - start - 1; i++) { for (size_t i = 0; i < position_.offset - start - 1; i++) {
char32_t cur = TRY(_str[start + i]); char32_t cur = TRY(_str[start + i]);
if (cur != '\\') { if (cur != '\\') {
// TODO: optimize this // TODO: optimize this
result = TRY(result.concat(_arena, &cur, 1)); result = TRY(result.concat(&cur, 1));
continue; continue;
} }
++i; ++i;
@ -189,32 +189,32 @@ Result<Value> Reader::read_string() {
char32_t next = TRY(_str[start + i]); char32_t next = TRY(_str[start + i]);
if (next == '\0') { if (next == '\0') {
result = TRY(result.concat(_arena, "\0")); result = TRY(result.concat("\0"));
continue; continue;
} }
switch (next) { switch (next) {
case 'b': case 'b':
result = TRY(result.concat(_arena, "\b")); result = TRY(result.concat("\b"));
continue; continue;
case 'f': case 'f':
result = TRY(result.concat(_arena, "\f")); result = TRY(result.concat("\f"));
continue; continue;
case 'n': case 'n':
result = TRY(result.concat(_arena, "\n")); result = TRY(result.concat("\n"));
continue; continue;
case 'r': case 'r':
result = TRY(result.concat(_arena, "\r")); result = TRY(result.concat("\r"));
continue; continue;
case 't': case 't':
result = TRY(result.concat(_arena, "\t")); result = TRY(result.concat("\t"));
continue; continue;
case 'v': case 'v':
result = TRY(result.concat(_arena, "\v")); result = TRY(result.concat("\v"));
continue; continue;
} }
result = TRY(result.concat(_arena, "\\")); result = TRY(result.concat("\\"));
result = TRY(result.concat(_arena, &next, 1)); result = TRY(result.concat(&next, 1));
} }
if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError;
@ -274,12 +274,12 @@ Result<Value> Reader::read_number() {
buf[position_.offset - start] = '\0'; buf[position_.offset - start] = '\0';
if (is_float) { if (is_float) {
res = Value(TRY(Float::create(_arena, strtod(buf, 0)))); res = Value(TRY(Float::create(strtod(buf, 0))));
if (match("f64")) { if (match("f64")) {
forward(3); forward(3);
} }
} else { } else {
res = Value(TRY(Int64::create(_arena, strtoll(buf, 0, 10)))); res = Value(TRY(Int64::create(strtoll(buf, 0, 10))));
} }
if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError;
@ -296,11 +296,11 @@ Result<Value> Reader::read_symbol() {
size_t end = position_.offset; size_t end = position_.offset;
String str = TRY(_str.sub(_arena, start, end)); String str = TRY(_str.sub(start, end));
if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError; if (!is_separator(get()) && !is_eof()) return ErrorCode::ReadError;
return Value(TRY(Symbol::create(_arena, str))); return Value(TRY(Symbol::create(str)));
} }
char32_t Reader::get(size_t offset) { char32_t Reader::get(size_t offset) {
@ -409,17 +409,17 @@ bool Reader::forward_exponent() {
return forward_decimal_number(); return forward_decimal_number();
} }
Result<Value> read_one(Arena& arena, Value& value) { Result<Value> read_one(Value& value) {
if (!value.is<String>()) return ErrorCode::TypeMismatch; if (!value.is<String>()) return ErrorCode::TypeMismatch;
auto r = Reader(arena, *value.to<String>()); auto r = Reader(*value.to<String>());
return r.read_one(); return r.read_one();
} }
Result<Value> read_one(Arena& arena, String& value) { Result<Value> read_one(String& value) {
auto r = Reader(arena, value); auto r = Reader(value);
return r.read_one(); return r.read_one();
} }
Result<Value> read_one(Arena& arena, const char* value) { Result<Value> read_one(const char* value) {
auto s = TRY(String::create(arena, value)); auto s = TRY(String::create(value));
auto r = Reader(arena, s); auto r = Reader(s);
return r.read_one(); return r.read_one();
} }

View file

@ -5,7 +5,7 @@
class Reader { class Reader {
public: public:
Reader(Arena& arena, String& str) : _arena(arena), _str(str) {} Reader(String& str) : _str(str) {}
Result<Value> read_one(); Result<Value> read_one();
Result<Value> read_multiple(); Result<Value> read_multiple();
@ -38,11 +38,10 @@ class Reader {
bool match(const char* str); bool match(const char* str);
bool match(char c); bool match(char c);
Arena& _arena;
String& _str; String& _str;
SourcePosition position_{1, 1, 0}; SourcePosition position_{1, 1, 0};
}; };
Result<Value> read_one(Arena& arena, Value& value); Result<Value> read_one(Value& value);
Result<Value> read_one(Arena& arena, String& value); Result<Value> read_one(String& value);
Result<Value> read_one(Arena& arena, const char* value); Result<Value> read_one(const char* value);

View file

@ -9,19 +9,19 @@
StaticArena<64 * 1024 * 1024> arena; StaticArena<64 * 1024 * 1024> arena;
int main() { int main() {
auto s = DIEX(String::create(arena, "(+ 1 2 3)")); auto s = DIEX(String::create("(+ 1 2 3)"));
auto reader = Reader(arena, s); auto reader = Reader(s);
auto r = DIEX(reader.read_one()); auto r = DIEX(reader.read_one());
auto writer = Writer(arena); auto writer = Writer();
auto s2 = DIEX(writer.write_one(r)); auto s2 = DIEX(writer.write_one(r));
DIEX(arena.gc()); DIEX(arena_gc());
DIEX(debug_print(arena, s2)); DIEX(debug_print(s2));
Compiler c = Compiler(arena); Compiler c = Compiler();
auto compiled = DIEX(c.compile(r)); auto compiled = DIEX(c.compile(r));
return 0; return 0;

View file

@ -33,7 +33,7 @@ Result<String> Writer::write_int64(Int64& val) {
sprintf(tmp, "%lu", val.value()); sprintf(tmp, "%lu", val.value());
size_t len = strlen(tmp); size_t len = strlen(tmp);
return String::create(_arena, tmp); return String::create(tmp);
} }
bool needs_dot(char* str) { bool needs_dot(char* str) {
@ -58,17 +58,15 @@ Result<String> Writer::write_float(Float& val) {
len += 2; len += 2;
} }
return String::create(_arena, tmp); return String::create(tmp);
} }
Result<String> Writer::write_nil(Nil& val) { Result<String> Writer::write_nil(Nil& val) { return String::create("nil"); }
return String::create(_arena, "nil");
}
Result<String> Writer::write_bool(Bool& val) { Result<String> Writer::write_bool(Bool& val) {
if (val.value()) return String::create(_arena, "true"); if (val.value()) return String::create("true");
return String::create(_arena, "false"); return String::create("false");
} }
Result<String> Writer::write_bytearray(ByteArray& val) { Result<String> Writer::write_bytearray(ByteArray& val) {
@ -76,7 +74,7 @@ Result<String> Writer::write_bytearray(ByteArray& val) {
} }
Result<String> Writer::write_string(String& val) { Result<String> Writer::write_string(String& val) {
String res = TRY(String::create(_arena, "\"")); String res = TRY(String::create("\""));
// TODO: optimize this // TODO: optimize this
for (uint64_t i = 0; i < val.size(); i++) { for (uint64_t i = 0; i < val.size(); i++) {
@ -103,13 +101,13 @@ Result<String> Writer::write_string(String& val) {
}; };
if (replace != 0) { if (replace != 0) {
res = TRY(res.concat(_arena, replace)); res = TRY(res.concat(replace));
} else { } else {
res = TRY(res.concat(_arena, &c, 1)); res = TRY(res.concat(&c, 1));
} }
} }
res = TRY(res.concat(_arena, "\"")); res = TRY(res.concat("\""));
return res; return res;
} }
@ -127,7 +125,7 @@ int is_valid_symbol_char(char32_t codepoint) {
} }
Result<String> Writer::write_symbol(Symbol& val) { Result<String> Writer::write_symbol(Symbol& val) {
String res = TRY(String::create(_arena, "")); String res = TRY(String::create(""));
// TODO: optimize this // TODO: optimize this
for (uint64_t i = 0; i < val.size(); i++) { for (uint64_t i = 0; i < val.size(); i++) {
@ -135,7 +133,7 @@ Result<String> Writer::write_symbol(Symbol& val) {
if (!is_valid_symbol_char(c)) return ErrorCode::InvalidSymbol; if (!is_valid_symbol_char(c)) return ErrorCode::InvalidSymbol;
res = TRY(res.concat(_arena, &c, 1)); res = TRY(res.concat(&c, 1));
} }
return res; return res;
@ -146,9 +144,9 @@ Result<String> Writer::write_syntax(Syntax& val) {
} }
Result<String> Writer::write_pair(Pair& val) { Result<String> Writer::write_pair(Pair& val) {
String res = TRY(String::create(_arena, "(")); String res = TRY(String::create("("));
Value cur = TRY(val.copy(_arena)); Value cur = TRY(val.copy());
bool is_first = true; bool is_first = true;
while (!cur.is<Nil>()) { while (!cur.is<Nil>()) {
@ -156,65 +154,65 @@ Result<String> Writer::write_pair(Pair& val) {
Pair& pair = *cur.to<Pair>(); Pair& pair = *cur.to<Pair>();
Value first = TRY(pair.first(_arena)); Value first = TRY(pair.first());
if (!is_first) res = TRY(res.concat(_arena, " ")); if (!is_first) res = TRY(res.concat(" "));
String first_str = TRY(write_one(first)); String first_str = TRY(write_one(first));
res = TRY(res.concat(_arena, first_str)); res = TRY(res.concat(first_str));
cur = TRY(pair.rest(_arena)); cur = TRY(pair.rest());
is_first = false; is_first = false;
} }
res = TRY(res.concat(_arena, ")")); res = TRY(res.concat(")"));
return res; return res;
} }
Result<String> Writer::write_array(Array& val) { Result<String> Writer::write_array(Array& val) {
String res = TRY(String::create(_arena, "[")); String res = TRY(String::create("["));
bool is_first = true; bool is_first = true;
for (uint64_t i = 0; i < val.size(); i++) { for (uint64_t i = 0; i < val.size(); i++) {
Value cur = TRY(val.get(_arena, i)); Value cur = TRY(val.get(i));
if (!is_first) res = TRY(res.concat(_arena, " ")); if (!is_first) res = TRY(res.concat(" "));
String first_str = TRY(write_one(cur)); String first_str = TRY(write_one(cur));
res = TRY(res.concat(_arena, first_str)); res = TRY(res.concat(first_str));
is_first = false; is_first = false;
} }
res = TRY(res.concat(_arena, "]")); res = TRY(res.concat("]"));
return res; return res;
} }
Result<String> Writer::write_dict(Dict& val) { Result<String> Writer::write_dict(Dict& val) {
String res = TRY(String::create(_arena, "{")); String res = TRY(String::create("{"));
bool is_first = true; bool is_first = true;
for (uint64_t i = 0; i < val.size(); i++) { for (uint64_t i = 0; i < val.size(); i++) {
Value k = TRY(Value::create(_arena, val._value->data[i * 2].get())); Value k = TRY(Value::create(val._value->data[i * 2].get()));
Value v = TRY(Value::create(_arena, val._value->data[i * 2 + 1].get())); Value v = TRY(Value::create(val._value->data[i * 2 + 1].get()));
if (!is_first) res = TRY(res.concat(_arena, " ")); if (!is_first) res = TRY(res.concat(" "));
String first_str = TRY(write_one(k)); String first_str = TRY(write_one(k));
res = TRY(res.concat(_arena, first_str)); res = TRY(res.concat(first_str));
res = TRY(res.concat(_arena, " ")); res = TRY(res.concat(" "));
String second_str = TRY(write_one(v)); String second_str = TRY(write_one(v));
res = TRY(res.concat(_arena, second_str)); res = TRY(res.concat(second_str));
is_first = false; is_first = false;
} }
res = TRY(res.concat(_arena, "}")); res = TRY(res.concat("}"));
return res; return res;
} }
Result<String> write_one(Arena& arena, Value& value) { Result<String> write_one(Value& value) {
auto w = Writer(arena); auto w = Writer();
return w.write_one(value); return w.write_one(value);
} }

View file

@ -5,7 +5,7 @@
class Writer { class Writer {
public: public:
Writer(Arena& arena) : _arena(arena){}; Writer(){};
Result<String> write_one(Value& obj); Result<String> write_one(Value& obj);
Result<String> write_multiple(Value& obj); Result<String> write_multiple(Value& obj);
@ -22,17 +22,15 @@ class Writer {
Result<String> write_dict(Dict& val); Result<String> write_dict(Dict& val);
Result<String> write_symbol(Symbol& val); Result<String> write_symbol(Symbol& val);
Result<String> write_syntax(Syntax& val); Result<String> write_syntax(Syntax& val);
Arena& _arena;
}; };
Result<String> write_one(Arena& arena, Value& value); Result<String> write_one(Value& value);
template <class T> template <class T>
Result<String> write_one(Arena& arena, T& value) Result<String> write_one(T& value)
requires std::derived_from<T, Object> requires std::derived_from<T, Object>
{ {
auto w = Writer(arena); auto w = Writer();
auto v = DIEX(value.copy(arena)); auto v = DIEX(value.copy());
return w.write_one(v); return w.write_one(v);
} }

View file

@ -7,20 +7,20 @@
StaticArena<64 * 1024 * 1024> arena; StaticArena<64 * 1024 * 1024> arena;
TEST_CASE(array_append) { TEST_CASE(array_append) {
auto a = DIEX(Array::create(arena)); auto a = DIEX(Array::create());
a = DIEX(a.append(arena, 1)); a = DIEX(a.append(1));
a = DIEX(a.append(arena, 2)); a = DIEX(a.append(2));
a = DIEX(a.append(arena, 3)); a = DIEX(a.append(3));
DIEX(arena.gc()); DIEX(arena_gc());
auto s = DIEX(write_one(arena, a)); auto s = DIEX(write_one(a));
DIEX(arena.gc()); DIEX(arena_gc());
ASSERT_EQUALS(s, "[1 2 3]"); ASSERT_EQUALS(s, "[1 2 3]");
auto v = DIEX(a.get(arena, 1)); auto v = DIEX(a.get(1));
ASSERT_EQUALS(v, 2); ASSERT_EQUALS(v, 2);
} }

View file

@ -7,33 +7,33 @@
StaticArena<64 * 1024 * 1024> arena; StaticArena<64 * 1024 * 1024> arena;
TEST_CASE(dict_insert) { TEST_CASE(dict_insert) {
auto d = DIEX(Dict::create(arena)); auto d = DIEX(Dict::create());
d = DIEX(d.insert(arena, 1, 2)); d = DIEX(d.insert(1, 2));
d = DIEX(d.insert(arena, 1, 3)); d = DIEX(d.insert(1, 3));
d = DIEX(d.insert(arena, 3, 3)); d = DIEX(d.insert(3, 3));
d = DIEX(d.insert(arena, 0, 4)); d = DIEX(d.insert(0, 4));
d = DIEX(d.insert(arena, 0, 5)); d = DIEX(d.insert(0, 5));
d = DIEX(d.insert(arena, 2, 6)); d = DIEX(d.insert(2, 6));
DIEX(arena.gc()); DIEX(arena_gc());
auto s = DIEX(write_one(arena, d)); auto s = DIEX(write_one(d));
DIEX(arena.gc()); DIEX(arena_gc());
ASSERT_EQUALS(s, "{0 5 1 3 2 6 3 3}"); ASSERT_EQUALS(s, "{0 5 1 3 2 6 3 3}");
} }
TEST_CASE(dict_read) { TEST_CASE(dict_read) {
auto v = DIEX(read_one(arena, "{}")); auto v = DIEX(read_one("{}"));
auto s = DIEX(write_one(arena, v)); auto s = DIEX(write_one(v));
ASSERT_EQUALS(s, "{}"); ASSERT_EQUALS(s, "{}");
v = DIEX(read_one(arena, "{1 2 3 4}")); v = DIEX(read_one("{1 2 3 4}"));
s = DIEX(write_one(arena, v)); s = DIEX(write_one(v));
ASSERT_EQUALS(s, "{1 2 3 4}"); ASSERT_EQUALS(s, "{1 2 3 4}");
auto vv = DIEX(v.get(arena, 1)); auto vv = DIEX(v.get(1));
ASSERT_EQUALS(vv, 2); ASSERT_EQUALS(vv, 2);
} }

View file

@ -7,14 +7,14 @@
StaticArena<64 * 1024 * 1024> arena; StaticArena<64 * 1024 * 1024> arena;
TEST_CASE(symbol_basic) { TEST_CASE(symbol_basic) {
auto a = DIEX(Symbol::create(arena, "foo")); auto a = DIEX(Symbol::create("foo"));
auto b = DIEX(Symbol::create(arena, "foo")); auto b = DIEX(Symbol::create("foo"));
ASSERT_EQUALS(a, b); ASSERT_EQUALS(a, b);
auto s = DIEX(write_one(arena, a)); auto s = DIEX(write_one(a));
DIEX(arena.gc()); DIEX(arena_gc());
ASSERT_EQUALS(s, "foo"); ASSERT_EQUALS(s, "foo");
} }

View file

@ -43,38 +43,36 @@ bool run_tests() {
#define TEST_CASE(fun_) TEST_CASE_IMPL(MACRO_CONCAT(fun_, _COUNTER_)) #define TEST_CASE(fun_) TEST_CASE_IMPL(MACRO_CONCAT(fun_, _COUNTER_))
Result<Value> to_value(Arena& arena, Value& val) { return val.copy(arena); } Result<Value> to_value(Value& val) { return val.copy(); }
Result<Value> to_value(Arena& arena, const Value& val) { Result<Value> to_value(const Value& val) { return val.copy(); }
return val.copy(arena);
}
template <class T> template <class T>
requires std::derived_from<T, Object> requires std::derived_from<T, Object>
Result<Value> to_value(Arena& arena, T& val) { Result<Value> to_value(T& val) {
return val.copy(arena); return val.copy();
} }
template <class T> template <class T>
requires(!std::derived_from<T, Object> && !std::is_fundamental<T>::value) requires(!std::derived_from<T, Object> && !std::is_fundamental<T>::value)
Result<Value> to_value(Arena& arena, T& val) { Result<Value> to_value(T& val) {
return Value::create(arena, val); return Value::create(val);
} }
template <class T> template <class T>
requires(!std::derived_from<T, Object> && std::is_fundamental<T>::value) requires(!std::derived_from<T, Object> && std::is_fundamental<T>::value)
Result<Value> to_value(Arena& arena, T val) { Result<Value> to_value(T val) {
return Value::create(arena, val); return Value::create(val);
} }
#define ASSERT_EQUALS(lhs, rhs) \ #define ASSERT_EQUALS(lhs, rhs) \
do { \ do { \
auto lv = DIEX(to_value(arena, lhs)); \ auto lv = DIEX(to_value(lhs)); \
auto rv = DIEX(to_value(arena, rhs)); \ auto rv = DIEX(to_value(rhs)); \
short c = DIEX(lv.cmp(arena, rv)); \ short c = DIEX(lv.cmp(rv)); \
if (c != 0) { \ if (c != 0) { \
fprintf(stderr, "Values not equal at %s:%d\n", __FILE__, __LINE__); \ fprintf(stderr, "Values not equal at %s:%d\n", __FILE__, __LINE__); \
debug_print(arena, lv); \ debug_print(lv); \
debug_print(arena, rv); \ debug_print(rv); \
exit(EXIT_FAILURE); \ exit(EXIT_FAILURE); \
} \ } \
} while (0) } while (0)