diff --git a/src/arena.hpp b/src/arena.hpp index 0514aba..db057f0 100644 --- a/src/arena.hpp +++ b/src/arena.hpp @@ -39,7 +39,7 @@ class GcRoot : public GcRootBase { GcRoot& operator=(GcRoot&& rhs); static Result> create(T* ptr, Arena& arena); - Result> copy(Arena& arena) { + Result> copy(Arena& arena) const { return GcRoot::create((T*)_ptr, arena); } diff --git a/src/common.cpp b/src/common.cpp index e66d1d8..e095795 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -78,44 +78,44 @@ Result syntax_unwrap(Arena& arena, Value& val) { return syntax->get_value(arena); } -Result Nil::copy(Arena& arena) { return Value(Nil()); } +Result Nil::copy(Arena& arena) const { return Value(Nil()); } -Result Int64::copy(Arena& arena) { +Result Int64::copy(Arena& arena) const { return Value(Int64(TRY(_value.copy(arena)))); } -Result Float::copy(Arena& arena) { +Result Float::copy(Arena& arena) const { return Value(Float(TRY(_value.copy(arena)))); } -Result Array::copy(Arena& arena) { +Result Array::copy(Arena& arena) const { return Value(Array(TRY(_value.copy(arena)))); } -Result ByteArray::copy(Arena& arena) { +Result ByteArray::copy(Arena& arena) const { return Value(ByteArray(TRY(_value.copy(arena)))); } -Result Dict::copy(Arena& arena) { +Result Dict::copy(Arena& arena) const { return Value(Dict(TRY(_value.copy(arena)))); } -Result String::copy(Arena& arena) { +Result String::copy(Arena& arena) const { return Value(String(TRY(_value.copy(arena)))); } -Result Symbol::copy(Arena& arena) { +Result Symbol::copy(Arena& arena) const { return Value(Symbol(TRY(_value.copy(arena)))); } -Result Syntax::copy(Arena& arena) { +Result Syntax::copy(Arena& arena) const { return Value(Syntax(TRY(_value.copy(arena)))); } -Result Pair::copy(Arena& arena) { +Result Pair::copy(Arena& arena) const { return Value(Pair(TRY(_value.copy(arena)))); } -Result Bool::copy(Arena& arena) { +Result Bool::copy(Arena& arena) const { return Value(Bool(TRY(_value.copy(arena)))); } @@ -176,6 +176,11 @@ Result Array::get(Arena& arena, uint64_t idx) { return Value::create(arena, val); } +Result Array::get(Arena& arena, Value& key) { + if (!key.is()) return ErrorCode::TypeMismatch; + return get(arena, key.to()->value()); +} + Result Array::append(Arena& arena, Value& rhs) { uint64_t res_size = size() + 1; @@ -293,3 +298,7 @@ Result Dict::cmp(Arena& arena, Dict& rhs) { } return 0; } + +Result Object::get(Arena& arena, Value& key) { + return ErrorCode::TypeMismatch; +} diff --git a/src/common.hpp b/src/common.hpp index b456fb5..9eeef78 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -6,6 +6,7 @@ #include #include "arena.hpp" +#include "error.hpp" #include "pod.hpp" #include "utf8.hpp" @@ -30,7 +31,7 @@ short cmp_tag(Tag lhs, Tag rhs); class Object { public: virtual Tag tag() = 0; - virtual Result copy(Arena& arena) = 0; + virtual Result copy(Arena& arena) const = 0; virtual PodObject* pod() = 0; virtual void move(Object*) = 0; virtual ~Object() = default; @@ -60,6 +61,7 @@ class Object { virtual Result cmp(Arena&, ByteArray&) { return cmp_tag(tag(), Tag::ByteArray); } + virtual Result get(Arena& arena, Value& key); Object() = default; Object(const Object&) = delete; @@ -90,7 +92,7 @@ class Nil : public Object { return Nil(TRY(MkGcRoot(pod, arena))); } - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; virtual void move(Object* obj) final { new (obj) Nil(std::move(_value)); } @@ -132,9 +134,10 @@ class Array : public Object { } uint64_t size() { return _value->size; } - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; Result get(Arena& arena, uint64_t idx); + virtual Result get(Arena& arena, Value& key) final; Result append(Arena& arena, Value& rhs); @@ -214,7 +217,7 @@ class ByteArray : public Object { static Result create(Arena& arena, String& str); uint64_t size() { return _value->size; } - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; Result operator[](uint64_t idx) { if (idx >= _value->size) return ErrorCode::IndexOutOfRange; @@ -307,9 +310,9 @@ class Dict : public Object { return Dict(TRY(MkGcRoot(pod, arena))); } - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; - Result get(Arena& arena, Value& key); + virtual Result get(Arena& arena, Value& key) final; Result insert(Arena& arena, Value& key, Value& value); @@ -400,7 +403,7 @@ class String : public Object { } uint64_t size() { return _value->size; } - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; Result operator[](uint64_t idx) { if (idx >= _value->size) return ErrorCode::IndexOutOfRange; @@ -493,7 +496,7 @@ class Symbol : public Object { } static Result create(Arena& arena, String& rhs); - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; uint64_t size() { return _value->size; } @@ -527,7 +530,7 @@ class Syntax : public Object { Result get_value(Arena& arena); - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; private: GcRoot _value; @@ -555,7 +558,7 @@ class Pair : public Object { Result first(Arena& arena); Result rest(Arena& arena); - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; private: GcRoot _value; @@ -595,7 +598,7 @@ class Int64 : public Object { int64_t value() { return _value->value; } - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; private: GcRoot _value; @@ -635,7 +638,7 @@ class Float : public Object { double value() { return _value->value; } - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; private: GcRoot _value; @@ -670,7 +673,7 @@ class Bool : public Object { bool value() { return _value->value; } - virtual Result copy(Arena& arena) final; + virtual Result copy(Arena& arena) const final; private: GcRoot _value; @@ -731,11 +734,19 @@ class Value { return ((Object*)buf)->cmp(arena, *(Object*)rhs.buf); } + Result get(Arena& arena, Value& key) { + return ((Object*)buf)->get(arena, key); + } + Result get(Arena& arena, int64_t key) { + Value k = TRY(Int64::create(arena, key)); + return ((Object*)buf)->get(arena, k); + } + // 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); } + Result copy(Arena& arena) const { return ((Object*)buf)->copy(arena); } private: uint8_t buf[24]; diff --git a/test/dict.cpp b/test/dict.cpp index 1dac3dc..48b6e17 100644 --- a/test/dict.cpp +++ b/test/dict.cpp @@ -33,4 +33,7 @@ TEST_CASE(dict_read) { v = DIEX(read_one(arena, "{1 2 3 4}")); s = DIEX(write_one(arena, v)); ASSERT_EQUALS(s, "{1 2 3 4}"); + + auto vv = DIEX(v.get(arena, 1)); + ASSERT_EQUALS(vv, 2); } diff --git a/test/test.hpp b/test/test.hpp index f738f7c..4c0d9f2 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "common.hpp" #include "result.hpp" @@ -42,44 +43,33 @@ bool run_tests() { #define TEST_CASE(fun_) TEST_CASE_IMPL(MACRO_CONCAT(fun_, _COUNTER_)) -template -struct Capture { - Capture(T& value) : value(value) {} - T& value; -}; - -template -struct Capture { - Capture(T& value) : value(value) {} - T& value; -}; - -template -struct Capture { - Capture(T&& value) : value(value) {} - T value; -}; - -Value& to_value(Arena& arena, Value& val) { return val; } - -template - requires std::derived_from -Value to_value(Arena& arena, T& val) { - return DIEX(val.copy(arena)); +Result to_value(Arena& arena, Value& val) { return val.copy(arena); } +Result to_value(Arena& arena, const Value& val) { + return val.copy(arena); } template - requires(!std::derived_from) -Value to_value(Arena& arena, T& val) { - return DIEX(Value::create(arena, val)); + requires std::derived_from +Result to_value(Arena& arena, T& val) { + return val.copy(arena); +} + +template + requires(!std::derived_from && !std::is_fundamental::value) +Result to_value(Arena& arena, T& val) { + return Value::create(arena, val); +} + +template + requires(!std::derived_from && std::is_fundamental::value) +Result to_value(Arena& arena, T val) { + return Value::create(arena, val); } #define ASSERT_EQUALS(lhs, rhs) \ do { \ - auto l = Capture(lhs); \ - auto r = Capture(rhs); \ - auto lv = to_value(arena, l.value); \ - auto rv = to_value(arena, r.value); \ + auto lv = DIEX(to_value(arena, lhs)); \ + auto rv = DIEX(to_value(arena, rhs)); \ short c = DIEX(lv.cmp(arena, rv)); \ if (c != 0) { \ fprintf(stderr, "Values not equal at %s:%d\n", __FILE__, __LINE__); \