2024-07-19 01:29:30 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <concepts>
|
|
|
|
#include <cstdint>
|
2024-07-20 21:42:49 +00:00
|
|
|
#include <cstring>
|
2024-07-19 01:29:30 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include "arena.hpp"
|
|
|
|
#include "pod.hpp"
|
|
|
|
|
|
|
|
// Forward declarations
|
|
|
|
|
|
|
|
class Value;
|
|
|
|
|
|
|
|
class Object {
|
|
|
|
public:
|
|
|
|
virtual Tag tag() = 0;
|
2024-07-26 18:32:27 +00:00
|
|
|
virtual Result<Value> copy(Arena& arena) = 0;
|
2024-07-27 15:25:44 +00:00
|
|
|
virtual PodObject* pod() = 0;
|
2024-07-27 18:40:13 +00:00
|
|
|
virtual ~Object() = default;
|
|
|
|
Object() = default;
|
|
|
|
Object(const Object&) = delete;
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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)) {}
|
2024-07-19 01:29:30 +00:00
|
|
|
|
|
|
|
virtual Tag tag() final { return Tag::Nil; }
|
2024-07-27 15:25:44 +00:00
|
|
|
virtual PodObject* pod() final { return _value.get(); }
|
|
|
|
|
|
|
|
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>());
|
|
|
|
|
|
|
|
return Nil(TRY(MkGcRoot(pod, arena)));
|
|
|
|
}
|
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
virtual Result<Value> copy(Arena& arena) final;
|
2024-07-27 15:25:44 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
GcRoot<PodNil> _value;
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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-19 01:29:30 +00:00
|
|
|
virtual Tag tag() final { return Tag::String; }
|
2024-07-27 15:25:44 +00:00
|
|
|
virtual PodObject* pod() final { return _value.get(); }
|
2024-07-19 01:29:30 +00:00
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
static Result<String> create(Arena& arena, PodString* obj) {
|
|
|
|
return String(TRY(MkGcRoot(obj, arena)));
|
|
|
|
}
|
2024-07-20 21:42:49 +00:00
|
|
|
static Result<String> create(Arena& arena, char32_t* chars, int64_t size) {
|
|
|
|
auto pod_string = TRY(arena.alloc<PodString>(size * sizeof(char32_t)));
|
|
|
|
|
|
|
|
memcpy(pod_string->data, chars, size * sizeof(char32_t));
|
2024-07-27 00:01:38 +00:00
|
|
|
pod_string->size = size;
|
2024-07-20 21:42:49 +00:00
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
return String(TRY(MkGcRoot(pod_string, arena)));
|
2024-07-20 21:42:49 +00:00
|
|
|
}
|
|
|
|
|
2024-07-27 00:01:38 +00:00
|
|
|
static Result<String> create(Arena& arena, const char* str) {
|
|
|
|
uint64_t size = strlen(str);
|
|
|
|
auto pod_string = TRY(arena.alloc<PodString>(size * sizeof(char32_t)));
|
|
|
|
|
|
|
|
for (uint64_t i = 0; i < size; i++) pod_string->data[i] = str[i];
|
|
|
|
pod_string->size = size;
|
|
|
|
|
|
|
|
return String(TRY(MkGcRoot(pod_string, arena)));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t size() { return _value->size; }
|
|
|
|
|
|
|
|
Result<char32_t> operator[](uint64_t idx) {
|
|
|
|
if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
|
|
|
|
return _value->data[idx];
|
|
|
|
}
|
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
virtual Result<Value> copy(Arena& arena) final;
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
private:
|
2024-07-26 18:32:27 +00:00
|
|
|
GcRoot<PodString> _value;
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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)) {}
|
2024-07-19 01:29:30 +00:00
|
|
|
virtual Tag tag() final { return Tag::Symbol; }
|
2024-07-27 15:25:44 +00:00
|
|
|
virtual PodObject* pod() final { return _value.get(); }
|
2024-07-19 01:29:30 +00:00
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
static Result<Symbol> create(Arena& arena, PodSymbol* obj) {
|
|
|
|
return Symbol(TRY(MkGcRoot(obj, arena)));
|
|
|
|
}
|
|
|
|
|
2024-07-20 21:42:49 +00:00
|
|
|
static Result<Symbol> create(Arena& arena, char32_t* chars, int64_t size) {
|
|
|
|
auto pod_symbol = TRY(arena.alloc<PodSymbol>(size * sizeof(char32_t)));
|
|
|
|
|
|
|
|
memcpy(pod_symbol->data, chars, size * sizeof(char32_t));
|
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
return Symbol(TRY(MkGcRoot(pod_symbol, arena)));
|
2024-07-20 21:42:49 +00:00
|
|
|
}
|
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
virtual Result<Value> copy(Arena& arena) final;
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
private:
|
2024-07-26 18:32:27 +00:00
|
|
|
GcRoot<PodSymbol> _value;
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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)) {}
|
2024-07-19 01:29:30 +00:00
|
|
|
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-07-19 01:29:30 +00:00
|
|
|
|
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-07-19 01:29:30 +00:00
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
virtual Result<Value> copy(Arena& arena) final;
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
private:
|
2024-07-26 18:32:27 +00:00
|
|
|
GcRoot<PodSyntax> _value;
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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)) {}
|
2024-07-19 01:29:30 +00:00
|
|
|
virtual Tag tag() final { return Tag::Pair; }
|
2024-07-27 15:25:44 +00:00
|
|
|
virtual PodObject* pod() final { return _value.get(); }
|
2024-07-19 01:29:30 +00:00
|
|
|
|
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
|
|
|
|
|
|
|
virtual Result<Value> copy(Arena& arena) final;
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
private:
|
2024-07-26 18:32:27 +00:00
|
|
|
GcRoot<PodPair> _value;
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Int64 : public Object {
|
|
|
|
public:
|
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)) {}
|
2024-07-19 01:29:30 +00:00
|
|
|
virtual Tag tag() final { return Tag::Int64; }
|
2024-07-27 15:25:44 +00:00
|
|
|
virtual PodObject* pod() final { return _value.get(); }
|
|
|
|
|
|
|
|
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>());
|
|
|
|
pod->value = val;
|
|
|
|
|
|
|
|
return Int64(TRY(MkGcRoot(pod, arena)));
|
|
|
|
}
|
2024-07-19 01:29:30 +00:00
|
|
|
|
2024-07-27 15:25:44 +00:00
|
|
|
int64_t value() { return _value->value; }
|
2024-07-19 01:29:30 +00:00
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
virtual Result<Value> copy(Arena& arena) final;
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
private:
|
2024-07-27 15:25:44 +00:00
|
|
|
GcRoot<PodInt64> _value;
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Float : public Object {
|
|
|
|
public:
|
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)) {}
|
2024-07-19 01:29:30 +00:00
|
|
|
virtual Tag tag() final { return Tag::Float; }
|
2024-07-27 15:25:44 +00:00
|
|
|
virtual PodObject* pod() final { return _value.get(); }
|
|
|
|
|
|
|
|
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>());
|
|
|
|
pod->value = val;
|
|
|
|
|
|
|
|
return Float(TRY(MkGcRoot(pod, arena)));
|
|
|
|
}
|
2024-07-19 01:29:30 +00:00
|
|
|
|
2024-07-27 15:25:44 +00:00
|
|
|
double value() { return _value->value; }
|
2024-07-19 01:29:30 +00:00
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
virtual Result<Value> copy(Arena& arena) final;
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
private:
|
2024-07-27 15:25:44 +00:00
|
|
|
GcRoot<PodFloat> _value;
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
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(); }
|
|
|
|
|
|
|
|
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>());
|
|
|
|
pod->value = val;
|
|
|
|
|
|
|
|
return Bool(TRY(MkGcRoot(pod, arena)));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value() { return _value->value; }
|
|
|
|
|
|
|
|
virtual Result<Value> copy(Arena& arena) final;
|
|
|
|
|
|
|
|
private:
|
|
|
|
GcRoot<PodBool> _value;
|
|
|
|
};
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
// 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) {
|
|
|
|
memcpy(buf, val.buf, 24);
|
|
|
|
new (val.buf) Nil();
|
|
|
|
}
|
2024-07-26 18:32:27 +00:00
|
|
|
Value(const Value&) = delete;
|
2024-07-19 01:29:30 +00:00
|
|
|
|
|
|
|
template <class T>
|
2024-07-26 18:32:27 +00:00
|
|
|
Value(T&& obj)
|
|
|
|
requires std::derived_from<T, Object>
|
2024-07-19 01:29:30 +00:00
|
|
|
{
|
2024-07-26 18:32:27 +00:00
|
|
|
new (buf) T(std::move(obj));
|
2024-07-19 01:29:30 +00:00
|
|
|
}
|
|
|
|
|
2024-07-27 15:25:44 +00:00
|
|
|
Value& operator=(Value&& val) {
|
|
|
|
memcpy(buf, val.buf, 24);
|
|
|
|
new (val.buf) Nil();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2024-07-26 19:20:13 +00:00
|
|
|
static Result<Value> create(Arena& arena, PodObject* obj);
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
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-19 01:29:30 +00:00
|
|
|
Object& operator*() { return *(Object*)(buf); }
|
|
|
|
Object* operator->() { return (Object*)(buf); }
|
|
|
|
|
2024-07-26 18:32:27 +00:00
|
|
|
Result<Value> copy(Arena& arena) { return ((Object*)buf)->copy(arena); }
|
|
|
|
|
2024-07-19 01:29:30 +00:00
|
|
|
private:
|
2024-07-26 18:32:27 +00:00
|
|
|
uint8_t buf[24];
|
2024-07-19 01:29:30 +00:00
|
|
|
};
|
|
|
|
|
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);
|