main
Brett 2024-03-13 19:04:22 -04:00
parent 76c34baaec
commit 36bb3ffefa
6 changed files with 154 additions and 53 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(lilfbtf5 VERSION 0.1.19)
project(lilfbtf5 VERSION 0.1.20)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

View File

@ -42,6 +42,7 @@ namespace fb
using function_id = blt::u32;
using arg_c_t = blt::size_t;
using func_t_call_t = std::function<void(func_t&, blt::span<detail::node_t*>)>;
using func_t_init_t = std::function<void(func_t&)>;
using function_name = const std::string&;
using type_name = const std::string&;
}

View File

@ -21,10 +21,79 @@
#include <lilfbtf/fwddecl.h>
#include <blt/std/hashmap.h>
#include <blt/std/memory_util.h>
#include <vector>
#include <cstdlib>
namespace fb
{
template<typename K, typename T, bool init = false>
class associative_array
{
private:
K size_;
T* data_;
void expand()
{
K new_size = static_cast<K>(size_ == 0 ? 16 : blt::mem::next_byte_allocation(size_));
T* new_data = static_cast<T*>(std::malloc(new_size * sizeof(T)));
if constexpr (init)
{
for (blt::size_t i = size_; i < new_size; i++)
new(&new_size[i]) T();
}
for (blt::size_t i = 0; i < size_; i++)
new(&new_data[i]) T(std::move(data_[i]));
std::free(data_);
data_ = new_data;
size_ = new_size;
}
public:
associative_array(): size_(0), data_(nullptr)
{}
T& operator[](K index)
{
return data_[index];
}
const T& operator[](K index) const
{
return data_[index];
}
void insert(K index, const T& t)
{
while (index >= size_)
expand();
data_[index] = t;
}
void insert(K index, T&& t)
{
while (index >= size_)
expand();
data_[index] = std::move(t);
}
[[nodiscard]] inline T* data()
{
return data_;
}
[[nodiscard]] inline K size() const
{
return size_;
}
~associative_array()
{
std::free(data_);
}
};
class type_engine_t
{
private:
@ -36,19 +105,22 @@ namespace fb
blt::hashmap_t<std::string, function_id> name_to_function;
std::vector<std::string> function_to_name;
// TODO: we don't need a hashmap for this.
// Also a bad idea to store references, however these functions should be declared statically so this isn't as big of an issue.
blt::hashmap_t<function_id, std::reference_wrapper<func_t_call_t>> functions;
// function names -> type_id
blt::hashmap_t<std::string, type_id> function_outputs;
// function names -> list of type_id for parameters where index 0 = arg 1
blt::hashmap_t<std::string, std::vector<type_id>> function_inputs;
associative_array<function_id, std::reference_wrapper<func_t_call_t>> functions;
// function id -> list of type_id for parameters where index 0 = arg 1
associative_array<function_id, std::vector<type_id>> function_inputs;
associative_array<function_id, std::reference_wrapper<func_t_init_t>> terminal_initializer;
associative_array<type_id, std::vector<function_id>, true> terminals;
associative_array<type_id, std::vector<function_id>, true> non_terminals;
public:
type_engine_t() = default;
type_id register_type(type_name type_name);
function_id register_function(function_name func_name, func_t_call_t& func);
function_id register_function(function_name func_name, type_id output, func_t_call_t& func);
function_id register_terminal_function(function_name func_name, type_id output, func_t_call_t& func, func_t_init_t& initializer);
inline type_id get_type_id(type_name name)
{ return name_to_type[name]; }
@ -56,9 +128,25 @@ namespace fb
inline type_id get_function_id(function_name name)
{ return name_to_function[name]; }
type_engine_t& associate_output(function_name func_name, type_name type_name);
type_engine_t& associate_input(function_name func_name, const std::vector<std::string>& types);
type_engine_t& associate_input(function_name func_name, type_name);
inline func_t_call_t& get_function(function_id id)
{ return functions[id]; }
inline func_t_call_t& get_function(function_name name)
{ return get_function(get_function_id(name)); }
inline func_t_init_t& get_function_initializer(function_id id)
{ return terminal_initializer[id]; }
inline func_t_init_t& get_function_initializer(function_name name)
{ return get_function_initializer(get_function_id(name)); }
inline std::vector<function_id>& get_terminals(type_id type)
{ return terminals[type]; }
inline std::vector<function_id>& get_non_terminals(type_id type)
{ return non_terminals[type]; }
};
}

View File

@ -28,23 +28,32 @@ namespace fb
return id;
}
function_id type_engine_t::register_function(function_name func_name, func_t_call_t& func)
function_id type_engine_t::register_function(function_name func_name, type_id output, func_t_call_t& func)
{
function_id id = function_to_name.size();
name_to_function[func_name] = id;
functions.insert({id, func});
functions.insert(id, func);
non_terminals[output].push_back(id);
return id;
}
type_engine_t& type_engine_t::associate_output(function_name func_name, type_name type_name)
type_engine_t& type_engine_t::associate_input(function_name func_name, const std::vector<std::string>& types)
{
function_outputs[func_name] = get_type_id(type_name);
auto id = get_function_id(func_name);
std::vector<type_id> type_ids;
for (const auto& v : types)
type_ids.push_back(get_type_id(v));
function_inputs[id] = std::move(type_ids);
return *this;
}
type_engine_t& type_engine_t::associate_input(function_name func_name, type_name)
function_id type_engine_t::register_terminal_function(function_name func_name, type_id output, func_t_call_t& func, func_t_init_t& initializer)
{
return *this;
function_id id = function_to_name.size();
name_to_function[func_name] = id;
functions.insert(id, func);
terminals[output].push_back(id);
terminal_initializer.insert(id, initializer);
return id;
}
}

View File

@ -47,6 +47,9 @@ int main(int argc, const char** argv)
auto args = parser.parse_args(argc, argv);
std::hash<blt::size_t> hash;
BLT_TRACE0_STREAM << hash(500) << "\n";
if (args.contains("--tests"))
{
//fb::test2();

View File

@ -360,7 +360,7 @@ namespace fb
using any_t = any_t_base<8>;
//using any_t = any_t_variant;
class func_t;
class func_t_old;
class func_variant_t;
@ -368,20 +368,20 @@ namespace fb
class func_any_t;
using func_t_call_t = std::function<void(func_t&, blt::span<any_t>)>;
using func_t_call_t_old = std::function<void(func_t_old&, blt::span<any_t>)>;
using func_variant_t_call_t = std::function<void(func_variant_t&, blt::span<any_t_variant>)>;
using func_union_t_call_t = std::function<void(func_union_t&, blt::span<any_t_union>)>;
using func_any_t_call_t = std::function<void(func_any_t&, blt::span<std::any>)>;
class func_t
class func_t_old
{
private:
blt::size_t argc_ = 0;
const func_t_call_t& func;
const func_t_call_t_old& func;
protected:
any_t value;
public:
explicit func_t(blt::size_t argc, const func_t_call_t& func):
explicit func_t_old(blt::size_t argc, const func_t_call_t_old& func):
argc_(argc), func(func)
{}
@ -393,7 +393,7 @@ namespace fb
return value;
}
inline func_t& setValue(any_t val)
inline func_t_old& setValue(any_t val)
{
this->value = val;
return *this;
@ -404,7 +404,7 @@ namespace fb
func(*this, args);
};
~func_t() = default;
~func_t_old() = default;
};
class func_variant_t
@ -509,10 +509,10 @@ namespace fb
~func_any_t() = default;
};
const func_t_call_t add_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() + args[1].any_cast<double>()); };
const func_t_call_t sub_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() - args[1].any_cast<double>()); };
const func_t_call_t mul_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() * args[1].any_cast<double>()); };
const func_t_call_t div_f = [](func_t& us, blt::span<any_t> args) {
const func_t_call_t_old add_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() + args[1].any_cast<double>()); };
const func_t_call_t_old sub_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() - args[1].any_cast<double>()); };
const func_t_call_t_old mul_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() * args[1].any_cast<double>()); };
const func_t_call_t_old div_f = [](func_t_old& us, blt::span<any_t> args) {
auto dim = args[1].any_cast<double>();
if (dim == 0)
us.setValue(0);
@ -520,20 +520,20 @@ namespace fb
us.setValue(args[0].any_cast<double>() + dim);
};
const func_t_call_t value_f = [](func_t&, blt::span<any_t>) {};
const func_t_call_t if_f = [](func_t& us, blt::span<any_t> args) {
const func_t_call_t_old value_f = [](func_t_old&, blt::span<any_t>) {};
const func_t_call_t_old if_f = [](func_t_old& us, blt::span<any_t> args) {
if (args[0].any_cast<bool>())
us.setValue(args[1].any_cast<double>());
else
us.setValue(args[2].any_cast<double>());
};
const func_t_call_t equals_b_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<bool>() == args[1].any_cast<bool>()); };
const func_t_call_t equals_n_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() == args[1].any_cast<double>()); };
const func_t_call_t less_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() < args[1].any_cast<double>()); };
const func_t_call_t greater_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() > args[1].any_cast<double>()); };
const func_t_call_t not_f = [](func_t& us, blt::span<any_t> args) { us.setValue(!args[0].any_cast<bool>()); };
const func_t_call_t and_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<bool>() && args[1].any_cast<bool>()); };
const func_t_call_t or_f = [](func_t& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<bool>() || args[1].any_cast<bool>()); };
const func_t_call_t_old equals_b_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<bool>() == args[1].any_cast<bool>()); };
const func_t_call_t_old equals_n_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() == args[1].any_cast<double>()); };
const func_t_call_t_old less_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() < args[1].any_cast<double>()); };
const func_t_call_t_old greater_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<double>() > args[1].any_cast<double>()); };
const func_t_call_t_old not_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(!args[0].any_cast<bool>()); };
const func_t_call_t_old and_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<bool>() && args[1].any_cast<bool>()); };
const func_t_call_t_old or_f = [](func_t_old& us, blt::span<any_t> args) { us.setValue(args[0].any_cast<bool>() || args[1].any_cast<bool>()); };
const func_variant_t_call_t add_variant_f = [](func_variant_t& us, blt::span<any_t_variant> args) {
@ -671,41 +671,41 @@ namespace fb
};
func_t make_type(type_t type)
func_t_old make_type(type_t type)
{
switch (type)
{
case type_t::ADD:
return func_t{2, add_f};
return func_t_old{2, add_f};
case type_t::SUB:
return func_t{2, sub_f};
return func_t_old{2, sub_f};
case type_t::MUL:
return func_t{2, mul_f};
return func_t_old{2, mul_f};
case type_t::DIV:
return func_t{2, div_f};
return func_t_old{2, div_f};
case type_t::IF:
return func_t{3, if_f};
return func_t_old{3, if_f};
case type_t::EQUAL_B:
return func_t{2, equals_b_f};
return func_t_old{2, equals_b_f};
case type_t::EQUAL_N:
return func_t{2, equals_n_f};
return func_t_old{2, equals_n_f};
case type_t::LESS:
return func_t{2, less_f};
return func_t_old{2, less_f};
case type_t::GREATER:
return func_t{2, greater_f};
return func_t_old{2, greater_f};
case type_t::NOT:
return func_t{1, not_f};
return func_t_old{1, not_f};
case type_t::AND:
return func_t{2, and_f};
return func_t_old{2, and_f};
case type_t::OR:
return func_t{2, or_f};
return func_t_old{2, or_f};
case type_t::VALUE:
return func_t{0, value_f}.setValue(random_value());
return func_t_old{0, value_f}.setValue(random_value());
case type_t::END:
break;
}
BLT_WARN("How did we get here? input %d", static_cast<int>(type));
return func_t{0, value_f}.setValue(random_value());
return func_t_old{0, value_f}.setValue(random_value());
}
func_variant_t make_type_variant(type_t type)
@ -826,7 +826,7 @@ namespace fb
private:
struct node_t
{
func_t type;
func_t_old type;
type_t enum_type;
node_t** children = nullptr;