Reading back dicts
This commit is contained in:
parent
1f14624664
commit
07e2b44657
6 changed files with 156 additions and 47 deletions
|
@ -198,7 +198,7 @@ Result<Value> Dict::get(Arena& arena, Value& key) {
|
|||
if (pos > size()) return ErrorCode::KeyError;
|
||||
auto k = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get())));
|
||||
|
||||
if (TRY(k != key)) {
|
||||
if (TRY(k.cmp(arena, key)) != 0) {
|
||||
return ErrorCode::KeyError;
|
||||
}
|
||||
|
||||
|
@ -212,7 +212,7 @@ Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) {
|
|||
s += 1;
|
||||
} else {
|
||||
auto k = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get())));
|
||||
if (TRY(k != key)) s += 1;
|
||||
if (TRY(k.cmp(arena, key)) != 0) s += 1;
|
||||
}
|
||||
|
||||
auto pod = TRY(arena.alloc<PodDict>(2 * s * sizeof(OffPtr<PodObject>)));
|
||||
|
@ -247,7 +247,7 @@ Result<uint64_t> Dict::find(Arena& arena, Value& key) {
|
|||
uint64_t pos = (left + right) / 2;
|
||||
while (left < right) {
|
||||
auto v = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get())));
|
||||
auto c = TRY(v.cmp(key));
|
||||
auto c = TRY(v.cmp(arena, key));
|
||||
if (c == 0) {
|
||||
return pos;
|
||||
}
|
||||
|
@ -262,12 +262,34 @@ Result<uint64_t> Dict::find(Arena& arena, Value& key) {
|
|||
return left;
|
||||
}
|
||||
|
||||
Result<short> Int64::cmp(Float& rhs) {
|
||||
Result<short> Int64::cmp(Arena&, Float& rhs) {
|
||||
return (_value->value > rhs._value->value) -
|
||||
(_value->value < rhs._value->value);
|
||||
}
|
||||
|
||||
Result<short> Float::cmp(Int64& rhs) {
|
||||
Result<short> Float::cmp(Arena&, Int64& rhs) {
|
||||
return (_value->value > rhs._value->value) -
|
||||
(_value->value < rhs._value->value);
|
||||
}
|
||||
|
||||
Result<short> Dict::cmp(Arena& arena, Dict& rhs) {
|
||||
auto lsize = size() * 2;
|
||||
auto rsize = rhs.size() * 2;
|
||||
uint64_t i = 0;
|
||||
uint64_t j = 0;
|
||||
while (1) {
|
||||
if (i == lsize && j == lsize) return 0;
|
||||
|
||||
short cmp = short(i == lsize) - short(j == rsize);
|
||||
if (cmp != 0) return cmp;
|
||||
|
||||
Value lc = TRY(Value::create(arena, _value->data[i].get(_value.get())));
|
||||
Value rc =
|
||||
TRY(Value::create(arena, rhs._value->data[j].get(rhs._value.get())));
|
||||
cmp = TRY(lc.cmp(arena, rc));
|
||||
if (cmp != 0) return cmp;
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
113
src/common.hpp
113
src/common.hpp
|
@ -35,17 +35,29 @@ class Object {
|
|||
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&) {
|
||||
virtual Result<short> cmp(Arena&, Object&) = 0;
|
||||
virtual Result<short> cmp(Arena&, Nil&) { return cmp_tag(tag(), Tag::Nil); }
|
||||
virtual Result<short> cmp(Arena&, Int64&) {
|
||||
return cmp_tag(tag(), Tag::Int64);
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Float&) {
|
||||
return cmp_tag(tag(), Tag::Float);
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Bool&) { return cmp_tag(tag(), Tag::Bool); }
|
||||
virtual Result<short> cmp(Arena&, String&) {
|
||||
return cmp_tag(tag(), Tag::String);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -62,8 +74,10 @@ 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; }
|
||||
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Nil& rhs) final { return 0; }
|
||||
|
||||
static Result<Nil> create(Arena& arena, PodNil* obj) {
|
||||
return Nil(TRY(MkGcRoot(obj, arena)));
|
||||
|
@ -97,8 +111,10 @@ 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 Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Array& rhs) final { return 0; }
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Array(std::move(_value)); }
|
||||
|
||||
|
@ -162,8 +178,10 @@ 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 Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, ByteArray& rhs) final { return 0; }
|
||||
|
||||
virtual void move(Object* obj) final {
|
||||
new (obj) ByteArray(std::move(_value));
|
||||
|
@ -269,8 +287,10 @@ class Dict : public Object {
|
|||
|
||||
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 Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Dict& rhs) final;
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Dict(std::move(_value)); }
|
||||
|
||||
|
@ -329,8 +349,10 @@ 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 {
|
||||
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, String& rhs) final {
|
||||
auto lsize = size();
|
||||
auto rsize = rhs.size();
|
||||
uint64_t i = 0;
|
||||
|
@ -450,8 +472,10 @@ 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 Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Symbol& rhs) final { return 0; }
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Symbol(std::move(_value)); }
|
||||
|
||||
|
@ -490,8 +514,10 @@ 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 Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Syntax& rhs) final { return 0; }
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Syntax(std::move(_value)); }
|
||||
|
||||
|
@ -514,8 +540,10 @@ 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 Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Pair& rhs) final { return 0; }
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Pair(std::move(_value)); }
|
||||
|
||||
|
@ -542,12 +570,14 @@ class Int64 : public Object {
|
|||
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 {
|
||||
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Int64& rhs) final {
|
||||
return (_value->value > rhs._value->value) -
|
||||
(_value->value < rhs._value->value);
|
||||
}
|
||||
virtual Result<short> cmp(Float& rhs) final;
|
||||
virtual Result<short> cmp(Arena&, Float& rhs) final;
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Int64(std::move(_value)); }
|
||||
|
||||
|
@ -580,12 +610,14 @@ class Float : public Object {
|
|||
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 {
|
||||
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Float& rhs) final {
|
||||
return (_value->value > rhs._value->value) -
|
||||
(_value->value < rhs._value->value);
|
||||
}
|
||||
virtual Result<short> cmp(Int64& rhs) final;
|
||||
virtual Result<short> cmp(Arena&, Int64& rhs) final;
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Float(std::move(_value)); }
|
||||
|
||||
|
@ -617,8 +649,10 @@ 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 Result<short> cmp(Arena& arena, Object& rhs) final {
|
||||
return -TRY(rhs.cmp(arena, *this));
|
||||
}
|
||||
virtual Result<short> cmp(Arena&, Bool& rhs) final { return 0; }
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Bool(std::move(_value)); }
|
||||
|
||||
|
@ -693,12 +727,13 @@ 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<short> cmp(Arena& arena, Value& rhs) {
|
||||
return ((Object*)buf)->cmp(arena, *(Object*)rhs.buf);
|
||||
}
|
||||
|
||||
Result<bool> operator==(Value& rhs) { return TRY(cmp(rhs)) == 0; }
|
||||
Result<bool> operator!=(Value& rhs) { return TRY(cmp(rhs)) != 0; }
|
||||
// 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<Value> copy(Arena& arena) { return ((Object*)buf)->copy(arena); }
|
||||
|
||||
|
|
|
@ -60,8 +60,7 @@ Result<Value> Reader::read_one() {
|
|||
// return read_array();
|
||||
return ErrorCode::ReadError;
|
||||
} else if (match('{')) {
|
||||
// TODO: implement dicts
|
||||
// return read_dict();
|
||||
return read_dict();
|
||||
return ErrorCode::ReadError;
|
||||
}
|
||||
|
||||
|
@ -116,6 +115,33 @@ Result<Value> Reader::read_list() {
|
|||
return ErrorCode::ReadError;
|
||||
}
|
||||
|
||||
Result<Value> Reader::read_dict() {
|
||||
if (!match('{')) return ErrorCode::ReadError;
|
||||
|
||||
forward();
|
||||
|
||||
auto res = TRY(Dict::create(_arena));
|
||||
|
||||
while (1) {
|
||||
forward_whitespace();
|
||||
|
||||
if (is_eof()) {
|
||||
return ErrorCode::ReadError;
|
||||
}
|
||||
|
||||
if (match('}')) {
|
||||
forward();
|
||||
return Value(std::move(res));
|
||||
}
|
||||
|
||||
auto val1 = TRY(read_one());
|
||||
auto val2 = TRY(read_one());
|
||||
|
||||
res = TRY(res.insert(_arena, val1, val2));
|
||||
}
|
||||
|
||||
return ErrorCode::ReadError;
|
||||
}
|
||||
Result<Value> Reader::read_bool() {
|
||||
if (match("true")) {
|
||||
forward(4);
|
||||
|
@ -382,3 +408,18 @@ bool Reader::forward_exponent() {
|
|||
|
||||
return forward_decimal_number();
|
||||
}
|
||||
|
||||
Result<Value> read_one(Arena& arena, Value& value) {
|
||||
if (!value.is<String>()) return ErrorCode::TypeMismatch;
|
||||
auto r = Reader(arena, *value.to<String>());
|
||||
return r.read_one();
|
||||
}
|
||||
Result<Value> read_one(Arena& arena, String& value) {
|
||||
auto r = Reader(arena, value);
|
||||
return r.read_one();
|
||||
}
|
||||
Result<Value> read_one(Arena& arena, const char* value) {
|
||||
auto s = TRY(String::create(arena, value));
|
||||
auto r = Reader(arena, s);
|
||||
return r.read_one();
|
||||
}
|
||||
|
|
|
@ -42,3 +42,7 @@ class Reader {
|
|||
String& _str;
|
||||
SourcePosition position_{1, 1, 0};
|
||||
};
|
||||
|
||||
Result<Value> read_one(Arena& arena, Value& value);
|
||||
Result<Value> read_one(Arena& arena, String& value);
|
||||
Result<Value> read_one(Arena& arena, const char* value);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "common.hpp"
|
||||
#include "die.hpp"
|
||||
#include "reader.hpp"
|
||||
#include "test.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
|
@ -23,3 +24,9 @@ TEST_CASE(dict_insert) {
|
|||
|
||||
ASSERT_EQUALS(s, "{0 5 1 3 2 6 3 3}");
|
||||
}
|
||||
|
||||
TEST_CASE(dict_read) {
|
||||
auto v = DIEX(read_one(arena, "{1 2 3 4}"));
|
||||
auto s = DIEX(write_one(arena, v));
|
||||
ASSERT_EQUALS(s, "{1 2 3 4}");
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ Value to_value(Arena& arena, T& val) {
|
|||
auto r = Capture(rhs); \
|
||||
auto lv = to_value(arena, l.value); \
|
||||
auto rv = to_value(arena, r.value); \
|
||||
short c = DIEX(lv.cmp(rv)); \
|
||||
short c = DIEX(lv.cmp(arena, rv)); \
|
||||
if (c != 0) { \
|
||||
fprintf(stderr, "Values not equal at %s:%d\n", __FILE__, __LINE__); \
|
||||
debug_print(arena, lv); \
|
||||
|
|
Loading…
Reference in a new issue