types
parent
76c34baaec
commit
36bb3ffefa
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
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_ADDRSAN "Enable the address sanitizer" OFF)
|
||||||
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace fb
|
||||||
using function_id = blt::u32;
|
using function_id = blt::u32;
|
||||||
using arg_c_t = blt::size_t;
|
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_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 function_name = const std::string&;
|
||||||
using type_name = const std::string&;
|
using type_name = const std::string&;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,79 @@
|
||||||
|
|
||||||
#include <lilfbtf/fwddecl.h>
|
#include <lilfbtf/fwddecl.h>
|
||||||
#include <blt/std/hashmap.h>
|
#include <blt/std/hashmap.h>
|
||||||
|
#include <blt/std/memory_util.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace fb
|
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
|
class type_engine_t
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -36,19 +105,22 @@ namespace fb
|
||||||
blt::hashmap_t<std::string, function_id> name_to_function;
|
blt::hashmap_t<std::string, function_id> name_to_function;
|
||||||
std::vector<std::string> function_to_name;
|
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.
|
// 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;
|
associative_array<function_id, std::reference_wrapper<func_t_call_t>> functions;
|
||||||
// function names -> type_id
|
// function id -> list of type_id for parameters where index 0 = arg 1
|
||||||
blt::hashmap_t<std::string, type_id> function_outputs;
|
associative_array<function_id, std::vector<type_id>> function_inputs;
|
||||||
// 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_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:
|
public:
|
||||||
type_engine_t() = default;
|
type_engine_t() = default;
|
||||||
|
|
||||||
type_id register_type(type_name type_name);
|
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)
|
inline type_id get_type_id(type_name name)
|
||||||
{ return name_to_type[name]; }
|
{ return name_to_type[name]; }
|
||||||
|
@ -56,9 +128,25 @@ namespace fb
|
||||||
inline type_id get_function_id(function_name name)
|
inline type_id get_function_id(function_name name)
|
||||||
{ return name_to_function[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]; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
23
src/type.cpp
23
src/type.cpp
|
@ -28,23 +28,32 @@ namespace fb
|
||||||
return id;
|
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();
|
function_id id = function_to_name.size();
|
||||||
name_to_function[func_name] = id;
|
name_to_function[func_name] = id;
|
||||||
functions.insert({id, func});
|
functions.insert(id, func);
|
||||||
|
non_terminals[output].push_back(id);
|
||||||
return 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;
|
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)
|
||||||
{
|
{
|
||||||
|
function_id id = function_to_name.size();
|
||||||
return *this;
|
name_to_function[func_name] = id;
|
||||||
|
functions.insert(id, func);
|
||||||
|
terminals[output].push_back(id);
|
||||||
|
terminal_initializer.insert(id, initializer);
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -47,6 +47,9 @@ int main(int argc, const char** argv)
|
||||||
|
|
||||||
auto args = parser.parse_args(argc, argv);
|
auto args = parser.parse_args(argc, argv);
|
||||||
|
|
||||||
|
std::hash<blt::size_t> hash;
|
||||||
|
BLT_TRACE0_STREAM << hash(500) << "\n";
|
||||||
|
|
||||||
if (args.contains("--tests"))
|
if (args.contains("--tests"))
|
||||||
{
|
{
|
||||||
//fb::test2();
|
//fb::test2();
|
||||||
|
|
|
@ -360,7 +360,7 @@ namespace fb
|
||||||
using any_t = any_t_base<8>;
|
using any_t = any_t_base<8>;
|
||||||
//using any_t = any_t_variant;
|
//using any_t = any_t_variant;
|
||||||
|
|
||||||
class func_t;
|
class func_t_old;
|
||||||
|
|
||||||
class func_variant_t;
|
class func_variant_t;
|
||||||
|
|
||||||
|
@ -368,20 +368,20 @@ namespace fb
|
||||||
|
|
||||||
class func_any_t;
|
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_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_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>)>;
|
using func_any_t_call_t = std::function<void(func_any_t&, blt::span<std::any>)>;
|
||||||
|
|
||||||
class func_t
|
class func_t_old
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
blt::size_t argc_ = 0;
|
blt::size_t argc_ = 0;
|
||||||
const func_t_call_t& func;
|
const func_t_call_t_old& func;
|
||||||
protected:
|
protected:
|
||||||
any_t value;
|
any_t value;
|
||||||
public:
|
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)
|
argc_(argc), func(func)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ namespace fb
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline func_t& setValue(any_t val)
|
inline func_t_old& setValue(any_t val)
|
||||||
{
|
{
|
||||||
this->value = val;
|
this->value = val;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -404,7 +404,7 @@ namespace fb
|
||||||
func(*this, args);
|
func(*this, args);
|
||||||
};
|
};
|
||||||
|
|
||||||
~func_t() = default;
|
~func_t_old() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class func_variant_t
|
class func_variant_t
|
||||||
|
@ -509,10 +509,10 @@ namespace fb
|
||||||
~func_any_t() = default;
|
~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_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 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_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 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_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 div_f = [](func_t& us, blt::span<any_t> args) {
|
const func_t_call_t_old div_f = [](func_t_old& us, blt::span<any_t> args) {
|
||||||
auto dim = args[1].any_cast<double>();
|
auto dim = args[1].any_cast<double>();
|
||||||
if (dim == 0)
|
if (dim == 0)
|
||||||
us.setValue(0);
|
us.setValue(0);
|
||||||
|
@ -520,20 +520,20 @@ namespace fb
|
||||||
us.setValue(args[0].any_cast<double>() + dim);
|
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_old value_f = [](func_t_old&, 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 if_f = [](func_t_old& us, blt::span<any_t> args) {
|
||||||
if (args[0].any_cast<bool>())
|
if (args[0].any_cast<bool>())
|
||||||
us.setValue(args[1].any_cast<double>());
|
us.setValue(args[1].any_cast<double>());
|
||||||
else
|
else
|
||||||
us.setValue(args[2].any_cast<double>());
|
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_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 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_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 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_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 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_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 not_f = [](func_t& us, blt::span<any_t> args) { us.setValue(!args[0].any_cast<bool>()); };
|
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 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_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 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 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) {
|
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)
|
switch (type)
|
||||||
{
|
{
|
||||||
case type_t::ADD:
|
case type_t::ADD:
|
||||||
return func_t{2, add_f};
|
return func_t_old{2, add_f};
|
||||||
case type_t::SUB:
|
case type_t::SUB:
|
||||||
return func_t{2, sub_f};
|
return func_t_old{2, sub_f};
|
||||||
case type_t::MUL:
|
case type_t::MUL:
|
||||||
return func_t{2, mul_f};
|
return func_t_old{2, mul_f};
|
||||||
case type_t::DIV:
|
case type_t::DIV:
|
||||||
return func_t{2, div_f};
|
return func_t_old{2, div_f};
|
||||||
case type_t::IF:
|
case type_t::IF:
|
||||||
return func_t{3, if_f};
|
return func_t_old{3, if_f};
|
||||||
case type_t::EQUAL_B:
|
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:
|
case type_t::EQUAL_N:
|
||||||
return func_t{2, equals_n_f};
|
return func_t_old{2, equals_n_f};
|
||||||
case type_t::LESS:
|
case type_t::LESS:
|
||||||
return func_t{2, less_f};
|
return func_t_old{2, less_f};
|
||||||
case type_t::GREATER:
|
case type_t::GREATER:
|
||||||
return func_t{2, greater_f};
|
return func_t_old{2, greater_f};
|
||||||
case type_t::NOT:
|
case type_t::NOT:
|
||||||
return func_t{1, not_f};
|
return func_t_old{1, not_f};
|
||||||
case type_t::AND:
|
case type_t::AND:
|
||||||
return func_t{2, and_f};
|
return func_t_old{2, and_f};
|
||||||
case type_t::OR:
|
case type_t::OR:
|
||||||
return func_t{2, or_f};
|
return func_t_old{2, or_f};
|
||||||
case type_t::VALUE:
|
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:
|
case type_t::END:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BLT_WARN("How did we get here? input %d", static_cast<int>(type));
|
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)
|
func_variant_t make_type_variant(type_t type)
|
||||||
|
@ -826,7 +826,7 @@ namespace fb
|
||||||
private:
|
private:
|
||||||
struct node_t
|
struct node_t
|
||||||
{
|
{
|
||||||
func_t type;
|
func_t_old type;
|
||||||
type_t enum_type;
|
type_t enum_type;
|
||||||
node_t** children = nullptr;
|
node_t** children = nullptr;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue