/* * 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 // std::shared_ptr #include #include #include #include // typeid #include #include #include "ruc/format/formatter.h" #include "forward.h" namespace blaze { class Value { public: virtual ~Value() = default; 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 isAtom() const { return false; } protected: Value() {} }; // ----------------------------------------- template concept IsValue = std::same_as || std::derived_from; class Collection : public Value { public: virtual ~Collection() = default; void add(ValuePtr node); size_t size() const { return m_nodes.size(); } bool empty() const { return m_nodes.size() == 0; } const std::list& nodes() const { return m_nodes; } protected: Collection() = default; Collection(const std::list& nodes); template Collection(std::shared_ptr... nodes) { m_nodes = { nodes... }; } private: virtual bool isCollection() const override { return true; } std::list m_nodes; }; // ----------------------------------------- // () class List final : public Collection { public: List() = default; List(const std::list& nodes); template List(std::shared_ptr... nodes) : Collection(nodes...) { } virtual ~List() = default; private: virtual bool isList() const override { return true; } }; // ----------------------------------------- // [] class Vector final : public Collection { public: Vector() = default; Vector(const std::list& nodes); template Vector(std::shared_ptr... nodes) : Collection(nodes...) { } virtual ~Vector() = default; private: virtual bool isVector() const override { return true; } }; // ----------------------------------------- // {} class HashMap final : public Value { public: HashMap() = default; virtual ~HashMap() = default; void add(const std::string& key, ValuePtr value); const std::unordered_map& elements() const { return m_elements; } size_t size() const { return m_elements.size(); } bool empty() const { return m_elements.size() == 0; } private: virtual bool isHashMap() const override { return true; } std::unordered_map m_elements; }; // ----------------------------------------- // "string" class String final : public Value { public: String(const std::string& data); virtual ~String() = default; const std::string& data() const { return m_data; } 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; } 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; } 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(State state); virtual ~Constant() = default; State state() const { return m_state; } private: virtual bool isConstant() const override { return true; } const State m_state; }; // ----------------------------------------- // Symbols class Symbol final : public Value { public: Symbol(const std::string& symbol); virtual ~Symbol() = default; const std::string& symbol() const { return m_symbol; } private: virtual bool isSymbol() const override { return true; } const std::string m_symbol; }; // ----------------------------------------- class Callable : public Value { public: virtual ~Callable() = default; protected: Callable() = default; 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); virtual ~Function() = default; const std::string& name() const { return m_name; } FunctionType function() const { return m_function; } private: virtual bool isFunction() const override { return true; } const std::string m_name; const FunctionType m_function; }; // ----------------------------------------- class Lambda final : public Callable { public: Lambda(const std::vector& bindings, ValuePtr body, EnvironmentPtr env); virtual ~Lambda() = default; const std::vector& bindings() const { return m_bindings; } ValuePtr body() const { return m_body; } EnvironmentPtr env() const { return m_env; } private: virtual bool isLambda() const override { return true; } const std::vector m_bindings; const ValuePtr m_body; const EnvironmentPtr m_env; }; // ----------------------------------------- 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; } private: virtual bool isAtom() const override { return true; } ValuePtr m_value; }; // ----------------------------------------- template std::shared_ptr makePtr(Args&&... args) { return std::make_shared(std::forward(args)...); } // ----------------------------------------- // 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 isAtom(); } // clang-format on } // namespace blaze // ----------------------------------------- template<> struct ruc::format::Formatter : public Formatter { void format(Builder& builder, blaze::ValuePtr value) const; };