#pragma once #include #include #include #include #include "arena.hpp" #include "pod.hpp" // Forward declarations class Value; struct SourcePosition { size_t line{1}; size_t column{1}; size_t offset{0}; }; struct SourceRange { SourcePosition start; SourcePosition end; }; class PodInt64 final : public PodObject { public: PodInt64() : PodObject(Tag::Int64){}; int64_t value; }; class PodFloat final : public PodObject { public: PodFloat() : PodObject(Tag::Float){}; double value; }; class PodString final : public PodObject { public: PodString() : PodObject(Tag::String){}; uint64_t size; char32_t data[]; }; class PodSymbol final : public PodObject { public: PodSymbol() : PodObject(Tag::Symbol){}; uint64_t size; char32_t data[]; }; class PodSyntax : public PodObject { public: PodSyntax() : PodObject(Tag::Syntax){}; OffPtr filename; OffPtr modulename; OffPtr expression; SourceRange sourcerange; }; class PodPair : public PodObject { public: PodPair() : PodObject(Tag::Pair){}; OffPtr first; OffPtr second; }; class Object { public: virtual Tag tag() = 0; virtual Result copy(Arena& arena) = 0; }; class Nil : public Object { public: Nil() {} virtual Tag tag() final { return Tag::Nil; } virtual Result copy(Arena& arena) final; }; class String : public Object { public: String() {} String(GcRoot&& val) : _value(std::move(val)) {} virtual Tag tag() final { return Tag::String; } static Result create(Arena& arena, PodString* obj) { return String(TRY(MkGcRoot(obj, arena))); } static Result create(Arena& arena, char32_t* chars, int64_t size) { auto pod_string = TRY(arena.alloc(size * sizeof(char32_t))); memcpy(pod_string->data, chars, size * sizeof(char32_t)); return String(TRY(MkGcRoot(pod_string, arena))); } virtual Result copy(Arena& arena) final; private: GcRoot _value; }; class Symbol : public Object { public: Symbol() {} Symbol(GcRoot&& val) : _value(std::move(val)) {} virtual Tag tag() final { return Tag::Symbol; } static Result create(Arena& arena, PodSymbol* obj) { return Symbol(TRY(MkGcRoot(obj, arena))); } static Result create(Arena& arena, char32_t* chars, int64_t size) { auto pod_symbol = TRY(arena.alloc(size * sizeof(char32_t))); memcpy(pod_symbol->data, chars, size * sizeof(char32_t)); return Symbol(TRY(MkGcRoot(pod_symbol, arena))); } virtual Result copy(Arena& arena) final; private: GcRoot _value; }; class Syntax : public Object { public: Syntax() {} Syntax(GcRoot&& val) : _value(std::move(val)) {} Syntax(String filename, String modulename, Value expression); virtual Tag tag() final { return Tag::Syntax; } static Result create(Arena& arena, PodSyntax* obj) { return Syntax(TRY(MkGcRoot(obj, arena))); } Result get_value(Arena& arena); virtual Result copy(Arena& arena) final; private: GcRoot _value; }; class Pair : public Object { public: Pair() {} Pair(GcRoot&& val) : _value(std::move(val)) {} virtual Tag tag() final { return Tag::Pair; } static Result create(Arena& arena, PodPair* obj) { return Pair(TRY(MkGcRoot(obj, arena))); } static Result first(Arena& arena); virtual Result copy(Arena& arena) final; private: GcRoot _value; }; class Int64 : public Object { public: Int64() : _value(0) {} Int64(int64_t val) : _value(val) {} virtual ~Int64() = default; virtual Tag tag() final { return Tag::Int64; } int64_t value() { return _value; } virtual Result copy(Arena& arena) final; private: int64_t _value; }; class Float : public Object { public: Float() : _value(0) {} Float(double val) : _value(val) {} virtual ~Float() = default; virtual Tag tag() final { return Tag::Float; } double value() { return _value; } virtual Result copy(Arena& arena) final; private: double _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(); } Value(Value&& val) { memcpy(buf, val.buf, 24); } Value(const Value&) = delete; template Value(T&& obj) requires std::derived_from { new (buf) T(std::move(obj)); } static Result create(Arena& arena, PodObject* obj); template bool is() { return dynamic_cast((Object*)buf) != nullptr; } template T* to() { return dynamic_cast((Object*)buf); } Object& operator*() { return *(Object*)(buf); } Object* operator->() { return (Object*)(buf); } Result copy(Arena& arena) { return ((Object*)buf)->copy(arena); } private: uint8_t buf[24]; }; Result syntax_unwrap(Value& val);