Add dicts and super primitive test suite
This commit is contained in:
parent
42a5b7da2b
commit
a3724e1c78
12 changed files with 226 additions and 5 deletions
|
@ -46,6 +46,7 @@ install(TARGETS vli)
|
|||
enable_testing()
|
||||
|
||||
set(CPP_TESTS
|
||||
dict
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
122
src/common.hpp
122
src/common.hpp
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#pragma once
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#define die(message) \
|
||||
do { \
|
||||
fprintf(stderr, "ERROR: %s", message); \
|
||||
fprintf(stderr, "ERROR: %s:%d %s\n", __FILE__, __LINE__, message); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
|
|
@ -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){};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
4
test/dict.cpp
Normal file
|
@ -0,0 +1,4 @@
|
|||
#include "die.hpp"
|
||||
#include "test.hpp"
|
||||
|
||||
TEST_CASE(dict_insert) { die("test"); }
|
|
@ -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; }
|
Loading…
Reference in a new issue