/* * Copyright (C) 2023 Riyyi * * SPDX-License-Identifier: MIT */ #pragma once #include // std::derived_from, std::same_as #include // int64_t, uint8_t #include // std::function #include #include #include // std::shared_ptr #include #include #include #include // typeid #include #include "ruc/format/formatter.h" #include "forward.h" namespace blaze { template std::shared_ptr makePtr(Args&&... args) { return std::make_shared(std::forward(args)...); } // ----------------------------------------- class Value { public: virtual ~Value() = default; virtual ValuePtr withMetaImpl(ValuePtr meta) const = 0; ValuePtr withMeta(ValuePtr meta) const; ValuePtr meta() const; std::string className() const { return typeid(*this).name(); } template bool fastIs() const = delete; virtual bool isCollection() const { return false; } virtual bool isList() const { return false; } virtual bool isVector() const { return false; } virtual bool isHashMap() const { return false; } virtual bool isString() const { return false; } virtual bool isKeyword() const { return false; } virtual bool isNumber() const { return false; } virtual bool isConstant() const { return false; } virtual bool isSymbol() const { return false; } virtual bool isCallable() const { return false; } virtual bool isFunction() const { return false; } virtual bool isLambda() const { return false; } virtual bool isMacro() const { return false; } virtual bool isAtom() const { return false; } protected: Value() {} Value(ValuePtr meta) : m_meta(meta) { } ValuePtr m_meta; }; #define WITH_META(Type) \ virtual ValuePtr withMetaImpl(ValuePtr meta) const override \ { \ return makePtr(*this, meta); \ } #define WITH_NO_META() \ virtual ValuePtr withMetaImpl(ValuePtr meta) const override \ { \ (void)meta; \ return nullptr; \ } // ----------------------------------------- template concept IsValue = std::same_as || std::derived_from; class Collection : public Value { public: virtual ~Collection() = default; // TODO: rename size -> count size_t size() const { return m_nodes.size(); } bool empty() const { return m_nodes.size() == 0; } ValuePtr front() const { return m_nodes.front(); } ValueVector rest() const; const ValueVector& nodes() const { return m_nodes; } protected: Collection() = default; Collection(const ValueVector& nodes); Collection(ValueVectorIt begin, ValueVectorIt end); Collection(ValueVectorConstIt begin, ValueVectorConstIt end); Collection(const Collection& that, ValuePtr meta); template Collection(std::shared_ptr... nodes) { m_nodes = { nodes... }; } private: virtual bool isCollection() const override { return true; } ValueVector m_nodes; }; // ----------------------------------------- // () class List final : public Collection { public: List() = default; List(const ValueVector& nodes); List(ValueVectorIt begin, ValueVectorIt end); List(ValueVectorConstIt begin, ValueVectorConstIt end); List(const List& that, ValuePtr meta); template List(std::shared_ptr... nodes) : Collection(nodes...) { } virtual ~List() = default; WITH_META(List); private: virtual bool isList() const override { return true; } }; // ----------------------------------------- // [] class Vector final : public Collection { public: Vector() = default; Vector(const ValueVector& nodes); Vector(ValueVectorIt begin, ValueVectorIt end); Vector(ValueVectorConstIt begin, ValueVectorConstIt end); Vector(const Vector& that, ValuePtr meta); template Vector(std::shared_ptr... nodes) : Collection(nodes...) { } virtual ~Vector() = default; WITH_META(Vector); private: virtual bool isVector() const override { return true; } }; // ----------------------------------------- using Elements = std::map; // {} class HashMap final : public Value { public: HashMap() = default; HashMap(const Elements& elements); HashMap(const HashMap& that, ValuePtr meta); virtual ~HashMap() = default; static std::string getKeyString(ValuePtr key); bool exists(const std::string& key); bool exists(ValuePtr key); ValuePtr get(const std::string& key); ValuePtr get(ValuePtr key); const Elements& elements() const { return m_elements; } size_t size() const { return m_elements.size(); } bool empty() const { return m_elements.size() == 0; } WITH_META(HashMap); private: virtual bool isHashMap() const override { return true; } Elements m_elements; }; // ----------------------------------------- // "string" class String final : public Value { public: String(const std::string& data); String(char character); virtual ~String() = default; const std::string& data() const { return m_data; } size_t size() const { return m_data.size(); } bool empty() const { return m_data.empty(); } WITH_NO_META(); private: virtual bool isString() const override { return true; } const std::string m_data; }; // ----------------------------------------- // :keyword class Keyword final : public Value { public: Keyword(const std::string& data); virtual ~Keyword() = default; virtual bool isKeyword() const override { return true; } const std::string& keyword() const { return m_data; } WITH_NO_META(); private: const std::string m_data; }; // ----------------------------------------- // 123 class Number final : public Value { public: Number(int64_t number); virtual ~Number() = default; int64_t number() const { return m_number; } WITH_NO_META(); private: virtual bool isNumber() const override { return true; } const int64_t m_number { 0 }; }; // ----------------------------------------- // true, false, nil class Constant final : public Value { public: enum State : uint8_t { Nil, True, False, }; Constant() = default; Constant(State state); Constant(bool state); virtual ~Constant() = default; State state() const { return m_state; } WITH_NO_META(); private: virtual bool isConstant() const override { return true; } const State m_state { State::Nil }; }; // ----------------------------------------- // Symbols class Symbol final : public Value { public: Symbol(const std::string& symbol); virtual ~Symbol() = default; const std::string& symbol() const { return m_symbol; } WITH_NO_META(); private: virtual bool isSymbol() const override { return true; } const std::string m_symbol; }; // ----------------------------------------- class Callable : public Value { public: virtual ~Callable() = default; protected: Callable() = default; Callable(ValuePtr meta); private: virtual bool isCallable() const override { return true; } }; // ----------------------------------------- using FunctionType = std::function; class Function final : public Callable { public: Function(const std::string& name, FunctionType function); Function(const Function& that, ValuePtr meta); virtual ~Function() = default; const std::string& name() const { return m_name; } FunctionType function() const { return m_function; } WITH_META(Function); private: virtual bool isFunction() const override { return true; } const std::string m_name; const FunctionType m_function; }; // ----------------------------------------- class Lambda : public Callable { public: Lambda(const std::vector& bindings, ValuePtr body, EnvironmentPtr env); Lambda(const Lambda& that); Lambda(const Lambda& that, ValuePtr meta); virtual ~Lambda() = default; const std::vector& bindings() const { return m_bindings; } ValuePtr body() const { return m_body; } EnvironmentPtr env() const { return m_env; } WITH_META(Lambda); private: virtual bool isLambda() const override { return true; } const std::vector m_bindings; const ValuePtr m_body; const EnvironmentPtr m_env; }; // ----------------------------------------- class Macro final : public Lambda { public: Macro(const Lambda& that); WITH_NO_META(); private: virtual bool isLambda() const override { return false; } virtual bool isMacro() const override { return true; } }; // ----------------------------------------- class Atom final : public Value { public: Atom() = default; Atom(ValuePtr pointer); virtual ~Atom() = default; ValuePtr reset(ValuePtr value) { return m_value = value; } ValuePtr deref() const { return m_value; } WITH_NO_META(); private: virtual bool isAtom() const override { return true; } ValuePtr m_value; }; // ----------------------------------------- // clang-format off template<> inline bool Value::fastIs() const { return isCollection(); } template<> inline bool Value::fastIs() const { return isList(); } template<> inline bool Value::fastIs() const { return isVector(); } template<> inline bool Value::fastIs() const { return isHashMap(); } template<> inline bool Value::fastIs() const { return isString(); } template<> inline bool Value::fastIs() const { return isKeyword(); } template<> inline bool Value::fastIs() const { return isNumber(); } template<> inline bool Value::fastIs() const { return isConstant(); } template<> inline bool Value::fastIs() const { return isSymbol(); } template<> inline bool Value::fastIs() const { return isCallable(); } template<> inline bool Value::fastIs() const { return isFunction(); } template<> inline bool Value::fastIs() const { return isLambda(); } template<> inline bool Value::fastIs() const { return isMacro(); } template<> inline bool Value::fastIs() const { return isAtom(); } // clang-format on } // namespace blaze // ----------------------------------------- template<> struct ruc::format::Formatter : public Formatter { void format(Builder& builder, blaze::ValuePtr value) const; };