Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New MathObjectClass #232

Merged
merged 2 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion include/fintamath/core/IArithmetic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace fintamath {

class IArithmetic : public IMathObject {
FINTAMATH_PARENT_CLASS_BODY(IArithmetic)
FINTAMATH_PARENT_CLASS_BODY(IArithmetic, IMathObject)

public:
friend std::unique_ptr<IArithmetic> operator+(const IArithmetic &lhs, const IArithmetic &rhs) {
Expand Down
2 changes: 1 addition & 1 deletion include/fintamath/core/IComparable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace fintamath {

class IComparable : public IArithmetic {
FINTAMATH_PARENT_CLASS_BODY(IComparable)
FINTAMATH_PARENT_CLASS_BODY(IComparable, IArithmetic)

public:
friend std::strong_ordering operator<=>(const IComparable &lhs, const IComparable &rhs) {
Expand Down
9 changes: 5 additions & 4 deletions include/fintamath/core/IMathObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,30 @@
#include "fintamath/core/MathObjectBody.hpp"
#include "fintamath/core/MathObjectClass.hpp"
#include "fintamath/core/MathObjectUtils.hpp"
#include "fintamath/core/None.hpp"
#include "fintamath/core/Parser.hpp"

namespace fintamath {

class IMathObject {
FINTAMATH_PARENT_CLASS_BODY(IMathObject)
FINTAMATH_PARENT_CLASS_BODY(IMathObject, None)

public:
virtual ~IMathObject() = default;
virtual ~IMathObject() noexcept = default;

virtual std::unique_ptr<IMathObject> clone() const & = 0;

virtual std::unique_ptr<IMathObject> clone() && = 0;

virtual std::string toString() const {
return std::string(getClass().getName());
return std::string(getClass()->getName());
}

virtual std::unique_ptr<IMathObject> toMinimalObject() const {
return clone();
}

virtual MathObjectClass getClass() const = 0;
virtual MathObjectClass getClass() const noexcept = 0;

friend bool operator==(const IMathObject &lhs, const IMathObject &rhs) {
return lhs.equalsAbstract(rhs);
Expand Down
2 changes: 1 addition & 1 deletion include/fintamath/core/IMathObjectCRTP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class IMathObjectCRTP_ : public IMathObject {
return equals(cast<Derived>(rhs));
}

MathObjectClass getClass() const override {
MathObjectClass getClass() const noexcept override {
return Derived::getClassStatic();
}

Expand Down
44 changes: 27 additions & 17 deletions include/fintamath/core/MathObjectBody.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,53 @@
#include <memory>

#include "fintamath/core/MathObjectClass.hpp"
#include "fintamath/core/MathObjectIdStorage.hpp"
#include "fintamath/core/Parser.hpp"

#define FINTAMATH_CLASS_BODY(Class) \
public: \
static constexpr MathObjectClass getClassStatic() { \
return {#Class}; \
} \
\
#define FINTAMATH_CLASS_BODY(Class, ParentClass) \
public: \
using Parent = ParentClass; \
\
static MathObjectClass getClassStatic() noexcept; \
\
private:

#define FINTAMATH_PARENT_CLASS_BODY(Class) \
FINTAMATH_CLASS_BODY(Class) \
#define FINTAMATH_CLASS_IMPLEMENTATION(Class) \
MathObjectClass Class::getClassStatic() noexcept { \
static const detail::MathObjectClassImpl \
classImpl{#Class, Parent::getClassStatic()}; \
return &classImpl; \
}

#define FINTAMATH_PARENT_CLASS_BODY(Class, ParentClass) \
FINTAMATH_CLASS_BODY(Class, ParentClass) \
\
private: \
using Class##Parser = detail::Parser<std::unique_ptr<Class>>; \
\
static Class##Parser &getParser(); \
static Class##Parser &getParser() noexcept; \
\
public: \
static auto parse(std::string str) { \
static auto parse(std::string str) noexcept { \
return getParser().parse(std::move(str)); \
} \
\
static auto parseFirst(std::string str) { \
static auto parseFirst(std::string str) noexcept { \
return getParser().parseFirst(std::move(str)); \
} \
\
template <std::derived_from<Class> T> \
static void registerType() { \
MathObjectClass::bindTypes<Class, T>(); \
static void registerType() noexcept { \
MathObjectIdStorage::add(T::getClassStatic()); \
getParser().registerType<T>(); \
} \
\
private:

#define FINTAMATH_PARENT_CLASS_IMPLEMENTATION(Class) \
Class::Class##Parser &Class::getParser() { \
static Class##Parser parser; \
return parser; \
#define FINTAMATH_PARENT_CLASS_IMPLEMENTATION(Class) \
FINTAMATH_CLASS_IMPLEMENTATION(Class) \
\
Class::Class##Parser &Class::getParser() noexcept { \
static Class##Parser parser; \
return parser; \
}
82 changes: 18 additions & 64 deletions include/fintamath/core/MathObjectClass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,92 +11,46 @@

namespace fintamath {

class MathObjectClass;
namespace detail {

}

template <>
struct std::hash<fintamath::MathObjectClass> {
size_t operator()(const fintamath::MathObjectClass &rhs) const noexcept;
};

namespace fintamath {

class MathObjectClass final {
class MathObjectClassImpl final {
public:
using Name = std::string_view;

using Id = size_t;
using Ptr = const MathObjectClassImpl *;

using Children = std::unordered_set<MathObjectClass>;
public:
constexpr MathObjectClassImpl(const Name inName, const Ptr inParent = nullptr) noexcept
: name(inName),
parent(inParent) {
}

private:
using ClassToIdMap = std::unordered_map<MathObjectClass, Id>;
constexpr MathObjectClassImpl(const MathObjectClassImpl &) noexcept = delete;

using ChildToParentMap = std::unordered_map<MathObjectClass, MathObjectClass>;
constexpr MathObjectClassImpl(MathObjectClassImpl &&) noexcept = delete;

using ParentToChildrenMap = std::unordered_map<MathObjectClass, Children>;
constexpr MathObjectClassImpl &operator=(const MathObjectClassImpl &) noexcept = delete;

public:
constexpr MathObjectClass(const Name inName) : name(inName) {
}
constexpr MathObjectClassImpl &operator=(MathObjectClassImpl &&) noexcept = delete;

constexpr Name getName() const {
constexpr Name getName() const noexcept {
return name;
}

constexpr bool operator==(const MathObjectClass rhs) const {
return name == rhs.name;
constexpr Ptr getParent() const noexcept {
return parent;
}

std::strong_ordering operator<=>(MathObjectClass rhs) const;

std::optional<MathObjectClass> getParent() const;

const Children &getChildren(bool recursive = false) const;

template <typename Parent, std::derived_from<Parent> Child>
static void bindTypes();

private:
Id getId() const;

static ClassToIdMap &getClassToIdMap();

static ChildToParentMap &getChildToParentMap();

static ParentToChildrenMap &getParentToChildrenMap();

static ParentToChildrenMap &getParentToRecursiveChildrenMap();

private:
Name name;

inline static Id maxId = 0;
Ptr parent;

[[maybe_unused]] inline static const detail::Config config;
[[maybe_unused]] inline static const Config config;
};

template <typename Parent, std::derived_from<Parent> Child>
void MathObjectClass::bindTypes() {
MathObjectClass parent = Parent::getClassStatic();
MathObjectClass child = Child::getClassStatic();

getClassToIdMap()[parent] = ++maxId;
getClassToIdMap()[child] = ++maxId;

getChildToParentMap().insert_or_assign(child, parent);
getParentToChildrenMap()[parent].emplace(child);

for (std::optional superParent = child.getParent(); superParent; superParent = superParent->getParent()) {
Children &superParentChildren = getParentToRecursiveChildrenMap()[*superParent];
superParentChildren.emplace(child);
superParentChildren.insert(child.getChildren().begin(), child.getChildren().end());
}
}

}
using MathObjectClass = detail::MathObjectClassImpl::Ptr;

inline size_t std::hash<fintamath::MathObjectClass>::operator()(const fintamath::MathObjectClass &rhs) const noexcept {
return std::hash<fintamath::MathObjectClass::Name>{}(rhs.getName());
}
24 changes: 24 additions & 0 deletions include/fintamath/core/MathObjectIdStorage.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <unordered_map>

#include "fintamath/core/MathObjectClass.hpp"

namespace fintamath {

class MathObjectIdStorage {
using MathObjectClassToIdMap = std::unordered_map<MathObjectClass, size_t>;

public:
static size_t get(MathObjectClass objClass) noexcept;

static void add(MathObjectClass objClass) noexcept;

private:
static MathObjectClassToIdMap &getMap() noexcept;

private:
static inline size_t maxId = 1;
};

}
Loading