Add dicts and super primitive test suite

This commit is contained in:
Konstantin Nazarov 2024-08-01 18:56:38 +01:00
parent 42a5b7da2b
commit a3724e1c78
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
12 changed files with 226 additions and 5 deletions

View file

@ -46,6 +46,7 @@ install(TARGETS vli)
enable_testing()
set(CPP_TESTS
dict
)

View file

@ -74,6 +74,8 @@ Result<PodObject*> Arena::gc_pod(PodObject* obj) {
return gc_array((PodArray*)obj);
case Tag::ByteArray:
return gc_bytearray((PodByteArray*)obj);
case Tag::Dict:
return gc_dict((PodDict*)obj);
}
return ErrorCode::TypeMismatch;
@ -161,3 +163,7 @@ Result<PodObject*> Arena::gc_bytearray(PodByteArray* obj) {
memcpy(nobj->data, obj->data, obj->size);
return nobj;
}
Result<PodObject*> Arena::gc_dict(PodDict* obj) {
return ErrorCode::NotImplemented;
}

View file

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

View file

@ -25,6 +25,8 @@ Result<Value> Value::create(Arena& arena, PodObject* obj) {
return Value(TRY(Array::create(arena, (PodArray*)obj)));
case Tag::ByteArray:
return Value(TRY(ByteArray::create(arena, (PodByteArray*)obj)));
case Tag::Dict:
return Value(TRY(Dict::create(arena, (PodDict*)obj)));
case Tag::String:
return Value(TRY(String::create(arena, (PodString*)obj)));
case Tag::Symbol:
@ -92,6 +94,10 @@ Result<Value> ByteArray::copy(Arena& arena) {
return Value(ByteArray(TRY(_value.copy(arena))));
}
Result<Value> Dict::copy(Arena& arena) {
return Value(Dict(TRY(_value.copy(arena))));
}
Result<Value> String::copy(Arena& arena) {
return Value(String(TRY(_value.copy(arena))));
}
@ -173,3 +179,27 @@ Result<Array> Array::append(Arena& arena, Value& rhs) {
return Array(TRY(MkGcRoot(pod, arena)));
}
short cmp_tag(Tag lhs, Tag rhs) {
if (lhs < rhs) return -1;
if (rhs < lhs) return 1;
return 0;
}
Result<Value> Dict::get(Arena& arena, Value& key) {
return ErrorCode::TypeMismatch;
}
Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) {
return ErrorCode::TypeMismatch;
}
Result<short> Int64::cmp(Float& rhs) {
return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value);
}
Result<short> Float::cmp(Int64& rhs) {
return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value);
}

View file

@ -13,6 +13,18 @@
class Value;
class String;
class Nil;
class Int64;
class Float;
class Bool;
class String;
class Symbol;
class Syntax;
class Pair;
class Array;
class ByteArray;
short cmp_tag(Tag lhs, Tag rhs);
class Object {
public:
@ -21,6 +33,21 @@ class Object {
virtual PodObject* pod() = 0;
virtual void move(Object*) = 0;
virtual ~Object() = default;
virtual Result<short> cmp(Object&) = 0;
virtual Result<short> cmp(Nil&) { return cmp_tag(tag(), Tag::Nil); }
virtual Result<short> cmp(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(String&) { return cmp_tag(tag(), Tag::String); }
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(Pair&) { return cmp_tag(tag(), Tag::Pair); }
virtual Result<short> cmp(Array&) { return cmp_tag(tag(), Tag::Array); }
virtual Result<short> cmp(ByteArray&) {
return cmp_tag(tag(), Tag::ByteArray);
}
Object() = default;
Object(const Object&) = delete;
};
@ -34,6 +61,9 @@ class Nil : public Object {
virtual Tag tag() final { return Tag::Nil; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Nil& rhs) final { return 0; }
static Result<Nil> create(Arena& arena, PodNil* obj) {
return Nil(TRY(MkGcRoot(obj, arena)));
}
@ -66,6 +96,8 @@ class Array : public Object {
virtual Tag tag() final { return Tag::Array; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Array& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Array(std::move(_value)); }
@ -129,6 +161,8 @@ class ByteArray : public Object {
virtual Tag tag() final { return Tag::ByteArray; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(ByteArray& rhs) final { return 0; }
virtual void move(Object* obj) final {
new (obj) ByteArray(std::move(_value));
@ -220,6 +254,61 @@ class ByteArray : public Object {
GcRoot<PodByteArray> _value;
};
class Dict : public Object {
public:
Dict() {}
Dict(Dict&& rhs) : _value(std::move(rhs._value)) {}
Dict(GcRoot<PodDict>&& val) : _value(std::move(val)) {}
Dict& operator=(Dict&& rhs) {
_value = std::move(rhs._value);
return *this;
}
virtual Tag tag() final { return Tag::Dict; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Array& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Dict(std::move(_value)); }
static Result<Dict> create(Arena& arena, PodDict* obj) {
return Dict(TRY(MkGcRoot(obj, arena)));
}
static Result<Dict> create(Arena& arena) {
auto pod = TRY(arena.alloc<PodDict>());
pod->header.tag = Tag::Dict;
pod->size = 0;
return Dict(TRY(MkGcRoot(pod, arena)));
}
virtual Result<Value> copy(Arena& arena) final;
Result<Value> get(Arena& arena, Value& key);
Result<Dict> insert(Arena& arena, Value& key, Value& value);
Result<Dict> concat(Arena& arena, Dict& 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<PodDict>(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 Dict(TRY(MkGcRoot(pod, arena)));
}
private:
uint64_t size() { return _value->size; }
GcRoot<PodDict> _value;
};
class String : public Object {
public:
String() {}
@ -233,6 +322,8 @@ class String : public Object {
virtual Tag tag() final { return Tag::String; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(String& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) String(std::move(_value)); }
@ -333,6 +424,8 @@ class Symbol : public Object {
Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Symbol; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Symbol& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Symbol(std::move(_value)); }
@ -371,6 +464,8 @@ class Syntax : public Object {
Syntax(String filename, String modulename, Value expression);
virtual Tag tag() final { return Tag::Syntax; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Syntax& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Syntax(std::move(_value)); }
@ -393,6 +488,8 @@ class Pair : public Object {
Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Pair; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Pair& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Pair(std::move(_value)); }
@ -412,11 +509,19 @@ class Pair : public Object {
class Int64 : public Object {
public:
friend class Float;
Int64() {}
Int64(Int64&& rhs) : _value(std::move(rhs._value)) {}
Int64(GcRoot<PodInt64>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Int64; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Int64& rhs) final {
return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value);
}
virtual Result<short> cmp(Float& rhs) final;
virtual void move(Object* obj) final { new (obj) Int64(std::move(_value)); }
@ -442,11 +547,19 @@ class Int64 : public Object {
class Float : public Object {
public:
friend class Int64;
Float() {}
Float(Float&& rhs) : _value(std::move(rhs._value)) {}
Float(GcRoot<PodFloat>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Float; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Float& rhs) final {
return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value);
}
virtual Result<short> cmp(Int64& rhs) final;
virtual void move(Object* obj) final { new (obj) Float(std::move(_value)); }
@ -478,6 +591,8 @@ class Bool : public Object {
virtual Tag tag() final { return Tag::Bool; }
virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); }
virtual Result<short> cmp(Bool& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Bool(std::move(_value)); }
@ -507,7 +622,6 @@ class Value {
Value() { new (buf) Nil(); }
~Value() { ((Object*)buf)->~Object(); }
Value(Value&& val) {
// TODO: repoint the gc root properly
((Object*)val.buf)->move((Object*)buf);
new (val.buf) Nil();
}
@ -545,6 +659,12 @@ class Value {
Object& operator*() { return *(Object*)(buf); }
Object* operator->() { return (Object*)(buf); }
Result<short> cmp(Value& rhs) {
return ((Object*)buf)->cmp(*(Object*)rhs.buf);
}
Result<bool> operator==(Value& rhs) { return TRY(cmp(rhs)) == 0; }
Result<Value> copy(Arena& arena) { return ((Object*)buf)->copy(arena); }
private:

View file

@ -21,11 +21,13 @@ Result<Value> Compiler::compile_expr(Value& expr) {
case Tag::Syntax:
case Tag::Array:
case Tag::ByteArray:
case Tag::Dict:
return ErrorCode::TypeMismatch;
}
return ErrorCode::TypeMismatch;
}
Result<Value> Compiler::compile_list(Pair& expr) {
auto first = TRY(expr.first(_arena));
return ErrorCode::TypeMismatch;
}

View file

@ -1,8 +1,9 @@
#pragma once
#include <cstdio>
#include <cstdlib>
#define die(message) \
do { \
fprintf(stderr, "ERROR: %s", message); \
exit(EXIT_FAILURE); \
#define die(message) \
do { \
fprintf(stderr, "ERROR: %s:%d %s\n", __FILE__, __LINE__, message); \
exit(EXIT_FAILURE); \
} while (0)

View file

@ -16,6 +16,7 @@ enum class Tag : uint8_t {
Pair,
Array,
ByteArray,
Dict,
};
template <class T>
@ -92,6 +93,14 @@ class PodByteArray final : public PodObject {
char data[];
};
class PodDict final : public PodObject {
public:
PodDict() : PodObject(Tag::Dict){};
uint64_t size;
OffPtr<PodObject> data[];
};
class PodString final : public PodObject {
public:
PodString() : PodObject(Tag::String){};

View file

@ -14,6 +14,8 @@ Result<String> Writer::write_one(Value& obj) {
return write_array(*obj.to<Array>());
case Tag::ByteArray:
return write_bytearray(*obj.to<ByteArray>());
case Tag::Dict:
return write_dict(*obj.to<Dict>());
case Tag::String:
return write_string(*obj.to<String>());
case Tag::Symbol:
@ -186,3 +188,7 @@ Result<String> Writer::write_array(Array& val) {
res = TRY(res.concat(_arena, "]"));
return res;
}
Result<String> Writer::write_dict(Dict& val) {
return ErrorCode::NotImplemented;
}

View file

@ -19,6 +19,7 @@ class Writer {
Result<String> write_bool(Bool& val);
Result<String> write_array(Array& val);
Result<String> write_bytearray(ByteArray& val);
Result<String> write_dict(Dict& val);
Result<String> write_symbol(Symbol& val);
Result<String> write_syntax(Syntax& val);

4
test/dict.cpp Normal file
View file

@ -0,0 +1,4 @@
#include "die.hpp"
#include "test.hpp"
TEST_CASE(dict_insert) { die("test"); }

View file

@ -0,0 +1,40 @@
#pragma once
#include <cstdint>
const uint64_t MAX_TESTS = 1024 * 1024;
static void (*tests[MAX_TESTS])() = {0};
const char* add_test(void (*fun)(void)) {
for (uint64_t i = 0; i < MAX_TESTS; ++i) {
if (tests[i] == 0) {
tests[i] = fun;
break;
}
}
return 0;
}
bool run_tests() {
for (uint64_t i = 0; i < MAX_TESTS; ++i) {
if (tests[i] == 0) break;
tests[i]();
}
return true;
}
#define CONCAT_IMPL(x, y) x##y
#define MACRO_CONCAT(x, y) CONCAT_IMPL(x, y)
#define TEST_CASE_IMPL(ID, ...) \
static void ID(); \
static const char* MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \
add_test(&ID); \
void ID()
#define TEST_CASE(fun_) TEST_CASE_IMPL(MACRO_CONCAT(fun_, _COUNTER_))
int main() { return run_tests() ? 0 : 1; }