Reading back dicts

This commit is contained in:
Konstantin Nazarov 2024-08-03 13:43:59 +01:00
parent 1f14624664
commit 07e2b44657
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
6 changed files with 156 additions and 47 deletions

View file

@ -198,7 +198,7 @@ Result<Value> Dict::get(Arena& arena, Value& key) {
if (pos > size()) return ErrorCode::KeyError; if (pos > size()) return ErrorCode::KeyError;
auto k = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get()))); 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; return ErrorCode::KeyError;
} }
@ -212,7 +212,7 @@ Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) {
s += 1; s += 1;
} else { } else {
auto k = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get()))); 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>))); 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; uint64_t pos = (left + right) / 2;
while (left < right) { while (left < right) {
auto v = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get()))); 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) { if (c == 0) {
return pos; return pos;
} }
@ -262,12 +262,34 @@ Result<uint64_t> Dict::find(Arena& arena, Value& key) {
return left; return left;
} }
Result<short> Int64::cmp(Float& rhs) { Result<short> Int64::cmp(Arena&, 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(Int64& rhs) { Result<short> Float::cmp(Arena&, 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) {
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;
}

View file

@ -35,17 +35,29 @@ class Object {
virtual void move(Object*) = 0; virtual void move(Object*) = 0;
virtual ~Object() = default; virtual ~Object() = default;
virtual Result<short> cmp(Object&) = 0; virtual Result<short> cmp(Arena&, Object&) = 0;
virtual Result<short> cmp(Nil&) { return cmp_tag(tag(), Tag::Nil); } virtual Result<short> cmp(Arena&, Nil&) { return cmp_tag(tag(), Tag::Nil); }
virtual Result<short> cmp(Int64&) { return cmp_tag(tag(), Tag::Int64); } virtual Result<short> cmp(Arena&, Int64&) {
virtual Result<short> cmp(Float&) { return cmp_tag(tag(), Tag::Float); } return cmp_tag(tag(), Tag::Int64);
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(Arena&, Float&) {
virtual Result<short> cmp(Symbol&) { return cmp_tag(tag(), Tag::Symbol); } return cmp_tag(tag(), Tag::Float);
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(Arena&, Bool&) { return cmp_tag(tag(), Tag::Bool); }
virtual Result<short> cmp(Array&) { return cmp_tag(tag(), Tag::Array); } virtual Result<short> cmp(Arena&, String&) {
virtual Result<short> cmp(ByteArray&) { 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); return cmp_tag(tag(), Tag::ByteArray);
} }
@ -62,8 +74,10 @@ 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Nil& rhs) final { return 0; } return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Nil& rhs) final { return 0; }
static Result<Nil> create(Arena& arena, PodNil* obj) { static Result<Nil> create(Arena& arena, PodNil* obj) {
return Nil(TRY(MkGcRoot(obj, arena))); return Nil(TRY(MkGcRoot(obj, arena)));
@ -97,8 +111,10 @@ 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Array& rhs) final { return 0; } 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)); } 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 Tag tag() final { return Tag::ByteArray; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(ByteArray& rhs) final { return 0; } return -TRY(rhs.cmp(arena, *this));
}
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));
@ -269,8 +287,10 @@ 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Array& rhs) final { return 0; } 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)); } 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 Tag tag() final { return Tag::String; }
virtual PodObject* pod() final { return _value.get(); } virtual PodObject* pod() final { return _value.get(); }
virtual Result<short> cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(String& rhs) final { return -TRY(rhs.cmp(arena, *this));
}
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;
@ -450,8 +472,10 @@ 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Symbol& rhs) final { return 0; } 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)); } 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); 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Syntax& rhs) final { return 0; } 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)); } 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)) {} 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Pair& rhs) final { return 0; } 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)); } 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)) {} 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Int64& rhs) final { return -TRY(rhs.cmp(arena, *this));
}
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(Float& rhs) final; virtual Result<short> cmp(Arena&, 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)); }
@ -580,12 +610,14 @@ 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Float& rhs) final { return -TRY(rhs.cmp(arena, *this));
}
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(Int64& rhs) final; virtual Result<short> cmp(Arena&, 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)); }
@ -617,8 +649,10 @@ 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(Object& rhs) final { return -TRY(rhs.cmp(*this)); } virtual Result<short> cmp(Arena& arena, Object& rhs) final {
virtual Result<short> cmp(Bool& rhs) final { return 0; } 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)); } 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); }
Object* operator->() { return (Object*)(buf); } Object* operator->() { return (Object*)(buf); }
Result<short> cmp(Value& rhs) { Result<short> cmp(Arena& arena, Value& rhs) {
return ((Object*)buf)->cmp(*(Object*)rhs.buf); return ((Object*)buf)->cmp(arena, *(Object*)rhs.buf);
} }
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<bool> operator!=(Value& rhs) { return TRY(cmp(rhs)) != 0; }
Result<Value> copy(Arena& arena) { return ((Object*)buf)->copy(arena); } Result<Value> copy(Arena& arena) { return ((Object*)buf)->copy(arena); }

View file

@ -60,8 +60,7 @@ Result<Value> Reader::read_one() {
// return read_array(); // return read_array();
return ErrorCode::ReadError; return ErrorCode::ReadError;
} else if (match('{')) { } else if (match('{')) {
// TODO: implement dicts return read_dict();
// return read_dict();
return ErrorCode::ReadError; return ErrorCode::ReadError;
} }
@ -116,6 +115,33 @@ Result<Value> Reader::read_list() {
return ErrorCode::ReadError; 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() { Result<Value> Reader::read_bool() {
if (match("true")) { if (match("true")) {
forward(4); forward(4);
@ -382,3 +408,18 @@ bool Reader::forward_exponent() {
return forward_decimal_number(); 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();
}

View file

@ -42,3 +42,7 @@ class Reader {
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(Arena& arena, String& value);
Result<Value> read_one(Arena& arena, const char* value);

View file

@ -1,5 +1,6 @@
#include "common.hpp" #include "common.hpp"
#include "die.hpp" #include "die.hpp"
#include "reader.hpp"
#include "test.hpp" #include "test.hpp"
#include "writer.hpp" #include "writer.hpp"
@ -23,3 +24,9 @@ TEST_CASE(dict_insert) {
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) {
auto v = DIEX(read_one(arena, "{1 2 3 4}"));
auto s = DIEX(write_one(arena, v));
ASSERT_EQUALS(s, "{1 2 3 4}");
}

View file

@ -80,7 +80,7 @@ Value to_value(Arena& arena, T& val) {
auto r = Capture(rhs); \ auto r = Capture(rhs); \
auto lv = to_value(arena, l.value); \ auto lv = to_value(arena, l.value); \
auto rv = to_value(arena, r.value); \ auto rv = to_value(arena, r.value); \
short c = DIEX(lv.cmp(rv)); \ short c = DIEX(lv.cmp(arena, 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(arena, lv); \