Add test for dictionary "get()"

This commit is contained in:
Konstantin Nazarov 2024-08-03 18:53:14 +01:00
parent a52e4d278c
commit b0166cc7da
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
5 changed files with 70 additions and 57 deletions

View file

@ -39,7 +39,7 @@ class GcRoot : public GcRootBase {
GcRoot& operator=(GcRoot&& rhs); GcRoot& operator=(GcRoot&& rhs);
static Result<GcRoot<T>> create(T* ptr, Arena& arena); static Result<GcRoot<T>> create(T* ptr, Arena& arena);
Result<GcRoot<T>> copy(Arena& arena) { Result<GcRoot<T>> copy(Arena& arena) const {
return GcRoot<T>::create((T*)_ptr, arena); return GcRoot<T>::create((T*)_ptr, arena);
} }

View file

@ -78,44 +78,44 @@ Result<Value> syntax_unwrap(Arena& arena, Value& val) {
return syntax->get_value(arena); return syntax->get_value(arena);
} }
Result<Value> Nil::copy(Arena& arena) { return Value(Nil()); } Result<Value> Nil::copy(Arena& arena) const { return Value(Nil()); }
Result<Value> Int64::copy(Arena& arena) { Result<Value> Int64::copy(Arena& arena) const {
return Value(Int64(TRY(_value.copy(arena)))); return Value(Int64(TRY(_value.copy(arena))));
} }
Result<Value> Float::copy(Arena& arena) { Result<Value> Float::copy(Arena& arena) const {
return Value(Float(TRY(_value.copy(arena)))); return Value(Float(TRY(_value.copy(arena))));
} }
Result<Value> Array::copy(Arena& arena) { Result<Value> Array::copy(Arena& arena) const {
return Value(Array(TRY(_value.copy(arena)))); return Value(Array(TRY(_value.copy(arena))));
} }
Result<Value> ByteArray::copy(Arena& arena) { Result<Value> ByteArray::copy(Arena& arena) const {
return Value(ByteArray(TRY(_value.copy(arena)))); return Value(ByteArray(TRY(_value.copy(arena))));
} }
Result<Value> Dict::copy(Arena& arena) { Result<Value> Dict::copy(Arena& arena) const {
return Value(Dict(TRY(_value.copy(arena)))); return Value(Dict(TRY(_value.copy(arena))));
} }
Result<Value> String::copy(Arena& arena) { Result<Value> String::copy(Arena& arena) const {
return Value(String(TRY(_value.copy(arena)))); return Value(String(TRY(_value.copy(arena))));
} }
Result<Value> Symbol::copy(Arena& arena) { Result<Value> Symbol::copy(Arena& arena) const {
return Value(Symbol(TRY(_value.copy(arena)))); return Value(Symbol(TRY(_value.copy(arena))));
} }
Result<Value> Syntax::copy(Arena& arena) { Result<Value> Syntax::copy(Arena& arena) const {
return Value(Syntax(TRY(_value.copy(arena)))); return Value(Syntax(TRY(_value.copy(arena))));
} }
Result<Value> Pair::copy(Arena& arena) { Result<Value> Pair::copy(Arena& arena) const {
return Value(Pair(TRY(_value.copy(arena)))); return Value(Pair(TRY(_value.copy(arena))));
} }
Result<Value> Bool::copy(Arena& arena) { Result<Value> Bool::copy(Arena& arena) const {
return Value(Bool(TRY(_value.copy(arena)))); return Value(Bool(TRY(_value.copy(arena))));
} }
@ -176,6 +176,11 @@ Result<Value> Array::get(Arena& arena, uint64_t idx) {
return Value::create(arena, val); return Value::create(arena, val);
} }
Result<Value> Array::get(Arena& arena, Value& key) {
if (!key.is<Int64>()) return ErrorCode::TypeMismatch;
return get(arena, key.to<Int64>()->value());
}
Result<Array> Array::append(Arena& arena, Value& rhs) { Result<Array> Array::append(Arena& arena, Value& rhs) {
uint64_t res_size = size() + 1; uint64_t res_size = size() + 1;
@ -293,3 +298,7 @@ Result<short> Dict::cmp(Arena& arena, Dict& rhs) {
} }
return 0; return 0;
} }
Result<Value> Object::get(Arena& arena, Value& key) {
return ErrorCode::TypeMismatch;
}

View file

@ -6,6 +6,7 @@
#include <iostream> #include <iostream>
#include "arena.hpp" #include "arena.hpp"
#include "error.hpp"
#include "pod.hpp" #include "pod.hpp"
#include "utf8.hpp" #include "utf8.hpp"
@ -30,7 +31,7 @@ short cmp_tag(Tag lhs, Tag rhs);
class Object { class Object {
public: public:
virtual Tag tag() = 0; virtual Tag tag() = 0;
virtual Result<Value> copy(Arena& arena) = 0; virtual Result<Value> copy(Arena& arena) const = 0;
virtual PodObject* pod() = 0; virtual PodObject* pod() = 0;
virtual void move(Object*) = 0; virtual void move(Object*) = 0;
virtual ~Object() = default; virtual ~Object() = default;
@ -60,6 +61,7 @@ class Object {
virtual Result<short> cmp(Arena&, ByteArray&) { virtual Result<short> cmp(Arena&, ByteArray&) {
return cmp_tag(tag(), Tag::ByteArray); return cmp_tag(tag(), Tag::ByteArray);
} }
virtual Result<Value> get(Arena& arena, Value& key);
Object() = default; Object() = default;
Object(const Object&) = delete; Object(const Object&) = delete;
@ -90,7 +92,7 @@ class Nil : public Object {
return Nil(TRY(MkGcRoot(pod, arena))); return Nil(TRY(MkGcRoot(pod, arena)));
} }
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
virtual void move(Object* obj) final { new (obj) Nil(std::move(_value)); } 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; } uint64_t size() { return _value->size; }
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
Result<Value> get(Arena& arena, uint64_t idx); Result<Value> get(Arena& arena, uint64_t idx);
virtual Result<Value> get(Arena& arena, Value& key) final;
Result<Array> append(Arena& arena, Value& rhs); Result<Array> append(Arena& arena, Value& rhs);
@ -214,7 +217,7 @@ class ByteArray : public Object {
static Result<ByteArray> create(Arena& arena, String& str); static Result<ByteArray> create(Arena& arena, String& str);
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
Result<char> operator[](uint64_t idx) { Result<char> operator[](uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange; if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
@ -307,9 +310,9 @@ class Dict : public Object {
return Dict(TRY(MkGcRoot(pod, arena))); return Dict(TRY(MkGcRoot(pod, arena)));
} }
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
Result<Value> get(Arena& arena, Value& key); virtual Result<Value> get(Arena& arena, Value& key) final;
Result<Dict> insert(Arena& arena, Value& key, Value& value); Result<Dict> insert(Arena& arena, Value& key, Value& value);
@ -400,7 +403,7 @@ class String : public Object {
} }
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
Result<char32_t> operator[](uint64_t idx) { Result<char32_t> operator[](uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange; if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
@ -493,7 +496,7 @@ class Symbol : public Object {
} }
static Result<Symbol> create(Arena& arena, String& rhs); static Result<Symbol> create(Arena& arena, String& rhs);
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
uint64_t size() { return _value->size; } uint64_t size() { return _value->size; }
@ -527,7 +530,7 @@ class Syntax : public Object {
Result<Value> get_value(Arena& arena); Result<Value> get_value(Arena& arena);
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
private: private:
GcRoot<PodSyntax> _value; GcRoot<PodSyntax> _value;
@ -555,7 +558,7 @@ class Pair : public Object {
Result<Value> first(Arena& arena); Result<Value> first(Arena& arena);
Result<Value> rest(Arena& arena); Result<Value> rest(Arena& arena);
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
private: private:
GcRoot<PodPair> _value; GcRoot<PodPair> _value;
@ -595,7 +598,7 @@ class Int64 : public Object {
int64_t value() { return _value->value; } int64_t value() { return _value->value; }
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
private: private:
GcRoot<PodInt64> _value; GcRoot<PodInt64> _value;
@ -635,7 +638,7 @@ class Float : public Object {
double value() { return _value->value; } double value() { return _value->value; }
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
private: private:
GcRoot<PodFloat> _value; GcRoot<PodFloat> _value;
@ -670,7 +673,7 @@ class Bool : public Object {
bool value() { return _value->value; } bool value() { return _value->value; }
virtual Result<Value> copy(Arena& arena) final; virtual Result<Value> copy(Arena& arena) const final;
private: private:
GcRoot<PodBool> _value; GcRoot<PodBool> _value;
@ -731,11 +734,19 @@ class Value {
return ((Object*)buf)->cmp(arena, *(Object*)rhs.buf); return ((Object*)buf)->cmp(arena, *(Object*)rhs.buf);
} }
Result<Value> get(Arena& arena, Value& key) {
return ((Object*)buf)->get(arena, key);
}
Result<Value> 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 // TODO: cmp() probably doesn't need arena parameter
// 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<bool> operator!=(Value& rhs) { return TRY(cmp(rhs)) != 0; }
Result<Value> copy(Arena& arena) { return ((Object*)buf)->copy(arena); } Result<Value> copy(Arena& arena) const { return ((Object*)buf)->copy(arena); }
private: private:
uint8_t buf[24]; uint8_t buf[24];

View file

@ -33,4 +33,7 @@ TEST_CASE(dict_read) {
v = DIEX(read_one(arena, "{1 2 3 4}")); v = DIEX(read_one(arena, "{1 2 3 4}"));
s = DIEX(write_one(arena, v)); s = DIEX(write_one(arena, v));
ASSERT_EQUALS(s, "{1 2 3 4}"); ASSERT_EQUALS(s, "{1 2 3 4}");
auto vv = DIEX(v.get(arena, 1));
ASSERT_EQUALS(vv, 2);
} }

View file

@ -3,6 +3,7 @@
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
#include <type_traits>
#include "common.hpp" #include "common.hpp"
#include "result.hpp" #include "result.hpp"
@ -42,44 +43,33 @@ bool run_tests() {
#define TEST_CASE(fun_) TEST_CASE_IMPL(MACRO_CONCAT(fun_, _COUNTER_)) #define TEST_CASE(fun_) TEST_CASE_IMPL(MACRO_CONCAT(fun_, _COUNTER_))
template <class T> Result<Value> to_value(Arena& arena, Value& val) { return val.copy(arena); }
struct Capture { Result<Value> to_value(Arena& arena, const Value& val) {
Capture(T& value) : value(value) {} return val.copy(arena);
T& value;
};
template <class T>
struct Capture<T&> {
Capture(T& value) : value(value) {}
T& value;
};
template <class T>
struct Capture<T&&> {
Capture(T&& value) : value(value) {}
T value;
};
Value& to_value(Arena& arena, Value& val) { return val; }
template <class T>
requires std::derived_from<T, Object>
Value to_value(Arena& arena, T& val) {
return DIEX(val.copy(arena));
} }
template <class T> template <class T>
requires(!std::derived_from<T, Object>) requires std::derived_from<T, Object>
Value to_value(Arena& arena, T& val) { Result<Value> to_value(Arena& arena, T& val) {
return DIEX(Value::create(arena, val)); return val.copy(arena);
}
template <class T>
requires(!std::derived_from<T, Object> && !std::is_fundamental<T>::value)
Result<Value> to_value(Arena& arena, T& val) {
return Value::create(arena, val);
}
template <class T>
requires(!std::derived_from<T, Object> && std::is_fundamental<T>::value)
Result<Value> to_value(Arena& arena, T val) {
return Value::create(arena, val);
} }
#define ASSERT_EQUALS(lhs, rhs) \ #define ASSERT_EQUALS(lhs, rhs) \
do { \ do { \
auto l = Capture(lhs); \ auto lv = DIEX(to_value(arena, lhs)); \
auto r = Capture(rhs); \ auto rv = DIEX(to_value(arena, rhs)); \
auto lv = to_value(arena, l.value); \
auto rv = to_value(arena, r.value); \
short c = DIEX(lv.cmp(arena, rv)); \ short c = DIEX(lv.cmp(arena, rv)); \
if (c != 0) { \ if (c != 0) { \
fprintf(stderr, "Values not equal at %s:%d\n", __FILE__, __LINE__); \ fprintf(stderr, "Values not equal at %s:%d\n", __FILE__, __LINE__); \