Wrote RBTree. The real pointer-based rbtree. The fake one (with buffers) requires purging. But I have yet to debug the stupid delete operation
This commit is contained in:
parent
310b56e372
commit
704930efcc
@ -54,6 +54,7 @@ add_executable(codegen_l1_5 src/l1_5/anne/codegen.c)
|
||||
#target_link_libraries(3_render_test -lwayland-client -lm -lvulkan -lxkbcommon)
|
||||
|
||||
#add_executable(l2t0_2 src/l2/tests/data_structures/t0_2.c) // todo: I will get back
|
||||
add_executable(l2t0_3 src/l2/tests/data_structures/t0_3.c)
|
||||
add_executable(l2t2 src/l2/tests/data_structures/t2.c)
|
||||
|
||||
#add_executable(l2t0 src/l2/tests/data_structures/t0.c)
|
||||
|
||||
1
Makefile
1
Makefile
@ -60,7 +60,6 @@ out/l2/t0: src/l2/tests/data_structures/t0.c $(HEADERS_gen_l1_5)
|
||||
|
||||
.PHONY: run_l2_t0
|
||||
run_l2_t0: out/l2/t0
|
||||
mkdir -p src/l2/tests/data_structures/GRAPHS
|
||||
cd src/l2/tests/data_structures && ../../../../out/l2/t0
|
||||
|
||||
out/l2/r0: src/l2/tests/r0/r0.c $(HEADERS_src_l2) $(l_wl_protocols)
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "margaret/margaret_misc.h"
|
||||
#include "marie/graphics_geom.h"
|
||||
#include "liza.h"
|
||||
#include "codegen_from_l1_5.h"
|
||||
#include "embassy_l1_5.h"
|
||||
#include "margaret/png_pixel_masses.h"
|
||||
|
||||
int main() {
|
||||
|
||||
@ -10,7 +10,7 @@ void generate_l1_headers_for_l1_5() {
|
||||
SpanU8 ns = cstr("embassy_l1_5");
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("NamedVariableRecordRef"), false, true);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("NamedMethodSignatureRecordRef"), false, true);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("BuffRBTreeNode"), true, false);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("BufRBTreeNode"), true, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -38,6 +38,10 @@ void generate_headers_for_r0_r1_r2_r3() {
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("I_FishNode"), true, false);
|
||||
generate_eve_span_company_for_primitive(l, ns, cstr("J_AlphaVertex"), true, false);
|
||||
}
|
||||
// mkdir_nofail("l1/eve/ds_test");
|
||||
// { /* This structure is needed for testing purposes only */
|
||||
// generate_eve_span_company_for_primitive(l, cstr("ds_test"), cstr("RefRBTreeNode_S64"), true, false);
|
||||
// }
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -85,6 +85,35 @@ NODISCARD VecU8 prepend_spaces_to_SpanU8_lines(SpanU8 lines, int tabulation){
|
||||
return res;
|
||||
}
|
||||
|
||||
#define EVE_MESSAGE "/* Automatically generated file. Don't edit it.\n * Don't include it in more than one place */\n\n"
|
||||
void generate_SOME_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, VecU8 body, VecU8 name){
|
||||
VecU8 text = VecU8_fmt("/* Automatically generated file. Don't edit it.\n"
|
||||
"* Don't include it in more than one place */\n\n%v", body);
|
||||
VecU8 nt_path = VecU8_fmt("%s/eve/%s/%v.h%c", layer, bonus_ns, name, 0);
|
||||
write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text));
|
||||
VecU8_drop(nt_path);
|
||||
VecU8_drop(text);
|
||||
}
|
||||
|
||||
void generate_SOME_templ_inst_guarded_header(SpanU8 layer, SpanU8 bonus_ns, VecU8 all_dependencies, VecU8 body, VecU8 name){
|
||||
assert(layer.len > 1);
|
||||
VecU8 path = VecU8_fmt("%s/%s%s%v.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), name);
|
||||
GeneratedHeader head = begin_header(VecU8_to_span(&path));
|
||||
VecU8_drop(path);
|
||||
VecU8_append_vec(&head.result, all_dependencies);
|
||||
VecU8_append_span(&head.result, cstr("\n"));
|
||||
VecU8_append_vec(&head.result, body);
|
||||
finish_header(head);
|
||||
}
|
||||
|
||||
/* Assumed we are at some_layer/bonus_ns/header.h header */
|
||||
NODISCARD VecU8 codegen_include_relative_to_root(SpanU8 bonus_ns, SpanU8 abs_path){
|
||||
VecU8 res = vcstr("#include \"../../");
|
||||
int to_my_layer = get_number_of_parts_in_header_namespace(bonus_ns);
|
||||
for (int i = 0; i < to_my_layer; i++)
|
||||
VecU8_append_span(&res, cstr("../"));
|
||||
VecU8_append_span(&res, abs_path);
|
||||
VecU8_append_span(&res, cstr("\"\n"));
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -70,7 +70,7 @@ float pow2f(float x) {
|
||||
}
|
||||
|
||||
bool U64_is_2pow(U64 n){
|
||||
return n > 0 && (n & (n - 1) == 0);
|
||||
return n > 0 && ((n & (n - 1)) == 0);
|
||||
}
|
||||
|
||||
U8 U64_2pow_log(U64 n){
|
||||
|
||||
@ -2,13 +2,20 @@
|
||||
#define prototype1_src_l1_5_anne_l1_5_templ_very_base_h
|
||||
|
||||
#include "../codegen/buff_rbtree_set_map_template_inst.h"
|
||||
#include "../codegen/rbtree_set_map_template_inst.h"
|
||||
|
||||
void generate_l1_5_template_instantiation_for_base_types(){
|
||||
SpanU8 l = cstr("l1_5"), ns = cstr("");
|
||||
generate_buff_rbtree_Set_templ_inst_guarded_header(l, ns,cstr("#include \"../l1/VecAndSpan_U64.h\""),
|
||||
generate_buf_rbtree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../l1/VecAndSpan_U64.h\""),
|
||||
(set_instantiation_op){.T = cstr("U64"), .t_integer = true});
|
||||
generate_buff_rbtree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../l1/VecAndSpan_S64.h\""),
|
||||
generate_buf_rbtree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../l1/VecAndSpan_S64.h\""),
|
||||
(set_instantiation_op){.T = cstr("S64"), .t_integer = true});
|
||||
|
||||
// l1/core/int_primitives is included in l1_5/core/rb_tree_node.h, hence no additional dependencies needed
|
||||
generate_rbtree_Set_templ_inst_guarded_header(l, ns, cstr(""), (set_instantiation_op){
|
||||
.T = cstr("U64"), .t_integer = true }, true);
|
||||
generate_rbtree_Set_templ_inst_guarded_header(l, ns, cstr(""), (set_instantiation_op){
|
||||
.T = cstr("S64"), .t_integer = true }, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -9,14 +9,14 @@ void generate_l1_5_template_instantiations_for_margaret(){
|
||||
mkdir_nofail("l1_5/eve/margaret");
|
||||
|
||||
/* For MargaretMemAllocator */
|
||||
generate_buff_rbtree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){
|
||||
generate_buf_rbtree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){
|
||||
.T = cstr("MargaretFreeMemSegment"),
|
||||
.t_primitive = true,
|
||||
.alternative_less = cstr("MargaretFreeMemSegment_less"),
|
||||
.alternative_equal = cstr("MargaretFreeMemSegment_equal"),
|
||||
.alternative_comp_set_name_embed = cstr("Len"),
|
||||
});
|
||||
generate_buff_rbtree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){
|
||||
generate_buf_rbtree_Set_templ_inst_eve_header(l, ns, (set_instantiation_op){
|
||||
.T = cstr("MargaretFreeMemSegment"),
|
||||
.t_primitive = true,
|
||||
/* comparison takes additional U8 parameter */
|
||||
@ -25,12 +25,12 @@ void generate_l1_5_template_instantiations_for_margaret(){
|
||||
.alternative_comp_set_name_embed = cstr("LenRespAlign"),
|
||||
.guest_data_T = cstr("U8"),
|
||||
});
|
||||
generate_buff_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
|
||||
.K = cstr("U64"), .k_integer = true, .V = cstr("MargaretMemoryOccupation"), /* MargaretMemoryOccupation is not primitive */
|
||||
});
|
||||
generate_buff_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
|
||||
.K = cstr("U64"), .k_integer = true, .V = cstr("MargaretBufferOccupationSubBuffer"), .v_primitive = true,
|
||||
});
|
||||
// generate_buf_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
|
||||
// .K = cstr("U64"), .k_integer = true, .V = cstr("MargaretMemoryOccupation"), /* MargaretMemoryOccupation is not primitive */
|
||||
// });
|
||||
// generate_buf_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
|
||||
// .K = cstr("U64"), .k_integer = true, .V = cstr("MargaretBufferOccupationSubBuffer"), .v_primitive = true,
|
||||
// });
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -174,7 +174,7 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
|
||||
"}\n\n", set, set, TT));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"U64 %s_find(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */
|
||||
"U64 %s_find(const %s* self, %v key) {\n" /* set, set, taking_ref_k_argument */
|
||||
SPACE "U64 cur = self->root;\n"
|
||||
SPACE "while (cur != 0 && %v) {\n" /* key reference not equal cur element */
|
||||
SPACE SPACE "if (%v) {\n" /* key reference less than cur element */
|
||||
@ -202,11 +202,12 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
|
||||
TT, op.guest_data_T.len > 0 ? cstr(", .guest = self->guest") : cstr("")));
|
||||
}
|
||||
|
||||
// todo: move to common code
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"U64 %s_find_next(const %s* self, U64 x){\n"
|
||||
SPACE "assert(x != 0 && x < self->tree.len);\n"
|
||||
SPACE "if (self->tree.buf[x].right != 0)\n"
|
||||
SPACE SPACE "return RBTree_minimum_in_subtree(self->tree.buf, self->tree.buf[x].right);\n"
|
||||
SPACE SPACE "return BufRBTree_minimum_in_subtree(self->tree.buf, self->tree.buf[x].right);\n"
|
||||
SPACE "while (true) {\n"
|
||||
SPACE SPACE "U64 p = self->tree.buf[x].parent;\n"
|
||||
SPACE SPACE "if (p == 0)\n"
|
||||
@ -217,6 +218,7 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
|
||||
SPACE "}\n"
|
||||
"}\n\n", set, set));
|
||||
|
||||
// todo: move to comon code
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"U64 %s_find_prev(const %s* self, U64 x){\n"
|
||||
SPACE "assert(x != 0 && x < self->tree.len);\n"
|
||||
@ -338,9 +340,9 @@ void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
|
||||
));
|
||||
}
|
||||
|
||||
/* Generates methods _insert() _pop_substitute() _erase_substitute() for SetT
|
||||
* Takes ownership of strings Tc, Fc */
|
||||
void codegen_append_buff_rbtree_map__insert_kind_method(
|
||||
|
||||
// todo: no need for a separate method. Just write _try_insert() and derive all the shit from it
|
||||
void codegen_append_buf_rbtree_map__insert_kind_method(
|
||||
VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 method_name, VecU8 RT, VecU8 Tc, VecU8 Fc
|
||||
){
|
||||
VecU8 Tc_root = prepend_spaces_to_SpanU8_lines(VecU8_to_span(&Tc), 2);
|
||||
@ -350,6 +352,8 @@ void codegen_append_buff_rbtree_map__insert_kind_method(
|
||||
VecU8_drop(Tc);
|
||||
VecU8_drop(Fc);
|
||||
|
||||
// todo: fix it. No buffered rbttrees here. Only my pure poijter basa[ks tree
|
||||
|
||||
VecU8 line_that_appends_new_el_to_el_vec = op.V.len > 0 ?
|
||||
VecU8_fmt("VecKVP%sTo%s_append(&self->el, (KVP%sTo%s){.key = key, .value = value});", op.K, op.V, op.K, op.V) :
|
||||
VecU8_fmt("Vec%s_append(&self->el, key);", op.K);
|
||||
@ -412,6 +416,7 @@ void codegen_append_buff_rbtree_map__insert_kind_method(
|
||||
VecU8_drop(line_that_appends_new_el_to_el_vec);
|
||||
}
|
||||
|
||||
// todo: no need for a separate function. Do just like in normal RBTree
|
||||
void codegen_append_buff_rbtree_map__method_empty_index_erase(VecU8* res, SpanU8 set){
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"/* UNSAFE. Use when you dropped the symbol that is about to be deleted */\n"
|
||||
@ -452,6 +457,7 @@ void codegen_append_buff_rbtree_map__method_empty_index_erase(VecU8* res, SpanU8
|
||||
set, set));
|
||||
}
|
||||
|
||||
// todo: no need for a separate method.
|
||||
void codegen_append_buff_rbtree_map__erase_kind_method(
|
||||
VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 method_name, VecU8 RT,
|
||||
VecU8 Fc, VecU8 Tc_cur_available, VecU8 Tc_returning
|
||||
@ -538,7 +544,7 @@ void codegen_append_buff_rbtree_map__method_at(VecU8* res, map_instantiation_op
|
||||
));
|
||||
}
|
||||
|
||||
NODISCARD VecU8 get_name_of_buff_rbtree_set_structure(set_instantiation_op op){
|
||||
NODISCARD VecU8 get_name_of_buf_rbtree_set_structure(set_instantiation_op op){
|
||||
if (op.alternative_comp_set_name_embed.len)
|
||||
return VecU8_fmt("BuffRBTreeBy%s_Set%s", op.alternative_comp_set_name_embed, op.T);
|
||||
return VecU8_fmt("BuffRBTree_Set%s", op.T);
|
||||
@ -547,10 +553,10 @@ NODISCARD VecU8 get_name_of_buff_rbtree_set_structure(set_instantiation_op op){
|
||||
/* src/l1_5/core/rb_tree_node.h is a dependency of all instantiations of rb_tree_set template
|
||||
* Don't forget to include them
|
||||
* */
|
||||
NODISCARD VecU8 generate_buff_rbtree_Set_template_instantiation(set_instantiation_op op){
|
||||
NODISCARD VecU8 generate_buf_rbtree_Set_template_instantiation(set_instantiation_op op){
|
||||
set_instantiation_op_fix(&op);
|
||||
VecU8 res = VecU8_new();
|
||||
VecU8 g_set = get_name_of_buff_rbtree_set_structure(op);
|
||||
VecU8 g_set = get_name_of_buf_rbtree_set_structure(op);
|
||||
SpanU8 set = VecU8_to_span(&g_set);
|
||||
|
||||
map_instantiation_op map_op = {.K = op.T,
|
||||
@ -564,7 +570,7 @@ NODISCARD VecU8 generate_buff_rbtree_Set_template_instantiation(set_instantiatio
|
||||
|
||||
/* Method _insert() does not try to replace the existing element with equal key,
|
||||
* it returns true if insertion was done, false if collision happened and key was not inserted */
|
||||
codegen_append_buff_rbtree_map__insert_kind_method(&res, map_op, set, cstr("insert"), vcstr("bool"),
|
||||
codegen_append_buf_rbtree_map__insert_kind_method(&res, map_op, set, cstr("insert"), vcstr("bool"),
|
||||
vcstr("return true;\n"),
|
||||
op.t_primitive ?
|
||||
vcstr("return false;\n") :
|
||||
@ -592,32 +598,18 @@ NODISCARD VecU8 generate_buff_rbtree_Set_template_instantiation(set_instantiatio
|
||||
}
|
||||
|
||||
|
||||
void generate_buff_rbtree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, set_instantiation_op op) {
|
||||
VecU8 text = vcstr(EVE_MESSAGE);
|
||||
VecU8_append_vec(&text, generate_buff_rbtree_Set_template_instantiation(op));
|
||||
VecU8 nt_path = VecU8_fmt("%s/eve/%s/%v.h%c", layer, bonus_ns, get_name_of_buff_rbtree_set_structure(op), 0);
|
||||
write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text));
|
||||
VecU8_drop(nt_path);
|
||||
VecU8_drop(text);
|
||||
void generate_buf_rbtree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, set_instantiation_op op) {
|
||||
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
|
||||
generate_buf_rbtree_Set_template_instantiation(op), get_name_of_buf_rbtree_set_structure(op));
|
||||
}
|
||||
|
||||
void generate_buff_rbtree_Set_templ_inst_guarded_header(
|
||||
void generate_buf_rbtree_Set_templ_inst_guarded_header(
|
||||
SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, set_instantiation_op op
|
||||
){
|
||||
assert(layer.len > 1);
|
||||
VecU8 path = VecU8_fmt("%s/%s%s%v.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""),
|
||||
get_name_of_buff_rbtree_set_structure(op));
|
||||
GeneratedHeader head = begin_header(VecU8_to_span(&path));
|
||||
VecU8_drop(path);
|
||||
VecU8_append_span(&head.result, cstr("#include \"../../"));
|
||||
int to_my_layer = get_number_of_parts_in_header_namespace(bonus_ns);
|
||||
for (int i = 0; i < to_my_layer; i++)
|
||||
VecU8_append_span(&head.result, cstr("../"));
|
||||
VecU8_append_span(&head.result, cstr("src/l1_5/core/buff_rb_tree_node.h\"\n"));
|
||||
VecU8_append_span(&head.result, dependencies);
|
||||
VecU8_append_span(&head.result, cstr("\n\n"));
|
||||
VecU8_append_vec(&head.result, generate_buff_rbtree_Set_template_instantiation(op));
|
||||
finish_header(head);
|
||||
VecU8 all_dependencies = VecU8_fmt("%v%s",
|
||||
codegen_include_relative_to_root(bonus_ns, cstr("src/l1_5/core/buff_rb_tree_node.h")), dependencies);
|
||||
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, all_dependencies,
|
||||
generate_buf_rbtree_Set_template_instantiation(op), get_name_of_buf_rbtree_set_structure(op));
|
||||
}
|
||||
|
||||
/* ========= Now we add Map<K, V> into the picture ======== */
|
||||
@ -637,31 +629,31 @@ void codegen_append_buff_rbtree_map__method_at_iter(VecU8* res, map_instantiatio
|
||||
op.k_integer ? cstr("") : cstr("&"), op.v_integer ? cstr("") : cstr("&")));
|
||||
}
|
||||
|
||||
NODISCARD VecU8 get_name_of_buff_rbtree_map_structure(map_instantiation_op op){
|
||||
NODISCARD VecU8 get_name_of_buf_rbtree_map_structure(map_instantiation_op op){
|
||||
if (op.alternative_comp_map_name_embed.len)
|
||||
return VecU8_fmt("BuffRBTreeBy%s_Map%sTo%s", op.alternative_comp_map_name_embed, op.K, op.V);
|
||||
return VecU8_fmt("BuffRBTree_Map%sTo%s", op.K, op.V);
|
||||
}
|
||||
|
||||
NODISCARD VecU8 generate_buff_rbtree_Map_template_instantiation(map_instantiation_op op){
|
||||
NODISCARD VecU8 generate_buf_rbtree_Map_template_instantiation(map_instantiation_op op){
|
||||
assert(op.V.len > 0);
|
||||
map_instantiation_op_fix(&op);
|
||||
VecU8 res = VecU8_new();
|
||||
VecU8 map_g = get_name_of_buff_rbtree_map_structure(op);
|
||||
VecU8 map_g = get_name_of_buf_rbtree_map_structure(op);
|
||||
SpanU8 map = VecU8_to_span(&map_g);
|
||||
|
||||
VecU8 kvp_g = VecU8_fmt("KVP%sTo%s", op.K, op.V);
|
||||
codegen_append_buff_rbtree_map__structure_and_simplest_methods(&res, op, map, VecU8_to_span(&kvp_g));
|
||||
VecU8_drop(kvp_g);
|
||||
|
||||
codegen_append_buff_rbtree_map__insert_kind_method(&res, op, map, cstr("insert"), vcstr("bool"),
|
||||
codegen_append_buf_rbtree_map__insert_kind_method(&res, op, map, cstr("insert"), vcstr("bool"),
|
||||
vcstr("return true;\n"),
|
||||
VecU8_fmt("%v%v" "return false;\n",
|
||||
op.k_primitive ? vcstr("") : VecU8_fmt("%s_drop(key);\n", op.K),
|
||||
op.v_primitive ? vcstr("") : VecU8_fmt("%s_drop(value);\n", op.V)));
|
||||
|
||||
|
||||
codegen_append_buff_rbtree_map__insert_kind_method(&res, op, map, cstr("erase_substitute"), vcstr("bool"),
|
||||
codegen_append_buf_rbtree_map__insert_kind_method(&res, op, map, cstr("erase_substitute"), vcstr("bool"),
|
||||
vcstr("return true;\n"),
|
||||
VecU8_fmt("%v%v"
|
||||
"self->el.buf[cur - 1].key = key;\n"
|
||||
@ -671,7 +663,7 @@ NODISCARD VecU8 generate_buff_rbtree_Map_template_instantiation(map_instantiatio
|
||||
op.k_primitive ? vcstr("") : VecU8_fmt("%s_drop(self->el.buf[cur - 1].value);\n", op.V)
|
||||
));
|
||||
|
||||
codegen_append_buff_rbtree_map__insert_kind_method(&res, op, map, cstr("pop_substitute"),
|
||||
codegen_append_buf_rbtree_map__insert_kind_method(&res, op, map, cstr("pop_substitute"),
|
||||
VecU8_fmt("Option%s", op.V),
|
||||
VecU8_fmt("return None_%s();\n", op.V),
|
||||
VecU8_fmt(
|
||||
@ -711,32 +703,18 @@ NODISCARD VecU8 generate_buff_rbtree_Map_template_instantiation(map_instantiatio
|
||||
return res;
|
||||
}
|
||||
|
||||
void generate_buff_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op) {
|
||||
VecU8 text = vcstr(EVE_MESSAGE);
|
||||
VecU8_append_vec(&text, generate_buff_rbtree_Map_template_instantiation(op));
|
||||
VecU8 nt_path = VecU8_fmt("%s/eve/%s/%v.h%c", layer, bonus_ns, get_name_of_buff_rbtree_map_structure(op), 0);
|
||||
write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text));
|
||||
VecU8_drop(nt_path);
|
||||
VecU8_drop(text);
|
||||
void generate_buf_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op) {
|
||||
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
|
||||
generate_buf_rbtree_Map_template_instantiation(op), get_name_of_buf_rbtree_map_structure(op));
|
||||
}
|
||||
|
||||
void generate_buff_rbtree_Map_templ_inst_guarded_header(
|
||||
void generate_buf_rbtree_Map_templ_inst_guarded_header(
|
||||
SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, map_instantiation_op op
|
||||
){
|
||||
assert(layer.len > 1);
|
||||
VecU8 path = VecU8_fmt("%s/%s%s%v.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""),
|
||||
get_name_of_buff_rbtree_map_structure(op));
|
||||
GeneratedHeader head = begin_header(VecU8_to_span(&path));
|
||||
VecU8_drop(path);
|
||||
VecU8_append_span(&head.result, cstr("#include \"../../"));
|
||||
int to_my_layer = get_number_of_parts_in_header_namespace(bonus_ns);
|
||||
for (int i = 0; i < to_my_layer; i++)
|
||||
VecU8_append_span(&head.result, cstr("../"));
|
||||
VecU8_append_span(&head.result, cstr("src/l1_5/core/buff_rb_tree_node.h\"\n"));
|
||||
VecU8_append_span(&head.result, dependencies);
|
||||
VecU8_append_span(&head.result, cstr("\n\n"));
|
||||
VecU8_append_vec(&head.result, generate_buff_rbtree_Map_template_instantiation(op));
|
||||
finish_header(head);
|
||||
VecU8 all_dependencies = VecU8_fmt("%v%s",
|
||||
codegen_include_relative_to_root(bonus_ns, cstr("src/l1_5/core/buff_rb_tree_node.h")), dependencies);
|
||||
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, all_dependencies,
|
||||
generate_buf_rbtree_Map_template_instantiation(op), get_name_of_buf_rbtree_map_structure(op));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -12,66 +12,432 @@ NODISCARD VecU8 codegen_rbtree__node_structure(map_instantiation_op op){
|
||||
VecU8 node_g = codegen_rbtree__node_struct_name(op);
|
||||
SpanU8 node = VecU8_to_span(&node_g);
|
||||
VecU8 res = VecU8_fmt(
|
||||
"typedef struct %s %s;\n\n" /* node, node */
|
||||
"struct {\n"
|
||||
SPACE "%s* left;\n" /* node */
|
||||
SPACE "%s* right;\n" /* node */
|
||||
SPACE "%s* parent;\n" /* node */
|
||||
SPACE "int color;\n"
|
||||
SPACE "%v;\n" /* Key key[] / KVP w[] */
|
||||
"} %s;\n\n",
|
||||
node, node, node, node, node,
|
||||
op.V.len > 0 ? VecU8_fmt("KVP%sTo%s w[]", op.K, op.V) : VecU8_fmt("%s key[]", op.K),
|
||||
"typedef struct {\n"
|
||||
SPACE "RBTreeNode base;\n"
|
||||
SPACE "%s key;\n" /* op.K*/
|
||||
"" /* "" / op.V value; */
|
||||
"} %s;\n\n", /* node */
|
||||
op.K, op.V.len > 0 ? VecU8_fmt(SPACE "%s value;\n", op.V) : vcstr(""),
|
||||
node);
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"%s* %s_minimum_in_subtree(const %s* x, const %s* NIL) {\n"
|
||||
SPACE "assert(x != NIL);\n"
|
||||
SPACE ""
|
||||
"}\n"));
|
||||
VecU8_drop(node_g);
|
||||
return res;
|
||||
}
|
||||
|
||||
NODISCARD VecU8 codegen_rbtree_map__key_of_cur_el(map_instantiation_op op){
|
||||
return VecU8_fmt("((%v *)cur)->key", codegen_rbtree__node_struct_name(op));
|
||||
}
|
||||
|
||||
/* Assuming A nd B are passed as intended */
|
||||
NODISCARD VecU8 codegen_rbtree_map__less(map_instantiation_op op, VecU8 A, VecU8 B){
|
||||
if (op.guest_data_T.len > 0) {
|
||||
assert(op.alternative_equal.len > 0);
|
||||
return VecU8_fmt("%s(%v, %v, self->guest)", op.alternative_less, A, B);
|
||||
}
|
||||
if (op.alternative_equal.len > 0)
|
||||
return VecU8_fmt("%s(%v, %v)", op.alternative_less, A, B);
|
||||
if (op.k_integer)
|
||||
return VecU8_fmt("%v < %v", A, B);
|
||||
return VecU8_fmt("%s_less_%s(%v %v)", op.K, op.K, A, B);
|
||||
}
|
||||
|
||||
NODISCARD VecU8 codegen_rbtree_map__exp_passing_key_ref(map_instantiation_op op){
|
||||
return op.k_integer ? vcstr("key") : vcstr("&key");
|
||||
}
|
||||
|
||||
NODISCARD VecU8 codegen_rbtree_map__exp_passing_cur_key(map_instantiation_op op){
|
||||
return VecU8_fmt("%s" "((%v*)cur)->key", op.k_integer ? cstr("") : cstr("&"), codegen_rbtree__node_struct_name(op));
|
||||
}
|
||||
|
||||
|
||||
NODISCARD VecU8 codegen_rbtree_map__taking_ref_k_argument(map_instantiation_op op){
|
||||
return op.k_integer ? VecU8_from_span(op.K) : VecU8_fmt("const %s*", op.K);
|
||||
}
|
||||
|
||||
NODISCARD VecU8 codegen_rbtree_map__taking_t_argument(map_instantiation_op op){
|
||||
return op.V.len > 0 ? VecU8_fmt("%s key, %s value", op.K, op.V) : VecU8_fmt("%s key", op.K);
|
||||
}
|
||||
|
||||
void codegen_append_rbtree_map__structure_and_simplest_methods(
|
||||
VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 TT
|
||||
){
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "RBTreeNode_%s* root;\n" /* TT */
|
||||
SPACE "RBTreeNode_%s* NIL;\n" /* TT */
|
||||
SPACE "RBTreeNode* root;\n"
|
||||
SPACE "RBTreeNode* NIL;\n"
|
||||
"%v" /* "" / guest field */
|
||||
"} %s;\n\n", TT, TT,
|
||||
"} %s;\n\n",
|
||||
op.guest_data_T.len == 0 ? vcstr("") : VecU8_fmt("%s guest;\n", op.guest_data_T),
|
||||
set));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"NODISCARD %s %s_new(" "%v" ") {\n" /* set, set, "" / GT guest */
|
||||
SPACE "RBTreeNode_%s* NIL = (RBTreeNode_%s*)safe_malloc(sizeof(RBTreeNode_%s));\n" /* TT, TT, TT*/
|
||||
/* Only color field initialization is important (should be 0) */
|
||||
SPACE "RBTreeNode* NIL = (RBTreeNode*)safe_calloc(1, sizeof(RBTreeNode));\n"
|
||||
SPACE "return (%s){.root = NIL, .NIL = NIL" "%s" "};\n" /* set, "" / , .guest = guest */
|
||||
"}\n\n",
|
||||
set, set, op.guest_data_T.len == 0 ? vcstr("") : VecU8_fmt("%s guest", op.guest_data_T),
|
||||
TT, TT, TT,
|
||||
set, op.guest_data_T.len == 0 ? cstr("") : cstr(", .guest = guest")));
|
||||
|
||||
// todo: figure out mutability restrictions shit later
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"NODISCARD %s %s_drop(%s self) {\n"));
|
||||
"RBTreeNode_%s* %s_find_min(const %s* self) {\n" /* TT, set, set */
|
||||
SPACE "if (self->root == self->NIL)\n"
|
||||
SPACE SPACE "return NULL;\n"
|
||||
SPACE "return (RBTreeNode_%s*)RBTreeNode_minimum_in_subtree(self->root, self->NIL);\n" /* TT */
|
||||
"}\n\n", TT, set, set, TT));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"RBTreeNode_%s* %s_find_max(const %s* self) {\n" /* TT, set, set */
|
||||
SPACE "if (self->root == self->NIL)\n"
|
||||
SPACE SPACE "return NULL;\n"
|
||||
SPACE "return (RBTreeNode_%s*)RBTreeNode_maximum_in_subtree(self->root, self->NIL);\n" /* TT */
|
||||
"}\n\n", TT, set, set, TT));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"RBTreeNode_%s* %s_find_next(const %s* self, RBTreeNode_%s* x){\n" /* TT, set, set, TT */
|
||||
SPACE "return (RBTreeNode_%s *)RBTreeNode_find_next((RBTreeNode*)x, self->NIL);\n" /* TT */
|
||||
"}\n\n", TT, set, set, TT, TT));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"RBTreeNode_%s* %s_find_prev(const %s* self, RBTreeNode_%s* x){\n" /* TT, set, set, TT */
|
||||
SPACE "return (RBTreeNode_%s *)RBTreeNode_find_prev((RBTreeNode*)x, self->NIL);\n" /* TT */
|
||||
"}\n\n", TT, set, set, TT, TT));
|
||||
|
||||
/* Here we read and write something to ->left, ->right field of NIL sentinel node.
|
||||
* These fields are correct pointers (NULL), so everything is ok */
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"void %s_drop(%s self){\n" /* set, set */
|
||||
SPACE "RBTreeNode* cur = self.root;\n"
|
||||
SPACE "while (cur != self.NIL){\n"
|
||||
SPACE SPACE "if (cur->left != self.NIL) {\n"
|
||||
SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE "} else if (cur->right != self.NIL) {\n"
|
||||
SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
/* This is actually safe, although cur->parent may be self.NIL */
|
||||
SPACE SPACE SPACE "if (cur->parent->left == cur)\n"
|
||||
SPACE SPACE SPACE SPACE "cur->parent->left = self.NIL;\n"
|
||||
SPACE SPACE SPACE "else"
|
||||
SPACE SPACE SPACE SPACE "cur->parent->right = self.NIL;\n"
|
||||
SPACE SPACE SPACE "RBTreeNode* parent = cur->parent;\n"
|
||||
"%v" /* "" / tabulation op.K_drop((RBTreeNode_TT*)cur->key */
|
||||
"%v" /* "" / tabulation op.V_drop((RBTreeNode_TT*)cur->value */
|
||||
SPACE SPACE SPACE "free((void*)cur);\n"
|
||||
SPACE SPACE SPACE "cur = parent;\n"
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "free(self.NIL);\n"
|
||||
"}\n\n", set, set,
|
||||
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_TT*)cur)->key);\n", op.K, TT),
|
||||
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE SPACE "%s_drop(((RBTreeNode_TT*)cur)->value);\n", op.V, TT)
|
||||
));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"RBTreeNode_%s* %s_find(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_k_argument */
|
||||
SPACE "RBTreeNode* cur = self->root;\n"
|
||||
SPACE "while (cur != self->NIL) {\n"
|
||||
SPACE SPACE "if (%v) {\n" /* key < cur->key */
|
||||
SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE "} else if (%v) {\n" /* cur->key < key */
|
||||
SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
SPACE SPACE SPACE "return (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "return NULL;\n"
|
||||
"}\n\n",
|
||||
TT, set, set, codegen_rbtree_map__taking_ref_k_argument(op),
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_key_ref(op), codegen_rbtree_map__exp_passing_cur_key(op)),
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), codegen_rbtree_map__exp_passing_key_ref(op)),
|
||||
TT));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"RBTreeNode_%s* %s_find_max_less(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_t_argument */
|
||||
SPACE "RBTreeNode_%s* last_less = NULL;\n" /* TT */
|
||||
SPACE "RBTreeNode* cur = self->root;\n"
|
||||
SPACE "while (cur != self->NIL) {\n"
|
||||
SPACE SPACE "if (%v) {\n" /* key < cur->key */
|
||||
SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE "} else if (%v) {\n" /* cur->key < key */
|
||||
SPACE SPACE SPACE "last_less = (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE SPACE "if (cur == self->NIL)\n"
|
||||
SPACE SPACE SPACE SPACE "return last_less;\n"
|
||||
SPACE SPACE SPACE "while (cur->right != self->NIL)\n"
|
||||
SPACE SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE SPACE "return (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "return last_less;\n"
|
||||
"}\n\n",
|
||||
TT, set, set, codegen_rbtree_map__taking_ref_k_argument(op), TT,
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_key_ref(op), codegen_rbtree_map__exp_passing_cur_key(op)),
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), codegen_rbtree_map__exp_passing_key_ref(op)),
|
||||
TT, TT));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"RBTreeNode_%s* %s_find_max_less_or_eq(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_t_argument */
|
||||
SPACE "RBTreeNode_%s* last_less = NULL;\n" /* TT */
|
||||
SPACE "RBTreeNode* cur = self->root;\n"
|
||||
SPACE "while (cur != self->NIL) {\n"
|
||||
SPACE SPACE "if (%v) {\n" /* key < cur->key */
|
||||
SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE "} else if (%v) {\n" /* cur->key < key */
|
||||
SPACE SPACE SPACE "last_less = (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
SPACE SPACE SPACE "return (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "return last_less;\n"
|
||||
"}\n\n",
|
||||
TT, set, set, codegen_rbtree_map__taking_ref_k_argument(op), TT,
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_key_ref(op), codegen_rbtree_map__exp_passing_cur_key(op)),
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), codegen_rbtree_map__exp_passing_key_ref(op)),
|
||||
TT, TT));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"RBTreeNode_%s* %s_find_min_grtr(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_t_argument */
|
||||
SPACE "RBTreeNode_%s* last_grtr = NULL;\n" /* TT */
|
||||
SPACE "RBTreeNode* cur = self->root;\n"
|
||||
SPACE "while (cur != self->NIL) {\n"
|
||||
SPACE SPACE "if (%v) {\n" /* key < cur->key */
|
||||
SPACE SPACE SPACE "last_grtr = (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE "} else if (%v) {\n" /* cur->key < key */
|
||||
SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE SPACE "if (cur == self->NIL)\n"
|
||||
SPACE SPACE SPACE SPACE "return last_grtr;\n"
|
||||
SPACE SPACE SPACE "while (cur->left != self->NIL)\n"
|
||||
SPACE SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE SPACE "return (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "return last_grtr;\n"
|
||||
"}\n\n",
|
||||
TT, set, set, codegen_rbtree_map__taking_ref_k_argument(op), TT,
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_key_ref(op), codegen_rbtree_map__exp_passing_cur_key(op)),
|
||||
TT,
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), codegen_rbtree_map__exp_passing_key_ref(op)),
|
||||
TT));
|
||||
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"RBTreeNode_%s* %s_find_min_grtr_or_eq(const %s* self, %v key) {\n" /* TT, set, set, taking_ref_t_argument */
|
||||
SPACE "RBTreeNode_%s* last_grtr = NULL;\n" /* TT */
|
||||
SPACE "RBTreeNode* cur = self->root;\n"
|
||||
SPACE "while (cur != self->NIL) {\n"
|
||||
SPACE SPACE "if (%v) {\n" /* key < cur->key */
|
||||
SPACE SPACE SPACE "last_grtr = (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE "} else if (%v) {\n" /* cur->key < key */
|
||||
SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
SPACE SPACE SPACE "return (RBTreeNode_%s*)cur;\n" /* TT */
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "return last_grtr;\n"
|
||||
"}\n\n",
|
||||
TT, set, set, codegen_rbtree_map__taking_ref_k_argument(op), TT,
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_key_ref(op), codegen_rbtree_map__exp_passing_cur_key(op)),
|
||||
TT,
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), codegen_rbtree_map__exp_passing_key_ref(op)),
|
||||
TT));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
/* This method is unsafe. Arguments key, value will be taken if 0 is returned,
|
||||
* or left on their place if not-0 is returned */
|
||||
"/* UNSAFE */\n"
|
||||
"NODISCARD RBTreeNode_%s* %s_try_insert(%s* self, %v) {\n" /* TT, set, set, taking_t_argument */
|
||||
SPACE "RBTreeNode** surprising = &self->root;\n"
|
||||
SPACE "RBTreeNode* prev = self->NIL;\n"
|
||||
SPACE "RBTreeNode* cur = self->root;\n"
|
||||
SPACE "while (cur != self->NIL){\n"
|
||||
SPACE SPACE "prev = cur;\n"
|
||||
SPACE SPACE "if (%v) {\n" /* key < cur->key */
|
||||
SPACE SPACE SPACE "surprising = &cur->left;\n"
|
||||
SPACE SPACE SPACE "cur = cur->left;\n"
|
||||
SPACE SPACE "} else if (%v) {\n" /* cur->key < key */
|
||||
SPACE SPACE SPACE "surprising = &cur->right;\n"
|
||||
SPACE SPACE SPACE "cur = cur->right;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
SPACE SPACE SPACE "return (RBTreeNode_%s *)cur;\n" /* TT */
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "RBTreeNode_%s* new_node = (RBTreeNode_%s *)safe_malloc(sizeof(RBTreeNode_%s));\n" /* TT, TT, TT */
|
||||
SPACE "*new_node = (RBTreeNode_%s){ .base.parent = prev,\n" /* TT */
|
||||
SPACE SPACE ".base.left = self->NIL, .base.right = self->NIL, .base.color = RBTREE_RED,\n"
|
||||
SPACE SPACE ".key = key" "%s" "};\n" /* "" / ,.value = value */
|
||||
SPACE "*surprising = (RBTreeNode*)new_node;\n"
|
||||
SPACE "RBTree_fix_after_insert(&self->root, self->NIL, (RBTreeNode*)new_node);\n"
|
||||
SPACE "return NULL;\n"
|
||||
"}\n\n",
|
||||
TT, set, set, codegen_rbtree_map__taking_t_argument(op),
|
||||
codegen_rbtree_map__less(op, vcstr("key"), codegen_rbtree_map__exp_passing_cur_key(op)),
|
||||
codegen_rbtree_map__less(op, codegen_rbtree_map__exp_passing_cur_key(op), vcstr("key")),
|
||||
TT,
|
||||
TT, TT, TT,
|
||||
TT, op.v_primitive ? cstr("") : cstr(", .value = value")));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"bool %s_insert(%s* self, %v){\n" /* set, set, taking_t_argument */
|
||||
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key" "%s" ");\n" /* TT, set, "" /, value */
|
||||
SPACE "if (col == NULL)\n"
|
||||
SPACE SPACE "return true;\n"
|
||||
"%v" "%v" /* "" / dropping key, "" / dropping value */
|
||||
SPACE "return false;\n"
|
||||
"}\n\n",
|
||||
set, set, codegen_rbtree_map__taking_t_argument(op),
|
||||
TT, set, op.V.len > 0 ? cstr(", value") : cstr(""),
|
||||
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(key);\n", op.K),
|
||||
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(value);\n", op.V)));
|
||||
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"bool %s_erase(%s* self, %v key) {\n" /* set, set, taking_ref_k_argument */
|
||||
SPACE "RBTreeNode_%s* v = %s_find(self, key);\n" /* TT, set */
|
||||
SPACE "if (v == NULL)\n"
|
||||
SPACE SPACE "return false;\n"
|
||||
"%v" /* "" / op.K_drop(v->key) */
|
||||
"%v" /* "" / op.V_drop(v->value) */
|
||||
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, (RBTreeNode*)v);\n"
|
||||
SPACE "return true;\n"
|
||||
"}\n\n", set, set, codegen_rbtree_map__taking_ref_k_argument(op),
|
||||
TT, set,
|
||||
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->key);\n", op.K),
|
||||
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->value);\n", op.V)));
|
||||
}
|
||||
|
||||
|
||||
NODISCARD VecU8 get_name_of_rbtree_set_structure(set_instantiation_op op){
|
||||
if (op.alternative_comp_set_name_embed.len > 0)
|
||||
return VecU8_fmt("RBTreeBy%s_Set%s", op.alternative_comp_set_name_embed, op.T);
|
||||
return VecU8_fmt("RBTree_Set%s", op.T);
|
||||
}
|
||||
|
||||
NODISCARD VecU8 generate_rbtree_Set_template_instantiation(set_instantiation_op op, bool generate_node_struct){
|
||||
set_instantiation_op_fix(&op);
|
||||
map_instantiation_op map_op = {
|
||||
.K = op.T, .k_integer = op.t_integer, .k_primitive = op.t_primitive, .k_clonable = op.t_clonable,
|
||||
.V = cstr(""), .v_primitive = true, .v_clonable = true,
|
||||
.alternative_comp_map_name_embed = op.alternative_comp_set_name_embed, .alternative_less = op.alternative_less,
|
||||
.guest_data_T = op.guest_data_T
|
||||
};
|
||||
|
||||
VecU8 res = VecU8_new();
|
||||
VecU8 set_g = get_name_of_rbtree_set_structure(op);
|
||||
if (generate_node_struct)
|
||||
VecU8_append_vec(&res, codegen_rbtree__node_structure(map_op));
|
||||
codegen_append_rbtree_map__structure_and_simplest_methods(&res, map_op, VecU8_to_span(&set_g), op.T);
|
||||
VecU8_drop(set_g);
|
||||
return res;
|
||||
}
|
||||
|
||||
void generate_rbtree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, set_instantiation_op op, bool generate_node_struct) {
|
||||
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
|
||||
generate_rbtree_Set_template_instantiation(op, generate_node_struct), get_name_of_rbtree_set_structure(op));
|
||||
}
|
||||
|
||||
void generate_rbtree_Set_templ_inst_guarded_header(
|
||||
SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, set_instantiation_op op, bool generate_node_struct
|
||||
){
|
||||
VecU8 all_dependencies = VecU8_fmt("%v%s",
|
||||
codegen_include_relative_to_root(bonus_ns, cstr("src/l1_5/core/rb_tree_node.h")), dependencies);
|
||||
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, all_dependencies,
|
||||
generate_rbtree_Set_template_instantiation(op, generate_node_struct), get_name_of_rbtree_set_structure(op));
|
||||
}
|
||||
|
||||
|
||||
/* Don't forget to do the map stuff, Set is not enough */
|
||||
|
||||
NODISCARD VecU8 get_name_of_rbtree_map_structure(map_instantiation_op op){
|
||||
if (op.alternative_comp_map_name_embed.len > 0)
|
||||
return VecU8_fmt("RBTreeBy%s_Map%sTo%s", op.alternative_comp_map_name_embed, op.K, op.V);
|
||||
return VecU8_fmt("RBTree_Map%sTo%s", op.K, op.V);
|
||||
}
|
||||
|
||||
NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op op){
|
||||
NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op op, bool generate_node_struct){
|
||||
map_instantiation_op_fix(&op);
|
||||
|
||||
VecU8 res = VecU8_new();
|
||||
VecU8 map_g = get_name_of_rbtree_map_structure(op);
|
||||
SpanU8 map = VecU8_to_span(&map_g);
|
||||
VecU8 kvp_g = VecU8_fmt("KVP%sTo%s", op.K, op.V);
|
||||
SpanU8 kvp = VecU8_to_span(&kvp_g);
|
||||
|
||||
if (generate_node_struct)
|
||||
VecU8_append_vec(&res, codegen_rbtree__node_structure(op));
|
||||
codegen_append_rbtree_map__structure_and_simplest_methods(&res, op, map, kvp);
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"%s" "Option%s %s_pop_substitute(%s* self, %s key, %s value) {\n" /* "" / NODISCARD , op.V, map, map, op.K, op.V */
|
||||
/* Using unsafe method with conditional ownership transfer */
|
||||
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key, value);\n" /* kvp, map */
|
||||
SPACE "if (col == NULL) {\n"
|
||||
SPACE SPACE "return None_%s();\n" /* op.V */
|
||||
SPACE "} else {\n"
|
||||
"%v" /* "" / dropping col->key */
|
||||
SPACE SPACE "%s saved = col->value;\n" /* op.V */
|
||||
SPACE SPACE "col->key = key;\n"
|
||||
SPACE SPACE "col->value = value;\n"
|
||||
SPACE SPACE "return Some_%s(saved);\n" /* op.V */
|
||||
SPACE "}\n"
|
||||
"}\n\n",
|
||||
op.v_primitive ? cstr("") : cstr("NODISCARD "), op.V, map, map, op.K, op.V,
|
||||
kvp, map, op.V,
|
||||
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE"%s_drop(col->key);\n", op.K),
|
||||
op.V, op.V));
|
||||
|
||||
if (!op.v_primitive) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"bool %s_erase_substitute(%s* self, %s key, %s value) {\n" /* map, map, op.K, op.V */
|
||||
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key, value);\n" /* kvp, map */
|
||||
SPACE "if (col == NULL)\n"
|
||||
SPACE SPACE "return true;\n"
|
||||
"%v" "%v" /* "" / op.K_drop(col->key), "" / op.V_drop(col->value) */
|
||||
SPACE "col->key = key;\n"
|
||||
SPACE "col->value = value;\n"
|
||||
SPACE "return false;\n"
|
||||
"}\n\n",
|
||||
map, map, op.K, op.V, kvp, map,
|
||||
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->key);\n", op.K),
|
||||
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->value);\n", op.V)));
|
||||
}
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"Option%s %s_pop(%s* self, %v key) {\n" /* op.V, map, map, taking_ref_k_argument */
|
||||
SPACE "RBTreeNode_%s* v = %s_find(self, key);\n" /* kvp, map */
|
||||
SPACE "if (v == NULL)\n"
|
||||
SPACE SPACE "return None_%s();\n" /* op.V */
|
||||
"%v" /* "" / op.K_drop(v->key) */
|
||||
"%s saved = v->value;\n" /* op.V */
|
||||
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, v);\n"
|
||||
SPACE "return Some_%s();\n" /* op.V */
|
||||
"}\n\n",
|
||||
op.V, map, map, codegen_rbtree_map__taking_ref_k_argument(op),
|
||||
kvp, map, op.V,
|
||||
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->key);\n", op.K),
|
||||
op.V, op.V));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
void generate_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op, bool generate_node_struct) {
|
||||
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
|
||||
generate_rbtree_Map_template_instantiation(op, generate_node_struct), get_name_of_rbtree_map_structure(op));
|
||||
}
|
||||
|
||||
void generate_rbtree_Map_templ_inst_guarded_header(
|
||||
SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, map_instantiation_op op, bool generate_node_struct
|
||||
){
|
||||
VecU8 all_dependencies = VecU8_fmt("%v%s",
|
||||
codegen_include_relative_to_root(bonus_ns, cstr("src/l1_5/core/rb_tree_node.h")), dependencies);
|
||||
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, all_dependencies,
|
||||
generate_rbtree_Map_template_instantiation(op, generate_node_struct), get_name_of_rbtree_map_structure(op));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "../../l1/core/util.h"
|
||||
|
||||
// todo: jam that one bit into parent field of BufRBTreeNode
|
||||
typedef enum {
|
||||
RBTree_black = 0,
|
||||
RBTree_red = 1,
|
||||
@ -16,7 +17,7 @@ typedef struct {
|
||||
RBTreeColor color;
|
||||
} BufRBTreeNode;
|
||||
|
||||
#include "../../../gen/l1/eve/embassy_l1_5/VecBuffRBTreeNode.h"
|
||||
#include "../../../gen/l1/eve/embassy_l1_5/VecBufRBTreeNode.h"
|
||||
|
||||
void BufRBTree_left_rotate(BufRBTreeNode* tree, U64* root, U64 x){
|
||||
assert(x != 0);
|
||||
@ -219,4 +220,6 @@ void BufRBTree_fix_after_delete(BufRBTreeNode* tree, U64* root, U64 me){
|
||||
tree[me].color = RBTree_black;
|
||||
}
|
||||
|
||||
// todo: move here erase_empty method (renmaed to _erase_empty_by_index)
|
||||
|
||||
#endif
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
#include "../../l1/core/util.h"
|
||||
|
||||
typedef enum {
|
||||
RBTree_black = 0,
|
||||
RBTree_red = 1,
|
||||
RBTREE_BLACK = 0,
|
||||
RBTREE_RED = 1,
|
||||
} RBTreeClr;
|
||||
|
||||
typedef struct RBTreeNode RBTreeNode;
|
||||
@ -16,29 +16,108 @@ struct RBTreeNode{
|
||||
RBTreeClr color;
|
||||
};
|
||||
|
||||
// todo: implement and then use
|
||||
void BufRBTree_left_rotate(RBTreeNode** root, RBTreeNode* NIL, RBTreeNode* x){
|
||||
// assert(x != 0);
|
||||
// U64 y = tree[x].right;
|
||||
// assert(y != 0);
|
||||
// tree[x].right = tree[y].left;
|
||||
// if (tree[x].right != 0)
|
||||
// tree[tree[x].right].parent = x;
|
||||
//
|
||||
// tree[y].parent = tree[x].parent;
|
||||
// if (tree[y].parent == 0) {
|
||||
// *root = y;
|
||||
// } else if (x == tree[tree[x].parent].left) {
|
||||
// tree[tree[x].parent].left = y;
|
||||
// } else {
|
||||
// tree[tree[x].parent].right = y;
|
||||
// }
|
||||
// tree[x].parent = y;
|
||||
// tree[y].left = x;
|
||||
void RBTree_left_rotate(RBTreeNode** root, RBTreeNode* NIL, RBTreeNode* x){
|
||||
assert(x != NIL);
|
||||
RBTreeNode* y = x->right;
|
||||
assert(y != NIL);
|
||||
x->right = y->left;
|
||||
if (y->left != NIL)
|
||||
y->left->parent = x;
|
||||
|
||||
y->parent = x->parent;
|
||||
if (x->parent == NIL)
|
||||
*root = y;
|
||||
else if (x == x->parent->left)
|
||||
x->parent->left = y;
|
||||
else
|
||||
x->parent->right = y;
|
||||
|
||||
x->parent = y;
|
||||
y->left = x;
|
||||
}
|
||||
|
||||
void RBTree_right_rotate(RBTreeNode** root, RBTreeNode* NIL, RBTreeNode* x){
|
||||
assert(x != NIL);
|
||||
RBTreeNode* y = x->left;
|
||||
assert(y != NIL);
|
||||
x->left = y->right;
|
||||
if (y->right != NIL)
|
||||
y->right->parent = x;
|
||||
|
||||
y->parent = x->parent;
|
||||
if (x->parent == NIL)
|
||||
*root = y;
|
||||
else if (x->parent->right == x)
|
||||
x->parent->right = y;
|
||||
else
|
||||
x->parent->left = y;
|
||||
|
||||
x->parent = y;
|
||||
y->right = x;
|
||||
}
|
||||
|
||||
void RBTree_fix_after_insert(RBTreeNode** root, RBTreeNode* NIL, RBTreeNode* me){
|
||||
assert(me != NIL);
|
||||
while (true) {
|
||||
RBTreeNode* mom = me->parent;
|
||||
if (mom == NIL)
|
||||
break;
|
||||
if (mom->color == RBTREE_BLACK)
|
||||
return;
|
||||
RBTreeNode* grandma = mom->parent;
|
||||
assert(grandma != NIL);
|
||||
assert(grandma->color == RBTREE_BLACK);
|
||||
RBTreeNode* aunt = grandma->left == mom ? grandma->right : grandma->left;
|
||||
assert(aunt != mom);
|
||||
if (aunt->color == RBTREE_RED) {
|
||||
/* Easy case */
|
||||
mom->color = RBTREE_BLACK;
|
||||
aunt->color = RBTREE_BLACK;
|
||||
grandma->color = RBTREE_RED;
|
||||
me = grandma;
|
||||
} else if (grandma->left == mom) {
|
||||
/* Hard case: firstborn orientation */
|
||||
if (mom->right == me) {
|
||||
RBTree_left_rotate(root, NIL, mom);
|
||||
me->color = RBTREE_BLACK;
|
||||
} else {
|
||||
mom->color = RBTREE_BLACK;
|
||||
}
|
||||
RBTree_right_rotate(root, NIL, grandma);
|
||||
grandma->color = RBTREE_RED;
|
||||
return;
|
||||
} else {
|
||||
/* Hard case: benjamin orientation */
|
||||
if (mom->left == me) {
|
||||
RBTree_right_rotate(root, NIL, mom);
|
||||
me->color = RBTREE_BLACK;
|
||||
} else {
|
||||
mom->color = RBTREE_BLACK;
|
||||
}
|
||||
RBTree_left_rotate(root, NIL, grandma);
|
||||
grandma->color = RBTREE_RED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(*root == me);
|
||||
me->color = RBTREE_BLACK;
|
||||
}
|
||||
|
||||
|
||||
RBTreeNode* RBTree_minimum_in_subtree(RBTreeNode* x, RBTreeNode* NIL){
|
||||
void RBTree_steal_neighbours(RBTreeNode** root, RBTreeNode* NIL, RBTreeNode* fr, RBTreeNode* to){
|
||||
if (fr->parent == NIL)
|
||||
*root = to;
|
||||
else if (fr->parent->left == fr)
|
||||
fr->parent->left = to;
|
||||
else
|
||||
fr->parent->right = to;
|
||||
fr->left->parent = to;
|
||||
fr->right->parent = to;
|
||||
*to = *fr;
|
||||
}
|
||||
|
||||
|
||||
RBTreeNode* RBTreeNode_minimum_in_subtree(RBTreeNode* x, RBTreeNode* NIL){
|
||||
assert(x != NIL);
|
||||
while (x->left != NIL)
|
||||
x = x->left;
|
||||
@ -52,4 +131,149 @@ RBTreeNode* RBTreeNode_maximum_in_subtree(RBTreeNode* x, RBTreeNode* NIL){
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Returns NULL instead of NIL */
|
||||
RBTreeNode* RBTreeNode_find_next(RBTreeNode* x, RBTreeNode* NIL){
|
||||
assert(x != NIL);
|
||||
if (x->right != NIL)
|
||||
return RBTreeNode_minimum_in_subtree(x->right, NIL);
|
||||
while (true) {
|
||||
RBTreeNode* p = x->parent;
|
||||
if (p == NIL)
|
||||
return NULL;
|
||||
if (p->left == x)
|
||||
return p;
|
||||
x = p;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns NULL instead of NIL */
|
||||
RBTreeNode* RBTreeNode_find_prev(RBTreeNode* x, RBTreeNode* NIL){
|
||||
assert(x != NIL);
|
||||
if (x->left != NIL)
|
||||
return RBTreeNode_maximum_in_subtree(x->left, NIL);
|
||||
while (true) {
|
||||
RBTreeNode* p = x->parent;
|
||||
if (p == NIL)
|
||||
return NULL;
|
||||
if (p->right == x)
|
||||
return p;
|
||||
x = p;
|
||||
}
|
||||
}
|
||||
|
||||
/* me may be NIL at the beginning. ->parent field of NIL is meaningful */
|
||||
void RBTree_fix_after_delete(RBTreeNode** root, RBTreeNode* NIL, RBTreeNode* me){
|
||||
assert((*root)->parent == NIL);
|
||||
while (me != *root && me->color == RBTREE_BLACK) {
|
||||
RBTreeNode* mom = me->parent;
|
||||
assert(mom != NIL);
|
||||
if (me == mom->left) { /* We are on the left */
|
||||
RBTreeNode* sister = mom->right;
|
||||
assert(sister != NIL);
|
||||
if (sister->color == RBTREE_RED) { /* Case 1 */
|
||||
mom->color = RBTREE_RED;
|
||||
sister->color = RBTREE_BLACK;
|
||||
RBTree_left_rotate(root, NIL, mom);
|
||||
/* Reassignation required */
|
||||
sister = mom->right;
|
||||
assert(sister != NIL);
|
||||
}
|
||||
/* Cases 2,3,4 */
|
||||
RBTreeNode* nephew_firstborn = sister->left;
|
||||
RBTreeNode* nephew_benjamin = sister->right;
|
||||
if (nephew_firstborn->color == RBTREE_BLACK && nephew_benjamin->color == RBTREE_BLACK) {
|
||||
/* Case 2 */
|
||||
sister->color = RBTREE_RED;
|
||||
me = mom;
|
||||
continue;
|
||||
}
|
||||
/* Cases 3,4 */
|
||||
if (nephew_benjamin->color == RBTREE_BLACK) {
|
||||
/* Case 3 */
|
||||
nephew_firstborn->color = RBTREE_BLACK;
|
||||
sister->color = RBTREE_RED;
|
||||
RBTree_right_rotate(root, NIL, sister);
|
||||
/* Reassignation required */
|
||||
nephew_benjamin = sister;
|
||||
sister = nephew_firstborn;
|
||||
assert(sister != NIL);
|
||||
/*nephew_firstborn = sister->left;*/
|
||||
}
|
||||
/* Case 4 */
|
||||
sister->color = mom->color;
|
||||
mom->color = RBTREE_BLACK;
|
||||
nephew_benjamin->color = RBTREE_BLACK;
|
||||
RBTree_left_rotate(root, NIL, mom);
|
||||
me = *root;
|
||||
} else { /* We are on the right */
|
||||
assert(me == mom->right);
|
||||
RBTreeNode* sister = mom->left;
|
||||
assert(sister != NULL);
|
||||
if (sister->color == RBTREE_RED) { /* Case 1 */
|
||||
mom->color = RBTREE_RED;
|
||||
sister->color = RBTREE_BLACK;
|
||||
RBTree_right_rotate(root, NIL, mom);
|
||||
/* Reassignation required */
|
||||
sister = mom->left;
|
||||
assert(sister != NIL);
|
||||
}
|
||||
/* Cases 2,3,4 (every instance of red-black tree has an itchy substring in source code containing 2,3,4) */
|
||||
RBTreeNode* nephew_firstborn = sister->left;
|
||||
RBTreeNode* nephew_benjamin = sister->right;
|
||||
if (nephew_firstborn->color == RBTREE_BLACK && nephew_benjamin->color == RBTREE_BLACK) {
|
||||
/* Case 2 */
|
||||
sister->color = RBTREE_RED;
|
||||
me = mom;
|
||||
continue;
|
||||
}
|
||||
/* Cases 3,4 */
|
||||
if (nephew_firstborn->color == RBTREE_BLACK) {
|
||||
/* Case 3 */
|
||||
nephew_benjamin->color = RBTREE_BLACK;
|
||||
sister->color = RBTREE_RED;
|
||||
RBTree_left_rotate(root, NIL, sister);
|
||||
/* Reassignation required */
|
||||
nephew_firstborn = sister;
|
||||
sister = nephew_benjamin;
|
||||
assert(sister != NIL);
|
||||
/*nephew_benjamin = sister->right;*/
|
||||
}
|
||||
/* Case 4 */
|
||||
sister->color = mom->color;
|
||||
mom->color = RBTREE_BLACK;
|
||||
nephew_firstborn->color = RBTREE_BLACK;
|
||||
RBTree_right_rotate(root, NIL, mom);
|
||||
me = *root;
|
||||
}
|
||||
}
|
||||
me->color = RBTREE_BLACK;
|
||||
}
|
||||
|
||||
/* Assumes that z->key and z->value were already dropped properly. Frees z node */
|
||||
void RBTree_erase_empty_by_iter(RBTreeNode** root, RBTreeNode* NIL, RBTreeNode* z) {
|
||||
assert(z != NULL);
|
||||
assert(z != NIL);
|
||||
RBTreeNode* y = (z->left == NULL || z->right == 0) ? z : RBTreeNode_minimum_in_subtree(z, NIL);
|
||||
RBTreeNode* x = y->left == NIL ? y->right : y->left;
|
||||
assert(x != y && x != z);
|
||||
RBTreeNode* x_adopter = y->parent;
|
||||
x->parent = x_adopter;
|
||||
if (x_adopter == NIL)
|
||||
*root = x;
|
||||
else if (x_adopter->left == y)
|
||||
x_adopter->left = x;
|
||||
else
|
||||
x_adopter->right = x;
|
||||
RBTreeClr y_org_clr = y->color;
|
||||
if (z != y) {
|
||||
RBTree_steal_neighbours(root, NIL, z, y);
|
||||
if (x_adopter == z)
|
||||
x_adopter = y;
|
||||
}
|
||||
x->parent = x_adopter;
|
||||
if (y_org_clr == RBTREE_BLACK)
|
||||
RBTree_fix_after_delete(root, NIL, x);
|
||||
free((void*)z);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -5,17 +5,17 @@
|
||||
#include "../../../l1/system/fsmanip.h"
|
||||
#include "../../../l1/system/creating_child_proc.h"
|
||||
|
||||
void check_structure_h_dfs(const VecRBTreeNode* tree, U64 x, VecU8* f){
|
||||
void check_structure_h_dfs(const VecBufRBTreeNode* tree, U64 x, VecU8* f){
|
||||
if (x == 0)
|
||||
return;
|
||||
if (*VecU8_at(f, x - 1) != 0)
|
||||
check(false);
|
||||
*VecU8_mat(f, x - 1) = 1;
|
||||
check_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->left, f);
|
||||
check_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->right, f);
|
||||
check_structure_h_dfs(tree, VecBufRBTreeNode_at(tree, x)->left, f);
|
||||
check_structure_h_dfs(tree, VecBufRBTreeNode_at(tree, x)->right, f);
|
||||
}
|
||||
|
||||
U32 check_structure_h_dfs_2(RBTreeNode* tree, U64 x){
|
||||
U32 check_structure_h_dfs_2(BufRBTreeNode* tree, U64 x){
|
||||
if (x == 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -420,10 +420,10 @@ void chaos(){
|
||||
void triple_black(){
|
||||
BuffRBTree_SetS64 set;
|
||||
{
|
||||
VecRBTreeNode tree = VecRBTreeNode_new_zeroinit(4);
|
||||
tree.buf[1] = (RBTreeNode){.parent = 3};
|
||||
tree.buf[2] = (RBTreeNode){.parent = 3};
|
||||
tree.buf[3] = (RBTreeNode){.left = 2, .right = 1};
|
||||
VecBufRBTreeNode tree = VecBufRBTreeNode_new_zeroinit(4);
|
||||
tree.buf[1] = (BufRBTreeNode){.parent = 3};
|
||||
tree.buf[2] = (BufRBTreeNode){.parent = 3};
|
||||
tree.buf[3] = (BufRBTreeNode){.left = 2, .right = 1};
|
||||
VecS64 el = VecS64_new_reserved(3);
|
||||
VecS64_append(&el, 300);
|
||||
VecS64_append(&el, 100);
|
||||
|
||||
262
src/l2/tests/data_structures/t0_3.c
Normal file
262
src/l2/tests/data_structures/t0_3.c
Normal file
@ -0,0 +1,262 @@
|
||||
#include "../../../../gen/l1_5/RBTree_SetS64.h"
|
||||
#include "../../../../gen/l1/VecAndSpan_U8.h"
|
||||
#include "../../../../gen/l1/VecAndSpan_S64.h"
|
||||
|
||||
#include "../../../l1/core/VecU8_as_str.h"
|
||||
#include "../../../l1/system/fileio.h"
|
||||
#include "../../../l1/system/fsmanip.h"
|
||||
#include "../../../l1/system/creating_child_proc.h"
|
||||
|
||||
typedef RBTreeNode_S64* RefRBTreeNode_S64;
|
||||
|
||||
#include "../../../../gen/l1/eve/ds_test/VecRefRBTreeNode_S64.h"
|
||||
|
||||
S64 min_key_in_subtree(RBTreeNode_S64* x, RBTreeNode* NIL){
|
||||
check(x != NULL && &x->base != NIL);
|
||||
S64 ans = x->key;
|
||||
if (x->base.left != NIL)
|
||||
ans = MIN_S64(ans, min_key_in_subtree((RBTreeNode_S64*)x->base.left, NIL));
|
||||
if (x->base.right != NIL)
|
||||
ans = MIN_S64(ans, min_key_in_subtree((RBTreeNode_S64*)x->base.right, NIL));
|
||||
return ans;
|
||||
}
|
||||
|
||||
S64 max_key_in_subtree(RBTreeNode_S64* x, RBTreeNode* NIL){
|
||||
check(x != NULL && &x->base != NIL);
|
||||
S64 ans = x->key;
|
||||
if (x->base.left != NIL)
|
||||
ans = MAX_S64(ans, max_key_in_subtree((RBTreeNode_S64*)x->base.left, NIL));
|
||||
if (x->base.right != NIL)
|
||||
ans = MAX_S64(ans, max_key_in_subtree((RBTreeNode_S64*)x->base.right, NIL));
|
||||
return ans;
|
||||
}
|
||||
|
||||
int check_structure_h_dfs(RBTree_SetS64* set, RBTreeNode_S64* x){
|
||||
check(x != NULL);
|
||||
if (&x->base == set->NIL)
|
||||
return 0;
|
||||
int a = x->base.left == set->NIL ? 0 : check_structure_h_dfs(set, (RBTreeNode_S64*)x->base.left);
|
||||
int b = x->base.right == set->NIL ? 0 : check_structure_h_dfs(set, (RBTreeNode_S64*)x->base.right);
|
||||
check(a == b);
|
||||
if (&x->base == set->root) {
|
||||
check(x->base.parent == set->NIL);
|
||||
} else {
|
||||
check(x->base.parent != set->NIL);
|
||||
}
|
||||
if (x->base.left != set->NIL)
|
||||
check(x->base.left->parent == &x->base);
|
||||
if (x->base.right != set->NIL)
|
||||
check(x->base.right->parent == &x->base);
|
||||
|
||||
if (x->base.left != set->NIL)
|
||||
check(max_key_in_subtree((RBTreeNode_S64*)x->base.left, set->NIL) < x->key);
|
||||
if (x->base.right != set->NIL)
|
||||
check(x->key < min_key_in_subtree((RBTreeNode_S64*)x->base.right, set->NIL));
|
||||
|
||||
if (x->base.color == RBTREE_RED) {
|
||||
check(x->base.left->color == RBTREE_BLACK);
|
||||
check(x->base.right->color == RBTREE_BLACK);
|
||||
}
|
||||
|
||||
return a + (x->base.color == RBTREE_BLACK ? 1 : 0);
|
||||
}
|
||||
|
||||
void check_correctness(RBTree_SetS64* set){
|
||||
check(set->root->color == RBTREE_BLACK);
|
||||
check_structure_h_dfs(set, (RBTreeNode_S64*)set->root);
|
||||
}
|
||||
|
||||
|
||||
void save_tree_to_file(const RBTree_SetS64* set, SpanU8 name){
|
||||
// check_only_structure(set);
|
||||
|
||||
VecU8 graph = vcstr(
|
||||
"digraph rbtree {\n"
|
||||
" fontsize = 20\n"
|
||||
" rankdir = TB\n"
|
||||
" bgcolor = \"lightgray\"\n"
|
||||
" node [fontname = \"Arial\", style=\"rounded,filled\", shape=circle];\n\n");
|
||||
|
||||
VecRefRBTreeNode_S64 bfs_nxt = VecRefRBTreeNode_S64_new();
|
||||
VecRefRBTreeNode_S64 bfs = VecRefRBTreeNode_S64_new();
|
||||
if (set->root != set->NIL)
|
||||
VecRefRBTreeNode_S64_append(&bfs_nxt, (RBTreeNode_S64*)set->root);
|
||||
while (bfs_nxt.len > 0) {
|
||||
VecRefRBTreeNode_S64 t = bfs_nxt;
|
||||
bfs_nxt = bfs;
|
||||
bfs = t;
|
||||
for (size_t j = 0; j < bfs.len; j++) {
|
||||
RBTreeNode_S64* cur = *VecRefRBTreeNode_S64_at(&bfs, j);
|
||||
assert(cur != NULL);
|
||||
if (cur->base.left != set->NIL)
|
||||
VecRefRBTreeNode_S64_append(&bfs, (RBTreeNode_S64*)cur->base.left);
|
||||
if (cur->base.right != set->NIL)
|
||||
VecRefRBTreeNode_S64_append(&bfs, (RBTreeNode_S64*)cur->base.right);
|
||||
|
||||
VecU8_append_vec(&graph, VecU8_fmt(
|
||||
" v%i [label=%i, color=%s, fontcolor=%s]\n",
|
||||
cur->key, cur->key,
|
||||
cur->base.color == RBTREE_BLACK ? cstr("black") : cstr("red"),
|
||||
cur->base.color == RBTREE_BLACK ? cstr("white") : cstr("black")));
|
||||
|
||||
if (cur->base.left != set->NIL)
|
||||
VecU8_append_vec(&graph, VecU8_fmt(" v%i -> v%i [label=left]\n",
|
||||
cur->key, ((RBTreeNode_S64*)cur->base.left)->key));
|
||||
if (cur->base.right != set->NIL)
|
||||
VecU8_append_vec(&graph, VecU8_fmt(" v%i -> v%i [label=right]\n",
|
||||
cur->key, ((RBTreeNode_S64*)cur->base.right)->key));
|
||||
}
|
||||
bfs.len = 0;
|
||||
}
|
||||
VecU8_append_span(&graph, cstr("}\n"));
|
||||
mkdir_nofail("GRAPHS");
|
||||
VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.gv%c", name, 0);
|
||||
write_whole_file_or_abort((CSTR)dot_filename_nt.buf, VecU8_to_span(&graph));
|
||||
VecU8_drop(graph);
|
||||
VecU8_drop(dot_filename_nt);
|
||||
VecU8 command_nt = VecU8_fmt("dot -Tpng GRAPHS/GRAPH_%s.gv -o GRAPHS/GRAPH_%s.png%c", name, name, 0);
|
||||
calling_system_func_nofail((CSTR)command_nt.buf);
|
||||
VecU8_drop(command_nt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void insert_only(){
|
||||
{
|
||||
RBTree_SetS64 set = RBTree_SetS64_new();
|
||||
check_correctness(&set);
|
||||
RBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
RBTree_SetS64 set = RBTree_SetS64_new();
|
||||
for (S64 p = 0; p < 100; p++) {
|
||||
bool ret = RBTree_SetS64_insert(&set, 2 * p);
|
||||
check(ret);
|
||||
check_correctness(&set);
|
||||
// save_tree_to_file(&set, cstr("last_correct"));
|
||||
for (S64 i = 0; i <= p; i++) {
|
||||
RBTreeNode_S64* ret1 = RBTree_SetS64_find(&set, 2 * i);
|
||||
check(ret1 != NULL);
|
||||
RBTreeNode_S64* ret2 = RBTree_SetS64_find(&set, 2 * i + 1);
|
||||
check(ret2 == NULL);
|
||||
}
|
||||
}
|
||||
RBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
RBTree_SetS64 set = RBTree_SetS64_new();
|
||||
for (S64 p = -99; p <= 0; p++) {
|
||||
bool ret = RBTree_SetS64_insert(&set, 2 * p);
|
||||
check(ret);
|
||||
check_correctness(&set);
|
||||
// save_tree_to_file(&set, cstr("last_correct"));
|
||||
for (S64 i = -99; i <= p; i++) {
|
||||
RBTreeNode_S64* ret1 = RBTree_SetS64_find(&set, 2 * i);
|
||||
check(ret1 != NULL);
|
||||
RBTreeNode_S64* ret2 = RBTree_SetS64_find(&set, 2 * i + 1);
|
||||
check(ret2 == NULL);
|
||||
}
|
||||
}
|
||||
RBTree_SetS64_drop(set);
|
||||
}
|
||||
for (int s = 0; s < 1000; s++) {
|
||||
srand(s);
|
||||
VecS64 have = VecS64_new();
|
||||
RBTree_SetS64 set = RBTree_SetS64_new();
|
||||
for (int m = 0; m < 1000; m++) {
|
||||
S64 x = (S64)rand();
|
||||
bool in = false;
|
||||
for (size_t j = 0; j < have.len; j++) {
|
||||
if (have.buf[j] == x)
|
||||
in = true;
|
||||
}
|
||||
bool iret = RBTree_SetS64_insert(&set, x);
|
||||
if (in) {
|
||||
check(!iret);
|
||||
} else {
|
||||
check(iret);
|
||||
VecS64_append(&have, x);
|
||||
}
|
||||
}
|
||||
RBTree_SetS64_drop(set);
|
||||
}
|
||||
}
|
||||
|
||||
void s_4_t_42(){
|
||||
RBTreeNode_S64* v0 = safe_malloc(sizeof(RBTreeNode_S64));
|
||||
RBTreeNode_S64* v10 = safe_malloc(sizeof(RBTreeNode_S64));
|
||||
RBTreeNode_S64* v20 = safe_malloc(sizeof(RBTreeNode_S64));
|
||||
RBTreeNode_S64* v30 = safe_malloc(sizeof(RBTreeNode_S64));
|
||||
RBTreeNode* NIL = safe_calloc(1, sizeof(RBTreeNode));
|
||||
*v0 = (RBTreeNode_S64){ .base.parent = &v20->base, .base.left = NIL, .base.right = &v10->base,
|
||||
.base.color = RBTREE_BLACK, .key = 0};
|
||||
*v10 = (RBTreeNode_S64){ .base.parent = &v0->base, .base.left = NIL, .base.right = NIL,
|
||||
.base.color = RBTREE_RED, .key = 10};
|
||||
*v20 = (RBTreeNode_S64){ .base.parent = NIL, .base.left = &v0->base, .base.right = &v30->base,
|
||||
.base.color = RBTREE_BLACK, .key = 20};
|
||||
*v30 = (RBTreeNode_S64){ .base.parent = &v20->base, .base.left = NIL, .base.right = NIL,
|
||||
.base.color = RBTREE_BLACK, .key = 30};
|
||||
RBTree_SetS64 set = {.root = &v20->base, .NIL = NIL};
|
||||
check_correctness(&set);
|
||||
save_tree_to_file(&set, cstr("SOROK_ONE"));
|
||||
check(RBTree_SetS64_erase(&set, 20));
|
||||
save_tree_to_file(&set, cstr("I_AM_LOOSING_MY_FUCKING_MIND"));
|
||||
check_correctness(&set);
|
||||
}
|
||||
|
||||
void stress(){
|
||||
printf("Are you ready for real stress?\n");
|
||||
for (int s = 4; s < 1000; s++) {
|
||||
srand(s);
|
||||
RBTree_SetS64 set = RBTree_SetS64_new();
|
||||
VecS64 real_set = VecS64_new();
|
||||
U32 n = (U32)s;
|
||||
VecS64 complementary_set = VecS64_new_reserved(n);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
VecS64_append(&complementary_set, (S64)i * 10);
|
||||
}
|
||||
for (int t = 0; t < 1000; t++) {
|
||||
/* Do something */
|
||||
int do_insertion = rand() % 2;
|
||||
if (real_set.len == 0)
|
||||
do_insertion = 1;
|
||||
if (complementary_set.len == 0)
|
||||
do_insertion = 0;
|
||||
if (do_insertion) {
|
||||
assert(complementary_set.len > 0);
|
||||
size_t j = rand() % complementary_set.len;
|
||||
S64 v = VecS64_unordered_pop(&complementary_set, j);
|
||||
VecS64_append(&real_set, v);
|
||||
check(RBTree_SetS64_insert(&set, v));
|
||||
check_correctness(&set);
|
||||
} else {
|
||||
assert(real_set.len > 0);
|
||||
size_t j = rand() % real_set.len;
|
||||
S64 v = VecS64_unordered_pop(&real_set, j);
|
||||
VecS64_append(&complementary_set, v);
|
||||
check(RBTree_SetS64_erase(&set, v));
|
||||
check_correctness(&set);
|
||||
}
|
||||
// VecU8 name = VecU8_fmt("t_%u", (U64)t);
|
||||
// save_tree_to_file(&set, VecU8_to_span(&name));
|
||||
/* We did something */
|
||||
for (size_t j = 0; j < real_set.len; j++) {
|
||||
check(RBTree_SetS64_find(&set, real_set.buf[j]) != NULL);
|
||||
}
|
||||
for (size_t j = 0; j < complementary_set.len; j++) {
|
||||
check(RBTree_SetS64_find(&set, complementary_set.buf[j]) == NULL);
|
||||
}
|
||||
}
|
||||
VecS64_drop(real_set);
|
||||
VecS64_drop(complementary_set);
|
||||
RBTree_SetS64_drop(set);
|
||||
printf("Seed s=%d passed test\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
// insert_only();
|
||||
// stress();
|
||||
s_4_t_42();
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user