#pragma once
#ifndef UNIVERSE_H
#define UNIVERSE_H
#include <deque>
#include <unordered_map>
#include "Symbol.h"
namespace objcgen {
enum class TypeNamespace : std::uint8_t {
Primary,
Protocols,
Keywords,
Tagged,
Max = Tagged,
};
constexpr std::uint8_t TYPE_NAMESPACE_COUNT = static_cast<std::uint8_t>(TypeNamespace::Max) + 1;
using type_order_t = std::vector<std::pair<TypeNamespace, std::string>>;
template <class TypeSymbol> type_order_t::const_iterator find_first(type_order_t::const_iterator it);
template <class TypeSymbol> class UniverseIterator final {
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = TypeSymbol;
using pointer = value_type*;
using reference = value_type&;
type_order_t::const_iterator it_;
[[nodiscard]] reference get() const;
public:
explicit UniverseIterator(type_order_t::const_iterator it) : it_(std::move(it))
{
}
reference operator*() const
{
return get();
}
pointer operator->()
{
return &get();
}
UniverseIterator& operator++();
friend bool operator==(const UniverseIterator& lhs, const UniverseIterator& rhs)
{
return lhs.it_ == rhs.it_;
}
friend bool operator!=(const UniverseIterator& lhs, const UniverseIterator& rhs)
{
return !(lhs == rhs);
}
};
template <class TypeSymbol> struct UniverseTypes final {
[[nodiscard]] UniverseIterator<TypeSymbol> cbegin() const;
[[nodiscard]] UniverseIterator<TypeSymbol> cend() const;
[[nodiscard]] auto begin() const
{
return cbegin();
}
[[nodiscard]] auto end() const
{
return cend();
}
};
class TopLevelIterator final {
public:
explicit TopLevelIterator(std::deque<NonTypeSymbol>& members) noexcept : members_(members)
{
}
[[nodiscard]] auto begin() const noexcept
{
return members_.begin();
}
[[nodiscard]] auto end() const noexcept
{
return members_.end();
}
private:
std::deque<NonTypeSymbol>& members_;
};
class TopLevel final {
public:
auto get_iterator() noexcept
{
return TopLevelIterator(members_);
}
NonTypeSymbol& add_function(std::string name, TypeLikeSymbol& return_type, uint16_t modifiers);
private:
std::deque<NonTypeSymbol> members_;
};
class Universe final {
using type_map_t = std::unordered_map<std::string, NamedTypeSymbol*>;
template <class TypeSymbol> friend class UniverseIterator;
template <class TypeSymbol> friend struct UniverseTypes;
static constexpr int PREALLOCATED_TYPE_COUNT = 8192;
Universe();
type_map_t& types_map(const TypeNamespace index)
{
return types_[static_cast<std::uint8_t>(index)];
}
const type_map_t& types_map(const TypeNamespace index) const
{
return types_[static_cast<std::uint8_t>(index)];
}
template <class TypeSymbol> friend type_order_t::const_iterator find_first(type_order_t::const_iterator it);
TopLevel top_level_;
type_map_t types_[TYPE_NAMESPACE_COUNT];
type_order_t type_order_;
PrimitiveTypeSymbol unit_;
PrimitiveTypeSymbol bool_;
PrimitiveTypeSymbol int8_;
PrimitiveTypeSymbol int16_;
PrimitiveTypeSymbol int32_;
PrimitiveTypeSymbol int64_;
PrimitiveTypeSymbol uint8_;
PrimitiveTypeSymbol uint16_;
PrimitiveTypeSymbol uint32_;
PrimitiveTypeSymbol uint64_;
PrimitiveTypeSymbol float16_;
PrimitiveTypeSymbol float32_;
PrimitiveTypeSymbol float64_;
VArraySymbol int128_;
VArraySymbol uint128_;
TypeDeclarationSymbol class_;
TypeDeclarationSymbol id_;
TypeDeclarationSymbol sel_;
public:
static Universe& get();
NonTypeSymbol& register_top_level_function(std::string name, TypeLikeSymbol& return_type, uint16_t modifiers);
void register_type(NamedTypeSymbol* symbol);
[[nodiscard]] auto& unit() noexcept
{
return unit_;
}
[[nodiscard]] auto& boolean() noexcept
{
return bool_;
}
[[nodiscard]] auto& int8() noexcept
{
return int8_;
}
[[nodiscard]] auto& int16() noexcept
{
return int16_;
}
[[nodiscard]] auto& int32() noexcept
{
return int32_;
}
[[nodiscard]] auto& int64() noexcept
{
return int64_;
}
[[nodiscard]] auto& uint8() noexcept
{
return uint8_;
}
[[nodiscard]] auto& uint16() noexcept
{
return uint16_;
}
[[nodiscard]] auto& uint32() noexcept
{
return uint32_;
}
[[nodiscard]] auto& uint64() noexcept
{
return uint64_;
}
[[nodiscard]] auto& float16() noexcept
{
return float16_;
}
[[nodiscard]] auto& float32() noexcept
{
return float32_;
}
[[nodiscard]] auto& float64() noexcept
{
return float64_;
}
[[nodiscard]] auto& int128() noexcept
{
return int128_;
}
[[nodiscard]] auto& uint128() noexcept
{
return uint128_;
}
[[nodiscard]] auto& clazz() noexcept
{
return class_;
}
[[nodiscard]] auto& id() noexcept
{
return id_;
}
[[nodiscard]] auto& sel() noexcept
{
return sel_;
}
[[nodiscard]] TypeLikeSymbol* primitive_type(PrimitiveTypeCategory category, size_t size) noexcept;
[[nodiscard]] NamedTypeSymbol* type(NamedTypeSymbol::Kind where, const std::string& name) const noexcept;
[[nodiscard]] NamedTypeSymbol* type(TypeNamespace where, const std::string& name) const;
[[nodiscard]] NamedTypeSymbol* type(const std::string& name) const;
void process_rename(NamedTypeSymbol* symbol, const std::string& old_name);
TopLevelIterator top_level() noexcept;
auto all_declarations()
{
return UniverseTypes<NamedTypeSymbol>{};
}
auto type_definitions()
{
return UniverseTypes<TypeDeclarationSymbol>{};
}
};
template <class TypeSymbol> typename UniverseIterator<TypeSymbol>::reference UniverseIterator<TypeSymbol>::get() const
{
auto* symbol = Universe::get().type(it_->first, it_->second);
assert(symbol);
if constexpr (std::is_same_v<TypeSymbol, NamedTypeSymbol>) {
return *symbol;
} else {
assert(dynamic_cast<TypeSymbol*>(symbol));
return static_cast<TypeSymbol&>(*symbol);
}
}
template <class TypeSymbol> type_order_t::const_iterator find_first(type_order_t::const_iterator it)
{
if constexpr (!std::is_same_v<TypeSymbol, NamedTypeSymbol>) {
const auto& universe = Universe::get();
for (auto e = universe.type_order_.cend(); it != e; ++it) {
auto* symbol = universe.type(it->first, it->second);
assert(symbol);
if (dynamic_cast<TypeSymbol*>(symbol)) {
break;
}
}
}
return it;
}
template <class TypeSymbol> UniverseIterator<TypeSymbol>& UniverseIterator<TypeSymbol>::operator++()
{
it_ = find_first<TypeSymbol>(++it_);
return *this;
}
template <class TypeSymbol> UniverseIterator<TypeSymbol> UniverseTypes<TypeSymbol>::cbegin() const
{
return UniverseIterator<TypeSymbol>{find_first<TypeSymbol>(Universe::get().type_order_.cbegin())};
}
template <class TypeSymbol> UniverseIterator<TypeSymbol> UniverseTypes<TypeSymbol>::cend() const
{
return UniverseIterator<TypeSymbol>{Universe::get().type_order_.cend()};
}
}
#endif