#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; }; class Nil : public Object { public: Nil() {} virtual Tag tag() final { return Tag::Nil; } }; class String : public Object { public: String() : _value(0) {} String(PodString* val) : _value(val) {} virtual Tag tag() final { return Tag::String; } 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(pod_string); } private: PodString* _value; }; class Symbol : public Object { public: Symbol() : _value(0) {} Symbol(PodSymbol* val) : _value(val) {} virtual Tag tag() final { return Tag::Symbol; } 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(pod_symbol); } private: PodSymbol* _value; }; class Syntax : public Object { public: Syntax(PodSyntax* val) : _value(val) {} Syntax(String filename, String modulename, Value expression); virtual Tag tag() final { return Tag::Syntax; } Value get_value(); private: PodSyntax* _value; }; class Pair : public Object { public: Pair(PodPair* value) : _value(value) {} virtual Tag tag() final { return Tag::Pair; } private: PodPair* _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; } private: int64_t _value; }; class Float : public Object { public: Float() : _value(0) {} virtual ~Float() = default; virtual Tag tag() final { return Tag::Float; } double value() { return _value; } 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(); } template Value(const T& obj) requires std::derived_from && (sizeof(T) <= 16) { new (buf) T(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); } private: uint8_t buf[16]; }; Value pod_to_value(PodObject* obj); Value syntax_unwrap(Value);