valeri/src/common.hpp

769 lines
22 KiB
C++
Raw Normal View History

#pragma once
#include <concepts>
#include <cstdint>
#include <cstring>
#include <iostream>
#include "arena.hpp"
2024-08-03 17:53:14 +00:00
#include "error.hpp"
#include "pod.hpp"
#include "utf8.hpp"
// Forward declarations
class Value;
class String;
class Nil;
class Int64;
class Float;
class Bool;
class String;
class Symbol;
class Syntax;
class Pair;
class Array;
class ByteArray;
2024-08-01 21:45:16 +00:00
class Writer;
short cmp_tag(Tag lhs, Tag rhs);
class Object {
public:
virtual Tag tag() = 0;
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const = 0;
2024-07-27 15:25:44 +00:00
virtual PodObject* pod() = 0;
2024-07-29 23:14:09 +00:00
virtual void move(Object*) = 0;
2024-07-27 18:40:13 +00:00
virtual ~Object() = default;
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena&, Object&) = 0;
virtual Result<short> cmp(Arena&, Nil&) { return cmp_tag(tag(), Tag::Nil); }
virtual Result<short> cmp(Arena&, Int64&) {
return cmp_tag(tag(), Tag::Int64);
}
virtual Result<short> cmp(Arena&, Float&) {
return cmp_tag(tag(), Tag::Float);
}
virtual Result<short> cmp(Arena&, Bool&) { return cmp_tag(tag(), Tag::Bool); }
virtual Result<short> cmp(Arena&, String&) {
return cmp_tag(tag(), Tag::String);
}
virtual Result<short> cmp(Arena&, Symbol&) {
return cmp_tag(tag(), Tag::Symbol);
}
virtual Result<short> cmp(Arena&, Syntax&) {
return cmp_tag(tag(), Tag::Syntax);
}
virtual Result<short> cmp(Arena&, Pair&) { return cmp_tag(tag(), Tag::Pair); }
virtual Result<short> cmp(Arena&, Array&) {
return cmp_tag(tag(), Tag::Array);
}
virtual Result<short> cmp(Arena&, ByteArray&) {
return cmp_tag(tag(), Tag::ByteArray);
}
2024-08-03 17:53:14 +00:00
virtual Result<Value> get(Arena& arena, Value& key);
2024-07-27 18:40:13 +00:00
Object() = default;
Object(const Object&) = delete;
};
class Nil : public Object {
public:
Nil() {}
2024-07-27 18:40:13 +00:00
Nil(Nil&& rhs) : _value(std::move(rhs._value)) {}
2024-07-27 15:25:44 +00:00
Nil(GcRoot<PodNil>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Nil; }
2024-07-27 15:25:44 +00:00
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Nil& rhs) final { return 0; }
2024-07-27 15:25:44 +00:00
static Result<Nil> create(Arena& arena, PodNil* obj) {
return Nil(TRY(MkGcRoot(obj, arena)));
}
static Result<Nil> create(Arena& arena) {
auto pod = TRY(arena.alloc<PodNil>());
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::Nil;
2024-07-27 15:25:44 +00:00
return Nil(TRY(MkGcRoot(pod, arena)));
}
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-27 15:25:44 +00:00
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final { new (obj) Nil(std::move(_value)); }
2024-07-27 15:25:44 +00:00
private:
GcRoot<PodNil> _value;
};
class Array : public Object {
public:
Array() {}
Array(Array&& rhs) : _value(std::move(rhs._value)) {}
Array(GcRoot<PodArray>&& val) : _value(std::move(val)) {}
Array& operator=(Array&& rhs) {
_value = std::move(rhs._value);
return *this;
}
virtual Tag tag() final { return Tag::Array; }
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Array& rhs) final { return 0; }
virtual void move(Object* obj) final { new (obj) Array(std::move(_value)); }
static Result<Array> create(Arena& arena, PodArray* obj) {
return Array(TRY(MkGcRoot(obj, arena)));
}
static Result<Array> create(Arena& arena) {
auto pod = TRY(arena.alloc<PodArray>());
pod->header.tag = Tag::Array;
pod->size = 0;
return Array(TRY(MkGcRoot(pod, arena)));
}
uint64_t size() { return _value->size; }
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
Result<Value> get(Arena& arena, uint64_t idx);
2024-08-03 17:53:14 +00:00
virtual Result<Value> get(Arena& arena, Value& key) final;
Result<Array> append(Arena& arena, Value& rhs);
Result<Array> concat(Arena& arena, Array& rhs) {
uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(PodObject*) * lhs_size);
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size);
return Array(TRY(MkGcRoot(pod, arena)));
}
Result<Array> sub(Arena& arena, uint64_t start, uint64_t end) {
if (start > end) return ErrorCode::IndexOutOfRange;
uint64_t res_size = end - start;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size;
memcpy(pod->data, _value->data + start, sizeof(PodObject*) * res_size);
return Array(TRY(MkGcRoot(pod, arena)));
}
private:
GcRoot<PodArray> _value;
};
2024-07-28 14:42:18 +00:00
class ByteArray : public Object {
public:
ByteArray() {}
ByteArray(ByteArray&& rhs) : _value(std::move(rhs._value)) {}
ByteArray(GcRoot<PodByteArray>&& val) : _value(std::move(val)) {}
ByteArray& operator=(ByteArray&& rhs) {
_value = std::move(rhs._value);
return *this;
}
virtual Tag tag() final { return Tag::ByteArray; }
2024-07-28 14:42:18 +00:00
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, ByteArray& rhs) final { return 0; }
2024-07-28 14:42:18 +00:00
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final {
new (obj) ByteArray(std::move(_value));
}
2024-07-28 14:42:18 +00:00
static Result<ByteArray> create(Arena& arena, PodByteArray* obj) {
return ByteArray(TRY(MkGcRoot(obj, arena)));
}
static Result<ByteArray> create(Arena& arena, char* chars, int64_t size) {
auto pod = TRY(arena.alloc<PodByteArray>(size * sizeof(char)));
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::ByteArray;
2024-07-28 14:42:18 +00:00
memcpy(pod->data, chars, size * sizeof(char32_t));
pod->size = size;
return ByteArray(TRY(MkGcRoot(pod, arena)));
}
static Result<ByteArray> create(Arena& arena, const char* str) {
uint64_t size = strlen(str);
auto pod = TRY(arena.alloc<PodByteArray>(size * sizeof(char32_t)));
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::ByteArray;
2024-07-28 14:42:18 +00:00
memcpy(pod->data, str, size);
pod->size = size;
return ByteArray(TRY(MkGcRoot(pod, arena)));
}
static Result<ByteArray> create(Arena& arena, String& str);
2024-07-28 14:42:18 +00:00
uint64_t size() { return _value->size; }
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-28 14:42:18 +00:00
Result<char> operator[](uint64_t idx) {
2024-07-28 14:42:18 +00:00
if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
return _value->data[idx];
}
Result<ByteArray> concat(Arena& arena, const char* rhs) {
uint64_t rhs_size = strlen(rhs);
uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodByteArray>(res_size * sizeof(char)));
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char) * lhs_size);
memcpy(pod->data, rhs + lhs_size, sizeof(char) * rhs_size);
return ByteArray(TRY(MkGcRoot(pod, arena)));
}
Result<ByteArray> concat(Arena& arena, const char* rhs, uint64_t rhs_size) {
uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodByteArray>(res_size * sizeof(char)));
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char) * lhs_size);
memcpy(pod->data, rhs + lhs_size, sizeof(char) * rhs_size);
return ByteArray(TRY(MkGcRoot(pod, arena)));
}
Result<ByteArray> concat(Arena& arena, ByteArray& rhs) {
uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodByteArray>(res_size * sizeof(char)));
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char) * lhs_size);
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size);
return ByteArray(TRY(MkGcRoot(pod, arena)));
}
Result<ByteArray> sub(Arena& arena, uint64_t start, uint64_t end) {
if (start > end) return ErrorCode::IndexOutOfRange;
uint64_t res_size = end - start;
auto pod = TRY(arena.alloc<PodByteArray>(res_size * sizeof(char)));
pod->size = res_size;
memcpy(pod->data, _value->data + start, sizeof(char) * res_size);
return ByteArray(TRY(MkGcRoot(pod, arena)));
}
private:
GcRoot<PodByteArray> _value;
};
class Dict : public Object {
public:
2024-08-01 21:45:16 +00:00
friend class Writer;
Dict() {}
Dict(Dict&& rhs) : _value(std::move(rhs._value)) {}
Dict(GcRoot<PodDict>&& val) : _value(std::move(val)) {}
Dict& operator=(Dict&& rhs) {
_value = std::move(rhs._value);
return *this;
}
virtual Tag tag() final { return Tag::Dict; }
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Dict& rhs) final;
virtual void move(Object* obj) final { new (obj) Dict(std::move(_value)); }
static Result<Dict> create(Arena& arena, PodDict* obj) {
return Dict(TRY(MkGcRoot(obj, arena)));
}
static Result<Dict> create(Arena& arena) {
auto pod = TRY(arena.alloc<PodDict>());
pod->header.tag = Tag::Dict;
pod->size = 0;
return Dict(TRY(MkGcRoot(pod, arena)));
}
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-08-03 17:53:14 +00:00
virtual Result<Value> get(Arena& arena, Value& key) final;
Result<Dict> insert(Arena& arena, Value& key, Value& value);
2024-08-01 21:45:16 +00:00
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();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodDict>(res_size * sizeof(PodObject*)));
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(PodObject*) * lhs_size);
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size);
return Dict(TRY(MkGcRoot(pod, arena)));
}
private:
2024-08-01 21:45:16 +00:00
Result<uint64_t> find(Arena& arena, Value& key);
uint64_t size() { return _value->size; }
GcRoot<PodDict> _value;
};
class String : public Object {
public:
2024-07-26 18:32:27 +00:00
String() {}
2024-07-27 18:40:13 +00:00
String(String&& rhs) : _value(std::move(rhs._value)) {}
2024-07-26 18:32:27 +00:00
String(GcRoot<PodString>&& val) : _value(std::move(val)) {}
2024-07-27 22:13:59 +00:00
String& operator=(String&& rhs) {
_value = std::move(rhs._value);
return *this;
}
virtual Tag tag() final { return Tag::String; }
2024-07-27 15:25:44 +00:00
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, String& rhs) final {
2024-08-02 22:27:36 +00:00
auto lsize = size();
auto rsize = rhs.size();
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;
char32_t lc = _value->data[i];
char32_t rc = rhs._value->data[j];
cmp = (lc > rc) - (lc < rc);
if (cmp != 0) return cmp;
i++;
j++;
}
return 0;
}
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final { new (obj) String(std::move(_value)); }
2024-07-26 18:32:27 +00:00
static Result<String> create(Arena& arena, PodString* obj) {
return String(TRY(MkGcRoot(obj, arena)));
}
static Result<String> create(Arena& arena, char32_t* chars, int64_t size) {
2024-07-28 23:14:30 +00:00
auto pod = TRY(arena.alloc<PodString>(size * sizeof(char32_t)));
pod->header.tag = Tag::String;
2024-07-28 23:14:30 +00:00
memcpy(pod->data, chars, size * sizeof(char32_t));
pod->size = size;
2024-07-28 23:14:30 +00:00
return String(TRY(MkGcRoot(pod, arena)));
}
2024-07-27 00:01:38 +00:00
static Result<String> create(Arena& arena, const char* str) {
uint64_t size = strlen(str);
2024-07-28 23:14:30 +00:00
auto pod = TRY(arena.alloc<PodString>(size * sizeof(char32_t)));
pod->header.tag = Tag::String;
2024-07-27 00:01:38 +00:00
2024-07-28 23:14:30 +00:00
for (uint64_t i = 0; i < size; i++) pod->data[i] = str[i];
pod->size = size;
2024-07-27 00:01:38 +00:00
2024-07-28 23:14:30 +00:00
return String(TRY(MkGcRoot(pod, arena)));
2024-07-27 00:01:38 +00:00
}
uint64_t size() { return _value->size; }
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-27 00:01:38 +00:00
Result<char32_t> operator[](uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
return _value->data[idx];
}
2024-07-27 22:13:59 +00:00
Result<String> concat(Arena& arena, const char* rhs) {
uint64_t rhs_size = strlen(rhs);
uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodString>(res_size * sizeof(char32_t)));
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::String;
2024-07-27 22:13:59 +00:00
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size);
for (uint64_t i = 0; i < rhs_size; i++) pod->data[lhs_size + i] = rhs[i];
return String(TRY(MkGcRoot(pod, arena)));
}
Result<String> concat(Arena& arena, const char32_t* rhs, uint64_t rhs_size) {
uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodString>(res_size * sizeof(char32_t)));
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::String;
2024-07-27 22:13:59 +00:00
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size);
for (uint64_t i = 0; i < rhs_size; i++) pod->data[lhs_size + i] = rhs[i];
return String(TRY(MkGcRoot(pod, arena)));
}
Result<String> concat(Arena& arena, String& rhs) {
uint64_t rhs_size = rhs.size();
uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodString>(res_size * sizeof(char32_t)));
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::String;
2024-07-27 22:13:59 +00:00
pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(char32_t) * lhs_size);
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char32_t) * rhs_size);
return String(TRY(MkGcRoot(pod, arena)));
}
Result<String> sub(Arena& arena, uint64_t start, uint64_t end) {
if (start > end) return ErrorCode::IndexOutOfRange;
uint64_t res_size = end - start;
auto pod = TRY(arena.alloc<PodString>(res_size * sizeof(char32_t)));
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::String;
2024-07-27 22:13:59 +00:00
pod->size = res_size;
memcpy(pod->data, _value->data + start, sizeof(char32_t) * res_size);
return String(TRY(MkGcRoot(pod, arena)));
}
friend class Symbol;
2024-07-26 18:32:27 +00:00
private:
2024-07-26 18:32:27 +00:00
GcRoot<PodString> _value;
};
class Symbol : public Object {
public:
2024-07-26 18:32:27 +00:00
Symbol() {}
2024-07-27 18:40:13 +00:00
Symbol(Symbol&& rhs) : _value(std::move(rhs._value)) {}
2024-07-26 18:32:27 +00:00
Symbol(GcRoot<PodSymbol>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Symbol; }
2024-07-27 15:25:44 +00:00
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Symbol& rhs) final { return 0; }
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final { new (obj) Symbol(std::move(_value)); }
2024-07-26 18:32:27 +00:00
static Result<Symbol> create(Arena& arena, PodSymbol* obj) {
return Symbol(TRY(MkGcRoot(obj, arena)));
}
static Result<Symbol> create(Arena& arena, char32_t* chars, int64_t size) {
2024-07-28 23:14:30 +00:00
auto pod = TRY(arena.alloc<PodSymbol>(size * sizeof(char32_t)));
pod->header.tag = Tag::Symbol;
2024-07-28 23:14:30 +00:00
memcpy(pod->data, chars, size * sizeof(char32_t));
2024-07-28 23:14:30 +00:00
return Symbol(TRY(MkGcRoot(pod, arena)));
}
2024-07-27 22:13:59 +00:00
static Result<Symbol> create(Arena& arena, String& rhs);
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-26 18:32:27 +00:00
2024-07-28 16:54:04 +00:00
uint64_t size() { return _value->size; }
Result<char32_t> operator[](uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
return _value->data[idx];
}
private:
2024-07-26 18:32:27 +00:00
GcRoot<PodSymbol> _value;
};
class Syntax : public Object {
public:
2024-07-26 18:32:27 +00:00
Syntax() {}
2024-07-27 18:40:13 +00:00
Syntax(Syntax&& rhs) : _value(std::move(rhs._value)) {}
2024-07-26 18:32:27 +00:00
Syntax(GcRoot<PodSyntax>&& val) : _value(std::move(val)) {}
Syntax(String filename, String modulename, Value expression);
virtual Tag tag() final { return Tag::Syntax; }
2024-07-27 15:25:44 +00:00
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Syntax& rhs) final { return 0; }
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final { new (obj) Syntax(std::move(_value)); }
2024-07-26 18:32:27 +00:00
static Result<Syntax> create(Arena& arena, PodSyntax* obj) {
return Syntax(TRY(MkGcRoot(obj, arena)));
}
2024-07-26 19:20:13 +00:00
Result<Value> get_value(Arena& arena);
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-26 18:32:27 +00:00
private:
2024-07-26 18:32:27 +00:00
GcRoot<PodSyntax> _value;
};
class Pair : public Object {
public:
2024-07-26 18:32:27 +00:00
Pair() {}
2024-07-27 18:40:13 +00:00
Pair(Pair&& rhs) : _value(std::move(rhs._value)) {}
2024-07-26 18:32:27 +00:00
Pair(GcRoot<PodPair>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Pair; }
2024-07-27 15:25:44 +00:00
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Pair& rhs) final { return 0; }
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final { new (obj) Pair(std::move(_value)); }
2024-07-26 18:32:27 +00:00
static Result<Pair> create(Arena& arena, PodPair* obj) {
return Pair(TRY(MkGcRoot(obj, arena)));
}
2024-07-27 15:25:44 +00:00
static Result<Pair> create(Arena& arena, Value& first, Value& rest);
2024-07-26 18:32:27 +00:00
2024-07-27 15:25:44 +00:00
Result<Value> first(Arena& arena);
Result<Value> rest(Arena& arena);
2024-07-26 18:32:27 +00:00
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-26 18:32:27 +00:00
private:
2024-07-26 18:32:27 +00:00
GcRoot<PodPair> _value;
};
class Int64 : public Object {
public:
friend class Float;
2024-07-27 15:25:44 +00:00
Int64() {}
2024-07-27 18:40:13 +00:00
Int64(Int64&& rhs) : _value(std::move(rhs._value)) {}
2024-07-27 15:25:44 +00:00
Int64(GcRoot<PodInt64>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Int64; }
2024-07-27 15:25:44 +00:00
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Int64& rhs) final {
return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value);
}
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena&, Float& rhs) final;
2024-07-27 15:25:44 +00:00
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final { new (obj) Int64(std::move(_value)); }
2024-07-27 15:25:44 +00:00
static Result<Int64> create(Arena& arena, PodInt64* obj) {
return Int64(TRY(MkGcRoot(obj, arena)));
}
static Result<Int64> create(Arena& arena, double val) {
auto pod = TRY(arena.alloc<PodInt64>());
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::Int64;
2024-07-27 15:25:44 +00:00
pod->value = val;
return Int64(TRY(MkGcRoot(pod, arena)));
}
2024-07-27 15:25:44 +00:00
int64_t value() { return _value->value; }
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-26 18:32:27 +00:00
private:
2024-07-27 15:25:44 +00:00
GcRoot<PodInt64> _value;
};
class Float : public Object {
public:
friend class Int64;
2024-07-27 15:25:44 +00:00
Float() {}
2024-07-27 18:40:13 +00:00
Float(Float&& rhs) : _value(std::move(rhs._value)) {}
2024-07-27 15:25:44 +00:00
Float(GcRoot<PodFloat>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Float; }
2024-07-27 15:25:44 +00:00
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Float& rhs) final {
return (_value->value > rhs._value->value) -
(_value->value < rhs._value->value);
}
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena&, Int64& rhs) final;
2024-07-27 15:25:44 +00:00
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final { new (obj) Float(std::move(_value)); }
2024-07-27 15:25:44 +00:00
static Result<Float> create(Arena& arena, PodFloat* obj) {
return Float(TRY(MkGcRoot(obj, arena)));
}
static Result<Float> create(Arena& arena, double val) {
auto pod = TRY(arena.alloc<PodFloat>());
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::Float;
2024-07-27 15:25:44 +00:00
pod->value = val;
return Float(TRY(MkGcRoot(pod, arena)));
}
2024-07-27 15:25:44 +00:00
double value() { return _value->value; }
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-26 18:32:27 +00:00
private:
2024-07-27 15:25:44 +00:00
GcRoot<PodFloat> _value;
};
2024-07-27 18:40:13 +00:00
class Bool : public Object {
public:
Bool() {}
Bool(Bool&& rhs) : _value(std::move(rhs._value)) {}
Bool(GcRoot<PodBool>&& val) : _value(std::move(val)) {}
virtual Tag tag() final { return Tag::Bool; }
virtual PodObject* pod() final { return _value.get(); }
2024-08-03 12:43:59 +00:00
virtual Result<short> cmp(Arena& arena, Object& rhs) final {
return -TRY(rhs.cmp(arena, *this));
}
virtual Result<short> cmp(Arena&, Bool& rhs) final { return 0; }
2024-07-27 18:40:13 +00:00
2024-07-29 23:14:09 +00:00
virtual void move(Object* obj) final { new (obj) Bool(std::move(_value)); }
2024-07-27 18:40:13 +00:00
static Result<Bool> create(Arena& arena, PodBool* obj) {
return Bool(TRY(MkGcRoot(obj, arena)));
}
static Result<Bool> create(Arena& arena, bool val) {
auto pod = TRY(arena.alloc<PodBool>());
2024-07-28 23:14:30 +00:00
pod->header.tag = Tag::Bool;
2024-07-27 18:40:13 +00:00
pod->value = val;
return Bool(TRY(MkGcRoot(pod, arena)));
}
bool value() { return _value->value; }
2024-08-03 17:53:14 +00:00
virtual Result<Value> copy(Arena& arena) const final;
2024-07-27 18:40:13 +00:00
private:
GcRoot<PodBool> _value;
};
// note: this class doesn't perform proper destruction of objects in some cases
class Value {
public:
Value() { new (buf) Nil(); }
~Value() { ((Object*)buf)->~Object(); }
2024-07-27 00:01:38 +00:00
Value(Value&& val) {
2024-07-29 23:14:09 +00:00
((Object*)val.buf)->move((Object*)buf);
2024-07-27 00:01:38 +00:00
new (val.buf) Nil();
}
2024-07-26 18:32:27 +00:00
Value(const Value&) = delete;
template <class T>
2024-07-26 18:32:27 +00:00
Value(T&& obj)
requires std::derived_from<T, Object>
{
2024-07-26 18:32:27 +00:00
new (buf) T(std::move(obj));
}
2024-07-27 15:25:44 +00:00
Value& operator=(Value&& val) {
((Object*)buf)->~Object();
2024-07-29 23:14:09 +00:00
((Object*)val.buf)->move((Object*)buf);
2024-07-27 15:25:44 +00:00
new (val.buf) Nil();
return *this;
}
2024-07-26 19:20:13 +00:00
static Result<Value> create(Arena& arena, PodObject* obj);
2024-08-01 21:45:16 +00:00
static Result<Value> create(Arena& arena, const int64_t& value) {
return Value(TRY(Int64::create(arena, value)));
}
2024-08-02 22:27:36 +00:00
static Result<Value> create(Arena& arena, const char* value) {
return Value(TRY(String::create(arena, value)));
}
template <class T>
bool is() {
return dynamic_cast<T*>((Object*)buf) != nullptr;
}
template <class T>
T* to() {
return dynamic_cast<T*>((Object*)buf);
}
2024-07-27 15:25:44 +00:00
PodObject* pod() { return ((Object*)buf)->pod(); }
2024-07-28 16:54:04 +00:00
Tag tag() { return ((Object*)buf)->tag(); }
2024-07-27 15:25:44 +00:00
Object& operator*() { return *(Object*)(buf); }
Object* operator->() { return (Object*)(buf); }
2024-08-03 12:43:59 +00:00
Result<short> cmp(Arena& arena, Value& rhs) {
return ((Object*)buf)->cmp(arena, *(Object*)rhs.buf);
}
2024-08-03 17:53:14 +00:00
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);
}
2024-08-03 12:43:59 +00:00
// 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; }
2024-08-03 17:53:14 +00:00
Result<Value> copy(Arena& arena) const { return ((Object*)buf)->copy(arena); }
2024-07-26 18:32:27 +00:00
private:
2024-07-26 18:32:27 +00:00
uint8_t buf[24];
};
2024-07-26 18:32:27 +00:00
Result<Value> syntax_unwrap(Value& val);
2024-07-27 15:25:44 +00:00
Result<Value> reverse(Arena& arena, Value& val);
Result<void> debug_print(Arena& arena, String& val);
2024-08-02 22:27:36 +00:00
Result<void> debug_print(Arena& arena, Value& val);
2024-08-01 21:45:16 +00:00
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);
}