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) {
|
||||
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) {
|
||||
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) {
|
||||
|
|
|
@ -23,6 +23,7 @@ class Syntax;
|
|||
class Pair;
|
||||
class Array;
|
||||
class ByteArray;
|
||||
class Writer;
|
||||
|
||||
short cmp_tag(Tag lhs, Tag rhs);
|
||||
|
||||
|
@ -256,6 +257,7 @@ class ByteArray : public Object {
|
|||
|
||||
class Dict : public Object {
|
||||
public:
|
||||
friend class Writer;
|
||||
Dict() {}
|
||||
Dict(Dict&& rhs) : _value(std::move(rhs._value)) {}
|
||||
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);
|
||||
|
||||
template <class K, class V>
|
||||
Result<Dict> insert(Arena& arena, const K& key, const V& value);
|
||||
|
||||
Result<Dict> concat(Arena& arena, Dict& rhs) {
|
||||
uint64_t rhs_size = rhs.size();
|
||||
uint64_t lhs_size = size();
|
||||
|
@ -305,6 +310,8 @@ class Dict : public Object {
|
|||
}
|
||||
|
||||
private:
|
||||
Result<uint64_t> find(Arena& arena, Value& key);
|
||||
|
||||
uint64_t size() { return _value->size; }
|
||||
GcRoot<PodDict> _value;
|
||||
};
|
||||
|
@ -643,6 +650,10 @@ class Value {
|
|||
|
||||
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>
|
||||
bool is() {
|
||||
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<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<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,
|
||||
InvalidSymbol,
|
||||
MalformedList,
|
||||
KeyError,
|
||||
};
|
||||
|
|
|
@ -190,5 +190,29 @@ Result<String> Writer::write_array(Array& 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 "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