Add test for dictionary "get()"
This commit is contained in:
parent
a52e4d278c
commit
b0166cc7da
5 changed files with 70 additions and 57 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__); \
|
||||||
|
|
Loading…
Reference in a new issue