#ifndef FURVM_FUNCTION_HPP #define FURVM_FUNCTION_HPP #include "furvm/fwd.hpp" #include "furvm/handle.hpp" // IWYU pragma: keep #include #include #include #include #include #include #include namespace furvm { enum class function_t : std::uint8_t { Normal = 0, /**< A normal bytecode function. */ Native, /**< A native function implemented through furvm API. */ Import, /**< A function imported from another module. */ }; /** * @brief A native function. */ using native_function = std::string; /** * @brief A function import. */ struct import_function { mod_id mod; function_id function; }; /** * @brief Function signature. */ struct function_sig { std::vector params; std::optional returnType; bool operator==(const function_sig& rhs) const { return params == rhs.params; } bool operator!=(const function_sig& rhs) const { return !this->operator==(rhs); } }; class function { public: /** * @brief Constructs a normal function. * * @param signature Function's signature. * @param position Offset in bytecode of the function. */ template >> function(SigFwd&& signature, bytecode_pos position) : m_type(function_t::Normal), m_signature(std::forward(signature)), m_value(position) {} /** * @brief Constructs a native function. * * @param signature Function's signature. * @param native Native function tag. */ template && std::is_constructible_v>> function(SigFwd&& signature, Native&& native) : m_type(function_t::Native), m_signature(std::forward(signature)), m_value(std::forward(native)) {} /** * @brief Constructs an import function. * * @param mod Module's id. * @param function Function's id. */ template >> function(ModFwd&& mod, function_id function) : m_type(function_t::Import), m_signature(), m_value(import_function{ std::forward(mod), function }) {} /** * @brief Constructs an import function. * * @param mod Module. * @param function Function. */ function(const mod_h& mod, const function_h& function); /** * @brief Destructs a function. */ ~function(); /** * @brief Move constructor. */ function(function&&) noexcept; /** * @brief Move constructor. */ function& operator=(function&&) noexcept; /** * @brief Copy constructor. */ function(const function&); /** * @brief Copy constructor. */ function& operator=(const function&); public: /** * @brief Returns a type of this function. * * @return The type. */ constexpr function_t type() const { return m_type; } /** * @brief Returns this function's signature. * * @return The signature. */ function_sig signature() const { return m_signature; } public: /** * @brief Returns normal function's value. * * @return The value. */ std::size_t position() const { if (m_type != function_t::Normal) throw std::runtime_error("function type mismatch"); return m_value.position; } /** * @brief Returns native function's value. * * @return The value. */ const native_function& native() const { if (m_type != function_t::Native) throw std::runtime_error("function type mismatch"); return m_value.native; } /** * @brief Returns import function's value. * * @return The value. */ const import_function& imp() const { if (m_type != function_t::Import) throw std::runtime_error("function type mismatch"); return m_value.imp; } private: function_t m_type; function_sig m_signature; union value { std::size_t position = 0; native_function native; import_function imp; value() = default; value(std::size_t position) : position(position) {} template >> value(Native&& native) : native(std::forward(native)) {} value(const import_function& imp) : imp(imp) {} ~value() {} value(value&& other) = delete; value& operator=(value&& other) = delete; value(const value& other) = delete; value& operator=(const value& other) = delete; } m_value; }; namespace detail { struct function_sig_hash { std::size_t operator()(const function_sig& signature) const; }; } // namespace detail } // namespace furvm #endif // FURVM_FUNCTION_HPP