From 07e2b446571959c77b67021cc3447b4fd162e9cc Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sat, 3 Aug 2024 13:43:59 +0100 Subject: [PATCH] Reading back dicts --- src/common.cpp | 32 +++++++++++--- src/common.hpp | 113 ++++++++++++++++++++++++++++++++----------------- src/reader.cpp | 45 +++++++++++++++++++- src/reader.hpp | 4 ++ test/dict.cpp | 7 +++ test/test.hpp | 2 +- 6 files changed, 156 insertions(+), 47 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index abc5f74..e66d1d8 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -198,7 +198,7 @@ Result 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::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(2 * s * sizeof(OffPtr))); @@ -247,7 +247,7 @@ Result 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 Dict::find(Arena& arena, Value& key) { return left; } -Result Int64::cmp(Float& rhs) { +Result Int64::cmp(Arena&, Float& rhs) { return (_value->value > rhs._value->value) - (_value->value < rhs._value->value); } -Result Float::cmp(Int64& rhs) { +Result Float::cmp(Arena&, Int64& rhs) { return (_value->value > rhs._value->value) - (_value->value < rhs._value->value); } + +Result 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; +} diff --git a/src/common.hpp b/src/common.hpp index d5d0b99..b456fb5 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -35,17 +35,29 @@ class Object { virtual void move(Object*) = 0; virtual ~Object() = default; - virtual Result cmp(Object&) = 0; - virtual Result cmp(Nil&) { return cmp_tag(tag(), Tag::Nil); } - virtual Result cmp(Int64&) { return cmp_tag(tag(), Tag::Int64); } - virtual Result cmp(Float&) { return cmp_tag(tag(), Tag::Float); } - virtual Result cmp(Bool&) { return cmp_tag(tag(), Tag::Bool); } - virtual Result cmp(String&) { return cmp_tag(tag(), Tag::String); } - virtual Result cmp(Symbol&) { return cmp_tag(tag(), Tag::Symbol); } - virtual Result cmp(Syntax&) { return cmp_tag(tag(), Tag::Syntax); } - virtual Result cmp(Pair&) { return cmp_tag(tag(), Tag::Pair); } - virtual Result cmp(Array&) { return cmp_tag(tag(), Tag::Array); } - virtual Result cmp(ByteArray&) { + virtual Result cmp(Arena&, Object&) = 0; + virtual Result cmp(Arena&, Nil&) { return cmp_tag(tag(), Tag::Nil); } + virtual Result cmp(Arena&, Int64&) { + return cmp_tag(tag(), Tag::Int64); + } + virtual Result cmp(Arena&, Float&) { + return cmp_tag(tag(), Tag::Float); + } + virtual Result cmp(Arena&, Bool&) { return cmp_tag(tag(), Tag::Bool); } + virtual Result cmp(Arena&, String&) { + return cmp_tag(tag(), Tag::String); + } + virtual Result cmp(Arena&, Symbol&) { + return cmp_tag(tag(), Tag::Symbol); + } + virtual Result cmp(Arena&, Syntax&) { + return cmp_tag(tag(), Tag::Syntax); + } + virtual Result cmp(Arena&, Pair&) { return cmp_tag(tag(), Tag::Pair); } + virtual Result cmp(Arena&, Array&) { + return cmp_tag(tag(), Tag::Array); + } + virtual Result 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 cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Nil& rhs) final { return 0; } + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result cmp(Arena&, Nil& rhs) final { return 0; } static Result 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 cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Array& rhs) final { return 0; } + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result 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 cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(ByteArray& rhs) final { return 0; } + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result 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 cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Array& rhs) final { return 0; } + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result 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 cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(String& rhs) final { + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result 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&& val) : _value(std::move(val)) {} virtual Tag tag() final { return Tag::Symbol; } virtual PodObject* pod() final { return _value.get(); } - virtual Result cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Symbol& rhs) final { return 0; } + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result 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 cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Syntax& rhs) final { return 0; } + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result 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&& val) : _value(std::move(val)) {} virtual Tag tag() final { return Tag::Pair; } virtual PodObject* pod() final { return _value.get(); } - virtual Result cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Pair& rhs) final { return 0; } + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result 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&& val) : _value(std::move(val)) {} virtual Tag tag() final { return Tag::Int64; } virtual PodObject* pod() final { return _value.get(); } - virtual Result cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Int64& rhs) final { + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result cmp(Arena&, Int64& rhs) final { return (_value->value > rhs._value->value) - (_value->value < rhs._value->value); } - virtual Result cmp(Float& rhs) final; + virtual Result 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&& val) : _value(std::move(val)) {} virtual Tag tag() final { return Tag::Float; } virtual PodObject* pod() final { return _value.get(); } - virtual Result cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Float& rhs) final { + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result cmp(Arena&, Float& rhs) final { return (_value->value > rhs._value->value) - (_value->value < rhs._value->value); } - virtual Result cmp(Int64& rhs) final; + virtual Result 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 cmp(Object& rhs) final { return -TRY(rhs.cmp(*this)); } - virtual Result cmp(Bool& rhs) final { return 0; } + virtual Result cmp(Arena& arena, Object& rhs) final { + return -TRY(rhs.cmp(arena, *this)); + } + virtual Result 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 cmp(Value& rhs) { - return ((Object*)buf)->cmp(*(Object*)rhs.buf); + Result cmp(Arena& arena, Value& rhs) { + return ((Object*)buf)->cmp(arena, *(Object*)rhs.buf); } - Result operator==(Value& rhs) { return TRY(cmp(rhs)) == 0; } - Result operator!=(Value& rhs) { return TRY(cmp(rhs)) != 0; } + // TODO: cmp() probably doesn't need arena parameter + // Result operator==(Value& rhs) { return TRY(cmp(rhs)) == 0; } + // Result operator!=(Value& rhs) { return TRY(cmp(rhs)) != 0; } Result copy(Arena& arena) { return ((Object*)buf)->copy(arena); } diff --git a/src/reader.cpp b/src/reader.cpp index 79b6251..f157207 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -60,8 +60,7 @@ Result 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 Reader::read_list() { return ErrorCode::ReadError; } +Result 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 Reader::read_bool() { if (match("true")) { forward(4); @@ -382,3 +408,18 @@ bool Reader::forward_exponent() { return forward_decimal_number(); } + +Result read_one(Arena& arena, Value& value) { + if (!value.is()) return ErrorCode::TypeMismatch; + auto r = Reader(arena, *value.to()); + return r.read_one(); +} +Result read_one(Arena& arena, String& value) { + auto r = Reader(arena, value); + return r.read_one(); +} +Result read_one(Arena& arena, const char* value) { + auto s = TRY(String::create(arena, value)); + auto r = Reader(arena, s); + return r.read_one(); +} diff --git a/src/reader.hpp b/src/reader.hpp index 4d51cee..d4231a1 100644 --- a/src/reader.hpp +++ b/src/reader.hpp @@ -42,3 +42,7 @@ class Reader { String& _str; SourcePosition position_{1, 1, 0}; }; + +Result read_one(Arena& arena, Value& value); +Result read_one(Arena& arena, String& value); +Result read_one(Arena& arena, const char* value); diff --git a/test/dict.cpp b/test/dict.cpp index 52c4f4c..4ee20ef 100644 --- a/test/dict.cpp +++ b/test/dict.cpp @@ -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}"); +} diff --git a/test/test.hpp b/test/test.hpp index 0d889bf..f738f7c 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -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); \