Dictionary writing + insert
This commit is contained in:
parent
a3724e1c78
commit
216fb486cd
5 changed files with 129 additions and 4 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -11,4 +11,5 @@ enum class ErrorCode {
|
||||||
NotImplemented,
|
NotImplemented,
|
||||||
InvalidSymbol,
|
InvalidSymbol,
|
||||||
MalformedList,
|
MalformedList,
|
||||||
|
KeyError,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue