Dictionary writing + insert

This commit is contained in:
Konstantin Nazarov 2024-08-01 22:45:16 +01:00
parent a3724e1c78
commit 216fb486cd
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
5 changed files with 129 additions and 4 deletions

View file

@ -187,11 +187,71 @@ short cmp_tag(Tag lhs, Tag rhs) {
} }
Result<Value> Dict::get(Arena& arena, Value& key) { Result<Value> Dict::get(Arena& arena, Value& key) {
return ErrorCode::TypeMismatch; auto pos = TRY(find(arena, key));
if (pos > size()) return ErrorCode::KeyError;
auto k = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get())));
if (TRY(k != key)) {
return ErrorCode::KeyError;
}
return TRY(Value::create(arena, _value->data[pos * 2 + 1].get(_value.get())));
} }
Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) { Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) {
return ErrorCode::TypeMismatch; auto pos = TRY(find(arena, key));
auto s = size();
if (pos >= s) {
s += 1;
} else {
auto k = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get())));
if (TRY(k != key)) s += 1;
}
auto pod = TRY(arena.alloc<PodDict>(2 * s * sizeof(OffPtr<PodObject>)));
pod->size = s;
auto vpod = _value.get();
for (uint64_t i = 0, j = 0; i < s; i++, j++) {
if (i == pos) {
pod->data[i * 2] = OffPtr<PodObject>(pod, key.pod());
pod->data[i * 2 + 1] = OffPtr<PodObject>(pod, value.pod());
if (s > size() && i < s - 1) {
i++;
pod->data[i * 2] =
OffPtr<PodObject>(pod, _value->data[j * 2].get(vpod));
pod->data[i * 2 + 1] =
OffPtr<PodObject>(pod, _value->data[j * 2 + 1].get(vpod));
}
} else {
pod->data[i * 2] = OffPtr<PodObject>(pod, _value->data[j * 2].get(vpod));
pod->data[i * 2 + 1] =
OffPtr<PodObject>(pod, _value->data[j * 2 + 1].get(vpod));
}
}
return Dict(TRY(MkGcRoot(pod, arena)));
}
Result<uint64_t> Dict::find(Arena& arena, Value& key) {
uint64_t left = 0;
uint64_t right = size();
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));
if (c == 0) {
return pos;
}
if (c < 0) {
left = pos + 1;
}
if (c > 0) {
right = pos;
}
pos = (left + right) / 2;
}
return left;
} }
Result<short> Int64::cmp(Float& rhs) { Result<short> Int64::cmp(Float& rhs) {

View file

@ -23,6 +23,7 @@ class Syntax;
class Pair; class Pair;
class Array; class Array;
class ByteArray; class ByteArray;
class Writer;
short cmp_tag(Tag lhs, Tag rhs); short cmp_tag(Tag lhs, Tag rhs);
@ -256,6 +257,7 @@ class ByteArray : public Object {
class Dict : public Object { class Dict : public Object {
public: public:
friend class Writer;
Dict() {} Dict() {}
Dict(Dict&& rhs) : _value(std::move(rhs._value)) {} Dict(Dict&& rhs) : _value(std::move(rhs._value)) {}
Dict(GcRoot<PodDict>&& val) : _value(std::move(val)) {} Dict(GcRoot<PodDict>&& val) : _value(std::move(val)) {}
@ -291,6 +293,9 @@ class Dict : public Object {
Result<Dict> insert(Arena& arena, Value& key, Value& value); Result<Dict> insert(Arena& arena, Value& key, Value& value);
template <class K, class V>
Result<Dict> insert(Arena& arena, const K& key, const V& value);
Result<Dict> concat(Arena& arena, Dict& rhs) { Result<Dict> concat(Arena& arena, Dict& rhs) {
uint64_t rhs_size = rhs.size(); uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size(); uint64_t lhs_size = size();
@ -305,6 +310,8 @@ class Dict : public Object {
} }
private: private:
Result<uint64_t> find(Arena& arena, Value& key);
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
GcRoot<PodDict> _value; GcRoot<PodDict> _value;
}; };
@ -643,6 +650,10 @@ class Value {
static Result<Value> create(Arena& arena, PodObject* obj); static Result<Value> create(Arena& arena, PodObject* obj);
static Result<Value> create(Arena& arena, const int64_t& value) {
return Value(TRY(Int64::create(arena, value)));
}
template <class T> template <class T>
bool is() { bool is() {
return dynamic_cast<T*>((Object*)buf) != nullptr; return dynamic_cast<T*>((Object*)buf) != nullptr;
@ -664,6 +675,7 @@ class Value {
} }
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); }
@ -676,3 +688,11 @@ Result<Value> syntax_unwrap(Value& val);
Result<Value> reverse(Arena& arena, Value& val); Result<Value> reverse(Arena& arena, Value& val);
Result<void> debug_print(Arena& arena, String& val); Result<void> debug_print(Arena& arena, String& val);
template <class K, class V>
Result<Dict> Dict::insert(Arena& arena, const K& key, const V& value) {
Value k = TRY(Value::create(arena, key));
Value v = TRY(Value::create(arena, value));
return insert(arena, k, v);
}

View file

@ -11,4 +11,5 @@ enum class ErrorCode {
NotImplemented, NotImplemented,
InvalidSymbol, InvalidSymbol,
MalformedList, MalformedList,
KeyError,
}; };

View file

@ -190,5 +190,29 @@ Result<String> Writer::write_array(Array& val) {
} }
Result<String> Writer::write_dict(Dict& val) { Result<String> Writer::write_dict(Dict& val) {
return ErrorCode::NotImplemented; String res = TRY(String::create(_arena, "{"));
bool is_first = true;
for (uint64_t i = 0; i < val.size(); i++) {
Value k = TRY(
Value::create(_arena, val._value->data[i * 2].get(val._value.get())));
Value v = TRY(Value::create(
_arena, val._value->data[i * 2 + 1].get(val._value.get())));
if (!is_first) res = TRY(res.concat(_arena, " "));
String first_str = TRY(write_one(k));
res = TRY(res.concat(_arena, first_str));
res = TRY(res.concat(_arena, " "));
String second_str = TRY(write_one(v));
res = TRY(res.concat(_arena, second_str));
is_first = false;
}
res = TRY(res.concat(_arena, "}"));
return res;
} }

View file

@ -1,4 +1,24 @@
#include "common.hpp"
#include "die.hpp" #include "die.hpp"
#include "test.hpp" #include "test.hpp"
#include "writer.hpp"
TEST_CASE(dict_insert) { die("test"); } StaticArena<64 * 1024 * 1024> arena;
TEST_CASE(dict_insert) {
auto d = DIEX(Dict::create(arena));
d = DIEX(d.insert(arena, 1, 2));
d = DIEX(d.insert(arena, 1, 3));
d = DIEX(d.insert(arena, 3, 3));
d = DIEX(d.insert(arena, 0, 4));
d = DIEX(d.insert(arena, 0, 5));
d = DIEX(d.insert(arena, 2, 6));
auto w = Writer(arena);
auto dd = DIEX(d.copy(arena));
auto s = DIEX(w.write_one(dd));
DIEX(debug_print(arena, s));
}