diff --git a/CMakeLists.txt b/CMakeLists.txt index c586cb7..5062ca6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(lilfbtf5 VERSION 0.1.22) +project(lilfbtf5 VERSION 0.1.23) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) diff --git a/include/lilfbtf/type.h b/include/lilfbtf/type.h index e13d699..55a3119 100644 --- a/include/lilfbtf/type.h +++ b/include/lilfbtf/type.h @@ -107,11 +107,12 @@ namespace fb std::vector function_to_name; // Also a bad idea to store references, however these functions should be declared statically so this isn't as big of an issue. - associative_array> functions; + associative_array> functions; // function id -> list of type_id for parameters where index 0 = arg 1 associative_array> function_inputs; + associative_array function_argc; - associative_array> function_initializer; + associative_array> function_initializer; associative_array, true> terminals; associative_array, true> non_terminals; std::vector> all_non_terminals; @@ -120,30 +121,36 @@ namespace fb type_id register_type(type_name type_name); - function_id register_function(function_name func_name, type_name output, func_t_call_t& func, - std::optional> initializer); + function_id register_function(function_name func_name, type_name output, const func_t_call_t& func, arg_c_t argc, + std::optional> initializer = {}); - function_id register_terminal_function(function_name func_name, type_name output, func_t_call_t& func, - std::optional> initializer); + function_id register_terminal_function(function_name func_name, type_name output, const func_t_call_t& func, + std::optional> initializer = {}); - inline type_id get_type_id(type_name name) - { return name_to_type[name]; } + [[nodiscard]] inline type_id get_type_id(type_name name) const + { return name_to_type.at(name); } - inline type_id get_function_id(function_name name) - { return name_to_function[name]; } + [[nodiscard]] inline type_id get_function_id(function_name name) const + { return name_to_function.at(name); } + + [[nodiscard]] inline arg_c_t get_function_argc(function_id id) const + { return function_argc[id]; } + + [[nodiscard]] inline arg_c_t get_function_argc(function_name name) const + { return get_function_argc(get_function_id(name)); } type_engine_t& associate_input(function_name func_name, const std::vector& types); - inline func_t_call_t& get_function(function_id id) + [[nodiscard]] inline const func_t_call_t& get_function(function_id id) const { return functions[id]; } - inline func_t_call_t& get_function(function_name name) + [[nodiscard]] inline const func_t_call_t& get_function(function_name name) const { return get_function(get_function_id(name)); } - inline func_t_init_t& get_function_initializer(function_id id) + [[nodiscard]] inline const func_t_init_t& get_function_initializer(function_id id) const { return function_initializer[id]; } - inline func_t_init_t& get_function_initializer(function_name name) + [[nodiscard]] inline const func_t_init_t& get_function_initializer(function_name name) const { return get_function_initializer(get_function_id(name)); } inline std::vector& get_terminals(type_id type) diff --git a/src/type.cpp b/src/type.cpp index 4aeacc7..f9414fa 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -28,8 +28,8 @@ namespace fb return id; } - function_id type_engine_t::register_function(function_name func_name, type_name output, func_t_call_t& func, - std::optional> initializer) + function_id type_engine_t::register_function(function_name func_name, type_name output, const func_t_call_t& func, arg_c_t argc, + std::optional> initializer) { function_id id = function_to_name.size(); type_id tid = get_type_id(output); @@ -37,6 +37,7 @@ namespace fb functions.insert(id, func); non_terminals[tid].push_back(id); all_non_terminals.emplace_back(tid, id); + function_argc.insert(id, argc); if (auto& init = initializer) function_initializer.insert(id, init.value()); return id; @@ -52,14 +53,15 @@ namespace fb return *this; } - function_id type_engine_t::register_terminal_function(function_name func_name, type_name output, func_t_call_t& func, - std::optional> initializer) + function_id type_engine_t::register_terminal_function(function_name func_name, type_name output, const func_t_call_t& func, + std::optional> initializer) { function_id id = function_to_name.size(); type_id tid = get_type_id(output); name_to_function[func_name] = id; functions.insert(id, func); terminals[tid].push_back(id); + function_argc.insert(id, 0); if (auto& init = initializer) function_initializer.insert(id, init.value()); return id; diff --git a/tests/src/main.cpp b/tests/src/main.cpp index 734ced7..1de183c 100644 --- a/tests/src/main.cpp +++ b/tests/src/main.cpp @@ -19,49 +19,56 @@ struct data }; const fb::func_t_call_t add_f = [](fb::func_t& us, blt::span args) { - us.setValue(args[0]->value().any_cast() + args[1]->value().any_cast()); + us.setValue(args[0]->value().any_cast() + args[1]->value().any_cast()); }; const fb::func_t_call_t sub_f = [](fb::func_t& us, blt::span args) { - us.setValue(args[0]->value().any_cast() - args[1]->value().any_cast()); + us.setValue(args[0]->value().any_cast() - args[1]->value().any_cast()); }; const fb::func_t_call_t mul_f = [](fb::func_t& us, blt::span args) { - us.setValue(args[0]->value().any_cast() * args[1]->value().any_cast()); + us.setValue(args[0]->value().any_cast() * args[1]->value().any_cast()); }; const fb::func_t_call_t div_f = [](fb::func_t& us, blt::span args) { - auto dim = args[1]->value().any_cast(); + auto dim = args[1]->value().any_cast(); if (dim == 0) us.setValue(0); else - us.setValue(args[0]->value().any_cast() + dim); + us.setValue(args[0]->value().any_cast() + dim); }; const fb::func_t_call_t value_f = [](fb::func_t&, blt::span) {}; const fb::func_t_call_t if_f = [](fb::func_t& us, blt::span args) { if (args[0]->value().any_cast()) - us.setValue(args[1]->value().any_cast()); + us.setValue(args[1]->value().any_cast()); else - us.setValue(args[2]->value().any_cast()); + us.setValue(args[2]->value().any_cast()); }; const fb::func_t_call_t equals_b_f = [](fb::func_t& us, blt::span args) { us.setValue(args[0]->value().any_cast() == args[1]->value().any_cast()); }; const fb::func_t_call_t equals_n_f = [](fb::func_t& us, blt::span args) { - us.setValue(args[0]->value().any_cast() == args[1]->value().any_cast()); + us.setValue(args[0]->value().any_cast() == args[1]->value().any_cast()); }; const fb::func_t_call_t less_f = [](fb::func_t& us, blt::span args) { - us.setValue(args[0]->value().any_cast() < args[1]->value().any_cast()); + us.setValue(args[0]->value().any_cast() < args[1]->value().any_cast()); }; const fb::func_t_call_t greater_f = [](fb::func_t& us, blt::span args) { - us.setValue(args[0]->value().any_cast() > args[1]->value().any_cast()); + us.setValue(args[0]->value().any_cast() > args[1]->value().any_cast()); }; const fb::func_t_call_t not_f = [](fb::func_t& us, blt::span args) { us.setValue(!args[0]->value().any_cast()); }; -const fb::func_t_call_t and_f = [](fb::func_t& us, blt::span args) { +const fb::func_t_call_t and_b_f = [](fb::func_t& us, blt::span args) { us.setValue(args[0]->value().any_cast() && args[1]->value().any_cast()); }; -const fb::func_t_call_t or_f = [](fb::func_t& us, blt::span args) { +const fb::func_t_call_t or_b_f = [](fb::func_t& us, blt::span args) { us.setValue(args[0]->value().any_cast() || args[1]->value().any_cast()); }; +const fb::func_t_call_t and_n_f = [](fb::func_t& us, blt::span args) { + us.setValue(args[0]->value().any_cast() & args[1]->value().any_cast()); +}; +const fb::func_t_call_t or_n_f = [](fb::func_t& us, blt::span args) { + us.setValue(args[0]->value().any_cast() | args[1]->value().any_cast()); +}; + int main(int argc, const char** argv) { size_t size = 32; @@ -109,10 +116,39 @@ int main(int argc, const char** argv) typeEngine.register_type("u8"); typeEngine.register_type("bool"); + typeEngine.register_function("add", "u8", add_f, 2); + typeEngine.register_function("sub", "u8", sub_f, 2); + typeEngine.register_function("mul", "u8", mul_f, 2); + typeEngine.register_function("div", "u8", div_f, 2); + typeEngine.register_function("if", "u8", if_f, 3); + typeEngine.register_function("equals_b", "bool", equals_b_f, 2); + typeEngine.register_function("equals_n", "bool", equals_n_f, 2); + typeEngine.register_function("less", "bool", less_f, 2); + typeEngine.register_function("greater", "bool", greater_f, 2); + typeEngine.register_function("not", "bool", not_f, 1); + typeEngine.register_function("and_b", "bool", and_b_f, 2); + typeEngine.register_function("and_n", "u8", and_n_f, 2); + typeEngine.register_function("or_b", "bool", or_b_f, 2); + typeEngine.register_function("or_n", "u8", or_n_f, 2); - BLT_PRINT_PROFILE("Tree Construction"); - BLT_PRINT_PROFILE("Tree Evaluation"); - BLT_PRINT_PROFILE("Tree Destruction"); + typeEngine.associate_input("add", {"u8", "u8"}); + typeEngine.associate_input("sub", {"u8", "u8"}); + typeEngine.associate_input("mul", {"u8", "u8"}); + typeEngine.associate_input("div", {"u8", "u8"}); + typeEngine.associate_input("if", {"bool", "u8", "u8"}); + typeEngine.associate_input("equals_b", {"bool", "bool"}); + typeEngine.associate_input("equals_n", {"u8", "u8"}); + typeEngine.associate_input("less", {"u8", "u8"}); + typeEngine.associate_input("greater", {"u8", "u8"}); + typeEngine.associate_input("not", {"bool"}); + typeEngine.associate_input("and_b", {"bool", "bool"}); + typeEngine.associate_input("or_b", {"bool", "bool"}); + typeEngine.associate_input("and_n", {"u8", "u8"}); + typeEngine.associate_input("or_n", {"u8", "u8"}); + + //BLT_PRINT_PROFILE("Tree Construction"); + //BLT_PRINT_PROFILE("Tree Evaluation"); + //BLT_PRINT_PROFILE("Tree Destruction"); } return 0;