@@ -23,9 +23,9 @@ void furvm_generator::generate_function(furvm::mod& mod, const furlang::ir::func
|
|||||||
switch (function.type()) {
|
switch (function.type()) {
|
||||||
case furlang::ir::function_t::Normal: {
|
case furlang::ir::function_t::Normal: {
|
||||||
if (function.access() == furlang::ir::function_access_t::Public)
|
if (function.access() == furlang::ir::function_access_t::Public)
|
||||||
mod.emplace_function(function.name(), function.param_count(), mod.bytecode().size()).dispatch();
|
mod.emplace_function_named(function.name(), function.param_count(), mod.bytecode().size()).dispatch();
|
||||||
else
|
else
|
||||||
mod.emplace_function_private(function.name(), function.param_count(), mod.bytecode().size()).dispatch();
|
mod.emplace_function(function.param_count(), mod.bytecode().size()).dispatch();
|
||||||
|
|
||||||
function_context ctx;
|
function_context ctx;
|
||||||
for (furlang::ir::block_index idx = 0; idx < function.blocks().size(); ++idx) {
|
for (furlang::ir::block_index idx = 0; idx < function.blocks().size(); ++idx) {
|
||||||
@@ -48,9 +48,9 @@ void furvm_generator::generate_function(furvm::mod& mod, const furlang::ir::func
|
|||||||
} break;
|
} break;
|
||||||
case furlang::ir::function_t::Native: {
|
case furlang::ir::function_t::Native: {
|
||||||
if (function.access() == furlang::ir::function_access_t::Public)
|
if (function.access() == furlang::ir::function_access_t::Public)
|
||||||
mod.emplace_function(function.name(), function.param_count(), function.name()).dispatch();
|
mod.emplace_function_named(function.name(), function.param_count(), function.name()).dispatch();
|
||||||
else
|
else
|
||||||
mod.emplace_function_private(function.name(), function.param_count(), function.name()).dispatch();
|
mod.emplace_function(function.param_count(), function.name()).dispatch();
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ void furvm_generator::generate_instruction(furvm::mod& mod,
|
|||||||
const auto& call = dynamic_cast<const furlang::ir::call_instruction&>(instr);
|
const auto& call = dynamic_cast<const furlang::ir::call_instruction&>(instr);
|
||||||
|
|
||||||
// TODO: Implement a queue for unknown functions
|
// TODO: Implement a queue for unknown functions
|
||||||
furvm::function_id func = mod.get_function_id(call.name());
|
furvm::function_id func = mod.function_at(call.name()).id();
|
||||||
mod.bytecode().push_back(static_cast<furvm::byte>(furvm::instruction_t::Call));
|
mod.bytecode().push_back(static_cast<furvm::byte>(furvm::instruction_t::Call));
|
||||||
mod.bytecode().push_back((func >> 0) & 0xFF);
|
mod.bytecode().push_back((func >> 0) & 0xFF);
|
||||||
mod.bytecode().push_back((func >> 8) & 0xFF);
|
mod.bytecode().push_back((func >> 8) & 0xFF);
|
||||||
|
|||||||
@@ -36,29 +36,21 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Constructs a normal function.
|
* @brief Constructs a normal function.
|
||||||
*
|
*
|
||||||
* @param name Name of the function.
|
|
||||||
* @param paramCount Paremeter count.
|
* @param paramCount Paremeter count.
|
||||||
* @param position Offset in bytecode of the function.
|
* @param position Offset in bytecode of the function.
|
||||||
*/
|
*/
|
||||||
template <typename Name>
|
function(std::uint32_t paramCount, bytecode_pos position)
|
||||||
function(Name&& name, std::uint32_t paramCount, bytecode_pos position)
|
: m_type(function_t::Normal), m_paramCount(paramCount), m_value(position) {}
|
||||||
: m_name(std::forward<Name>(name)), m_type(function_t::Normal), m_paramCount(paramCount), m_value(position) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructs a native function.
|
* @brief Constructs a native function.
|
||||||
*
|
*
|
||||||
* @param name Name of the function.
|
|
||||||
* @param paramCount Paremeter count.
|
* @param paramCount Paremeter count.
|
||||||
* @param native Native function tag.
|
* @param native Native function tag.
|
||||||
*/
|
*/
|
||||||
template <typename Name,
|
template <typename Native, typename = std::enable_if_t<std::is_constructible_v<native_function, Native>>>
|
||||||
typename Native,
|
function(std::uint32_t paramCount, Native&& native)
|
||||||
typename = std::enable_if_t<std::is_constructible_v<native_function, Native>>>
|
: m_type(function_t::Native), m_paramCount(paramCount), m_value(std::forward<Native>(native)) {}
|
||||||
function(Name&& name, std::uint32_t paramCount, Native&& native)
|
|
||||||
: m_name(std::forward<Name>(name)),
|
|
||||||
m_type(function_t::Native),
|
|
||||||
m_paramCount(paramCount),
|
|
||||||
m_value(std::forward<Native>(native)) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructs an import function.
|
* @brief Constructs an import function.
|
||||||
@@ -103,13 +95,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
function& operator=(const function&);
|
function& operator=(const function&);
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief Returns a name of this function.
|
|
||||||
*
|
|
||||||
* @return The name.
|
|
||||||
*/
|
|
||||||
constexpr const std::string& name() const { return m_name; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a type of this function.
|
* @brief Returns a type of this function.
|
||||||
*
|
*
|
||||||
@@ -154,7 +139,6 @@ public:
|
|||||||
return m_value.imp;
|
return m_value.imp;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
|
||||||
function_t m_type;
|
function_t m_type;
|
||||||
std::uint32_t m_paramCount;
|
std::uint32_t m_paramCount;
|
||||||
|
|
||||||
|
|||||||
@@ -86,51 +86,38 @@ public:
|
|||||||
function_h emplace_function(Args&&... args) {
|
function_h emplace_function(Args&&... args) {
|
||||||
function_h function;
|
function_h function;
|
||||||
if constexpr (std::is_constructible_v<class function, Args...>) {
|
if constexpr (std::is_constructible_v<class function, Args...>) {
|
||||||
function = m_functions.emplace_back(std::forward<Args>(args)...);
|
function = std::move(m_functions.emplace_back(std::forward<Args>(args)...));
|
||||||
} else {
|
} else {
|
||||||
function = m_functions.emplace(std::forward<Args>(args)...);
|
function = std::move(m_functions.emplace(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
m_functionMap[function.id()] = "";
|
||||||
m_functionMap[function->name()] = function.id();
|
|
||||||
m_publicFunctions[function->name()] = function.id();
|
|
||||||
return std::move(function);
|
return std::move(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Emplaces a function in the module's function container.
|
* @brief Emplaces a function in the module's function container.
|
||||||
*
|
*
|
||||||
* Emplaces the function in module's function container and name to function map .
|
* Emplaces the function in module's function container and name to function map.
|
||||||
*
|
*
|
||||||
* @param args Arguments forwarded into the container's emplace_back function.
|
* @param args Arguments forwarded into the container's emplace_back function.
|
||||||
* @return A handle to the emplaced function.
|
* @return A handle to the emplaced function.
|
||||||
*/
|
*/
|
||||||
template <typename... Args>
|
template <typename NameFwd,
|
||||||
function_h emplace_function_private(Args&&... args) {
|
typename... Args,
|
||||||
function_h function = m_functions.emplace_back(std::forward<Args>(args)...);
|
typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd>>>
|
||||||
m_functionMap[function->name()] = function.id();
|
function_h emplace_function_named(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;
|
||||||
return std::move(function);
|
return std::move(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Inserts a function in the module's function container.
|
|
||||||
*
|
|
||||||
* @param function Function to insert.
|
|
||||||
*/
|
|
||||||
template <typename Function>
|
|
||||||
auto push_back(Function&& function) {
|
|
||||||
return emplace_function(std::forward<Function>(function));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Inserts a function in the module's function container.
|
|
||||||
*
|
|
||||||
* @param function Function to insert.
|
|
||||||
*/
|
|
||||||
template <typename Function>
|
|
||||||
auto push_back_private(Function&& function) {
|
|
||||||
return emplace_function_private(std::forward<Function>(function));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a function from the module.
|
* @brief Returns a function from the module.
|
||||||
*
|
*
|
||||||
@@ -155,7 +142,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename NameFwd, typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd>>>
|
template <typename NameFwd, typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd>>>
|
||||||
auto function_at(NameFwd&& name) {
|
auto function_at(NameFwd&& name) {
|
||||||
return function_at(m_publicFunctions.at(std::forward<NameFwd>(name)));
|
return function_at(m_functionNames.at(std::forward<NameFwd>(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,18 +153,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename NameFwd, typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd>>>
|
template <typename NameFwd, typename = std::enable_if_t<std::is_constructible_v<std::string, NameFwd>>>
|
||||||
auto function_at(NameFwd&& name) const {
|
auto function_at(NameFwd&& name) const {
|
||||||
return function_at(m_publicFunctions.at(std::forward<NameFwd>(name)));
|
return function_at(m_functionNames.at(std::forward<NameFwd>(name)));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns an id of a function from the module.
|
|
||||||
*
|
|
||||||
* @param name Name of the function.
|
|
||||||
* @return An id of the function.
|
|
||||||
*/
|
|
||||||
template <typename NameFwd>
|
|
||||||
auto get_function_id(NameFwd&& name) {
|
|
||||||
return m_functionMap.at(std::forward<NameFwd>(name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -262,8 +238,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
bytecode_t m_bytecode;
|
bytecode_t m_bytecode;
|
||||||
|
|
||||||
std::unordered_map<std::string, function_id> m_functionMap;
|
std::unordered_map<std::string, function_id> m_functionNames;
|
||||||
std::unordered_map<std::string, function_id> m_publicFunctions;
|
std::unordered_map<function_id, std::string> m_functionMap;
|
||||||
handle_container<function_h> m_functions;
|
handle_container<function_h> m_functions;
|
||||||
|
|
||||||
handle_container<type_h> m_types;
|
handle_container<type_h> m_types;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ function::~function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function::function(function&& other) noexcept
|
function::function(function&& other) noexcept
|
||||||
: m_name(std::move(other.m_name)), m_type(other.m_type), m_paramCount(other.m_paramCount) {
|
: m_type(other.m_type), m_paramCount(other.m_paramCount) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
m_value.position = other.m_value.position;
|
m_value.position = other.m_value.position;
|
||||||
@@ -42,7 +42,6 @@ function::function(function&& other) noexcept
|
|||||||
function& function::operator=(function&& other) noexcept {
|
function& function::operator=(function&& other) noexcept {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
|
|
||||||
m_name = std::move(other.m_name);
|
|
||||||
m_type = other.m_type;
|
m_type = other.m_type;
|
||||||
m_paramCount = other.m_paramCount;
|
m_paramCount = other.m_paramCount;
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
@@ -63,7 +62,7 @@ function& function::operator=(function&& other) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function::function(const function& other)
|
function::function(const function& other)
|
||||||
: m_name(other.m_name), m_type(other.m_type), m_paramCount(other.m_paramCount) {
|
: m_type(other.m_type), m_paramCount(other.m_paramCount) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
m_value.position = other.m_value.position;
|
m_value.position = other.m_value.position;
|
||||||
@@ -81,7 +80,6 @@ function::function(const function& other)
|
|||||||
function& function::operator=(const function& other) {
|
function& function::operator=(const function& other) {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
|
|
||||||
m_name = other.m_name;
|
|
||||||
m_type = other.m_type;
|
m_type = other.m_type;
|
||||||
m_paramCount = other.m_paramCount;
|
m_paramCount = other.m_paramCount;
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
|
|||||||
+2
-2
@@ -60,8 +60,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
furvm::mod_h mod = context->emplace("main", s_bytecode, s_bytecode + sizeof(s_bytecode));
|
furvm::mod_h mod = context->emplace("main", s_bytecode, s_bytecode + sizeof(s_bytecode));
|
||||||
mod->emplace_type(std::make_shared<furvm::type>(context->at("core")->type_at(2), 10)).dispatch();
|
mod->emplace_type(std::make_shared<furvm::type>(context->at("core")->type_at(2), 10)).dispatch();
|
||||||
auto mainFunc = mod->emplace_function("main", 0, 0);
|
auto mainFunc = mod->emplace_function_named("main", 0, 0);
|
||||||
mod->emplace_function_private("print", 1, "print").dispatch();
|
mod->emplace_function(1, "print").dispatch();
|
||||||
#endif
|
#endif
|
||||||
mod->set_native_function("print", [](furvm::executor& executor) { print_thing(*executor.load_thing(0)); });
|
mod->set_native_function("print", [](furvm::executor& executor) { print_thing(*executor.load_thing(0)); });
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ std::ostream& mod::serialize(std::ostream& os) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function_h func = m_functions.at(id);
|
function_h func = m_functions.at(id);
|
||||||
bool isPublic = m_publicFunctions.find(func->name()) != m_publicFunctions.end();
|
detail::serialize(os, m_functionMap.at(func.id()));
|
||||||
detail::serialize(os, isPublic ? func->name() : ""); // private functions have empty names
|
|
||||||
detail::serialize(os, func->param_count());
|
detail::serialize(os, func->param_count());
|
||||||
detail::serialize(os, std::uint8_t(func->type()));
|
detail::serialize(os, std::uint8_t(func->type()));
|
||||||
switch (func->type()) {
|
switch (func->type()) {
|
||||||
@@ -98,12 +97,18 @@ mod mod::load(std::istream& is) {
|
|||||||
case function_t::Normal: {
|
case function_t::Normal: {
|
||||||
decltype(std::declval<function>().position()) offset = 0;
|
decltype(std::declval<function>().position()) offset = 0;
|
||||||
detail::load(is, offset);
|
detail::load(is, offset);
|
||||||
mod.emplace_function(id, std::move(name), paramCount, offset).dispatch();
|
if (name.empty())
|
||||||
|
mod.emplace_function_named(std::move(name), id, paramCount, offset).dispatch();
|
||||||
|
else
|
||||||
|
mod.emplace_function(id, paramCount, offset).dispatch();
|
||||||
} break;
|
} break;
|
||||||
case function_t::Native: {
|
case function_t::Native: {
|
||||||
std::string native;
|
std::string native;
|
||||||
detail::load(is, native);
|
detail::load(is, native);
|
||||||
mod.emplace_function(id, std::move(name), paramCount, std::move(native)).dispatch();
|
if (name.empty())
|
||||||
|
mod.emplace_function_named(std::move(name), id, paramCount, std::move(native)).dispatch();
|
||||||
|
else
|
||||||
|
mod.emplace_function(id, paramCount, std::move(native)).dispatch();
|
||||||
} break;
|
} break;
|
||||||
case function_t::Import: {
|
case function_t::Import: {
|
||||||
std::string modName;
|
std::string modName;
|
||||||
|
|||||||
Reference in New Issue
Block a user