#pragma once #include "data.hpp" #include "embeddedlabel.hpp" #include "instruction.hpp" #include "label.hpp" #include "section.hpp" #include #include #include namespace zasm { // Placeholder type that represents an empty node. // This type can be useful for scenarios where the user wants to keep track // of a volatile range by having this at the start and end as markers. struct NodePoint { }; class Node { public: enum class Id : uint32_t { Invalid = std::numeric_limits::max(), }; protected: const Id _id{ Id::Invalid }; const Node* _prev{}; const Node* _next{}; const std::variant _data{}; protected: template constexpr Node(Id nodeId, T&& val) noexcept : _id{ nodeId } , _data{ std::forward(val) } { } public: constexpr Node() = default; const Node* getPrev() const noexcept { return _prev; } const Node* getNext() const noexcept { return _next; } template constexpr bool holds() const noexcept { return std::holds_alternative(_data); } template constexpr const T& get() const { return std::get(_data); } template constexpr const T* getIf() const noexcept { return std::get_if(&_data); } template constexpr auto visit(F&& func) const { return std::visit(std::forward(func), _data); } /// /// Returns a unique identifier for this node. /// /// Id of node or Id::Invalid if this node is not valid constexpr Id getId() const noexcept { return _id; } constexpr bool operator<(const Node& other) const noexcept { return static_cast>(_id) < static_cast>(other._id); } constexpr bool operator>(const Node& other) const noexcept { return static_cast>(_id) > static_cast>(other._id); } }; } // namespace zasm