From b3b0eae267a7b27aeaee6799eabfd882cb6b0452 Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Fri, 3 Oct 2025 11:51:19 +0300 Subject: [PATCH] saving bug fix --- src/l1/core/int_primitives.h | 1 + src/l1/core/uint_segments.h | 29 ++++ src/l1/core/util.h | 1 - src/l1_5/anne/l1_5_templ_very_base.h | 18 ++- .../codegen/all_set_map_templ_util_inst.h | 12 +- .../codegen/rb_tree_set_map_template_inst.h | 126 ++++++++++++++++-- src/l1_5/core/rb_tree_node.h | 4 +- 7 files changed, 175 insertions(+), 16 deletions(-) create mode 100644 src/l1/core/uint_segments.h diff --git a/src/l1/core/int_primitives.h b/src/l1/core/int_primitives.h index 03f48cf..fe7a667 100644 --- a/src/l1/core/int_primitives.h +++ b/src/l1/core/int_primitives.h @@ -3,6 +3,7 @@ #include #include +#include typedef uint8_t U8; typedef uint16_t U16; diff --git a/src/l1/core/uint_segments.h b/src/l1/core/uint_segments.h new file mode 100644 index 0000000..8e57260 --- /dev/null +++ b/src/l1/core/uint_segments.h @@ -0,0 +1,29 @@ +#ifndef prototype1_src_l1_core_uint_segments_h +#define prototype1_src_l1_core_uint_segments_h + +#include "int_primitives.h" + +typedef struct { + U64 start; + U64 len; +} U64Segment; + +bool U64Segment_equal_U64Segment(const U64Segment* A, const U64Segment* B){ + return A->start == B->start && A->len == B->len; +} + +bool U64Segment_equal_by_start(const U64Segment* A, const U64Segment* B){ + return A->start == B->start; +} + +bool U64Segment_less_by_start(const U64Segment* A, const U64Segment* B){ + return A->start < B->start; +} + +bool U64Segment_less_by_len_and_start(const U64Segment* A, const U64Segment* B){ + if (A->len == B->len) + return A->start < B->start; + return A->len < B->len; +} + +#endif \ No newline at end of file diff --git a/src/l1/core/util.h b/src/l1/core/util.h index dfe2826..5011224 100644 --- a/src/l1/core/util.h +++ b/src/l1/core/util.h @@ -2,7 +2,6 @@ #define PROTOTYPE1_SRC_CORE_UTIL_H #include -#include #include #include #include diff --git a/src/l1_5/anne/l1_5_templ_very_base.h b/src/l1_5/anne/l1_5_templ_very_base.h index 479b283..9501ce9 100644 --- a/src/l1_5/anne/l1_5_templ_very_base.h +++ b/src/l1_5/anne/l1_5_templ_very_base.h @@ -4,14 +4,28 @@ #include "../codegen/rb_tree_set_map_template_inst.h" void generate_l1_5_template_instantiation_for_base_types(){ - SpanU8 l = cstr("l1_5"); - SpanU8 ns = cstr(""); + SpanU8 l = cstr("l1_5"), ns = cstr(""); SpanU8 dep = cstr( "#include \"../l1/VecAndSpan_int_primitives.h\"" ); // todo: split VecAndSpan_int_primitives into multiple files (one file per integer type) generate_rb_tree_Set_templ_inst_guarded_header(l, ns, dep, (set_instantiation_op){.T = cstr("U64"), .t_integer = true}); generate_rb_tree_Set_templ_inst_guarded_header(l, ns, dep, (set_instantiation_op){.T = cstr("S64"), .t_integer = true}); + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + (set_instantiation_op){ + .T = cstr("U64Segment"), + .t_primitive = true, + .alternative_equal = cstr("U64Segment_equal_by_start"), + .alternative_less = cstr("U64Segment_less_by_start"), + .alternative_comp_set_name_embed = cstr("Start") + }); + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + (set_instantiation_op){ + .T = cstr("U64Segment"), + .t_primitive = true, + .alternative_less = cstr("U64Segment_less_by_len_and_start"), + .alternative_comp_set_name_embed = cstr("LenAndStart") + }); } #endif diff --git a/src/l1_5/codegen/all_set_map_templ_util_inst.h b/src/l1_5/codegen/all_set_map_templ_util_inst.h index 1c0cd06..8d34226 100644 --- a/src/l1_5/codegen/all_set_map_templ_util_inst.h +++ b/src/l1_5/codegen/all_set_map_templ_util_inst.h @@ -3,8 +3,6 @@ #include "../../l1/codegen/util_template_inst.h" -// todo: continue from here - /* We assume that T is trivially movable */ typedef struct { SpanU8 T; @@ -12,10 +10,20 @@ typedef struct { bool t_integer; bool t_primitive; bool t_clonable; + SpanU8 alternative_equal; + SpanU8 alternative_less; + SpanU8 alternative_comp_set_name_embed; } set_instantiation_op; void set_instantiation_op_fix(set_instantiation_op* self){ assert(self->T.len > 0); + assert(!self->t_integer || self->alternative_equal.len == 0); + assert(!self->t_integer || self->alternative_less.len == 0); + assert((self->alternative_less.len == 0 && self->alternative_equal.len + && self->alternative_comp_set_name_embed.len + )||( + self->alternative_comp_set_name_embed.len != 0 && + (self->alternative_less.len != 0 || self->alternative_equal.len != 0))); if (self->t_ptr) self->t_integer = true; if (self->t_integer) diff --git a/src/l1_5/codegen/rb_tree_set_map_template_inst.h b/src/l1_5/codegen/rb_tree_set_map_template_inst.h index cd26652..17f7c23 100644 --- a/src/l1_5/codegen/rb_tree_set_map_template_inst.h +++ b/src/l1_5/codegen/rb_tree_set_map_template_inst.h @@ -7,6 +7,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key != self->el.buf[cur - 1]"); + if (op.alternative_equal.len != 0) + return VecU8_fmt("!%s(&key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("!%s_equal_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -14,6 +16,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiatio NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key < self->el.buf[cur - 1]"); + if (op.alternative_less.len != 0) + return VecU8_fmt("%s(&key, &self->el.buf[cur - 1])", op.alternative_less); return VecU8_fmt("%s_less_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -22,6 +26,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op NODISCARD VecU8 codegen_rb_tree_set_key_ref_NOT_EQUAL_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key != self->el.buf[cur - 1]"); + if (op.alternative_equal.len != 0) + return VecU8_fmt("!%s(key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("!%s_equal_%s(key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -29,6 +35,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_ref_NOT_EQUAL_element(set_instantiation_ NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key == self->el.buf[cur - 1]"); + if (op.alternative_equal.len != 0) + return VecU8_fmt("%s(key, &self->el.buf[cur - 1])", op.alternative_equal); return VecU8_fmt("%s_equal_%s(ref, &self->el.buf[cur - 1])", op.T, op.T); } @@ -36,6 +44,8 @@ NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op o NODISCARD VecU8 codegen_rb_tree_set_key_ref_LESS_element(set_instantiation_op op){ if (op.t_integer) return VecU8_fmt("key < self->el.buf[cur - 1]"); + if (op.alternative_less.len != 0) + return VecU8_fmt("%s(key, &self->el.buf[cur - 1])", op.alternative_less); return VecU8_fmt("%s_less_%s(key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -86,6 +96,12 @@ NODISCARD VecU8 codegen_rb_tree_set_taking_ref_t_argument(set_instantiation_op o return !op.t_integer ? VecU8_fmt("const %s*", op.T) : VecU8_from_span(op.T); } +NODISCARD VecU8 get_name_of_rb_tree_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); +} + /* Generates methods _insert() _pop_substitute() _erase_substitute() for SetT * Takes ownership of strings Tc, Fc */ void codegen_append_rb_tree_set_insert_kind_method( @@ -175,7 +191,7 @@ void codegen_append_rb_tree_set_erase_kind_method( SPACE "}\n" "%v" /* saving_prev */ SPACE "U64 z = cur;\n" - SPACE "U64 y = (self->tree.buf[z].left == 0 || self->tree.buf[z].right == 0) ? z : RBTree_minimum_in_subtree(self->tree.buf, self->tree.buf[z].right);\n" + SPACE "U64 y = (self->tree.buf[z].left == 0 || self->tree.buf[z].right == 0) ? z : 1(self->tree.buf, self->tree.buf[z].right);\n" SPACE "U64 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].right;\n" SPACE "assert(x != y && x != z);\n" SPACE "U64 x_adopter = self->tree.buf[y].parent;\n" @@ -223,7 +239,7 @@ void codegen_append_rb_tree_set_erase_kind_method( NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op op){ set_instantiation_op_fix(&op); VecU8 res = VecU8_new(); - VecU8 g_set = VecU8_fmt("BuffRBTree_Set%s", op.T); + VecU8 g_set = get_name_of_rb_tree_set_structure(op); SpanU8 set = VecU8_to_span(&g_set); VecU8_append_vec(&res, VecU8_fmt( "typedef struct {\n" @@ -294,7 +310,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op } 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_t_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 cue element */ @@ -379,20 +395,111 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op SPACE "return self->root != 0 ? RBTree_maximum_in_subtree(self->tree.buf, self->root) : 0;\n" "}\n\n", set, set)); - // todo: continue from here. Implement method _pop_and_substitute() + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_max_less(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ + SPACE "U64 last_less = 0;\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "cur = cur->left;\n" + SPACE SPACE SPACE "if (cur == 0)\n" + SPACE SPACE SPACE SPACE "return last_less;\n" + SPACE SPACE SPACE "while (self->tree.buf[cur].right != 0)\n" + SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE SPACE "return cur;\n" + SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */ + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "last_less = cur;\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return last_less;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); - // todo: All the other methods are secondary in importance + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_max_less_or_eq(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ + SPACE "U64 last_less = 0;\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "return cur;\n" + SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */ + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "last_less = cur;\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return last_less;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); + + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_min_grtr(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ + SPACE "U64 last_grtr = 0;\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "cur = cur->right;\n" + SPACE SPACE SPACE "if (cur == 0)\n" + SPACE SPACE SPACE SPACE "return last_grtr;\n" + SPACE SPACE SPACE "while (self->tree.buf[cur].left != 0)\n" + SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE SPACE "return cur;\n" + SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */ + SPACE SPACE SPACE "last_grtr = cur;\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return last_grtr;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); + + + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_min_grtr_or_eq(const %s* self, %v key) {\n" /* set, set, taking_ref_t_argument */ + SPACE "U64 last_grtr = 0;\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "return cur;\n" + SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */ + SPACE SPACE SPACE "last_grtr = cur;\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return last_grtr;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); VecU8_drop(g_set); return res; } -void generate_rb_tree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, option_template_instantiation_op op) { +void generate_rb_tree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, set_instantiation_op op) { VecU8 text = VecU8_from_cstr("/* Automatically generated file. Do not edit it.\n" " * Do not include it in more than one place */\n\n"); - VecU8_append_vec(&text, generate_OptionT_struct_and_methods(op)); - VecU8 nt_path = VecU8_fmt("%s/eve/%s/BuffRBTree_Set%s%c", layer, bonus_ns, op.T, 0); + VecU8_append_vec(&text, generate_rb_tree_Set_template_instantiation(op)); + VecU8 nt_path = VecU8_fmt("%s/eve/%s/%s.h%c", layer, bonus_ns, op.T, get_name_of_rb_tree_set_structure(op)); write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text)); VecU8_drop(nt_path); VecU8_drop(text); @@ -402,7 +509,8 @@ void generate_rb_tree_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%sBuffRBTree_Set%s.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), op.T); + VecU8 path = VecU8_fmt("%s/%s%s%v.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), + get_name_of_rb_tree_set_structure(op)); GeneratedHeader head = begin_header(VecU8_to_span(&path)); VecU8_drop(path); VecU8_append_span(&head.result, cstr("#include \"../../")); diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h index 44771f0..b01d103 100644 --- a/src/l1_5/core/rb_tree_node.h +++ b/src/l1_5/core/rb_tree_node.h @@ -121,7 +121,7 @@ void RBTree_steal_neighbours(RBTreeNode* tree, U64* root, U64 fr, U64 to){ /* helper function (used in _erase, _find_min methods). It is assumed that s is not null. * Guaranteed to return no-null */ -U64 RBTree_minimum_in_subtree(RBTreeNode* tree, U64 s){ +U64 RBTree_minimum_in_subtree(const RBTreeNode* tree, U64 s){ assert(s != 0); while (tree[s].left != 0) s = tree[s].left; @@ -131,7 +131,7 @@ U64 RBTree_minimum_in_subtree(RBTreeNode* tree, U64 s){ /* helper function (used in _find_max, _find_prev methods). It is assumed that s is not null. * Guaranteed to return no-null */ -U64 RBTree_maximum_in_subtree(RBTreeNode* tree, U64 s){ +U64 RBTree_maximum_in_subtree(const RBTreeNode* tree, U64 s){ assert(s != 0); while (tree[s].right != 0) s = tree[s].right;