hopefully fix evaluation order

thread
Brett 2024-08-03 19:51:38 -04:00
parent be90039a5a
commit ec71055078
9 changed files with 119 additions and 59 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.110) project(blt-gp VERSION 0.0.111)
include(CTest) include(CTest)

View File

@ -78,7 +78,8 @@ namespace blt::gp
{ {
blt::size_t offset = 0; blt::size_t offset = 0;
blt::size_t current_index = 0; blt::size_t current_index = 0;
((offset += (current_index++ > index ? stack_allocator::aligned_size<detail::remove_cv_ref<Args>>() : 0)), ...); ((offset += (current_index++ < index ? stack_allocator::aligned_size<detail::remove_cv_ref<Args>>() : 0)), ...);
//BLT_INFO("offset %ld for index %ld", offset, index);
return offset; return offset;
} }
@ -86,6 +87,8 @@ namespace blt::gp
inline static constexpr Return exec_sequence_to_indices(Func&& func, stack_allocator& allocator, std::integer_sequence<blt::u64, indices...>, inline static constexpr Return exec_sequence_to_indices(Func&& func, stack_allocator& allocator, std::integer_sequence<blt::u64, indices...>,
ExtraArgs&& ... args) ExtraArgs&& ... args)
{ {
//blt::size_t arg_size = (stack_allocator::aligned_size<detail::remove_cv_ref<Args>>() + ...);
//BLT_TRACE(arg_size);
// expands Args and indices, providing each argument with its index calculating the current argument byte offset // expands Args and indices, providing each argument with its index calculating the current argument byte offset
return std::forward<Func>(func)(std::forward<ExtraArgs>(args)..., return std::forward<Func>(func)(std::forward<ExtraArgs>(args)...,
allocator.from<detail::remove_cv_ref<Args>>(getByteOffset<indices>())...); allocator.from<detail::remove_cv_ref<Args>>(getByteOffset<indices>())...);
@ -174,6 +177,7 @@ namespace blt::gp
return name; return name;
} }
operator_id id = -1;
private: private:
function_t func; function_t func;
std::optional<std::string_view> name; std::optional<std::string_view> name;

View File

@ -40,6 +40,7 @@
#include <blt/std/hashmap.h> #include <blt/std/hashmap.h>
#include <blt/std/types.h> #include <blt/std/types.h>
#include <blt/std/utility.h> #include <blt/std/utility.h>
#include <blt/std/meta.h>
#include <blt/std/memory.h> #include <blt/std/memory.h>
#include <blt/std/thread.h> #include <blt/std/thread.h>
#include <blt/gp/fwdecl.h> #include <blt/gp/fwdecl.h>
@ -105,10 +106,11 @@ namespace blt::gp
{} {}
template<typename ArgType, typename Return, typename... Args> template<typename ArgType, typename Return, typename... Args>
operator_builder& add_operator(const operation_t<ArgType, Return(Args...)>& op, bool is_static = false) operator_builder& add_operator(operation_t<ArgType, Return(Args...)>& op, bool is_static = false)
{ {
auto return_type_id = system.get_type<Return>().id(); auto return_type_id = system.get_type<Return>().id();
auto operator_id = blt::gp::operator_id(storage.operators.size()); auto operator_id = blt::gp::operator_id(storage.operators.size());
op.id = operator_id;
operator_info info; operator_info info;
@ -128,27 +130,15 @@ namespace blt::gp
BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!"); BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!");
info.function = op.template make_callable<Context>(); info.function = op.template make_callable<Context>();
// info.transfer = [](std::optional<std::reference_wrapper<stack_allocator>> to, stack_allocator& from) {
//#if BLT_DEBUG_LEVEL >= 3
// auto value = from.pop<Return>();
// //BLT_TRACE_STREAM << value << "\n";
// if (to){
// to->get().push(value);
// }
//#else
// if (to)
// {
// to->get().push(from.pop<Return>());
// } else
// {
// from.pop<Return>();
// }
//#endif
//
// };
storage.operators.push_back(info); storage.operators.push_back(info);
storage.print_funcs.push_back([](std::ostream& out, stack_allocator& stack) { storage.print_funcs.push_back([&op](std::ostream& out, stack_allocator& stack) {
out << stack.pop<Return>(); if constexpr (blt::meta::is_streamable_v<Return>) {
out << stack.pop<Return>();
(void)(op); // remove warning
} else {
out << "[Printing Value on '" << (op.get_name() ? *op.get_name() : "") << "' Not Supported!]";
}
}); });
storage.names.push_back(op.get_name()); storage.names.push_back(op.get_name());
if (is_static) if (is_static)

View File

@ -151,8 +151,11 @@ namespace blt::gp
if (blk == nullptr) if (blk == nullptr)
throw std::runtime_error("Some nonsense is going on. This function already smells"); throw std::runtime_error("Some nonsense is going on. This function already smells");
if (blk->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(TYPE_SIZE)) if (blk->used_bytes_in_block() < static_cast<blt::ptrdiff_t>(TYPE_SIZE))
{
BLT_WARN_STREAM << size() << "\n";
throw std::runtime_error((std::string("Mismatched Types! Not enough space left in block! Bytes: ") += std::to_string( throw std::runtime_error((std::string("Mismatched Types! Not enough space left in block! Bytes: ") += std::to_string(
blk->used_bytes_in_block()) += " Size: " + std::to_string(sizeof(NO_REF_T))).c_str()); blk->used_bytes_in_block()) += " Size: " + std::to_string(sizeof(NO_REF_T))).c_str());
}
return *reinterpret_cast<NO_REF_T*>(blk->metadata.offset - remaining_bytes); return *reinterpret_cast<NO_REF_T*>(blk->metadata.offset - remaining_bytes);
} }

View File

@ -26,7 +26,6 @@
#include <blt/std/memory.h> #include <blt/std/memory.h>
#include <blt/gp/fwdecl.h> #include <blt/gp/fwdecl.h>
#include <blt/gp/stack.h> #include <blt/gp/stack.h>
#include <blt/gp/operations.h>
#include <random> #include <random>
namespace blt::gp namespace blt::gp

@ -1 +1 @@
Subproject commit fb17ff16c0e10193454921af0d27d1f5afd4ddd6 Subproject commit befd5e0ca1135c467f194d1d0e5691d301f93a34

View File

@ -56,9 +56,12 @@ namespace blt::gp
operations_stack.pop_back(); operations_stack.pop_back();
if (operation.is_value) if (operation.is_value)
{ {
//BLT_DEBUG("Processed Value %ld with size %ld", operation.id, stack_allocator::aligned_size(operation.type_size));
value_stack.transfer_bytes(values_process, operation.type_size); value_stack.transfer_bytes(values_process, operation.type_size);
continue; continue;
} }
//BLT_DEBUG("Processed function %ld with size %ld", operation.id, stack_allocator::aligned_size(operation.type_size));
//BLT_TRACE("Stack info: %ld %ld", values_process.size().total_used_bytes, value_stack.size().total_used_bytes);
operation.func(context, values_process, value_stack); operation.func(context, values_process, value_stack);
operations_stack.emplace_back(empty_callable, operation.type_size, operation.id, true); operations_stack.emplace_back(empty_callable, operation.type_size, operation.id, true);
} }

View File

@ -50,6 +50,8 @@ struct large_18290
blt::u8 data[18290]; blt::u8 data[18290];
}; };
large_18290 base{};
blt::gp::type_provider type_system; blt::gp::type_provider type_system;
blt::gp::gp_program program{type_system, SEED}; blt::gp::gp_program program{type_system, SEED};
@ -65,14 +67,29 @@ blt::gp::op_container_t make_value(const blt::gp::type& id)
return {empty, id.size(), 0, true}; return {empty, id.size(), 0, true};
} }
blt::gp::operation_t basic_2([](float a, float b) { blt::gp::operation_t add([](float a, float b) {
return a + b; return a + b;
}); });
blt::gp::operation_t sub([](float a, float b) {
return a - b;
});
blt::gp::operation_t basic_2t([](float a, bool b) { blt::gp::operation_t basic_2t([](float a, bool b) {
return b ? a : 0.0f; return b ? a : 0.0f;
}); });
blt::gp::operation_t cross_large_type([](const large_18290& input, const float a, const float b) {
BLT_TRACE("%f, %f", a, b);
large_18290 output{};
for (const auto& [index, ref] : blt::enumerate(input.data))
{
if (ref > static_cast<blt::u8>(a) && ref < static_cast<blt::u8>(b))
output.data[index] = ref;
}
return output;
});
blt::gp::operation_t f_literal([]() { blt::gp::operation_t f_literal([]() {
return 0.0f; return 0.0f;
}); });
@ -81,35 +98,68 @@ blt::gp::operation_t b_literal([]() {
return false; return false;
}); });
blt::gp::operation_t large_literal([]() {
return base;
});
void basic_tree() void basic_tree()
{ {
BLT_INFO("Testing if we can get a basic tree going."); BLT_INFO("Testing if we can get a basic tree going.");
blt::gp::tree_t tree; blt::gp::tree_t tree;
tree.get_operations().push_back(make_container(2)); tree.get_operations().push_back(make_container(sub.id));
tree.get_operations().push_back(make_value(type_system.get_type<float>())); tree.get_operations().push_back(make_value(type_system.get_type<float>()));
tree.get_operations().push_back(make_value(type_system.get_type<float>())); tree.get_operations().push_back(make_value(type_system.get_type<float>()));
tree.get_values().push(50.0f);
tree.get_values().push(120.0f); tree.get_values().push(120.0f);
tree.get_values().push(50.0f);
auto val = tree.get_evaluation_value<float>(nullptr); auto val = tree.get_evaluation_value<float>(nullptr);
BLT_TRACE(val); BLT_TRACE(val);
BLT_ASSERT(val == (50 + 120)); BLT_ASSERT(val == (120 - 50));
}
void large_cross_type_tree()
{
blt::gp::tree_t tree;
auto& ops = tree.get_operations();
auto& vals = tree.get_values();
ops.push_back(make_container(cross_large_type.id));
ops.push_back(make_container(large_literal.id));
ops.push_back(make_container(sub.id));
ops.push_back(make_value(type_system.get_type<float>()));
ops.push_back(make_value(type_system.get_type<float>()));
ops.push_back(make_value(type_system.get_type<float>()));
vals.push(50.0f);
vals.push(120.0f);
vals.push(5555.0f);
auto val = tree.get_evaluation_value<large_18290>(nullptr);
blt::black_box(val);
} }
int main() int main()
{ {
for (auto& v : base.data)
v = static_cast<blt::u8>(blt::random::murmur_random64c(691, std::numeric_limits<blt::u8>::min(), std::numeric_limits<blt::u8>::max()));
type_system.register_type<float>(); type_system.register_type<float>();
type_system.register_type<bool>(); type_system.register_type<bool>();
type_system.register_type<large_18290>();
blt::gp::operator_builder builder{type_system}; blt::gp::operator_builder builder{type_system};
builder.add_operator(f_literal); // 0 builder.add_operator(f_literal); // 0
builder.add_operator(b_literal); // 1 builder.add_operator(b_literal); // 1
builder.add_operator(basic_2); // 2 builder.add_operator(add); // 2
builder.add_operator(basic_2t); // 3 builder.add_operator(basic_2t); // 3
builder.add_operator(sub); // 4
builder.add_operator(large_literal); // 5
builder.add_operator(cross_large_type); // 6
program.set_operations(builder.build()); program.set_operations(builder.build());
basic_tree(); basic_tree();
large_cross_type_tree();
} }

View File

@ -33,7 +33,7 @@ struct log_box
~log_box() ~log_box()
{ {
for (auto& c : text) for (auto& _ : text)
logger << '-'; logger << '-';
logger << '\n'; logger << '\n';
} }
@ -51,9 +51,18 @@ T make_data(T t, Func&& func)
return t; return t;
} }
template<typename T, typename Class, blt::size_t size>
static inline auto constexpr array_size(const T(Class::*)[size])
{
return size;
}
template<typename T, typename U> template<typename T, typename U>
blt::ptrdiff_t compare(const T& t, const U& u) blt::ptrdiff_t compare(const T& t, const U& u)
{ {
constexpr auto ts = array_size(&T::data);
constexpr auto us = array_size(&U::data);
BLT_ASSERT_MSG(ts == us, ("Array sizes don't match! " + std::to_string(ts) + " vs " + std::to_string(us)).c_str());
for (const auto& [index, v] : blt::enumerate(t.data)) for (const auto& [index, v] : blt::enumerate(t.data))
{ {
if (u.data[index] != v) if (u.data[index] != v)
@ -289,8 +298,8 @@ void test_basic()
BLT_INFO("Testing basic with stack"); BLT_INFO("Testing basic with stack");
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(50.0f);
stack.push(10.0f); stack.push(10.0f);
stack.push(50.0f);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
basic_2.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack); basic_2.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
@ -303,8 +312,8 @@ void test_basic()
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(std::array<blt::u8, blt::gp::stack_allocator::page_size_no_block() - sizeof(float)>{}); stack.push(std::array<blt::u8, blt::gp::stack_allocator::page_size_no_block() - sizeof(float)>{});
stack.push(50.0f);
stack.push(10.0f); stack.push(10.0f);
stack.push(50.0f);
auto size = stack.size(); auto size = stack.size();
BLT_TRACE_STREAM << size << "\n"; BLT_TRACE_STREAM << size << "\n";
BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!");
@ -323,10 +332,11 @@ void test_mixed()
BLT_INFO("Testing mixed with stack"); BLT_INFO("Testing mixed with stack");
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(50.0f);
stack.push(10.0f);
stack.push(true);
stack.push(false); stack.push(false);
stack.push(true);
stack.push(10.0f);
stack.push(50.0f);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
basic_mixed_4.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack); basic_mixed_4.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
@ -339,10 +349,10 @@ void test_mixed()
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(std::array<blt::u8, blt::gp::stack_allocator::page_size_no_block() - sizeof(float)>{}); stack.push(std::array<blt::u8, blt::gp::stack_allocator::page_size_no_block() - sizeof(float)>{});
stack.push(50.0f);
stack.push(10.0f);
stack.push(true);
stack.push(false); stack.push(false);
stack.push(true);
stack.push(10.0f);
stack.push(50.0f);
auto size = stack.size(); auto size = stack.size();
BLT_TRACE_STREAM << size << "\n"; BLT_TRACE_STREAM << size << "\n";
BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!");
@ -361,9 +371,10 @@ void test_large_256()
BLT_INFO("Testing large 256 with stack"); BLT_INFO("Testing large 256 with stack");
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(base_256);
stack.push(691.0f);
stack.push(69.420f); stack.push(69.420f);
stack.push(691.0f);
stack.push(base_256);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
large_256_basic_3.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack); large_256_basic_3.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
@ -376,9 +387,9 @@ void test_large_256()
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(std::array<blt::u8, blt::gp::stack_allocator::page_size_no_block() - sizeof(large_256)>{}); stack.push(std::array<blt::u8, blt::gp::stack_allocator::page_size_no_block() - sizeof(large_256)>{});
stack.push(base_256);
stack.push(691.0f);
stack.push(69.420f); stack.push(69.420f);
stack.push(691.0f);
stack.push(base_256);
auto size = stack.size(); auto size = stack.size();
BLT_TRACE_STREAM << size << "\n"; BLT_TRACE_STREAM << size << "\n";
BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!");
@ -397,9 +408,9 @@ void test_large_4096()
BLT_INFO("Testing large 4096 with stack"); BLT_INFO("Testing large 4096 with stack");
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(base_4096);
stack.push(33.0f);
stack.push(true); stack.push(true);
stack.push(33.0f);
stack.push(base_4096);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
large_4096_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack); large_4096_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
@ -411,16 +422,16 @@ void test_large_4096()
BLT_INFO("Testing large 4096 with stack over boundary"); BLT_INFO("Testing large 4096 with stack over boundary");
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(base_4096);
stack.push(33.0f);
stack.push(true); stack.push(true);
stack.push(33.0f);
stack.push(base_4096);
auto size = stack.size(); auto size = stack.size();
BLT_TRACE_STREAM << size << "\n"; BLT_TRACE_STREAM << size << "\n";
BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!");
large_4096_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack); large_4096_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
auto val = stack.pop<large_4096>(); auto val = stack.pop<large_4096>();
RUN_TEST(!compare(val, base_256), stack, "Large 4096 3 Boundary Test Passed", "Large 4096 3 Test Failed. Unexpected value produced '%lf'", val); RUN_TEST(!compare(val, base_4096), stack, "Large 4096 3 Boundary Test Passed", "Large 4096 3 Test Failed. Unexpected value produced '%lf'", val);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
BLT_ASSERT(stack.empty() && "Stack was not empty after evaluation over stack boundary"); BLT_ASSERT(stack.empty() && "Stack was not empty after evaluation over stack boundary");
} }
@ -431,9 +442,9 @@ void test_large_18290()
BLT_INFO("Testing large 18290 with stack"); BLT_INFO("Testing large 18290 with stack");
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(base_18290);
stack.push(-2543.0f);
stack.push(true); stack.push(true);
stack.push(-2543.0f);
stack.push(base_18290);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
large_18290_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack); large_18290_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
@ -446,9 +457,9 @@ void test_large_18290()
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(std::array<blt::u8, 20480 - 18290 - blt::gp::stack_allocator::block_size()>()); stack.push(std::array<blt::u8, 20480 - 18290 - blt::gp::stack_allocator::block_size()>());
stack.push(base_18290);
stack.push(-2543.0f);
stack.push(true); stack.push(true);
stack.push(-2543.0f);
stack.push(base_18290);
auto size = stack.size(); auto size = stack.size();
BLT_TRACE_STREAM << size << "\n"; BLT_TRACE_STREAM << size << "\n";
BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!");
@ -463,15 +474,15 @@ void test_large_18290()
BLT_INFO("Testing large 18290 with stack over multiple boundaries"); BLT_INFO("Testing large 18290 with stack over multiple boundaries");
{ {
blt::gp::stack_allocator stack; blt::gp::stack_allocator stack;
stack.push(base_18290); stack.push(true);
stack.push(-2543.0f); stack.push(-2543.0f);
stack.push(true); stack.push(true);
stack.push(-2543.0f);
stack.push(base_18290);
auto size = stack.size(); auto size = stack.size();
BLT_TRACE_STREAM << size << "\n"; BLT_TRACE_STREAM << size << "\n";
large_18290_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack); large_18290_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
stack.push(-2543.0f);
stack.push(true);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";
large_18290_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack); large_18290_basic_3b.make_callable<blt::gp::detail::empty_t>()(nullptr, stack, stack);
BLT_TRACE_STREAM << stack.size() << "\n"; BLT_TRACE_STREAM << stack.size() << "\n";