refactor: improve functions

Closes: #49
This commit is contained in:
2026-07-08 00:19:37 +02:00
parent 7de645d323
commit d49b4f5bc7
10 changed files with 188 additions and 122 deletions
+6
View File
@@ -1,6 +1,7 @@
#ifndef FURVM_DETAIL_HANDLE_HPP
#define FURVM_DETAIL_HANDLE_HPP
#include <functional>
#include <type_traits>
namespace furvm {
@@ -27,6 +28,11 @@ struct header_has_refcount<Header,
template <typename Header>
static constexpr auto header_has_refcount_v = header_has_refcount<Header>::value;
template <typename Handle, typename IdHash = std::hash<typename Handle::id_type>>
struct handle_hash {
std::size_t operator()(const Handle& handle) const { return IdHash{}(handle.id()); }
};
} // namespace detail
} // namespace furvm
+42 -13
View File
@@ -1,6 +1,7 @@
#ifndef FURVM_FUNCTION_HPP
#define FURVM_FUNCTION_HPP
#include "furlang/utility/hash.hpp"
#include "furvm/fwd.hpp"
#include "furvm/handle.hpp" // IWYU pragma: keep
@@ -9,6 +10,7 @@
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
namespace furvm {
@@ -31,26 +33,43 @@ struct import_function {
function_id function;
};
/**
* @brief Function signature.
*/
struct function_sig {
std::vector<type_h> params;
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 paramCount Paremeter count.
* @param signature Function's signature.
* @param position Offset in bytecode of the function.
*/
function(std::uint32_t paramCount, bytecode_pos position)
: m_type(function_t::Normal), m_paramCount(paramCount), m_value(position) {}
template <typename SigFwd, typename = std::enable_if_t<std::is_constructible_v<function_sig, SigFwd>>>
function(SigFwd&& signature, bytecode_pos position)
: m_type(function_t::Normal), m_signature(std::forward<SigFwd>(signature)), m_value(position) {}
/**
* @brief Constructs a native function.
*
* @param paramCount Paremeter count.
* @param signature Function's signature.
* @param native Native function tag.
*/
template <typename Native, typename = std::enable_if_t<std::is_constructible_v<native_function, Native>>>
function(std::uint32_t paramCount, Native&& native)
: m_type(function_t::Native), m_paramCount(paramCount), m_value(std::forward<Native>(native)) {}
template <typename SigFwd,
typename Native,
typename = std::enable_if_t<std::is_constructible_v<native_function, Native> &&
std::is_constructible_v<function_sig, SigFwd>>>
function(SigFwd&& signature, Native&& native)
: m_type(function_t::Native),
m_signature(std::forward<SigFwd>(signature)),
m_value(std::forward<Native>(native)) {}
/**
* @brief Constructs an import function.
@@ -60,7 +79,7 @@ public:
*/
template <typename ModFwd, typename = std::enable_if_t<std::is_constructible_v<mod_id, ModFwd>>>
function(ModFwd&& mod, function_id function)
: m_type(function_t::Import), m_paramCount(0), m_value(import_function{ std::forward<ModFwd>(mod), function }) {}
: m_type(function_t::Import), m_signature(), m_value(import_function{ std::forward<ModFwd>(mod), function }) {}
/**
* @brief Constructs an import function.
@@ -103,11 +122,11 @@ public:
constexpr function_t type() const { return m_type; }
/**
* @brief Returns this function's parameter count.
* @brief Returns this function's signature.
*
* @return The parameter count.
* @return The signature.
*/
constexpr std::uint32_t param_count() const { return m_paramCount; }
function_sig signature() const { return m_signature; }
public:
/**
* @brief Returns normal function's value.
@@ -139,8 +158,8 @@ public:
return m_value.imp;
}
private:
function_t m_type;
std::uint32_t m_paramCount;
function_t m_type;
function_sig m_signature;
union value {
std::size_t position = 0;
@@ -168,6 +187,16 @@ private:
} m_value;
};
namespace detail {
struct function_sig_hash {
std::size_t operator()(const function_sig& signature) const {
return furlang::utility::vector_hash<type_h, detail::handle_hash<type_h>>{}(signature.params);
}
};
} // namespace detail
} // namespace furvm
#endif // FURVM_FUNCTION_HPP
+4
View File
@@ -237,6 +237,10 @@ public:
* @brief Invalidates the handle without releasing.
*/
void dispatch() { m_value = nullptr; }
public:
bool operator==(const handle& rhs) const { return m_value == rhs.m_value; }
bool operator!=(const handle& rhs) const { return !this->operator==(rhs); }
private:
pair_type* m_value = nullptr;
};
+26 -23
View File
@@ -1,6 +1,7 @@
#ifndef FURVM_MODULE_HPP
#define FURVM_MODULE_HPP
#include "furlang/utility/hash.hpp"
#include "furvm/function.hpp"
#include "furvm/fwd.hpp"
#include "furvm/handle.hpp"
@@ -90,7 +91,6 @@ public:
} else {
function = std::move(m_functions.emplace(std::forward<Args>(args)...));
}
m_functionMap[function.id()] = "";
return std::move(function);
}
@@ -99,22 +99,23 @@ public:
*
* Emplaces the function in module's function container and name to function map.
*
* @param name Name of the function.
* @param args Arguments forwarded into the container's emplace_back function.
* @return A handle to the emplaced function.
*/
template <typename NameFwd,
typename... Args,
typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd>>>
function_h emplace_function_named(NameFwd&& name, Args&&... args) {
function_h emplace_function(NameFwd&& name, Args&&... args) {
function_h function;
if constexpr (std::is_constructible_v<class function, Args...>) {
function = std::move(m_functions.emplace_back(std::forward<Args>(args)...));
} else {
function = std::move(m_functions.emplace(std::forward<Args>(args)...));
}
std::string nameInst = std::forward<NameFwd>(name);
m_functionNames[nameInst] = function.id();
m_functionMap[function.id()] = nameInst;
auto pair = std::make_pair(std::forward<NameFwd>(name), function->signature());
m_functionMap[function.id()] = pair;
m_functionSigs[std::move(pair)] = function.id();
return std::move(function);
}
@@ -140,20 +141,13 @@ public:
* @param name Name of the function.
* @return A handle to the function.
*/
template <typename NameFwd, typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd>>>
auto function_at(NameFwd&& name) {
return function_at(m_functionNames.at(std::forward<NameFwd>(name)));
}
/**
* @brief Returns a function from the module.
*
* @param name Name of the function.
* @return A handle to the function.
*/
template <typename NameFwd, typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd>>>
auto function_at(NameFwd&& name) const {
return function_at(m_functionNames.at(std::forward<NameFwd>(name)));
template <typename NameFwd,
typename SigFwd,
typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd> &&
std::is_constructible_v<function_sig, SigFwd>>>
auto function_at(NameFwd&& name, SigFwd&& signature) {
return function_at(
m_functionSigs.at(std::make_pair<>(std::forward<NameFwd>(name), std::forward<SigFwd>(signature))));
}
/**
@@ -161,7 +155,13 @@ public:
*
* @param id Identifier of the function.
*/
void erase_function(function_id id) { m_functions.erase(id); }
void erase_function(function_id id) {
m_functions.erase(id);
if (auto it = m_functionMap.find(id); it != m_functionMap.end()) {
m_functionSigs.erase(it->second);
m_functionMap.erase(it);
}
}
public:
template <typename NameFwd, typename Func>
void set_native_function(NameFwd&& name, Func&& func) {
@@ -238,9 +238,12 @@ public:
private:
bytecode_t m_bytecode;
std::unordered_map<std::string, function_id> m_functionNames;
std::unordered_map<function_id, std::string> m_functionMap;
handle_container<function_h> m_functions;
using pair_type = std::pair<std::string, function_sig>;
using pair_hash =
furlang::utility::pair_hash<std::string, function_sig, std::hash<std::string>, detail::function_sig_hash>;
std::unordered_map<pair_type, function_id, pair_hash> m_functionSigs;
std::unordered_map<function_id, pair_type> m_functionMap;
handle_container<function_h> m_functions;
handle_container<type_h> m_types;