diff --git a/CMakeLists.txt b/CMakeLists.txt index 08239d5..81a65aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.0.131) +project(blt-gp VERSION 0.0.132) include(CTest) diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h index 5838fe1..013d728 100644 --- a/include/blt/gp/tree.h +++ b/include/blt/gp/tree.h @@ -79,7 +79,7 @@ namespace blt::gp return values; } - evaluation_context evaluate(void* context); + evaluation_context evaluate(void* context) const; blt::size_t get_depth(gp_program& program); @@ -113,6 +113,8 @@ namespace blt::gp void print(gp_program& program, std::ostream& output, bool print_literals = true, bool pretty_indent = false, bool include_types = false) const; + bool check(gp_program& program, void* context) const; + blt::ptrdiff_t find_endpoint(blt::gp::gp_program& program, blt::ptrdiff_t start); private: diff --git a/src/tree.cpp b/src/tree.cpp index 28270c6..82d9c96 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -26,7 +26,7 @@ namespace blt::gp { inline auto empty_callable = detail::callable_t([](void*, stack_allocator&, stack_allocator&) { BLT_ABORT("This should never be called!"); }); - evaluation_context tree_t::evaluate(void* context) + evaluation_context tree_t::evaluate(void* context) const { #if BLT_DEBUG_LEVEL >= 2 blt::size_t expected_bytes = 0; @@ -219,4 +219,61 @@ namespace blt::gp return index; } + + bool tree_t::check(gp_program& program, void* context) const + { + blt::size_t bytes_expected = 0; + auto bytes_size = values.size().total_used_bytes; + + for (const auto& op : get_operations()) + { + if (op.is_value) + bytes_expected += stack_allocator::aligned_size(op.type_size); + } + + if (bytes_expected != bytes_size) + { + BLT_WARN_STREAM << "Stack state: " << values.size() << "\n"; + BLT_WARN("Child tree bytes %ld vs expected %ld, difference: %ld", bytes_size, bytes_expected, + static_cast(bytes_expected) - static_cast(bytes_size)); + BLT_WARN("Amount of bytes in stack doesn't match the number of bytes expected for the operations"); + return false; + } + + // copy the initial values + evaluation_context results{}; + + auto value_stack = values; + auto& values_process = results.values; + + blt::size_t total_produced = 0; + blt::size_t total_consumed = 0; + + for (const auto& operation : blt::reverse_iterate(operations.begin(), operations.end())) + { + if (operation.is_value) + { + value_stack.transfer_bytes(values_process, operation.type_size); + total_produced += stack_allocator::aligned_size(operation.type_size); + continue; + } + auto& info = program.get_operator_info(operation.id); + for (auto& arg : info.argument_types) + total_consumed += stack_allocator::aligned_size(program.get_typesystem().get_type(arg).size()); + operation.func(context, values_process, values_process); + total_produced += stack_allocator::aligned_size(program.get_typesystem().get_type(info.return_type).size()); + } + + auto v1 = results.values.bytes_in_head(); + auto v2 = static_cast(stack_allocator::aligned_size(operations.front().type_size)); + if (v1 != v2) + { + auto vd = std::abs(v1 - v2); + BLT_ERROR("found %ld bytes expected %ld bytes, total difference: %ld", v1, v2, vd); + BLT_ERROR("Total Produced %ld || Total Consumed %ld || Total Difference %ld", total_produced, total_consumed, + std::abs(static_cast(total_produced) - static_cast(total_consumed))); + return false; + } + return true; + } } \ No newline at end of file