diff --git a/.idea/editor.xml b/.idea/editor.xml
index dfdaaeb..5fff85e 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -240,247 +240,5 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6bfd797..3dc402a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,7 +27,7 @@ macro(compile_options target_name)
sanitizers(${target_name})
endmacro()
-project(blt-gp VERSION 0.3.22)
+project(blt-gp VERSION 0.3.23)
include(CTest)
diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h
index f7e3b4a..8ebc32f 100644
--- a/include/blt/gp/stack.h
+++ b/include/blt/gp/stack.h
@@ -193,7 +193,7 @@ namespace blt::gp
constexpr auto size = aligned_size();
#if BLT_DEBUG_LEVEL > 0
if (bytes_stored < size)
- BLT_ABORT("Not enough bytes left to pop!");
+ throw std::runtime_error(("Not enough bytes left to pop!" __FILE__ ":") + std::to_string(__LINE__));
#endif
bytes_stored -= size;
return *reinterpret_cast(data_ + bytes_stored);
@@ -203,8 +203,9 @@ namespace blt::gp
{
#if BLT_DEBUG_LEVEL > 0
if (bytes_stored < bytes)
- BLT_ABORT(("Not enough bytes in stack to reference " + std::to_string(bytes) + " bytes requested but " + std::to_string(bytes) +
- " bytes stored!").c_str());
+ throw std::runtime_error(
+ "Not enough bytes in stack! " + std::to_string(bytes) + " bytes requested but only " + std::to_string(bytes_stored) +
+ (" bytes stored! (at " __FILE__ ":") + std::to_string(__LINE__));
#endif
return data_ + (bytes_stored - bytes);
}
@@ -237,8 +238,11 @@ namespace blt::gp
[[nodiscard]] std::pair&> access_pointer(const size_t bytes) const
{
auto& type_ref = from(bytes);
- return {type_ref, *std::launder(
- reinterpret_cast*>(reinterpret_cast(&type_ref) + detail::aligned_size(sizeof(T))))};
+ return {
+ type_ref, *std::launder(
+ reinterpret_cast*>(reinterpret_cast(&type_ref) +
+ detail::aligned_size(sizeof(T))))
+ };
}
void pop_bytes(const size_t bytes)
@@ -256,8 +260,9 @@ namespace blt::gp
{
#if BLT_DEBUG_LEVEL > 0
if (bytes_stored < aligned_bytes)
- BLT_ABORT(("Not enough bytes in stack to transfer " + std::to_string(aligned_bytes) + " bytes requested but " + std::to_string(aligned_bytes) +
- " bytes stored!").c_str());
+ BLT_ABORT(
+ ("Not enough bytes in stack to transfer " + std::to_string(aligned_bytes) + " bytes requested but " + std::to_string(aligned_bytes) +
+ " bytes stored!").c_str());
gp::detail::check_alignment(aligned_bytes);
#endif
to.copy_from(*this, aligned_bytes);
diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h
index 39e39c2..36c74d0 100644
--- a/include/blt/gp/tree.h
+++ b/include/blt/gp/tree.h
@@ -198,23 +198,30 @@ namespace blt::gp
}
};
- struct after_bytes_data_t
+ struct byte_only_transaction_t
{
- after_bytes_data_t(tree_t& tree, u8* data, const size_t bytes): tree(tree), data(data), bytes(bytes)
+ byte_only_transaction_t(tree_t& tree, const size_t bytes): tree(tree), data(nullptr), bytes(bytes)
+ {
+ move(bytes);
+ }
+
+ explicit byte_only_transaction_t(tree_t& tree): tree(tree), data(nullptr), bytes(0)
{
}
- after_bytes_data_t(const after_bytes_data_t& copy) = delete;
- after_bytes_data_t& operator=(const after_bytes_data_t& copy) = delete;
+ byte_only_transaction_t(const byte_only_transaction_t& copy) = delete;
+ byte_only_transaction_t& operator=(const byte_only_transaction_t& copy) = delete;
- after_bytes_data_t(after_bytes_data_t&& move) noexcept: tree(move.tree), data(std::exchange(move.data, nullptr)),
- bytes(std::exchange(move.bytes, 0))
+ byte_only_transaction_t(byte_only_transaction_t&& move) noexcept: tree(move.tree), data(std::exchange(move.data, nullptr)),
+ bytes(std::exchange(move.bytes, 0))
{
}
- after_bytes_data_t& operator=(after_bytes_data_t&& move) noexcept = delete;
+ byte_only_transaction_t& operator=(byte_only_transaction_t&& move) noexcept = delete;
- ~after_bytes_data_t()
+ void move(size_t bytes_to_move);
+
+ ~byte_only_transaction_t()
{
if (bytes > 0)
{
@@ -314,6 +321,8 @@ namespace blt::gp
void clear(gp_program& program);
+ void insert_operator(size_t index, const op_container_t& container);
+
void insert_operator(const op_container_t& container)
{
operations.emplace_back(container);
@@ -359,13 +368,35 @@ namespace blt::gp
[[nodiscard]] std::optional select_subtree_traverse(type_id type, u32 max_tries = 5, double terminal_chance = 0.1,
double depth_multiplier = 0.6) const;
+ /**
+ * Copies the subtree found at point into the provided out params
+ * @param point subtree point
+ * @param extent how far the subtree extends
+ * @param operators vector for storing subtree operators
+ * @param stack stack for storing subtree values
+ */
+ void copy_subtree(subtree_point_t point, ptrdiff_t extent, tracked_vector& operators, stack_allocator& stack);
+
/**
* Copies the subtree found at point into the provided out params
* @param point subtree point
* @param operators vector for storing subtree operators
* @param stack stack for storing subtree values
*/
- void copy_subtree(subtree_point_t point, std::vector& operators, stack_allocator& stack);
+ void copy_subtree(const subtree_point_t point, tracked_vector& operators, stack_allocator& stack)
+ {
+ copy_subtree(point, find_endpoint(point.pos), operators, stack);
+ }
+
+ void copy_subtree(const subtree_point_t point, const ptrdiff_t extent, tree_t& out_tree)
+ {
+ copy_subtree(point, extent, out_tree.operations, out_tree.values);
+ }
+
+ void copy_subtree(const subtree_point_t point, tree_t& out_tree)
+ {
+ copy_subtree(point, find_endpoint(point.pos), out_tree);
+ }
/**
* Swaps the subtrees between this tree and the other tree
@@ -425,9 +456,14 @@ namespace blt::gp
* temporarily moves the last bytes amount of data from the current stack. this can be useful for if you are going to do a lot
* of consecutive operations on the tree as this will avoid extra copy + reinsert.
* The object returned by this function will automatically move the data back in when it goes out of scope.
- * @param bytes amount of bytes to remove.
+ * @param operator_index operator index to move from. this is inclusive
*/
- after_bytes_data_t temporary_move(size_t bytes);
+ void temporary_move(const size_t operator_index)
+ {
+ // return obt_move_t{*this, operator_index};
+ }
+
+ void modify_operator(size_t point, operator_id new_id, std::optional return_type = {});
/**
* User function for evaluating this tree using a context reference. This function should only be used if the tree is expecting the context value
@@ -489,8 +525,8 @@ namespace blt::gp
return evaluation_ref{val, ctx};
}
- void print(std::ostream& output, bool print_literals = true, bool pretty_indent = false,
- bool include_types = false) const;
+ void print(std::ostream& out, bool print_literals = true, bool pretty_indent = false, bool include_types = false,
+ ptrdiff_t marked_index = -1) const;
bool check(void* context) const;
@@ -537,8 +573,6 @@ namespace blt::gp
return operations[point];
}
- void modify_operator(size_t point, operator_id new_id, std::optional return_type = {});
-
[[nodiscard]] subtree_point_t subtree_from_point(ptrdiff_t point) const;
template
@@ -616,6 +650,10 @@ namespace blt::gp
stack_allocator values;
gp_program* m_program;
+ /*
+ * Static members
+ * --------------
+ */
protected:
template
static void execute(void* context, stack_allocator& write_stack, stack_allocator& read_stack, Operator& operation)
diff --git a/src/transformers.cpp b/src/transformers.cpp
index 0cd183d..48c50ff 100644
--- a/src/transformers.cpp
+++ b/src/transformers.cpp
@@ -80,28 +80,8 @@ namespace blt::gp
}
#if BLT_DEBUG_LEVEL >= 2
- blt::size_t c1_found_bytes = c1.get_values().size().total_used_bytes;
- blt::size_t c2_found_bytes = c2.get_values().size().total_used_bytes;
- blt::size_t c1_expected_bytes = std::accumulate(c1.get_operations().begin(), c1.get_operations().end(), 0ul,
- [](const auto& v1, const auto& v2)
- {
- if (v2.is_value())
- return v1 + v2.type_size();
- return v1;
- });
- blt::size_t c2_expected_bytes = std::accumulate(c2.get_operations().begin(), c2.get_operations().end(), 0ul,
- [](const auto& v1, const auto& v2)
- {
- if (v2.is_value())
- return v1 + v2.type_size();
- return v1;
- });
- if (c1_found_bytes != c1_expected_bytes || c2_found_bytes != c2_expected_bytes)
- {
- BLT_WARN("C1 Found bytes %ld vs Expected Bytes %ld", c1_found_bytes, c1_expected_bytes);
- BLT_WARN("C2 Found bytes %ld vs Expected Bytes %ld", c2_found_bytes, c2_expected_bytes);
- BLT_ABORT("Amount of bytes in stack doesn't match the number of bytes expected for the operations");
- }
+ if (!c1.check(detail::debug::context_ptr) || !c2.check(detail::debug::context_ptr))
+ throw std::runtime_error("Tree check failed");
#endif
c1.get_depth(program);
@@ -156,51 +136,8 @@ namespace blt::gp
// this will check to make sure that the tree is in a correct and executable state. it requires that the evaluation is context free!
#if BLT_DEBUG_LEVEL >= 2
- // BLT_ASSERT(new_vals_r.empty());
- //BLT_ASSERT(stack_after.empty());
- blt::size_t bytes_expected = 0;
- auto bytes_size = vals_r.size().total_used_bytes;
-
- for (const auto& op : c.get_operations())
- {
- if (op.is_value())
- bytes_expected += op.type_size();
- }
-
- if (bytes_expected != bytes_size)
- {
- BLT_WARN_STREAM << "Stack state: " << vals_r.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_TRACE("Total bytes after: %ld", total_bytes_after);
- BLT_ABORT("Amount of bytes in stack doesn't match the number of bytes expected for the operations");
- }
- auto copy = c;
- try
- {
- if (!copy.check(detail::debug::context_ptr))
- throw std::runtime_error("Tree check failed");
- // TODO a work around for the whole needing to access a now private function
- // const auto& result = copy.evaluate(*static_cast(detail::debug::context_ptr));
- // blt::black_box(result);
- }
- catch (...)
- {
- std::cout << "This occurred at point " << begin_point << " ending at (old) " << end_point << "\n";
- std::cout << "our root type is " << ops_r[begin_point].id() << " with size " << ops_r[begin_point].type_size()
- << "\n";
- std::cout << "now Named: " << (program.get_name(ops_r[begin_point].id()) ? *program.get_name(ops_r[begin_point].id()) : "Unnamed") <<
- "\n";
- std::cout << "Was named: " << (program.get_name(begin_operator_id) ? *program.get_name(begin_operator_id) : "Unnamed") << "\n";
- //std::cout << "Parent:" << std::endl;
- //p.print(program, std::cout, false, true);
- std::cout << "Child:" << std::endl;
- c.print(std::cout, false, true);
- std::cout << std::endl;
- c.print(std::cout, true, true);
- std::cout << std::endl;
- throw std::exception();
- }
+ if (!c.check(detail::debug::context_ptr))
+ throw std::runtime_error("Mutate Point tree check failed");
#endif
return node.pos + new_tree.size();
}
@@ -214,6 +151,15 @@ namespace blt::gp
#if BLT_DEBUG_LEVEL >= 2
tree_t c_copy = c;
+ if (!c.check(detail::debug::context_ptr))
+ {
+ std::cout << "Parent: " << std::endl;
+ p.print(std::cout, false, false);
+ std::cout << "Child Values:" << std::endl;
+ c.print(std::cout, false, false);
+ std::cout << std::endl;
+ BLT_ABORT("Pre-check Tree Check Failed.");
+ }
#endif
// select an operator to apply
@@ -279,7 +225,7 @@ namespace blt::gp
{
// don't need to update if the index is the last
for (auto& new_child : iterate(children_data.end() - static_cast(index),
- children_data.end()))
+ children_data.end()))
{
// remove the old tree size, then add the new tree size to get the correct positions.
new_child.start =
@@ -292,20 +238,8 @@ namespace blt::gp
child_end = static_cast(child_start + tree.size());
#if BLT_DEBUG_LEVEL >= 2
- blt::size_t found_bytes = vals.size().total_used_bytes;
- blt::size_t expected_bytes = std::accumulate(ops.begin(),
- ops.end(), 0ul,
- [](const auto& v1, const auto& v2)
- {
- if (v2.is_value())
- return v1 + v2.type_size();
- return v1;
- });
- if (found_bytes != expected_bytes)
- {
- BLT_WARN("Found bytes %ld vs Expected Bytes %ld", found_bytes, expected_bytes);
- BLT_ABORT("Amount of bytes in stack doesn't match the number of bytes expected for the operations");
- }
+ if (!c.check(detail::debug::context_ptr))
+ throw std::runtime_error("Adjust Tree check failed");
#endif
}
}
@@ -325,8 +259,9 @@ namespace blt::gp
{
// not enough args
size_t start_index = c_node + 1;
- size_t total_bytes_after = c.total_value_bytes(start_index);
- auto move = c.temporary_move(total_bytes_after);
+ // size_t total_bytes_after = c.total_value_bytes(start_index);
+ // TODO: transactions?
+ // auto move = c.temporary_move(total_bytes_after);
for (ptrdiff_t i = static_cast(replacement_func_info.argc.argc) - 1;
i >= current_func_info.argc.argc; i--)
@@ -347,11 +282,11 @@ namespace blt::gp
if (!c.check(detail::debug::context_ptr))
{
std::cout << "Parent: " << std::endl;
- c_copy.print(std::cout, false, true);
+ c_copy.print(std::cout, false, false);
std::cout << "Child Values:" << std::endl;
- c.print(std::cout, true, true);
+ c.print(std::cout, false, false);
std::cout << std::endl;
- BLT_ABORT("Tree Check Failed.");
+ BLT_ABORT("Adjust Tree Check Failed.");
}
#endif
}
@@ -374,7 +309,7 @@ namespace blt::gp
do
{
auto& replacement_func_info = program.get_operator_info(random_replacement);
- for (const auto& [index, v] : blt::enumerate(replacement_func_info.argument_types))
+ for (const auto& [index, v] : enumerate(replacement_func_info.argument_types))
{
if (v.id == current_func_info.return_type.id)
{
@@ -389,18 +324,18 @@ namespace blt::gp
auto& replacement_func_info = program.get_operator_info(random_replacement);
auto new_argc = replacement_func_info.argc.argc;
// replacement function should be valid. let's make a copy of us.
- auto current_end = c.find_endpoint(static_cast(c_node));
- blt::size_t for_bytes = c.total_value_bytes(c_node, current_end);
- blt::size_t after_bytes = c.total_value_bytes(current_end);
+ auto current_end = c.find_endpoint(static_cast(c_node));
+ // size_t for_bytes = c.total_value_bytes(c_node, current_end);
+ // size_t after_bytes = c.total_value_bytes(current_end);
auto size = current_end - c_node;
- auto combined_ptr = get_thread_pointer_for_size(for_bytes + after_bytes);
+ // auto combined_ptr = get_thread_pointer_for_size(for_bytes + after_bytes);
- vals.copy_to(combined_ptr, for_bytes + after_bytes);
- vals.pop_bytes(static_cast(for_bytes + after_bytes));
+ // vals.copy_to(combined_ptr, for_bytes + after_bytes);
+ // vals.pop_bytes(static_cast(for_bytes + after_bytes));
- blt::size_t start_index = c_node;
- for (blt::ptrdiff_t i = new_argc - 1; i > static_cast(arg_position); i--)
+ size_t start_index = c_node;
+ for (ptrdiff_t i = new_argc - 1; i > static_cast(arg_position); i--)
{
auto& tree = get_static_tree_tl(program);
config.generator.get().generate(tree,
@@ -408,14 +343,10 @@ namespace blt::gp
program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
config.replacement_max_depth
});
- blt::size_t total_bytes_for = tree.total_value_bytes();
- vals.copy_from(tree.get_values(), total_bytes_for);
- ops.insert(ops.begin() + static_cast(start_index), tree.get_operations().begin(),
- tree.get_operations().end());
- start_index += tree.get_operations().size();
+ start_index = c.insert_subtree(tree_t::subtree_point_t(static_cast(start_index)), tree);
}
start_index += size;
- vals.copy_from(combined_ptr, for_bytes);
+ // vals.copy_from(combined_ptr, for_bytes);
for (blt::ptrdiff_t i = static_cast(arg_position) - 1; i >= 0; i--)
{
auto& tree = get_static_tree_tl(program);
@@ -424,42 +355,34 @@ namespace blt::gp
program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
config.replacement_max_depth
});
- blt::size_t total_bytes_for = tree.total_value_bytes();
- vals.copy_from(tree.get_values(), total_bytes_for);
- ops.insert(ops.begin() + static_cast(start_index), tree.get_operations().begin(),
- tree.get_operations().end());
- start_index += tree.get_operations().size();
+ start_index = c.insert_subtree(tree_t::subtree_point_t(static_cast(start_index)), tree);
}
- vals.copy_from(combined_ptr + for_bytes, after_bytes);
-
- ops.insert(ops.begin() + static_cast(c_node),
- {
- program.get_typesystem().get_type(replacement_func_info.return_type).size(),
- random_replacement,
- program.is_operator_ephemeral(random_replacement),
- program.get_operator_flags(random_replacement)
- });
+ // vals.copy_from(combined_ptr + for_bytes, after_bytes);
+ c.insert_operator(c_node, {
+ program.get_typesystem().get_type(replacement_func_info.return_type).size(),
+ random_replacement,
+ program.is_operator_ephemeral(random_replacement),
+ program.get_operator_flags(random_replacement)
+ });
#if BLT_DEBUG_LEVEL >= 2
if (!c.check(detail::debug::context_ptr))
{
std::cout << "Parent: " << std::endl;
- p.print(std::cout, false, true);
+ p.print(std::cout, false, false);
std::cout << "Child:" << std::endl;
- c.print(std::cout, false, true);
- std::cout << "Child Values:" << std::endl;
- c.print(std::cout, true, true);
+ c.print(std::cout, false, false);
std::cout << std::endl;
- BLT_ABORT("Tree Check Failed.");
+ BLT_ABORT("SUB_FUNC Tree Check Failed.");
}
#endif
}
break;
case mutation_operator::JUMP_FUNC:
{
- auto& info = program.get_operator_info(ops[c_node].id());
- blt::size_t argument_index = -1ul;
- for (const auto& [index, v] : blt::enumerate(info.argument_types))
+ auto& info = program.get_operator_info(c.get_operator(c_node).id());
+ size_t argument_index = -1ul;
+ for (const auto& [index, v] : enumerate(info.argument_types))
{
if (v.id == info.return_type.id)
{
@@ -470,60 +393,69 @@ namespace blt::gp
if (argument_index == -1ul)
continue;
- static thread_local tracked_vector child_data;
+ thread_local tracked_vector child_data;
child_data.clear();
c.find_child_extends(child_data, c_node, info.argument_types.size());
auto child_index = child_data.size() - 1 - argument_index;
- auto child = child_data[child_index];
- auto for_bytes = c.total_value_bytes(child.start, child.end);
- auto after_bytes = c.total_value_bytes(child_data.back().end);
+ const auto child = child_data[child_index];
- auto storage_ptr = get_thread_pointer_for_size(for_bytes + after_bytes);
- vals.copy_to(storage_ptr + for_bytes, after_bytes);
- vals.pop_bytes(static_cast(after_bytes));
+ thread_local tree_t child_tree{program};
- for (auto i = static_cast(child_data.size() - 1); i > static_cast(child_index); i--)
- {
- auto& cc = child_data[i];
- auto bytes = c.total_value_bytes(cc.start, cc.end);
- vals.pop_bytes(static_cast(bytes));
- ops.erase(ops.begin() + cc.start, ops.begin() + cc.end);
- }
- vals.copy_to(storage_ptr, for_bytes);
- vals.pop_bytes(static_cast(for_bytes));
- for (auto i = static_cast(child_index - 1); i >= 0; i--)
- {
- auto& cc = child_data[i];
- auto bytes = c.total_value_bytes(cc.start, cc.end);
- vals.pop_bytes(static_cast(bytes));
- ops.erase(ops.begin() + cc.start, ops.begin() + cc.end);
- }
- ops.erase(ops.begin() + static_cast(c_node));
- vals.copy_from(storage_ptr, for_bytes + after_bytes);
+ c.copy_subtree(tree_t::subtree_point_t(child.start), child.end, child_tree);
+ c.delete_subtree(tree_t::subtree_point_t(static_cast(c_node)));
+ c.insert_subtree(tree_t::subtree_point_t(static_cast(c_node)), child_tree);
+ child_tree.clear(program);
+
+ // auto for_bytes = c.total_value_bytes(child.start, child.end);
+ // auto after_bytes = c.total_value_bytes(child_data.back().end);
+
+ // auto storage_ptr = get_thread_pointer_for_size(for_bytes + after_bytes);
+ // vals.copy_to(storage_ptr + for_bytes, after_bytes);
+ // vals.pop_bytes(static_cast(after_bytes));
+ //
+ // for (auto i = static_cast(child_data.size() - 1); i > static_cast(child_index); i--)
+ // {
+ // auto& cc = child_data[i];
+ // auto bytes = c.total_value_bytes(cc.start, cc.end);
+ // vals.pop_bytes(static_cast(bytes));
+ // ops.erase(ops.begin() + cc.start, ops.begin() + cc.end);
+ // }
+ // vals.copy_to(storage_ptr, for_bytes);
+ // vals.pop_bytes(static_cast(for_bytes));
+ // for (auto i = static_cast(child_index - 1); i >= 0; i--)
+ // {
+ // auto& cc = child_data[i];
+ // auto bytes = c.total_value_bytes(cc.start, cc.end);
+ // vals.pop_bytes(static_cast(bytes));
+ // ops.erase(ops.begin() + cc.start, ops.begin() + cc.end);
+ // }
+ // ops.erase(ops.begin() + static_cast(c_node));
+ // vals.copy_from(storage_ptr, for_bytes + after_bytes);
#if BLT_DEBUG_LEVEL >= 2
if (!c.check(detail::debug::context_ptr))
{
std::cout << "Parent: " << std::endl;
- p.print(std::cout, false, true);
+ p.print(std::cout, false, false, false, static_cast(c_node));
std::cout << "Child Values:" << std::endl;
- c.print(std::cout, true, true);
+ c.print(std::cout, false, false);
std::cout << std::endl;
- BLT_ABORT("Tree Check Failed.");
+ BLT_ERROR("Failed at mutation index %lu/%lu", c_node, c.size());
+ BLT_ABORT("JUMP_FUNC Tree Check Failed.");
}
#endif
}
break;
case mutation_operator::COPY:
{
- auto& info = program.get_operator_info(ops[c_node].id());
- blt::size_t pt = -1ul;
- blt::size_t pf = -1ul;
+ auto& info = program.get_operator_info(c.get_operator(c_node).id());
+ size_t pt = -1ul;
+ size_t pf = -1ul;
for (const auto& [index, v] : blt::enumerate(info.argument_types))
{
- for (blt::size_t i = index + 1; i < info.argument_types.size(); i++)
+ for (size_t i = index + 1; i < info.argument_types.size(); i++)
{
auto& v1 = info.argument_types[i];
if (v == v1)
@@ -541,8 +473,8 @@ namespace blt::gp
if (pt == -1ul || pf == -1ul)
continue;
- blt::size_t from = 0;
- blt::size_t to = 0;
+ size_t from = 0;
+ size_t to = 0;
if (program.get_random().choice())
{
@@ -555,7 +487,7 @@ namespace blt::gp
to = pt;
}
- static thread_local tracked_vector child_data;
+ thread_local tracked_vector child_data;
child_data.clear();
c.find_child_extends(child_data, c_node, info.argument_types.size());
@@ -564,33 +496,51 @@ namespace blt::gp
auto to_index = child_data.size() - 1 - to;
auto& from_child = child_data[from_index];
auto& to_child = child_data[to_index];
- blt::size_t from_bytes = c.total_value_bytes(from_child.start, from_child.end);
- blt::size_t after_from_bytes = c.total_value_bytes(from_child.end);
- blt::size_t to_bytes = c.total_value_bytes(to_child.start, to_child.end);
- blt::size_t after_to_bytes = c.total_value_bytes(to_child.end);
- auto after_bytes = std::max(after_from_bytes, after_to_bytes);
+ thread_local tree_t copy_tree{program};
+ c.copy_subtree(tree_t::subtree_point_t{from_child.start}, from_child.end, copy_tree);
+ c.replace_subtree(tree_t::subtree_point_t{to_child.start}, to_child.end, copy_tree);
+ copy_tree.clear(program);
- auto from_ptr = get_thread_pointer_for_size(from_bytes);
- auto after_ptr = get_thread_pointer_for_size(after_bytes);
+#if BLT_DEBUG_LEVEL >= 2
+ if (!c.check(detail::debug::context_ptr))
+ {
+ std::cout << "Parent: " << std::endl;
+ p.print(std::cout, false, false);
+ std::cout << "Child Values:" << std::endl;
+ c.print(std::cout, false, false);
+ std::cout << std::endl;
+ BLT_ABORT("COPY Tree Check Failed.");
+ }
+#endif
- vals.copy_to(after_ptr, after_from_bytes);
- vals.pop_bytes(static_cast(after_from_bytes));
- vals.copy_to(from_ptr, from_bytes);
- vals.copy_from(after_ptr, after_from_bytes);
-
- vals.copy_to(after_ptr, after_to_bytes);
- vals.pop_bytes(static_cast(after_to_bytes + to_bytes));
-
- vals.copy_from(from_ptr, from_bytes);
- vals.copy_from(after_ptr, after_to_bytes);
-
- static thread_local tracked_vector op_copy;
- op_copy.clear();
- op_copy.insert(op_copy.begin(), ops.begin() + from_child.start, ops.begin() + from_child.end);
-
- ops.erase(ops.begin() + to_child.start, ops.begin() + to_child.end);
- ops.insert(ops.begin() + to_child.start, op_copy.begin(), op_copy.end());
+ // size_t from_bytes = c.total_value_bytes(from_child.start, from_child.end);
+ // size_t after_from_bytes = c.total_value_bytes(from_child.end);
+ // size_t to_bytes = c.total_value_bytes(to_child.start, to_child.end);
+ // size_t after_to_bytes = c.total_value_bytes(to_child.end);
+ //
+ // auto after_bytes = std::max(after_from_bytes, after_to_bytes);
+ //
+ // auto from_ptr = get_thread_pointer_for_size(from_bytes);
+ // auto after_ptr = get_thread_pointer_for_size(after_bytes);
+ //
+ // vals.copy_to(after_ptr, after_from_bytes);
+ // vals.pop_bytes(static_cast(after_from_bytes));
+ // vals.copy_to(from_ptr, from_bytes);
+ // vals.copy_from(after_ptr, after_from_bytes);
+ //
+ // vals.copy_to(after_ptr, after_to_bytes);
+ // vals.pop_bytes(static_cast(after_to_bytes + to_bytes));
+ //
+ // vals.copy_from(from_ptr, from_bytes);
+ // vals.copy_from(after_ptr, after_to_bytes);
+ //
+ // static thread_local tracked_vector op_copy;
+ // op_copy.clear();
+ // op_copy.insert(op_copy.begin(), ops.begin() + from_child.start, ops.begin() + from_child.end);
+ //
+ // ops.erase(ops.begin() + to_child.start, ops.begin() + to_child.end);
+ // ops.insert(ops.begin() + to_child.start, op_copy.begin(), op_copy.end());
}
break;
case mutation_operator::END:
@@ -607,11 +557,11 @@ namespace blt::gp
if (!c.check(detail::debug::context_ptr))
{
std::cout << "Parent: " << std::endl;
- p.print(std::cout, false, true);
+ p.print(std::cout, false, false);
std::cout << "Child Values:" << std::endl;
- c.print(std::cout, true, true);
+ c.print(std::cout, false, false);
std::cout << std::endl;
- BLT_ABORT("Tree Check Failed.");
+ BLT_ABORT("Advanced Mutation Tree Check Failed.");
}
#endif
diff --git a/src/tree.cpp b/src/tree.cpp
index 198064f..42906a1 100644
--- a/src/tree.cpp
+++ b/src/tree.cpp
@@ -54,7 +54,16 @@ namespace blt::gp
return "(" + std::string(program.get_typesystem().get_type(id).name()) + ")";
}
- void tree_t::print(std::ostream& out, bool print_literals, bool pretty_print, bool include_types) const
+ void tree_t::byte_only_transaction_t::move(const size_t bytes_to_move)
+ {
+ bytes = bytes_to_move;
+ data = get_thread_pointer_for_size(bytes);
+ tree.values.copy_to(data, bytes);
+ tree.values.pop_bytes(bytes);
+ }
+
+ void tree_t::print(std::ostream& out, const bool print_literals, const bool pretty_print, const bool include_types,
+ const ptrdiff_t marked_index) const
{
std::stack arguments_left;
blt::size_t indent = 0;
@@ -72,11 +81,15 @@ namespace blt::gp
copy.transfer_bytes(reversed, v.type_size());
}
}
- for (const auto& v : operations)
+ for (const auto& [i, v] : enumerate(operations))
{
auto info = m_program->get_operator_info(v.id());
const auto name = m_program->get_name(v.id()) ? m_program->get_name(v.id()).value() : "NULL";
auto return_type = get_return_type(*m_program, info.return_type, include_types);
+ if (static_cast(i) == marked_index)
+ {
+ out << "[ERROR OCCURRED HERE] -> ";
+ }
if (info.argc.argc > 0)
{
create_indent(out, indent, pretty_print) << "(";
@@ -249,10 +262,10 @@ namespace blt::gp
return {};
}
- void tree_t::copy_subtree(const subtree_point_t point, std::vector& operators, stack_allocator& stack)
+ void tree_t::copy_subtree(const subtree_point_t point, const ptrdiff_t extent, tracked_vector& operators, stack_allocator& stack)
{
const auto point_begin_itr = operations.begin() + point.pos;
- const auto point_end_itr = operations.begin() + find_endpoint(point.pos);
+ const auto point_end_itr = operations.begin() + extent;
const size_t after_bytes = accumulate_type_sizes(point_end_itr, operations.end());
@@ -395,8 +408,8 @@ namespace blt::gp
{
if (v.get_flags().is_ephemeral() && v.has_ephemeral_drop())
{
- auto& pointer = other_tree.values.access_pointer(copy_bytes, v.type_size());
- --*pointer;
+ auto& pointer = other_tree.values.access_pointer_forward(copy_bytes, v.type_size());
+ ++*pointer;
}
copy_bytes += v.type_size();
}
@@ -442,7 +455,7 @@ namespace blt::gp
ptrdiff_t tree_t::insert_subtree(const subtree_point_t point, tree_t& other_tree)
{
const size_t after_bytes = accumulate_type_sizes(operations.begin() + point.pos, operations.end());
- auto move = temporary_move(after_bytes);
+ byte_only_transaction_t transaction{*this, after_bytes};
auto insert = operations.begin() + point.pos;
size_t bytes = 0;
@@ -464,14 +477,6 @@ namespace blt::gp
return static_cast(point.pos + other_tree.size());
}
- tree_t::after_bytes_data_t tree_t::temporary_move(const size_t bytes)
- {
- const auto data = get_thread_pointer_for_size(bytes);
- values.copy_to(data, bytes);
- values.pop_bytes(bytes);
- return after_bytes_data_t{*this, data, bytes};
- }
-
ptrdiff_t tree_t::find_endpoint(ptrdiff_t start) const
{
@@ -514,7 +519,7 @@ namespace blt::gp
bool tree_t::check(void* context) const
{
- blt::size_t bytes_expected = 0;
+ size_t bytes_expected = 0;
const auto bytes_size = values.size().total_used_bytes;
for (const auto& op : operations)
@@ -525,47 +530,60 @@ namespace blt::gp
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");
+ BLT_ERROR_STREAM << "Stack state: " << values.size() << "\n";
+ BLT_ERROR("Child tree bytes %ld vs expected %ld, difference: %ld", bytes_size, bytes_expected,
+ static_cast(bytes_expected) - static_cast(bytes_size));
+ BLT_ERROR("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;
-
size_t total_produced = 0;
size_t total_consumed = 0;
+ size_t index = 0;
- for (const auto& operation : iterate(operations).rev())
+ try
{
- if (operation.is_value())
+ // copy the initial values
+ evaluation_context results{};
+
+ auto value_stack = values;
+ auto& values_process = results.values;
+
+ for (const auto& operation : iterate(operations).rev())
{
- value_stack.transfer_bytes(values_process, operation.type_size());
- total_produced += operation.type_size();
- continue;
+ ++index;
+ if (operation.is_value())
+ {
+ value_stack.transfer_bytes(values_process, operation.type_size());
+ total_produced += operation.type_size();
+ continue;
+ }
+ auto& info = m_program->get_operator_info(operation.id());
+ for (auto& arg : info.argument_types)
+ total_consumed += m_program->get_typesystem().get_type(arg).size();
+ m_program->get_operator_info(operation.id()).func(context, values_process, values_process);
+ total_produced += m_program->get_typesystem().get_type(info.return_type).size();
+ }
+
+ const auto v1 = results.values.bytes_in_head();
+ const auto v2 = static_cast(operations.front().type_size());
+
+ m_program->get_destroy_func(operations.front().id())(detail::destroy_t::RETURN, results.values);
+ if (v1 != v2)
+ {
+ const 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;
}
- auto& info = m_program->get_operator_info(operation.id());
- for (auto& arg : info.argument_types)
- total_consumed += m_program->get_typesystem().get_type(arg).size();
- m_program->get_operator_info(operation.id()).func(context, values_process, values_process);
- total_produced += m_program->get_typesystem().get_type(info.return_type).size();
}
-
- const auto v1 = results.values.bytes_in_head();
- const auto v2 = static_cast(operations.front().type_size());
-
- m_program->get_destroy_func(operations.front().id())(detail::destroy_t::RETURN, results.values);
- if (v1 != v2)
+ catch (std::exception& e)
{
- const auto vd = std::abs(v1 - v2);
- BLT_ERROR("found %ld bytes expected %ld bytes, total difference: %ld", v1, v2, vd);
+ BLT_ERROR("Exception occurred \"%s\"", e.what());
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)));
+ BLT_ERROR("We failed at index %lu", index);
return false;
}
return true;
@@ -611,8 +629,8 @@ namespace blt::gp
// BLT_TRACE(ptr->load());
// if (*ptr == 0)
// {
- // BLT_TRACE("Deleting pointers!");
- // delete ptr.get();
+ // BLT_TRACE("Deleting pointers!");
+ // delete ptr.get();
// }
}
total_bytes += op.type_size();
@@ -622,6 +640,16 @@ namespace blt::gp
values.reset();
}
+ void tree_t::insert_operator(const size_t index, const op_container_t& container)
+ {
+ if (container.get_flags().is_ephemeral())
+ {
+ byte_only_transaction_t move{*this, total_value_bytes(index)};
+ handle_operator_inserted(container);
+ }
+ operations.insert(operations.begin() + static_cast(index), container);
+ }
+
tree_t::subtree_point_t tree_t::subtree_from_point(ptrdiff_t point) const
{
return {point, m_program->get_operator_info(operations[point].id()).return_type};
@@ -631,11 +659,29 @@ namespace blt::gp
{
if (!return_type)
return_type = m_program->get_operator_info(new_id).return_type;
+ byte_only_transaction_t move_data{*this};
+ if (operations[point].is_value())
+ {
+ const size_t after_bytes = accumulate_type_sizes(operations.begin() + static_cast(point) + 1, operations.end());
+ move_data.move(after_bytes);
+ if (operations[point].get_flags().is_ephemeral() && operations[point].has_ephemeral_drop())
+ {
+ const auto& ptr = values.access_pointer(operations[point].type_size(), operations[point].type_size());
+ --*ptr;
+ if (*ptr == 0)
+ {
+ // TODO:
+ }
+ }
+ values.pop_bytes(operations[point].type_size());
+ }
operations[point] = {
m_program->get_typesystem().get_type(*return_type).size(),
new_id,
m_program->is_operator_ephemeral(new_id),
m_program->get_operator_flags(new_id)
};
+ if (operations[point].get_flags().is_ephemeral())
+ handle_operator_inserted(operations[point]);
}
}