From b0cd4a92cd79c879be2460de380fad81e139042a Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Thu, 18 Sep 2025 11:51:00 +0300 Subject: [PATCH 1/9] Saving unfinished work: another refactoring of l1 codegen. Yet another... --- CMakeLists.txt | 45 ++-- Makefile | 31 ++- src/l1/anne/codegen_from_l1_5.h | 1 + src/l1/anne/liza.h | 5 +- src/l1/anne/some_tests.h | 6 +- src/l1/anne/util_temp_geom.h | 14 +- src/l1/anne/util_temp_very_base.h | 17 +- src/l1/anne/util_temp_vulkan.h | 33 ++- src/l1/codegen/codegen.h | 23 ++ src/l1/codegen/util_template_inst.h | 223 ++++++++++-------- src/l1/core/VecU8_as_str.h | 99 +++++++- .../codegen/all_set_map_templ_util_inst.h | 135 +++++++++++ .../codegen/rb_tree_set_map_template_inst.h | 102 ++++++++ src/l1_5/core/rb_tree_node.h | 19 ++ src/l2/liza/playing_sound_loop.h | 2 +- src/l2/margaret/vulkan_utils.h | 1 + src/l2/tests/r2/r2b.c | 2 + 17 files changed, 607 insertions(+), 151 deletions(-) create mode 100644 src/l1_5/codegen/all_set_map_templ_util_inst.h create mode 100644 src/l1_5/codegen/rb_tree_set_map_template_inst.h create mode 100644 src/l1_5/core/rb_tree_node.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7591810..919c75b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,29 +27,30 @@ add_compile_definitions(_POSIX_C_SOURCE=200112L) add_compile_definitions(_GNU_SOURCE) add_compile_options(-fno-trapping-math) -#add_executable(codegen_l1 src/l1/anne/codegen.c) -#target_compile_definitions(codegen_l1 -# PRIVATE PROTOTYPE1_L1_CODEGEN_BOOTSTRAP_USE_CHICKEN_VECU8) +add_executable(codegen_l1 src/l1/anne/codegen.c) +target_compile_definitions(codegen_l1 + PRIVATE PROTOTYPE1_L1_CODEGEN_BOOTSTRAP_USE_CHICKEN_VECU8) -add_executable(0_test src/l1_4/tests/t0.c) -add_executable(1_test src/l1_4/tests/t1.c) - -add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) - -add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c) -target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -lpng) - -add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c) -target_link_libraries(0r_tex_init_prep -lm -lpng) - -add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c) -target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon) - -add_executable(2a_render_test src/l2/tests/r2/r2a.c gen/l_wl_protocols/xdg-shell-private.c) -target_link_libraries(2a_render_test ${LIBPIPEWIRE_LIBS} -lwayland-client -lrt -lm -lxkbcommon) - -add_executable(3_render_test src/l2/tests/r3/r3.c gen/l_wl_protocols/xdg-shell-private.c) -target_link_libraries(3_render_test -lwayland-client -lm -lvulkan -lxkbcommon) +#add_executable(0_test src/l1_4/tests/t0.c) +#add_executable(1_test src/l1_4/tests/t1.c) +# +#add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) +# +#add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c +# src/l1/core/rb_tree_node.h) +#target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -lpng) +# +#add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c) +#target_link_libraries(0r_tex_init_prep -lm -lpng) +# +#add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c) +#target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon) +# +#add_executable(2a_render_test src/l2/tests/r2/r2a.c gen/l_wl_protocols/xdg-shell-private.c) +#target_link_libraries(2a_render_test ${LIBPIPEWIRE_LIBS} -lwayland-client -lrt -lm -lxkbcommon) +# +#add_executable(3_render_test src/l2/tests/r3/r3.c gen/l_wl_protocols/xdg-shell-private.c) +#target_link_libraries(3_render_test -lwayland-client -lm -lvulkan -lxkbcommon) #add_executable(0_play_test src/l3/tests/p0.c) #target_link_libraries(0_play_test -lncurses) diff --git a/Makefile b/Makefile index e18fd5c..91d9d48 100644 --- a/Makefile +++ b/Makefile @@ -53,22 +53,51 @@ gen/l_wl_protocols/xdg-shell-private.c: $(wl_protocols)/stable/xdg-shell/xdg-she xdg_shell_private := gen/l_wl_protocols/xdg-shell-private.c l_wl_protocols := gen/l_wl_protocols/xdg-shell-client.h $(xdg_shell_private) + out/l2/r0: src/l2/tests/r0/r0.c $(HEADERS_src_l2) $(l_wl_protocols) mkdir -p out/l2 $(cc) $(cflags) -o $@ $< $(xdg_shell_private) -lvulkan -lm -lxkbcommon -lwayland-client -lpng +out/l2/r0_tex_init_prep: src/l2/tests/r0/r0_tex_init_prep.c $(HEADERS_src_l2) + mkdir -p out/l2 + $(cc) $(cflags) -o $@ $< -lm -lpng + +.PHONY: run_r0 +run_r0: out/l2/r0 + cd src/l2/tests/r0 && ../../../../out/l2/r0 + +.PHONY: run_r0_tex_init_prep +run_r0_tex_init_prep: out/l2/r0_tex_init_prep + cd src/l2/tests/r0 && ../../../../out/l2/r0_tex_init_prep + + out/l2/r1: src/l2/tests/r1/r1.c $(HEADERS_src_l2) $(l_wl_protocols) mkdir -p out/l2 $(cc) $(cflags) -o $@ $< $(xdg_shell_private) -lwayland-client -lrt -lxkbcommon -lm -out/l2/r2a: src/l2/tests/r2/r2a.c $(HEADERS_src_l2) $(l_wl_protocols) +.PHONY: run_r1 +run_r1: out/l2/r1 + ./out/l2/r1 + + +out/l2/r2: src/l2/tests/r2/r2a.c $(HEADERS_src_l2) $(l_wl_protocols) mkdir -p out/l2 $(cc) $(cflags) -o $@ $< $(xdg_shell_private) -lwayland-client -lrt -lxkbcommon -lm $(libpipewire_flags) +.PHONY: run_r2 +run_r2: out/l2/r2 + ./out/l2/r2 + + out/l2/r3: src/l2/tests/r3/r3.c $(HEADERS_src_l2) $(l_wl_protocols) mkdir -p out/l2 $(cc) $(cflags) -o $@ $< $(xdg_shell_private) -lwayland-client -lrt -lxkbcommon -lm -lvulkan +.PHONY: run_r3 +run_r3: out/l2/r3 + ./out/l2/r3 + + .PHONY: clean clean: rm -rf gen out diff --git a/src/l1/anne/codegen_from_l1_5.h b/src/l1/anne/codegen_from_l1_5.h index 6781f65..82d8e06 100644 --- a/src/l1/anne/codegen_from_l1_5.h +++ b/src/l1/anne/codegen_from_l1_5.h @@ -10,6 +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("RBTreeNode"), true, false); } #endif \ No newline at end of file diff --git a/src/l1/anne/liza.h b/src/l1/anne/liza.h index 99dca6c..ab248d9 100644 --- a/src/l1/anne/liza.h +++ b/src/l1/anne/liza.h @@ -7,8 +7,9 @@ void generate_liza_l1_headers() { SpanU8 l = cstr("l1"); SpanU8 ns = cstr("liza"); mkdir_nofail("l1/eve/liza"); - generate_util_templ_inst_eve_header(l, ns, cstr("BoxLizaSound"), - (util_templates_instantiation_options){ .vec = true}); + // todo: continue OptionT + util_templates_instantiation_options refactoring from here + generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ + .T = cstr("BoxLizaSound"), .vec = true}); generate_util_templ_inst_eve_header(l, ns, cstr("PlayingSound"), (util_templates_instantiation_options){.vec_extended = true}); generate_util_templ_inst_eve_header(l, ns, cstr("BoxLizaInstrument"), diff --git a/src/l1/anne/some_tests.h b/src/l1/anne/some_tests.h index ca058c4..f776133 100644 --- a/src/l1/anne/some_tests.h +++ b/src/l1/anne/some_tests.h @@ -25,9 +25,9 @@ void generate_headers_for_r0_r1_r2_r3() { mkdir_nofail("l1/eve/r2"); { /* r2 */ SpanU8 ns = cstr("r2"); - generate_util_templ_inst_eve_header(l, ns, cstr("PlayingSound"), (util_templates_instantiation_options){ - .vec_extended = true}); - + generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ + .T = cstr("PlayingSound"), .vec_extended = true + }); } } diff --git a/src/l1/anne/util_temp_geom.h b/src/l1/anne/util_temp_geom.h index f1916cd..6b24d2d 100644 --- a/src/l1/anne/util_temp_geom.h +++ b/src/l1/anne/util_temp_geom.h @@ -10,10 +10,9 @@ void generate_util_temp_geom_headers() { VecU8_append_span(&head.result, cstr("#include \"../../src/l1/core/util.h\"\n\n")); SpanU8 T[] = {cstr("cvec3"), cstr("cvec4")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { - VecU8_append_vec(&head.result, generate_util_templates_instantiation(T[i], - (util_templates_instantiation_options){ - .t_primitive = true, .vec = true, .span = true, .collab_vec_span = true, - })); + VecU8_append_vec(&head.result, generate_util_templates_instantiation((util_templates_instantiation_options){ + .T = T[i], .t_primitive = true, .vec = true, .span = true, .collab_vec_span = true, + })); } finish_header(head); } @@ -23,10 +22,9 @@ void generate_util_temp_geom_headers() { VecU8_append_span(&head.result, cstr("#include \"../../src/l1/core/util.h\"\n\n")); SpanU8 T[] = {cstr("vec2"), cstr("vec3"), cstr("vec4")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { - VecU8_append_vec(&head.result, generate_util_templates_instantiation(T[i], - (util_templates_instantiation_options){ - .t_primitive = true, .vec = true, .span = true, .collab_vec_span = true, - })); + VecU8_append_vec(&head.result, generate_util_templates_instantiation((util_templates_instantiation_options){ + .T = T[i], .t_primitive = true, .vec = true, .span = true, .collab_vec_span = true, + })); } finish_header(head); } diff --git a/src/l1/anne/util_temp_very_base.h b/src/l1/anne/util_temp_very_base.h index c4ea880..22ad5bc 100644 --- a/src/l1/anne/util_temp_very_base.h +++ b/src/l1/anne/util_temp_very_base.h @@ -10,7 +10,8 @@ void generate_util_temp_very_base_headers() { VecU8_append_span(&head.result, cstr("#include \"../../src/l1/core/util.h\"\n\n")); SpanU8 T[4] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { - VecU8_append_vec(&head.result, generate_util_templates_instantiation(T[i], (util_templates_instantiation_options){ + VecU8_append_vec(&head.result, generate_util_templates_instantiation((util_templates_instantiation_options){ + .T = T[i], .t_integer = true, .t_primitive = true, .vec = true, .vec_extended = true, .vec_equal = true, .span = true, .span_extended = true, .mut_span = true, .collab_vec_span = true, .collab_vec_span_extended = true, @@ -23,8 +24,8 @@ void generate_util_temp_very_base_headers() { VecU8_append_span(&head.result, cstr("#include \"../../src/l1/core/util.h\"\n\n")); SpanU8 T[4] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { - VecU8_append_vec(&head.result, generate_util_templates_instantiation(T[i], (util_templates_instantiation_options){ - .t_integer = true, .t_primitive = true, .option = true + VecU8_append_vec(&head.result, generate_OptionT_struct_and_methods((option_template_instantiation_op){ + .T = T[i], .t_integer = true, .t_primitive = true })); } finish_header(head); @@ -34,8 +35,9 @@ void generate_util_temp_very_base_headers() { VecU8_append_span(&head.result, cstr("#include \"VecAndSpan_int_primitives.h\"\n\n")); SpanU8 T[4] = {cstr("VecU8"), cstr("VecU16"), cstr("VecU32"), cstr("VecU64")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { - VecU8_append_vec(&head.result, generate_util_templates_instantiation(T[i], (util_templates_instantiation_options){ - .t_clonable = true, .vec = true, .vec_extended = true, .span = true, .collab_vec_span = true, .vec_equal = true, + VecU8_append_vec(&head.result, generate_util_templates_instantiation((util_templates_instantiation_options){ + .T = T[i], .t_clonable = true, .vec = true, .vec_extended = true, + .span = true, .collab_vec_span = true, .vec_equal = true, })); } VecU8_append_vec(&head.result, generate_VecT_new_of_size_method(cstr("VecU8"))); @@ -46,9 +48,8 @@ void generate_util_temp_very_base_headers() { VecU8_append_span(&head.result, cstr("#include \"VecAndSpan_int_primitives.h\"\n\n")); SpanU8 T[1] = {cstr("SpanU8")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { - VecU8_append_vec(&head.result, generate_util_templates_instantiation(T[i], (util_templates_instantiation_options){ - .t_primitive = true, .vec = true, .span = true, .mut_span = true, - .collab_vec_span = true, + VecU8_append_vec(&head.result, generate_util_templates_instantiation((util_templates_instantiation_options){ + .T = T[i], .t_primitive = true, .vec = true, .span = true, .mut_span = true, .collab_vec_span = true, })); } finish_header(head); diff --git a/src/l1/anne/util_temp_vulkan.h b/src/l1/anne/util_temp_vulkan.h index 0318a46..1201086 100644 --- a/src/l1/anne/util_temp_vulkan.h +++ b/src/l1/anne/util_temp_vulkan.h @@ -11,16 +11,29 @@ void generate_util_templ_inst_for_vulkan_headers() { mkdir_nofail("l1/vulkan"); generate_guarded_span_company_for_primitive(l, ns, cstr("VkQueueFamilyProperties"), vulkan_dep, true, false); generate_guarded_span_company_for_primitive(l, ns, cstr("VkExtensionProperties"), vulkan_dep, true, false); - generate_util_templ_inst_guarded_header(l, ns, cstr("VkSurfaceFormatKHR"), vulkan_dep, - (util_templates_instantiation_options){ .t_primitive = true, .vec = true, .option = true }); - generate_util_templ_inst_guarded_header(l, ns, cstr("VkPresentModeKHR"), vulkan_dep, - (util_templates_instantiation_options){ .t_primitive = true, .vec = true, .option = true }); - generate_util_templ_inst_guarded_header(l, ns, cstr("VkCompositeAlphaFlagBitsKHR"), vulkan_dep, - (util_templates_instantiation_options){ .t_primitive = true, .option = true }); - generate_util_templ_inst_guarded_header(l, ns, cstr("VkExtent2D"), vulkan_dep, - (util_templates_instantiation_options){ .t_primitive = true, .option = true }); - generate_util_templ_inst_guarded_header(l, ns, cstr("VkFormat"), vulkan_dep, - (util_templates_instantiation_options){ .t_primitive = true, .span = true, .option = true }); + + generate_guarded_span_company_for_primitive(l, ns, cstr("VkSurfaceFormatKHR"), vulkan_dep, true, false); + generate_guarded_span_company_for_primitive(l, ns, cstr("VkPresentModeKHR"), vulkan_dep, true, false); + generate_guarded_span_company_for_primitive(l, ns, cstr("VkFormat"), vulkan_dep, false, true); + + generate_Option_templ_inst_guarded_header(l, ns, vulkan_dep, (option_template_instantiation_op){ + .T = cstr("VkPresentModeKHR"), .t_integer = true + }); + generate_Option_templ_inst_guarded_header(l, ns, vulkan_dep, (option_template_instantiation_op){ + .T = cstr("VkFormat"), .t_integer = true + }); + generate_Option_templ_inst_guarded_header(l, ns, vulkan_dep, (option_template_instantiation_op){ + .T = cstr("VkSurfaceFormatKHR"), .t_primitive = true + }); + generate_Option_templ_inst_guarded_header(l, ns, vulkan_dep, (option_template_instantiation_op){ + .T = cstr("VkCompositeAlphaFlagBitsKHR"), .t_integer = true + }); + generate_Option_templ_inst_guarded_header(l, ns, vulkan_dep, (option_template_instantiation_op){ + .T = cstr("VkExtent2D"), .t_primitive = true + }); + // for these + + generate_guarded_span_company_for_primitive(l, ns, cstr("VkPhysicalDevice"), vulkan_dep, true, false); generate_guarded_span_company_for_primitive(l, ns, cstr("VkImage"), vulkan_dep, true, false); generate_guarded_span_company_for_primitive(l, ns, cstr("VkImageView"), vulkan_dep, true, false); diff --git a/src/l1/codegen/codegen.h b/src/l1/codegen/codegen.h index 3a218c3..668ab60 100644 --- a/src/l1/codegen/codegen.h +++ b/src/l1/codegen/codegen.h @@ -48,4 +48,27 @@ void finish_layer(SpanU8 layer_name) { VecU8_drop(nt_name); } +int get_number_of_parts_in_header_namespace(SpanU8 ns) { + int a = 0; + for (size_t i = 0; i < ns.len; i++) { + if (*SpanU8_at(ns, i) != '/' && (i == 0 || *SpanU8_at(ns, i - 1) == '/')) + a++; + } + return a; +} + +/* takes ownership of strings a, b */ +NODISCARD VecU8 codegen_T_ref_equal_T_ref(SpanU8 T, bool t_integer, VecU8 a, VecU8 b){ + if (t_integer) + return VecU8_fmt("(%s == %s)", VecU8_to_span(&a), VecU8_to_span(&b)); + return VecU8_fmt("%s_equal_%s(%v, %v)", T, T, a, b); +} + +/* takes ownership of strings a, b */ +NODISCARD VecU8 codegen_T_ref_less_T_ref(SpanU8 T, bool t_integer, VecU8 a, VecU8 b){ + if (t_integer) + return VecU8_fmt("(%s < %s)", VecU8_to_span(&a), VecU8_to_span(&b)); + return VecU8_fmt("%s_equal_%s(%v, %v)", T, T, a, b); +} + #endif diff --git a/src/l1/codegen/util_template_inst.h b/src/l1/codegen/util_template_inst.h index 99c08fb..5f151d6 100644 --- a/src/l1/codegen/util_template_inst.h +++ b/src/l1/codegen/util_template_inst.h @@ -387,65 +387,13 @@ NODISCARD VecU8 generate_SpanT_VecT_trivmove_collab(SpanU8 T, bool primitive, bo return res; } -NODISCARD VecU8 generate_OptionT_struct_and_methods(SpanU8 T, bool primitive, bool clonable) { - VecU8 g_OptionT = VecU8_fmt("Option%s", T); - SpanU8 OptionT = VecU8_to_span(&g_OptionT); - - VecU8 res = VecU8_fmt( - "typedef struct {\n" - SPACE4 "Option_variant variant;\n" - SPACE4 "%s some;\n" - "} %s;\n\n", T, OptionT); - - VecU8_append_vec(&res, VecU8_fmt("#define None_%s() (%s){ .variant = Option_None }\n\n", T, OptionT)); - VecU8_append_vec(&res, VecU8_fmt("%s Some_%s(%s obj) {\n" - SPACE4 "return (%s){ .variant = Option_Some, .some = obj };\n" - "}\n\n", OptionT, T, T, OptionT)); - - VecU8_append_vec(&res, VecU8_fmt( - "const %s* %s_expect_ref(const %s* self){\n" - SPACE4 "if (self->variant == Option_None)\n" - SPACE4 SPACE4 "abortf(\"Expected something in const %s* got None\\n\");\n" - SPACE4 "return &self->some;\n" - "}\n\n", T, OptionT, OptionT, OptionT)); - VecU8_append_vec(&res, VecU8_fmt( - "%s* %s_expect_mut_ref(%s* self){\n" - SPACE4 "if (self->variant == Option_None)\n" - SPACE4 SPACE4 "abortf(\"Expected something in %s* got None\\n\");\n" - SPACE4 "return &self->some;\n" - "}\n\n", T, OptionT, OptionT, OptionT)); - VecU8_append_vec(&res, VecU8_fmt( - "%s %s_expect(%s self){\n" - SPACE4 "if (self.variant == Option_None)\n" - SPACE4 SPACE4 "abortf(\"Expected something in %s got None\\n\");\n" - SPACE4 "return self.some;\n" - "}\n\n", T, OptionT, OptionT, OptionT)); - if (!primitive) { - VecU8_append_vec(&res, VecU8_fmt( - "void %s_drop(%s self) {\n" - SPACE4 "if (self.variant == Option_None)\n" - SPACE4 SPACE4 "%s_drop(self.some);\n" - "}\n\n", OptionT, OptionT, T)); - if (clonable) { - VecU8_append_vec(&res, VecU8_fmt( - "NODISCARD %s %s_clone(const %s* self) {\n" - SPACE4 "if (self->variant == Option_None)\n" - SPACE4 SPACE4 "return (%s) { .variant = Option_None };\n" - SPACE4 "return (%s){ .variant = Option_Some, .some = %s_clone(&self->some) };\n" - "}\n\n", OptionT, OptionT, OptionT, OptionT, OptionT, T)); - } - } - - VecU8_drop(g_OptionT); - return res; -} - /* The only reason this function exists is because in C it is easier to supply a lot of brace list arguments, * than function arguments. This struct is an argument for generate_util_templates_instantiation * It is assumed that all necessary properties of T have been met, including cases where * T needs to be sized (everywhere) and trivially movable (for VecT) */ typedef struct { + SpanU8 T; bool t_integer; bool t_primitive; bool t_clonable; @@ -459,10 +407,10 @@ typedef struct { bool span_sort; bool collab_vec_span; bool collab_vec_span_extended; - bool option; } util_templates_instantiation_options; void util_templates_instantiation_options_fix(util_templates_instantiation_options* op) { + assert(op->T.len > 0); if (op->t_integer) op->t_primitive = true; if (op->t_primitive) @@ -483,98 +431,84 @@ void util_templates_instantiation_options_fix(util_templates_instantiation_optio op->span = true; op->vec = true; } - assert(op->vec || op->span || op->option); + assert(op->vec || op->span); assert(op->t_primitive || !op->t_integer); assert(!op->t_primitive || op->t_clonable); } -NODISCARD VecU8 generate_util_templates_instantiation(SpanU8 T, util_templates_instantiation_options op) { +NODISCARD VecU8 generate_util_templates_instantiation(util_templates_instantiation_options op) { VecU8 res = VecU8_new(); util_templates_instantiation_options_fix(&op); if (op.vec) { - VecU8_append_vec(&res, generate_VecT_struct_and_base_methods(T, op.t_primitive, op.t_clonable)); + VecU8_append_vec(&res, generate_VecT_struct_and_base_methods(op.T, op.t_primitive, op.t_clonable)); } if (op.vec_extended) { assert(op.vec); - VecU8_append_vec(&res, generate_VecT_trivmove_extended_methods(T, op.t_primitive, op.t_clonable)); + VecU8_append_vec(&res, generate_VecT_trivmove_extended_methods(op.T, op.t_primitive, op.t_clonable)); } if (op.vec_equal) { assert(op.vec); - VecU8_append_vec(&res, generate_VecT_equal_method(T, op.t_integer)); + VecU8_append_vec(&res, generate_VecT_equal_method(op.T, op.t_integer)); } if (op.vec_new_of_size) { assert(op.vec); - VecU8_append_vec(&res, generate_VecT_new_of_size_method(T)); + VecU8_append_vec(&res, generate_VecT_new_of_size_method(op.T)); } if (op.span) { - VecU8_append_vec(&res, generate_SpanT_struct_and_methods(T, op.t_integer, op.mut_span, false, op.span_extended, op.span_sort)); + VecU8_append_vec(&res, generate_SpanT_struct_and_methods(op.T, op.t_integer, op.mut_span, false, op.span_extended, op.span_sort)); } if (op.collab_vec_span) { assert(op.vec && op.span); - VecU8_append_vec(&res, generate_SpanT_VecT_trivmove_collab(T, op.t_primitive, op.t_clonable, op.mut_span, op.collab_vec_span_extended)); - } - if (op.option) { - VecU8_append_vec(&res, generate_OptionT_struct_and_methods(T, op.t_primitive, op.t_clonable)); + VecU8_append_vec(&res, generate_SpanT_VecT_trivmove_collab(op.T, op.t_primitive, op.t_clonable, op.mut_span, op.collab_vec_span_extended)); } return res; } -NODISCARD VecU8 util_templates_instantiation_get_appropriate_filename( - SpanU8 T, util_templates_instantiation_options op - ) { +NODISCARD VecU8 util_templates_instantiation_get_appropriate_filename(util_templates_instantiation_options op) { util_templates_instantiation_options_fix(&op); - return VecU8_fmt("%s%s%s%s%s""%s%s.h", + return VecU8_fmt("%s%s%s""%s%s.h", op.vec ? cstr("Vec") : cstr(""), op.vec && op.span ? cstr("And") : cstr(""), op.span ? cstr("Span") : cstr(""), - (op.span || op.vec) && op.option ? cstr("And") : cstr(""), op.option ? cstr("Option") : cstr(""), - (int)op.vec + (int)op.span + (int)op.option > 1 ? cstr("_") : cstr(""), T); + (int)op.vec + (int)op.span > 1 ? cstr("_") : cstr(""), op.T); } -void generate_util_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, SpanU8 T, util_templates_instantiation_options op) { +void generate_util_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, util_templates_instantiation_options 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_util_templates_instantiation(T, op)); - VecU8 filename = util_templates_instantiation_get_appropriate_filename(T, op); + VecU8_append_vec(&text, generate_util_templates_instantiation(op)); + VecU8 filename = util_templates_instantiation_get_appropriate_filename(op); // todo: add %v that takes a vector - VecU8 nt_path = VecU8_fmt("%s/eve/%s/%s%c", layer, bonus_ns, VecU8_to_span(&filename), 0); + VecU8 nt_path = VecU8_fmt("%s/eve/%s/%v%c", layer, bonus_ns, filename, 0); write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text)); VecU8_drop(nt_path); - VecU8_drop(filename); VecU8_drop(text); } void generate_eve_span_company_for_primitive(SpanU8 layer, SpanU8 ns, SpanU8 T, bool with_vector, bool with_span) { - generate_util_templ_inst_eve_header(layer, ns, T, (util_templates_instantiation_options){ + generate_util_templ_inst_eve_header(layer, ns, (util_templates_instantiation_options){ + .T = T, .t_primitive = true, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span }); } void generate_eve_span_company_for_non_primitive_clonable(SpanU8 layer, SpanU8 ns, SpanU8 T, bool with_vector, bool with_span) { - generate_util_templ_inst_eve_header(layer, ns, T, (util_templates_instantiation_options){ + generate_util_templ_inst_eve_header(layer, ns, (util_templates_instantiation_options){ + .T = T, .t_clonable = true, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span }); } void generate_eve_span_company_for_non_primitive_non_clonable(SpanU8 layer, SpanU8 ns, SpanU8 T, bool with_vector, bool with_span) { - generate_util_templ_inst_eve_header(layer, ns, T, (util_templates_instantiation_options){ + generate_util_templ_inst_eve_header(layer, ns, (util_templates_instantiation_options){ + .T = T, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span }); } -int get_number_of_parts_in_header_namespace(SpanU8 ns) { - int a = 0; - for (size_t i = 0; i < ns.len; i++) { - if (*SpanU8_at(ns, i) != '/' && (i == 0 || *SpanU8_at(ns, i - 1) == '/')) - a++; - } - return a; -} - void generate_util_templ_inst_guarded_header( - SpanU8 layer, SpanU8 bonus_ns, SpanU8 T, SpanU8 dependencies, - util_templates_instantiation_options op + SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, util_templates_instantiation_options op ) { assert(layer.len > 1); - VecU8 filename = util_templates_instantiation_get_appropriate_filename(T, op); + VecU8 filename = util_templates_instantiation_get_appropriate_filename(op); VecU8 path = VecU8_fmt("%s/%s%s%s", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), VecU8_to_span(&filename)); GeneratedHeader head = begin_header(VecU8_to_span(&path)); VecU8_drop(path); @@ -586,14 +520,15 @@ void generate_util_templ_inst_guarded_header( VecU8_append_span(&head.result, cstr("src/l1/core/util.h\"\n")); VecU8_append_span(&head.result, dependencies); VecU8_append_span(&head.result, cstr("\n\n")); - VecU8_append_vec(&head.result, generate_util_templates_instantiation(T, op)); + VecU8_append_vec(&head.result, generate_util_templates_instantiation(op)); finish_header(head); } void generate_guarded_span_company_for_primitive( SpanU8 layer, SpanU8 ns, SpanU8 T, SpanU8 dependencies, bool with_vector, bool with_span ) { - generate_util_templ_inst_guarded_header(layer, ns, T, dependencies, (util_templates_instantiation_options){ + generate_util_templ_inst_guarded_header(layer, ns, dependencies, (util_templates_instantiation_options){ + .T = T, .t_primitive = true, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span }); } @@ -601,7 +536,8 @@ void generate_guarded_span_company_for_primitive( void generate_guarded_span_company_for_non_primitive_clonable( SpanU8 layer, SpanU8 ns, SpanU8 T, SpanU8 dependencies, bool with_vector, bool with_span ) { - generate_util_templ_inst_guarded_header(layer, ns, T, dependencies, (util_templates_instantiation_options){ + generate_util_templ_inst_guarded_header(layer, ns, dependencies, (util_templates_instantiation_options){ + .T = T, .t_clonable = true, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span }); } @@ -609,9 +545,106 @@ void generate_guarded_span_company_for_non_primitive_clonable( void generate_guarded_span_company_for_non_primitive_non_clonable( SpanU8 layer, SpanU8 ns, SpanU8 T, SpanU8 dependencies, bool with_vector, bool with_span ) { - generate_util_templ_inst_guarded_header(layer, ns, T, dependencies, (util_templates_instantiation_options){ + generate_util_templ_inst_guarded_header(layer, ns, dependencies, (util_templates_instantiation_options){ + .T = T, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span }); } +typedef struct{ + SpanU8 T; + bool t_ptr; + bool t_integer; + bool t_primitive; + bool t_clonable; +} option_template_instantiation_op; + +void option_template_instantiation_op_fix(option_template_instantiation_op* self){ + assert(self->T.len > 0); + if (self->t_ptr) + self->t_integer = true; + if (self->t_integer) + self->t_primitive = true; + if (self->t_primitive) + self->t_clonable = true; +} + +NODISCARD VecU8 generate_OptionT_struct_and_methods(option_template_instantiation_op op) { + VecU8 g_OptionT = VecU8_fmt("Option%s", op.T); + SpanU8 OptionT = VecU8_to_span(&g_OptionT); + + VecU8 res = VecU8_new(); + if (op.t_ptr) { + VecU8_append_vec(&res, VecU8_fmt("typedef %s %s;\n", op.T, OptionT)); + VecU8_append_vec(&res, VecU8_fmt("#define None_%s() NULL\n", op.T)); + VecU8_append_vec(&res, VecU8_fmt("%s Some_%s(%s ref) {\n" SPACE4 "return ref;\n}\n\n", OptionT, op.T, op.T)); + VecU8_append_vec(&res, VecU8_fmt( + "%s %s_expect(%s self) {\n" + SPACE4 "return self;\n" + "}\n\n", op.T, OptionT, OptionT)); + } else { + VecU8_append_vec(&res, VecU8_fmt( + "typedef struct {\n" + SPACE4 "Option_variant variant;\n" + SPACE4 "%s some;\n" + "} %s;\n\n", op.T, OptionT)); + VecU8_append_vec(&res, VecU8_fmt("#define None_%s() (%s){ .variant = Option_None }\n\n", op.T, OptionT)); + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s Some_%s(%s obj) {\n" + SPACE4 "return (%s){ .variant = Option_Some, .some = obj };\n" + "}\n\n", OptionT, op.T, op.T, OptionT)); + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s %s_expect(%s self){\n" + SPACE4 "if (self.variant == Option_None)\n" + SPACE4 SPACE4 "abortf(\"Expected something in %s got None\\n\");\n" + SPACE4 "return self.some;\n" + "}\n\n", op.T, OptionT, OptionT, OptionT)); + if (!op.t_primitive) { + VecU8_append_vec(&res, VecU8_fmt( + "void %s_drop(%s self) {\n" + SPACE4 "if (self.variant == Option_None)\n" + SPACE4 SPACE4 "%s_drop(self.some);\n" + "}\n\n", OptionT, OptionT, op.T)); + if (op.t_clonable) { + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s %s_clone(const %s* self) {\n" + SPACE4 "if (self->variant == Option_None)\n" + SPACE4 SPACE4 "return (%s) { .variant = Option_None };\n" + SPACE4 "return (%s){ .variant = Option_Some, .some = %s_clone(&self->some) };\n" + "}\n\n", OptionT, OptionT, OptionT, OptionT, OptionT, op.T)); + } + } + } + VecU8_drop(g_OptionT); + return res; +} + +void generate_Option_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, option_template_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/Option%s%c", layer, bonus_ns, op.T, 0); + write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text)); + VecU8_drop(nt_path); + VecU8_drop(text); +} + +void generate_Option_templ_inst_guarded_header( + SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, option_template_instantiation_op op + ) { + assert(layer.len > 1); + VecU8 path = VecU8_fmt("%s/%s%sOption%s.h", layer, bonus_ns, bonus_ns.len ? cstr("/") : cstr(""), op.T); + 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/core/util.h\"\n")); + VecU8_append_span(&head.result, dependencies); + VecU8_append_span(&head.result, cstr("\n\n")); + VecU8_append_vec(&head.result, generate_OptionT_struct_and_methods(op)); + finish_header(head); +} + #endif diff --git a/src/l1/core/VecU8_as_str.h b/src/l1/core/VecU8_as_str.h index cc3a320..d40a992 100644 --- a/src/l1/core/VecU8_as_str.h +++ b/src/l1/core/VecU8_as_str.h @@ -19,6 +19,8 @@ VecU8 VecU8_from_cstr(const char* dc) { SpanU8 SpanU8_from_cstr(const char* dc) { return (SpanU8){.data = (const U8*)dc, .len = strlen(dc)}; } + +#define vcstr(dc) (VecU8_from_cstr(dc)) #define cstr(dc) ((SpanU8){(const U8*)dc, sizeof(dc) - 1}) /* Not thread safe (for stdout) !*/ @@ -57,6 +59,82 @@ NODISCARD VecU8 VecU8_format(const char *fmt, ...) { return (VecU8){ .buf = buf, .len = len, .capacity = len + 1 }; } +size_t S64_stringification_get_length(S64 x){ + if (x == -9223372036854775807L-1) + return 20; + int i = 0; + if (x <= 0) { + x = -x; + i++; + } + while (x > 0) { + i++; + x /= 10; + } + return i; +} + +void S64_stringification_into_buf(S64 x, VecU8* targ){ + if (x == 0) { + VecU8_append(targ, '0'); + } else if (x == -9223372036854775807L-1) { + VecU8_append_span(targ, cstr("-9223372036854775807")); + } else { + if (x < 0) { + VecU8_append(targ, '-'); + x = -x; + } + int digits = 0; + while (x > 0) { + VecU8_append(targ, '0' + (x % 10)); + x /= 10; + digits++; + } + U8* left = targ->buf + targ->len - digits; + U8* right = targ->buf + targ->len - 1; + while (left < right) { + U8 t = *right; + *right = *left; + *left = t; + left++; + right++; + } + } +} + +size_t U64_stringification_get_length(U64 x){ + if (x == 0) + return 1; + int i = 0; + while (x > 0) { + i++; + x /= 10; + } + return i; +} + +void U64_stringification_into_buf(U64 x, VecU8* targ){ + if (x == 0) { + VecU8_append(targ, '0'); + } else { + int digits = 0; + while (x > 0) { + VecU8_append(targ, '0' + (x % 10)); + x /= 10; + digits++; + } + U8* left = targ->buf + targ->len - digits; + U8* right = targ->buf + targ->len - 1; + while (left < right) { + U8 t = *right; + *right = *left; + *left = t; + left++; + right++; + } + } +} + // todo: add %d (when I figure out how to do it) NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) { assert(fmt); @@ -73,7 +151,17 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) { k += s.len; } else if (*ch == 'c') { va_arg(args, int); - k ++; + k++; + } else if (*ch == 'v') { + /* We had not taken ownership of YET (will take it the next iteration) */ + VecU8 vs = va_arg(args, VecU8); + k += vs.len; + } else if (*ch == 's') { + S64 x = va_arg(args, S64); + k += S64_stringification_get_length(x); + } else if (*ch == 'u') { + U64 x = va_arg(args, U64); + k += U64_stringification_get_length(x); } else abortf("Format syntax error at pos %lu! Watch out, be careful", (size_t)(ch - fmt)); } else { @@ -95,6 +183,15 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) { } else if (*ch == 'c') { int byte = va_arg(args, int); VecU8_append(&res, (U8)byte); + } else if (*ch == 'v') { + VecU8 vs = va_arg(args, VecU8); + VecU8_append_vec(&res, vs); /* Moved ownership of vs argument */ + } else if (*ch == 's') { + S64 x = va_arg(args, S64); + S64_stringification_into_buf(x, &res); + } else if (*ch == 'u') { + U64 x = va_arg(args, U64); + U64_stringification_into_buf(x, &res); } else assert(false); } else { 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 new file mode 100644 index 0000000..e2ae2ea --- /dev/null +++ b/src/l1_5/codegen/all_set_map_templ_util_inst.h @@ -0,0 +1,135 @@ +#ifndef PROTOTYPE1_SRC_L1_5_CODEGEN_ALL_SET_MAP_TEMPL_UTIL_INST_H +#define PROTOTYPE1_SRC_L1_5_CODEGEN_ALL_SET_MAP_TEMPL_UTIL_INST_H + +#include "../../l1/codegen/util_template_inst.h" + +// todo: continue from here + +/* We assume that T is trivially movable */ +typedef struct { + SpanU8 T; + bool t_ptr; + bool t_integer; + bool t_primitive; + bool t_clonable; +} set_instantiation_op; + +void set_instantiation_op_fix(set_instantiation_op* self){ + assert(self->T.len > 0); + if (self->t_ptr) + self->t_integer = true; + if (self->t_integer) + self->t_primitive = true; + if (self->t_primitive) + self->t_clonable = true; +} + +// /* K and V still must be sized and trivially movable */ +// typedef struct { +// SpanU8 K; +// bool k_integer; +// bool k_primitive; +// bool k_clonable; +// SpanU8 V; +// bool v_primitive; +// bool v_clonable; +// } map_instantiation_options; +// +// void map_instantiation_options_fix(map_instantiation_options* self){ +// if (self->K.len == 0) +// abortf("Key cannot be void"); +// if (self->k_integer) +// self->k_primitive = true; +// if (self->k_primitive) +// self->k_clonable = true; +// +// if (self->V.len == 0) +// self->v_primitive = true; +// if (self->v_primitive) +// self->v_clonable = true; +// } + + +// NODISCARD VecU8 codegen_expr_MapKToV_option_ref_mut_pair_type(map_instantiation_options op){ +// if (op.V.len) +// return VecU8_fmt("OptionRefMutPairMap%sTo%s", op.K, op.V); +// return VecU8_fmt("OptionRefMut%s", op.K); +// } +// +// /* Generates PairMapKToV structure + [drop] + [clone] methods +// * Instantiates Option and Vec +// * Generates alias RefPairMapKToV = const PairMapKToV* +// * Instantiates Option template +// * Generates RefMutMapKToV structure (const ptr to key with mutable ptr to value) +// * Instantiates Option template +// * If `vec_vec_pair_needed` option is set, Vec> template will be instantiated +// * Vec> is needed in Hash_Map implementation +// */ +// NODISCARD VecU8 generate_MapKToV_pair_type(map_instantiation_options op, bool vec_vec_pair_needed){ +// map_instantiation_options_fix(&op); +// if (op.V.len == 0) +// abortf("No need to generate structure for Key Value pair when Value is void\n"); +// VecU8 g_pair = codegen_expr_MapKToV_pair_type(op); +// SpanU8 pair = VecU8_to_span(&g_pair); +// VecU8 result = VecU8_fmt( +// "typedef struct {\n" +// SPACE4 "%s key;\n" +// SPACE4 "%s value;\n" +// "} %s;\n\n", op.K, op.V, pair); +// +// if (!op.k_primitive || !op.v_primitive) { +// VecU8_append_vec(&result, VecU8_fmt("void %s_drop(%s self) {\n", pair, pair)); +// if (!op.k_primitive) +// VecU8_append_vec(&result, VecU8_fmt("%s_drop();\n", op.K)); +// if (!op.v_primitive) +// VecU8_append_vec(&result, VecU8_fmt("%s_drop();\n", op.V)); +// VecU8_append_span(&result, cstr("}\n\n")); +// } +// +// if (op.k_clonable && op.v_clonable && !(op.k_primitive && op.v_primitive)) { +// VecU8_append_vec(&result, VecU8_fmt("%s%s %s_clone(const %s* self) {\n", +// (op.k_primitive && op.v_primitive) ? cstr("") : cstr("NODISCARD"), pair, pair, pair)); +// VecU8_append_vec(&result, VecU8_fmt( +// SPACE4 "return (%s) {.key = %v, .value = %v};\n" +// "}\n\n", +// op.k_primitive ? vcstr("self->key") : VecU8_fmt("%s_clone(&self->key)"), +// op.v_primitive ? vcstr("self->value") : VecU8_fmt("%s_clone(&self->value)"))); +// } +// +// VecU8_append_vec(&result, generate_util_templates_instantiation(pair, (util_templates_instantiation_options){ +// .t_integer = op.k_integer, .t_primitive = op.k_primitive, .t_clonable = op.k_clonable, +// .vec = true, .vec_extended = true, .option = true})); +// +// VecU8 g_vec_pair = codegen_expr_MapKToV_vec_pair_type(op); +// SpanU8 vec_pair = VecU8_to_span(&g_vec_pair); +// VecU8 g_ref_pair = codegen_expr_MapKToV_ref_pair_type(op); +// SpanU8 ref_pair = VecU8_to_span(&g_ref_pair); +// +// VecU8_append_vec(&result, VecU8_fmt("typedef const %s* %s;\n\n", pair, ref_pair)); +// VecU8_append_vec(&result, generate_util_templates_instantiation(ref_pair, +// (util_templates_instantiation_options){.t_integer = true, .option = true})); +// +// VecU8 g_ref_mut_pair = codegen_expr_MapKToV_ref_mut_pair_type(op); +// SpanU8 ref_mut_pair = VecU8_to_span(&g_ref_pair); +// +// VecU8_append_vec(&result, VecU8_fmt( +// "typedef struct {\n" +// SPACE4 "const %s* key;\n" +// SPACE4 "%s* value;\n" +// "} %s\n\n", op.K, op.V, ref_mut_pair)); +// VecU8_append_vec(&result, generate_util_templates_instantiation(ref_mut_pair, +// (util_templates_instantiation_options){.t_integer = true, .option = true})); +// +// if (vec_vec_pair_needed) { +// VecU8_append_vec(&result, generate_util_templates_instantiation(vec_pair, +// (util_templates_instantiation_options){.vec = true})); +// } +// +// VecU8_drop(g_ref_mut_pair); +// VecU8_drop(g_ref_pair); +// VecU8_drop(g_vec_pair); +// VecU8_drop(g_pair); +// return result; +// } + +#endif 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 new file mode 100644 index 0000000..a610b3e --- /dev/null +++ b/src/l1_5/codegen/rb_tree_set_map_template_inst.h @@ -0,0 +1,102 @@ +#ifndef PROTOTYPE1_SRC_L1_5_CODEGEN_RB_TREE_SET_MAP_TEMPLATE_INST_H +#define PROTOTYPE1_SRC_L1_5_CODEGEN_RB_TREE_SET_MAP_TEMPLATE_INST_H + +#include "all_set_map_templ_util_inst.h" + +NODISCARD VecU8 generate_rb_tree_set_template_instantiation(set_instantiation_op op){ + VecU8 res = VecU8_new(); + VecU8 set = VecU8_fmt("BuffRBTree_Set%s", op.T); + VecU8_append_vec(&res, VecU8_fmt( + "typedef struct {\n" + SPACE4 "" + "}\n\n" + )); + // todo: continue from here after I finish the dumb option shit + VecU8_drop(set); + return res; +} + + /* This type will require not only the definition of T=MapPair, but also Vec, Option<>, Option<&mut T> and Option<&T> + * Also it requires l1_5/core/rb_tree_node.h to be included by that point */ +// NODISCARD VecU8 generate_rb_tree_set_template_instantiation(map_instantiation_options op, bool +// bool implementation_mark){ +// VecU8 g_map = get_rb_tree_MapKToV_name(op, implementation_mark); +// SpanU8 map = VecU8_to_span(&g_map); +// VecU8 g_pair = get_MapKToV_pair_name(op); +// SpanU8 pair = VecU8_to_span(&g_pair); +// VecU8 g_vec_pair = VecU8_fmt("Vec%s", pair); +// SpanU8 vec_pair = VecU8_to_span(&g_vec_pair); +// VecU8 g_option_pair = VecU8_fmt("Option%s", pair); +// SpanU8 option_pair = VecU8_to_span(&g_option_pair); +// VecU8 g_option_ref_pair = VecU8_fmt("OptionRef%s", pair); +// SpanU8 option_ref_pair = VecU8_to_span(&g_option_ref_pair); +// VecU8 g_option_ref_mut_pair = VecU8_fmt("OptionRefMut%s", pair); +// SpanU8 option_ref_mut_pair = VecU8_to_span(&g_option_ref_mut_pair); +// +// VecU8 res = VecU8_new(); +// +// VecU8_append_vec(&res, VecU8_fmt( +// "typedef struct {\n" +// SPACE4 "VecRBTreeNode tree;\n" +// SPACE4 "size_t root;\n" +// SPACE4 "%s el;\n" +// "} %s;\n\n", vec_pair, map)); +// +// VecU8_append_vec(&res, VecU8_fmt( +// "NODISCARD %s %s_new() {\n" +// SPACE4 "return (%s){.tree = VecRBTreeNode_new_zeroinit(1), .root = 0, .el = %s_new()};\n" +// "}\n\n", map, map, map, vec_pair)); +// +// VecU8_append_vec(&res, VecU8_fmt( +// "NODISCARD %s %s_new_reserved(size_t n) {\n" +// SPACE4 "return (%s){.tree = VecRBTreeNode_new_reserved(1 + n), .root = 0, .el = %s_new_reserved(n)};\n" +// "}\n\n", map, map, map, vec_pair)); +// +// VecU8_append_vec(&res, VecU8_fmt( +// "void %s_drop(%s self) {\n" +// SPACE4 "VecRBTreeNode_drop(self.tree);\n" +// SPACE4 "%s_drop(self.el);\n" +// "}\n\n", vec_pair)); +// +// VecU8_append_vec(&res, VecU8_fmt( +// "bool %s_contains(const %s* self, const %s* key){\n" +// SPACE4 "size_t cur = self->root;\n" +// SPACE4 "while (cur > 0) {\n" +// SPACE4 SPACE4 "const RBTreeNode* node = VecRBTreeNode_at(&self->tree, cur);\n" +// SPACE4 SPACE4 "if %v\n" +// SPACE4 SPACE4 SPACE4 "return true;\n" +// SPACE4 SPACE4 "cur = %v ? node->left : node -> right;\n" +// SPACE4 "}\n" +// SPACE4 "return false\n" +// "}\n\n", map, map, op.K, +// codegen_T_ref_equal_T_ref(op.K, op.k_integer, vcstr("key"), codegen_rb_tree_el_keyptr(op, cstr("cur"))), +// codegen_T_ref_less_T_ref(op.K, op.k_integer, vcstr("key"), codegen_rb_tree_el_keyptr(op, cstr("cur"))))); +// +// /* Map may want to get mutable reference to Value of minimal pair +// * Btw, UB happens when you call this function on an empty map +// */ +// VecU8_append_vec(&res, VecU8_fmt( +// "const %s* %s_min_unsafe(const %s* self) {\n" +// SPACE4 "size_t cur = self->root;\n" +// SPACE4 "while (self->tree[cur]->left) {\n" +// SPACE4 SPACE4 "cur = self->tree[cur]->left;\n" +// SPACE4"}\n" +// SPACE4 "return &self->el[cur - 1]\n" +// "\n\n", pair, )); +// +// VecU8_append_vec(&res, VecU8_fmt( +// "const %s* %s_max_unsafe(const %s* self) {\n" +// SPACE4 "size_t cur = self->root;\n" +// SPACE4 "while (self->tree[cur]->left) {\n" +// SPACE4 SPACE4 "cur = self->tree[cur]->left;\n" +// SPACE4"}\n" +// SPACE4 "return &self->el[cur - 1]\n" +// "\n\n", T, set)); +// +// VecU8_drop(g_option); +// VecU8_drop(g_vec); +// VecU8_drop(g_set); +// +// return res; +// } +#endif \ No newline at end of file diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h new file mode 100644 index 0000000..af1d512 --- /dev/null +++ b/src/l1_5/core/rb_tree_node.h @@ -0,0 +1,19 @@ +#ifndef PROTOTYPE1_SRC_L1_5_CORE_RB_TREE_NODE_H +#define PROTOTYPE1_SRC_L1_5_CORE_RB_TREE_NODE_H + +#include "../../l1/core/util.h" + + +#define RBTree_black 0 +#define RBTree_red 1 + +typedef struct { + size_t left; + size_t right; + size_t parent; + bool color; +} RBTreeNode; + +#include "../../../gen/l1/eve/embassy_l1_5/VecRBTreeNode.h" + +#endif diff --git a/src/l2/liza/playing_sound_loop.h b/src/l2/liza/playing_sound_loop.h index 58c2a74..6008bd6 100644 --- a/src/l2/liza/playing_sound_loop.h +++ b/src/l2/liza/playing_sound_loop.h @@ -22,7 +22,7 @@ typedef struct { typedef struct { void* r; const LizaSound_Table* t; -} MutRefLizaSound; +} RefMutLizaSound; /* Existence of Box type implies that _drop method is virtual according to this trait */ typedef struct { diff --git a/src/l2/margaret/vulkan_utils.h b/src/l2/margaret/vulkan_utils.h index 52263cf..d5a7ef9 100644 --- a/src/l2/margaret/vulkan_utils.h +++ b/src/l2/margaret/vulkan_utils.h @@ -23,6 +23,7 @@ #include "../../../gen/l1/vulkan/VecAndOption_VkPresentModeKHR.h" #include "../../../gen/l1/vulkan/VecAndOption_VkSurfaceFormatKHR.h" #include +// #include diff --git a/src/l2/tests/r2/r2b.c b/src/l2/tests/r2/r2b.c index b8a96e4..de11835 100644 --- a/src/l2/tests/r2/r2b.c +++ b/src/l2/tests/r2/r2b.c @@ -6,6 +6,8 @@ #include "../../../l1/system/pthread.h" #include "../../margaret/time_utils.h" +// todo: delete this file + #define DEFAULT_RATE 44100 #define DEFAULT_CHANNELS 2 #define DEFAULT_VOLUME 0.1 From 254d4da92eee17f9a15b0d04033b8e5349e9f3b4 Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Thu, 18 Sep 2025 17:48:07 +0300 Subject: [PATCH 2/9] INSERTION --- CMakeLists.txt | 8 +- src/l1/anne/liza.h | 12 +- src/l1/anne/margaret/vulkan_utils.h | 22 ++- src/l1/codegen/util_template_inst.h | 1 + .../codegen/all_set_map_templ_util_inst.h | 108 ----------- .../codegen/rb_tree_set_map_template_inst.h | 171 +++++++++--------- src/l1_5/core/rb_tree_node.h | 96 +++++++++- src/l2/margaret/vulkan_utils.h | 11 +- 8 files changed, 207 insertions(+), 222 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 919c75b..70daa25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,14 +27,14 @@ add_compile_definitions(_POSIX_C_SOURCE=200112L) add_compile_definitions(_GNU_SOURCE) add_compile_options(-fno-trapping-math) -add_executable(codegen_l1 src/l1/anne/codegen.c) -target_compile_definitions(codegen_l1 - PRIVATE PROTOTYPE1_L1_CODEGEN_BOOTSTRAP_USE_CHICKEN_VECU8) +#add_executable(codegen_l1 src/l1/anne/codegen.c) +#target_compile_definitions(codegen_l1 +# PRIVATE PROTOTYPE1_L1_CODEGEN_BOOTSTRAP_USE_CHICKEN_VECU8) #add_executable(0_test src/l1_4/tests/t0.c) #add_executable(1_test src/l1_4/tests/t1.c) # -#add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) +add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) # #add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c # src/l1/core/rb_tree_node.h) diff --git a/src/l1/anne/liza.h b/src/l1/anne/liza.h index ab248d9..f312982 100644 --- a/src/l1/anne/liza.h +++ b/src/l1/anne/liza.h @@ -10,12 +10,12 @@ void generate_liza_l1_headers() { // todo: continue OptionT + util_templates_instantiation_options refactoring from here generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ .T = cstr("BoxLizaSound"), .vec = true}); - generate_util_templ_inst_eve_header(l, ns, cstr("PlayingSound"), - (util_templates_instantiation_options){.vec_extended = true}); - generate_util_templ_inst_eve_header(l, ns, cstr("BoxLizaInstrument"), - (util_templates_instantiation_options){ .vec = true}); - generate_util_templ_inst_eve_header(l, ns, cstr("MyInstrument"), - (util_templates_instantiation_options){ .vec = true}); + generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ + .T = cstr("PlayingSound"), .vec_extended = true}); + generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ + .T = cstr("BoxLizaInstrument"), .vec = true}); + generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ + .T = cstr("MyInstrument"), .vec = true}); } #endif \ No newline at end of file diff --git a/src/l1/anne/margaret/vulkan_utils.h b/src/l1/anne/margaret/vulkan_utils.h index 393523f..b42c067 100644 --- a/src/l1/anne/margaret/vulkan_utils.h +++ b/src/l1/anne/margaret/vulkan_utils.h @@ -7,18 +7,20 @@ void generate_margaret_eve_for_vulkan_utils() { SpanU8 l = cstr("l1"); SpanU8 ns = cstr("margaret"); mkdir_nofail("l1/eve/margaret"); - generate_util_templ_inst_eve_header(l, ns, cstr("MargaretScoredPhysicalDevice"), - (util_templates_instantiation_options){ .t_primitive = true, .vec = true, .span = true, - .mut_span = true, .collab_vec_span = true, .span_sort = true}); - + generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ + .T = cstr("MargaretScoredPhysicalDevice"), .t_primitive = true, .vec = true, .span = true, + .mut_span = true, .collab_vec_span = true, .span_sort = true + }); generate_eve_span_company_for_primitive(l, ns, cstr("MargaretBufferInMemoryInfo"), true, false); - generate_util_templ_inst_eve_header(l, ns, cstr("PtrMargaretBufferInMemoryInfo"), - (util_templates_instantiation_options){ .t_primitive = true, .vec = true, .span = true, .mut_span = true, - .collab_vec_span = true}); + generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ + .T = cstr("PtrMargaretBufferInMemoryInfo"), .t_primitive = true, .vec = true, .span = true, .mut_span = true, + .collab_vec_span = true + }); generate_eve_span_company_for_primitive(l, ns, cstr("MargaretImageInMemoryInfo"), true, false); - generate_util_templ_inst_eve_header(l, ns, cstr("PtrMargaretImageInMemoryInfo"), - (util_templates_instantiation_options){ .t_primitive = true, .vec = true, .span = true, .mut_span = true, - .collab_vec_span = true}); + generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){ + .T = cstr("PtrMargaretImageInMemoryInfo"), .t_primitive = true, .vec = true, .span = true, .mut_span = true, + .collab_vec_span = true + }); } #endif \ No newline at end of file diff --git a/src/l1/codegen/util_template_inst.h b/src/l1/codegen/util_template_inst.h index 5f151d6..58a0314 100644 --- a/src/l1/codegen/util_template_inst.h +++ b/src/l1/codegen/util_template_inst.h @@ -570,6 +570,7 @@ void option_template_instantiation_op_fix(option_template_instantiation_op* self } NODISCARD VecU8 generate_OptionT_struct_and_methods(option_template_instantiation_op op) { + option_template_instantiation_op_fix(&op); VecU8 g_OptionT = VecU8_fmt("Option%s", op.T); SpanU8 OptionT = VecU8_to_span(&g_OptionT); 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 e2ae2ea..1c0cd06 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 @@ -24,112 +24,4 @@ void set_instantiation_op_fix(set_instantiation_op* self){ self->t_clonable = true; } -// /* K and V still must be sized and trivially movable */ -// typedef struct { -// SpanU8 K; -// bool k_integer; -// bool k_primitive; -// bool k_clonable; -// SpanU8 V; -// bool v_primitive; -// bool v_clonable; -// } map_instantiation_options; -// -// void map_instantiation_options_fix(map_instantiation_options* self){ -// if (self->K.len == 0) -// abortf("Key cannot be void"); -// if (self->k_integer) -// self->k_primitive = true; -// if (self->k_primitive) -// self->k_clonable = true; -// -// if (self->V.len == 0) -// self->v_primitive = true; -// if (self->v_primitive) -// self->v_clonable = true; -// } - - -// NODISCARD VecU8 codegen_expr_MapKToV_option_ref_mut_pair_type(map_instantiation_options op){ -// if (op.V.len) -// return VecU8_fmt("OptionRefMutPairMap%sTo%s", op.K, op.V); -// return VecU8_fmt("OptionRefMut%s", op.K); -// } -// -// /* Generates PairMapKToV structure + [drop] + [clone] methods -// * Instantiates Option and Vec -// * Generates alias RefPairMapKToV = const PairMapKToV* -// * Instantiates Option template -// * Generates RefMutMapKToV structure (const ptr to key with mutable ptr to value) -// * Instantiates Option template -// * If `vec_vec_pair_needed` option is set, Vec> template will be instantiated -// * Vec> is needed in Hash_Map implementation -// */ -// NODISCARD VecU8 generate_MapKToV_pair_type(map_instantiation_options op, bool vec_vec_pair_needed){ -// map_instantiation_options_fix(&op); -// if (op.V.len == 0) -// abortf("No need to generate structure for Key Value pair when Value is void\n"); -// VecU8 g_pair = codegen_expr_MapKToV_pair_type(op); -// SpanU8 pair = VecU8_to_span(&g_pair); -// VecU8 result = VecU8_fmt( -// "typedef struct {\n" -// SPACE4 "%s key;\n" -// SPACE4 "%s value;\n" -// "} %s;\n\n", op.K, op.V, pair); -// -// if (!op.k_primitive || !op.v_primitive) { -// VecU8_append_vec(&result, VecU8_fmt("void %s_drop(%s self) {\n", pair, pair)); -// if (!op.k_primitive) -// VecU8_append_vec(&result, VecU8_fmt("%s_drop();\n", op.K)); -// if (!op.v_primitive) -// VecU8_append_vec(&result, VecU8_fmt("%s_drop();\n", op.V)); -// VecU8_append_span(&result, cstr("}\n\n")); -// } -// -// if (op.k_clonable && op.v_clonable && !(op.k_primitive && op.v_primitive)) { -// VecU8_append_vec(&result, VecU8_fmt("%s%s %s_clone(const %s* self) {\n", -// (op.k_primitive && op.v_primitive) ? cstr("") : cstr("NODISCARD"), pair, pair, pair)); -// VecU8_append_vec(&result, VecU8_fmt( -// SPACE4 "return (%s) {.key = %v, .value = %v};\n" -// "}\n\n", -// op.k_primitive ? vcstr("self->key") : VecU8_fmt("%s_clone(&self->key)"), -// op.v_primitive ? vcstr("self->value") : VecU8_fmt("%s_clone(&self->value)"))); -// } -// -// VecU8_append_vec(&result, generate_util_templates_instantiation(pair, (util_templates_instantiation_options){ -// .t_integer = op.k_integer, .t_primitive = op.k_primitive, .t_clonable = op.k_clonable, -// .vec = true, .vec_extended = true, .option = true})); -// -// VecU8 g_vec_pair = codegen_expr_MapKToV_vec_pair_type(op); -// SpanU8 vec_pair = VecU8_to_span(&g_vec_pair); -// VecU8 g_ref_pair = codegen_expr_MapKToV_ref_pair_type(op); -// SpanU8 ref_pair = VecU8_to_span(&g_ref_pair); -// -// VecU8_append_vec(&result, VecU8_fmt("typedef const %s* %s;\n\n", pair, ref_pair)); -// VecU8_append_vec(&result, generate_util_templates_instantiation(ref_pair, -// (util_templates_instantiation_options){.t_integer = true, .option = true})); -// -// VecU8 g_ref_mut_pair = codegen_expr_MapKToV_ref_mut_pair_type(op); -// SpanU8 ref_mut_pair = VecU8_to_span(&g_ref_pair); -// -// VecU8_append_vec(&result, VecU8_fmt( -// "typedef struct {\n" -// SPACE4 "const %s* key;\n" -// SPACE4 "%s* value;\n" -// "} %s\n\n", op.K, op.V, ref_mut_pair)); -// VecU8_append_vec(&result, generate_util_templates_instantiation(ref_mut_pair, -// (util_templates_instantiation_options){.t_integer = true, .option = true})); -// -// if (vec_vec_pair_needed) { -// VecU8_append_vec(&result, generate_util_templates_instantiation(vec_pair, -// (util_templates_instantiation_options){.vec = true})); -// } -// -// VecU8_drop(g_ref_mut_pair); -// VecU8_drop(g_ref_pair); -// VecU8_drop(g_vec_pair); -// VecU8_drop(g_pair); -// return result; -// } - #endif 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 a610b3e..ae46a72 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 @@ -3,100 +3,97 @@ #include "all_set_map_templ_util_inst.h" +// VecU8 codegen_rb_tree_NOT_EQUAL(set_instantiation_op op, SpanU8 A, SpanU8 B){ +// return op.t_integer ? VecU8_fmt("%s != %s", A, B) : VecU8_fmt("!%s_equal_%s(%s, %s)", op.T, op.T, A, B); +// } +// +// VecU8 codegen_rb_tree_LESS(set_instantiation_op op, SpanU8 A, SpanU8 B){ +// return op.t_integer ? VecU8_fmt("A < B", A, B) : VecU8_fmt("%s_less_%s(%s, %s)", op.T, op.T, A, B); +// } + +/* When key is given by value into some method of Buff_RBTreeSet */ +NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiation_op op, SpanU8 node_id_var_name){ + if (op.t_integer) + return VecU8_fmt("self->el.buf[%s - 1] != key", node_id_var_name); + return VecU8_fmt("!%s_equal_%s(&self->el.buf[%s - 1], &key)", op.T, op.T, node_id_var_name); +} + +/* When key is given by value into some method of Buff_RBTreeSet */ +NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op op, SpanU8 node_id_var_name){ + if (op.t_integer) + return VecU8_fmt("key < self->el.buf[%s - 1]", node_id_var_name); + return VecU8_fmt("%s_less_%s(&key, &self->el.buf[%s - 1])", op.T, op.T, node_id_var_name); +} + +/* 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_rb_tree_set_template_instantiation(set_instantiation_op op){ + set_instantiation_op_fix(&op); VecU8 res = VecU8_new(); VecU8 set = VecU8_fmt("BuffRBTree_Set%s", op.T); VecU8_append_vec(&res, VecU8_fmt( "typedef struct {\n" - SPACE4 "" - "}\n\n" - )); - // todo: continue from here after I finish the dumb option shit + SPACE4 "VecRBTreeNode tree;\n" + SPACE4 "U64 root;\n" + SPACE4 "Vec%s" + "} %s\n\n", op.T, VecU8_to_span(&set))); + + VecU8_append_vec(&res, VecU8_fmt( + "void %s_drop(%s self) {\n" + SPACE4 "VecRBTreeNode_drop(self->tree);\n" + SPACE4 "Vec%s_drop(self->el);\n" + "}\n\n", VecU8_to_span(&set), VecU8_to_span(&set), op.T)); + + /* Method insert does not try to replace the existing element with equal key, + * it returns true if insertion was done, false it collision happened and key was not inserted */ + VecU8_append_vec(&res, VecU8_fmt( + "bool %s_insert(%s* self, %s key) {\n" + SPACE4 "if (self->root == 0) {\n" + SPACE4 SPACE4 "assert(self->tree.len == 1);\n" + SPACE4 SPACE4 "VecRBTreeNode_append(&self->tree, (RBTreeNode){.color = RBTree_black});\n" + SPACE4 SPACE4 "Vec%s_append(&self->el, key);\n" + SPACE4 SPACE4 "self->root = 1;\n" + SPACE4 SPACE4 "return true;\n" + SPACE4 "}\n" + SPACE4 "U64 cur = self->root;\n" + SPACE4 "while (%v) {\n" + SPACE4 SPACE4 "if (%v) {\n" + SPACE4 SPACE4 SPACE4 "if (self->tree.buf[cur].left != 0) {\n" + SPACE4 SPACE4 SPACE4 SPACE4 "cur = self->tree.buf[cur].left\n" + SPACE4 SPACE4 SPACE4 "} else { \n" + /* We are inserting to the left of cur */ + SPACE4 SPACE4 SPACE4 SPACE4 "U64 n = self->tree.len;\n" + SPACE4 SPACE4 SPACE4 SPACE4 "VecRBTreeNode_append(&self->tree, (RBTreeeNode){.parent = cur, .color = RBTree_red});\n" + SPACE4 SPACE4 SPACE4 SPACE4 "self->tree.buf[cur].left = n;\n" + SPACE4 SPACE4 SPACE4 SPACE4 "RBTree_fix_after_insert(&self->tree, &self->root, n);\n" + SPACE4 SPACE4 SPACE4 SPACE4 "return true;\n" + SPACE4 SPACE4 SPACE4 "}\n" + SPACE4 SPACE4 "} else {\n" + SPACE4 SPACE4 SPACE4 "if (self->tree.buf[cur].right != 0) {\n" + SPACE4 SPACE4 SPACE4 SPACE4 "cur = self->tree.buf[cur].right\n" + SPACE4 SPACE4 SPACE4 "} else {\n" + /* We are inserting to the right of cur */ + SPACE4 SPACE4 SPACE4 SPACE4 "U64 n = self->tree.len;\n" + SPACE4 SPACE4 SPACE4 SPACE4 "VecRBTreeNode_append(&self->tree, (RBTreeeNode){.parent = cur, .color = RBTree_red});\n" + SPACE4 SPACE4 SPACE4 SPACE4 "self->tree.buf[cur].right = n;\n" + SPACE4 SPACE4 SPACE4 SPACE4 "RBTree_fix_after_insert(&self->tree, &self->root, n);\n" + SPACE4 SPACE4 SPACE4 SPACE4 "return true;\n" + SPACE4 SPACE4 SPACE4 "}\n" + SPACE4 SPACE4 "}\n" + SPACE4 "}\n" + SPACE4 "return false;\n" + "}\n\n", + VecU8_to_span(&set), VecU8_to_span(&set), op.T, + codegen_rb_tree_set_key_value_NOT_EQUAL_element(op, cstr("cur")), + codegen_rb_tree_set_key_value_LESS_element(op, cstr("cur")) + )); + + // VecU8_append_vec(&res, VecU8_fmt( + // "")); + VecU8_drop(set); return res; } - /* This type will require not only the definition of T=MapPair, but also Vec, Option<>, Option<&mut T> and Option<&T> - * Also it requires l1_5/core/rb_tree_node.h to be included by that point */ -// NODISCARD VecU8 generate_rb_tree_set_template_instantiation(map_instantiation_options op, bool -// bool implementation_mark){ -// VecU8 g_map = get_rb_tree_MapKToV_name(op, implementation_mark); -// SpanU8 map = VecU8_to_span(&g_map); -// VecU8 g_pair = get_MapKToV_pair_name(op); -// SpanU8 pair = VecU8_to_span(&g_pair); -// VecU8 g_vec_pair = VecU8_fmt("Vec%s", pair); -// SpanU8 vec_pair = VecU8_to_span(&g_vec_pair); -// VecU8 g_option_pair = VecU8_fmt("Option%s", pair); -// SpanU8 option_pair = VecU8_to_span(&g_option_pair); -// VecU8 g_option_ref_pair = VecU8_fmt("OptionRef%s", pair); -// SpanU8 option_ref_pair = VecU8_to_span(&g_option_ref_pair); -// VecU8 g_option_ref_mut_pair = VecU8_fmt("OptionRefMut%s", pair); -// SpanU8 option_ref_mut_pair = VecU8_to_span(&g_option_ref_mut_pair); -// -// VecU8 res = VecU8_new(); -// -// VecU8_append_vec(&res, VecU8_fmt( -// "typedef struct {\n" -// SPACE4 "VecRBTreeNode tree;\n" -// SPACE4 "size_t root;\n" -// SPACE4 "%s el;\n" -// "} %s;\n\n", vec_pair, map)); -// -// VecU8_append_vec(&res, VecU8_fmt( -// "NODISCARD %s %s_new() {\n" -// SPACE4 "return (%s){.tree = VecRBTreeNode_new_zeroinit(1), .root = 0, .el = %s_new()};\n" -// "}\n\n", map, map, map, vec_pair)); -// -// VecU8_append_vec(&res, VecU8_fmt( -// "NODISCARD %s %s_new_reserved(size_t n) {\n" -// SPACE4 "return (%s){.tree = VecRBTreeNode_new_reserved(1 + n), .root = 0, .el = %s_new_reserved(n)};\n" -// "}\n\n", map, map, map, vec_pair)); -// -// VecU8_append_vec(&res, VecU8_fmt( -// "void %s_drop(%s self) {\n" -// SPACE4 "VecRBTreeNode_drop(self.tree);\n" -// SPACE4 "%s_drop(self.el);\n" -// "}\n\n", vec_pair)); -// -// VecU8_append_vec(&res, VecU8_fmt( -// "bool %s_contains(const %s* self, const %s* key){\n" -// SPACE4 "size_t cur = self->root;\n" -// SPACE4 "while (cur > 0) {\n" -// SPACE4 SPACE4 "const RBTreeNode* node = VecRBTreeNode_at(&self->tree, cur);\n" -// SPACE4 SPACE4 "if %v\n" -// SPACE4 SPACE4 SPACE4 "return true;\n" -// SPACE4 SPACE4 "cur = %v ? node->left : node -> right;\n" -// SPACE4 "}\n" -// SPACE4 "return false\n" -// "}\n\n", map, map, op.K, -// codegen_T_ref_equal_T_ref(op.K, op.k_integer, vcstr("key"), codegen_rb_tree_el_keyptr(op, cstr("cur"))), -// codegen_T_ref_less_T_ref(op.K, op.k_integer, vcstr("key"), codegen_rb_tree_el_keyptr(op, cstr("cur"))))); -// -// /* Map may want to get mutable reference to Value of minimal pair -// * Btw, UB happens when you call this function on an empty map -// */ -// VecU8_append_vec(&res, VecU8_fmt( -// "const %s* %s_min_unsafe(const %s* self) {\n" -// SPACE4 "size_t cur = self->root;\n" -// SPACE4 "while (self->tree[cur]->left) {\n" -// SPACE4 SPACE4 "cur = self->tree[cur]->left;\n" -// SPACE4"}\n" -// SPACE4 "return &self->el[cur - 1]\n" -// "\n\n", pair, )); -// -// VecU8_append_vec(&res, VecU8_fmt( -// "const %s* %s_max_unsafe(const %s* self) {\n" -// SPACE4 "size_t cur = self->root;\n" -// SPACE4 "while (self->tree[cur]->left) {\n" -// SPACE4 SPACE4 "cur = self->tree[cur]->left;\n" -// SPACE4"}\n" -// SPACE4 "return &self->el[cur - 1]\n" -// "\n\n", T, set)); -// -// VecU8_drop(g_option); -// VecU8_drop(g_vec); -// VecU8_drop(g_set); -// -// return res; -// } #endif \ No newline at end of file diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h index af1d512..2872b0b 100644 --- a/src/l1_5/core/rb_tree_node.h +++ b/src/l1_5/core/rb_tree_node.h @@ -3,17 +3,105 @@ #include "../../l1/core/util.h" - -#define RBTree_black 0 -#define RBTree_red 1 +typedef enum { + RBTree_black = 0, + RBTree_red = 1, +} RBTreeColor; typedef struct { size_t left; size_t right; size_t parent; - bool color; + /* 0 is black, 1 is red */ + RBTreeColor color; } RBTreeNode; #include "../../../gen/l1/eve/embassy_l1_5/VecRBTreeNode.h" +void RBTree_left_rotate(RBTreeNode* tree, U64* root, U64 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_right_rotate(RBTreeNode* tree, U64* root, U64 x){ + assert(x != 0); + U64 y = tree[x].left; + assert(y != 0); + tree[x].left = tree[y].right; + if (tree[x].left != 0) + tree[tree[x].left].parent = x; + + tree[y].parent = tree[x].parent; + if (tree[y].parent != 0) { + *root = y; + } else if (x == tree[tree[x].parent].right) { + tree[tree[x].parent].right = y; + } else { + tree[tree[x].parent].left = y; + } + tree[x].parent = y; + tree[y].right = x; +} + +/* Helper function. Called in automatically generated code */ +void RBTree_fix_after_insert(RBTreeNode* tree, U64* root, U64 me){ + assert(me); + while (true) { + U64 mom = tree[me].parent; + if (mom == 0) + break; + if (tree[mom].color == RBTree_black) + break; + U64 grandma = tree[mom].parent; + U64 aunt = tree[grandma].left == mom ? tree[grandma].right : tree[grandma].left; + assert(aunt != mom); + if (tree[aunt].color == RBTree_red) { + /* Easy case */ + tree[mom].color = RBTree_black; + tree[aunt].color = RBTree_black; + tree[grandma].color = RBTree_red; + me = grandma; + } else if (tree[grandma].left == mom) { + /* Hard case: firstborn orientation */ + if (tree[mom].right == me) { + RBTree_left_rotate(tree, root, mom); + tree[me].color = RBTree_black; + } else { + tree[mom].color = RBTree_black; + } + RBTree_right_rotate(tree, root, grandma); + tree[grandma].color = RBTree_red; + return; + } else { + /* Hard case: benjamin orientation */ + if (tree[mom].left == me) { + RBTree_right_rotate(tree, root, mom); + tree[me].color = RBTree_black; + } else { + tree[mom].color = RBTree_black; + } + RBTree_left_rotate(tree, root, grandma); + tree[grandma].color = RBTree_red; + return; + } + } + assert(*root == me); + tree[me].color = RBTree_black; +} + #endif diff --git a/src/l2/margaret/vulkan_utils.h b/src/l2/margaret/vulkan_utils.h index d5a7ef9..8afcf30 100644 --- a/src/l2/margaret/vulkan_utils.h +++ b/src/l2/margaret/vulkan_utils.h @@ -16,12 +16,17 @@ #include "../../../gen/l1/vulkan/VecVkExtensionProperties.h" #include "../../../gen/l1/vulkan/VecVkImageView.h" #include "../../../gen/l1/vulkan/VecVkPhysicalDevice.h" -#include "../../../gen/l1/vulkan/SpanAndOption_VkFormat.h" +#include "../../../gen/l1/vulkan/SpanVkFormat.h" +#include "../../../gen/l1/vulkan/OptionVkFormat.h" #include "../../../gen/l1/vulkan/VecVkDescriptorPoolSize.h" #include "../../../gen/l1/vulkan/VecVkQueueFamilyProperties.h" #include "../../../gen/l1/vulkan/OptionVkCompositeAlphaFlagBitsKHR.h" -#include "../../../gen/l1/vulkan/VecAndOption_VkPresentModeKHR.h" -#include "../../../gen/l1/vulkan/VecAndOption_VkSurfaceFormatKHR.h" +#include "../../../gen/l1/vulkan/VecVkPresentModeKHR.h" +#include "../../../gen/l1/vulkan/OptionVkPresentModeKHR.h" +#include "../../../gen/l1/vulkan/OptionVkPresentModeKHR.h" +#include "../../../gen/l1/vulkan/VecVkPresentModeKHR.h" +#include "../../../gen/l1/vulkan/VecVkSurfaceFormatKHR.h" +#include "../../../gen/l1/vulkan/OptionVkSurfaceFormatKHR.h" #include // #include From 6b7a67cb1f4a2056f238db3dd2e2616b41ce360f Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Fri, 19 Sep 2025 00:09:37 +0300 Subject: [PATCH 3/9] Deletion --- src/l1/anne/geom.h | 48 ++-- src/l1/anne/pixel_masses.h | 108 ++++---- src/l1/codegen/codegen.h | 2 +- src/l1/codegen/util_template_inst.h | 236 +++++++++--------- src/l1_5/anne/codegen.c | 2 + src/l1_5/anne/l1_5_templ_very_base.h | 8 + src/l1_5/anne/marie/clipping.h | 22 +- .../codegen/rb_tree_set_map_template_inst.h | 214 +++++++++++----- src/l1_5/codegen/trait_wrap_boil.h | 2 +- src/l1_5/core/rb_tree_node.h | 103 ++++++++ src/l2/tests/t0.c | 3 + 11 files changed, 474 insertions(+), 274 deletions(-) create mode 100644 src/l1_5/anne/l1_5_templ_very_base.h create mode 100644 src/l2/tests/t0.c diff --git a/src/l1/anne/geom.h b/src/l1/anne/geom.h index 9829389..7ed358c 100644 --- a/src/l1/anne/geom.h +++ b/src/l1/anne/geom.h @@ -20,13 +20,13 @@ NODISCARD VecU8 generate_xvecn_struct_and_base_methods(SpanU8 xvec, SpanU8 memb, /* Structure definition */ VecU8_append_span(&res, cstr("typedef struct {\n")); for (int ci = 0; ci < n; ci++) { - VecU8_append_vec(&res, VecU8_fmt(SPACE4 "%s %s;\n", memb, vec_field_name(ci))); + VecU8_append_vec(&res, VecU8_fmt(SPACE "%s %s;\n", memb, vec_field_name(ci))); } VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", xvecn)); /* xvecn_add_xvecn method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_add_%s(%s A, %s B) {\n" - SPACE4 "return(%s){ ", + SPACE "return(%s){ ", xvecn, xvecn, xvecn, xvecn, xvecn, xvecn)); for (int ci = 0; ci < n; ci++) { if (ci) @@ -37,7 +37,7 @@ NODISCARD VecU8 generate_xvecn_struct_and_base_methods(SpanU8 xvec, SpanU8 memb, /* xvecn_minus_xvecn method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_minus_%s(%s A, %s B) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xvecn, xvecn, xvecn, xvecn, xvecn, xvecn)); for (int ci = 0; ci < n; ci++) { if (ci) @@ -48,7 +48,7 @@ NODISCARD VecU8 generate_xvecn_struct_and_base_methods(SpanU8 xvec, SpanU8 memb, /* xvecn_minus method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_minus(%s A) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xvecn, xvecn, xvecn, xvecn)); for (int ci = 0; ci < n; ci++) { if (ci) @@ -68,7 +68,7 @@ NODISCARD VecU8 generate_xvecn_struct_and_cool_methods(SpanU8 xvec, SpanU8 memb, /* xvecn_length method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_length(%s A) {\n" - SPACE4 "return %s(", + SPACE "return %s(", memb, xvecn, xvecn, sqrt_func)); for (int i = 0; i < n; i++) { if (i) @@ -79,7 +79,7 @@ NODISCARD VecU8 generate_xvecn_struct_and_cool_methods(SpanU8 xvec, SpanU8 memb, /* xvecn_mul_scal method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_mul_scal(%s A, %s B) {\n" - SPACE4 "return (%s) { ", + SPACE "return (%s) { ", xvecn, xvecn, xvecn, memb, xvecn)); for (int ci = 0; ci < n; ci++) { if (ci) @@ -90,12 +90,12 @@ NODISCARD VecU8 generate_xvecn_struct_and_cool_methods(SpanU8 xvec, SpanU8 memb, /* xvecn_div_by_scal method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_div_by_scal(%s A, %s B) {\n" - SPACE4 "return %s_mul_scal(A, 1/B);\n" + SPACE "return %s_mul_scal(A, 1/B);\n" "}\n\n", xvecn, xvecn, xvecn, memb, xvecn)); /* xvecn_mul_xvecn method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_mul_%s(%s A, %s B) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xvecn, xvecn, xvecn, xvecn, xvecn, xvecn)); for (int ci = 0; ci < n; ci++) { if (ci) @@ -106,7 +106,7 @@ NODISCARD VecU8 generate_xvecn_struct_and_cool_methods(SpanU8 xvec, SpanU8 memb, /* xvecn_dot method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_dot(%s A, %s B) {\n" - SPACE4 "return ", + SPACE "return ", memb, xvecn, xvecn, xvecn)); for (int i = 0; i < n; i++) { if (i) @@ -117,7 +117,7 @@ NODISCARD VecU8 generate_xvecn_struct_and_cool_methods(SpanU8 xvec, SpanU8 memb, /* xvecn_normalize method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_normalize(%s A) {\n" - SPACE4 "return %s_div_by_scal(A, %s_length(A));\n" + SPACE "return %s_div_by_scal(A, %s_length(A));\n" "}\n\n", xvecn, xvecn, xvecn, xvecn, xvecn)); VecU8_drop(g_xvecn); @@ -133,7 +133,7 @@ NODISCARD VecU8 generate_xvecn_method_and_one(SpanU8 xvec, int n) { VecU8 res = VecU8_fmt( "%s %s_and_one(%s A) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xvecn_pp, xvecn, xvecn, xvecn_pp); for (int i = 0; i < n; i++) { VecU8_append_vec(&res, VecU8_fmt("A.%s, ", vec_field_name(i))); @@ -150,7 +150,7 @@ NODISCARD VecU8 generate_xvec3_method_cross(SpanU8 xvec) { SpanU8 xvec3 = VecU8_to_span(&g_xvec3); VecU8 res = VecU8_fmt( "%s %s_cross(%s A, %s B) {\n" - SPACE4 "return (%s){A.y * B.z - A.z * B.y, -A.x * B.z + A.z * B.x, A.x * B.y - A.y * B.x};\n" + SPACE "return (%s){A.y * B.z - A.z * B.y, -A.x * B.z + A.z * B.x, A.x * B.y - A.y * B.x};\n" "}\n\n", xvec3, xvec3, xvec3, xvec3, xvec3); VecU8_drop(g_xvec3); return res; @@ -177,9 +177,9 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( int sv = (rows * sizeof_member) % 16; VecU8_append_span(&res, cstr("typedef struct {\n")); for (int x = 0; x < cols; x++) { - VecU8_append_vec(&res, VecU8_fmt(SPACE4 "%s %s;\n", xvecm, vec_field_name(x))); + VecU8_append_vec(&res, VecU8_fmt(SPACE "%s %s;\n", xvecm, vec_field_name(x))); if (sv) { - VecU8_append_vec(&res, VecU8_format(SPACE4 "char _padding_%d[%d];\n", x, 16 - sv)); + VecU8_append_vec(&res, VecU8_format(SPACE "char _padding_%d[%d];\n", x, 16 - sv)); } } VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", xmatnm)); @@ -192,7 +192,7 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( VecU8_append_vec(&res, VecU8_fmt("%s %s%s", memb, vec_field_name(x), vec_field_name(y))); } } - VecU8_append_vec(&res, VecU8_fmt(") {\n" SPACE4 "return (%s){ ", xmatnm)); + VecU8_append_vec(&res, VecU8_fmt(") {\n" SPACE "return (%s){ ", xmatnm)); for (int x = 0; x < cols; x++) { if (x) VecU8_append_span(&res, cstr(", ")); @@ -208,7 +208,7 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( /* xmatnm_add_xmatnm method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_add_%s(%s A, %s B) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xmatnm, xmatnm, xmatnm, xmatnm, xmatnm, xmatnm)); for (int x = 0; x < cols; x++) { if (x) @@ -220,7 +220,7 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( /* xmatnm_minus_xmatnm method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_minus_%s(%s A, %s B) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xmatnm, xmatnm, xmatnm, xmatnm, xmatnm, xmatnm)); for (int x = 0; x < cols; x++) { if (x) @@ -232,7 +232,7 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( /* xmatnm_minus method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_minus(%s A) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xmatnm, xmatnm, xmatnm, xmatnm)); for (int x = 0; x < cols; x++) { if (x) @@ -244,7 +244,7 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( /* xmatnm_mul_scal method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_mul_scal(%s A, %s B) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xmatnm, xmatnm, xmatnm, memb, xmatnm)); for (int x = 0; x < cols; x++) { if (x) @@ -256,7 +256,7 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( /* xmatnm_div_by_scal method */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_div_by_scal(%s A, %s B) {\n" - SPACE4 "return %s_mul_scal(A, 1/B);\n" + SPACE "return %s_mul_scal(A, 1/B);\n" "}\n\n", xmatnm, xmatnm, xmatnm, memb, xmatnm)); @@ -265,7 +265,7 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( /* xmatnm_mul_xvecn */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_mul_%s(%s A, %s B) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xvecm, xmatnm, xvecn, xmatnm, xvecn, xvecm)); for (int y = 0; y < rows; y++) { if (y) @@ -277,7 +277,7 @@ NODISCARD VecU8 generate_xmatnm_struct_and_methods( VecU8_append_vec(&res, VecU8_fmt("A.%s.%s * B.%s", vec_field_name(x), vec_field_name(y), vec_field_name(x))); } } - VecU8_append_span(&res, cstr("\n" SPACE4 "};\n}\n\n")); + VecU8_append_span(&res, cstr("\n" SPACE "};\n}\n\n")); VecU8_drop(g_xvecn); VecU8_drop(g_xvecm); @@ -293,7 +293,7 @@ NODISCARD VecU8 generate_xmatnm_transpose_method(SpanU8 xmat, SpanU8 xvec, SpanU SpanU8 xmatmn = VecU8_to_span(&g_xmatmn); VecU8 res = VecU8_fmt( "%s %s_transpose(%s A) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xmatmn, xmatnm, xmatnm, xmatmn); for (int bx = 0; bx < rows; bx++) { if (bx) @@ -347,7 +347,7 @@ NODISCARD VecU8 generate_xmatnm_method_mul_xmatkn(SpanU8 xmat, int n, int m, int VecU8 res = VecU8_fmt( "%s %s_mul_%s(%s A, %s B) {\n" - SPACE4 "return (%s){ ", + SPACE "return (%s){ ", xmatkm, xmatnm, xmatkn, xmatnm, xmatkn, xmatkm); for (int x = 0; x < k; x++) { if (x) diff --git a/src/l1/anne/pixel_masses.h b/src/l1/anne/pixel_masses.h index 8a7868d..a40ef32 100644 --- a/src/l1/anne/pixel_masses.h +++ b/src/l1/anne/pixel_masses.h @@ -7,8 +7,8 @@ NODISCARD VecU8 generate_texture_data_method_at(SpanU8 tex, SpanU8 pixvec, SpanU8 memb, bool const_access) { return VecU8_fmt( "%s%s* %s_%sat(%s%s* self, size_t x, size_t y) {\n" - SPACE4 "assert(x < self->width);\n" - SPACE4 "return %s_%sat(&self->pixels, x + y * self->width);\n" + SPACE "assert(x < self->width);\n" + SPACE "return %s_%sat(&self->pixels, x + y * self->width);\n" "}\n\n", const_access ? cstr("const ") : cstr(""), memb, tex, const_access ? cstr("") : cstr("m"), const_access ? cstr("const ") : cstr(""), tex, pixvec, const_access ? cstr("") : cstr("m")); @@ -22,24 +22,24 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 VecU8 res = VecU8_fmt( "typedef struct {\n" - SPACE4 "%s pixels;\n" - SPACE4 "size_t width;\n" + SPACE "%s pixels;\n" + SPACE "size_t width;\n" "} %s;\n\n", pixvec, tex); /* Method _new() */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_new(U32 width, U32 height) {\n" - SPACE4 "assert(!(SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10));\n" - SPACE4 "return (%s){.pixels = %s_new_zeroinit((size_t)width * height), .width = width};\n" + SPACE "assert(!(SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10));\n" + SPACE "return (%s){.pixels = %s_new_zeroinit((size_t)width * height), .width = width};\n" "}\n\n", tex, tex, tex, pixvec)); /* Method _drop() */ VecU8_append_vec(&res, VecU8_fmt( "void %s_drop(%s self) {\n" - SPACE4 "%s_drop(self.pixels);\n" + SPACE "%s_drop(self.pixels);\n" "}\n\n", tex, tex, pixvec)); /* Method _get_height() */ VecU8_append_vec(&res, VecU8_fmt( "size_t %s_get_height(const %s* self) {\n" - SPACE4 "return self->pixels.len / self->width;\n" + SPACE "return self->pixels.len / self->width;\n" "}\n\n", tex, tex)); /* Methods _at and _cat */ VecU8_append_vec(&res, generate_texture_data_method_at(tex, pixvec, memb, false)); @@ -47,7 +47,7 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 /* Method _get_size_in_bytes */ VecU8_append_vec(&res, VecU8_fmt( "size_t %s_get_size_in_bytes(const %s* self) {\n" - SPACE4 "return self->pixels.len * sizeof(%s);\n" + SPACE "return self->pixels.len * sizeof(%s);\n" "}\n\n", tex, tex, memb)); /* Method _to_bitmap_text() * We use the assumption that bytes in type member are tightly packed @@ -55,75 +55,75 @@ NODISCARD VecU8 generate_texture_data_struct_and_necc_methods(SpanU8 tex, SpanU8 */ VecU8_append_vec(&res, VecU8_fmt( "VecU8 %s_to_bitmap_text(const %s* self) {\n" - SPACE4 "assert(SIZE_MAX / self->pixels.len >= 100);\n" - SPACE4 "size_t len = self->pixels.len * sizeof(%s);\n" - SPACE4 "VecU8 res = VecU8_new_zeroinit(8 + len);\n" - SPACE4 "size_t width = self->width;\n" - SPACE4 "size_t height = self->pixels.len / self->width;\n" - SPACE4 "assert(UINT32_MAX / width >= 10 && UINT32_MAX / height >= 10);\n" - SPACE4 "for (int i = 0; i < 4; i++)\n" - SPACE4 SPACE4 "*VecU8_mat(&res, 0 + i) = (width >> (8 * i)) & 0xff;\n" - SPACE4 "for (int i = 0; i < 4; i++)\n" - SPACE4 SPACE4 "*VecU8_mat(&res, 4 + i) = (height >> (8 * i)) & 0xff;\n" - SPACE4 "memcpy(res.buf + 8, self->pixels.buf, len);\n" - SPACE4 "return res;\n" + SPACE "assert(SIZE_MAX / self->pixels.len >= 100);\n" + SPACE "size_t len = self->pixels.len * sizeof(%s);\n" + SPACE "VecU8 res = VecU8_new_zeroinit(8 + len);\n" + SPACE "size_t width = self->width;\n" + SPACE "size_t height = self->pixels.len / self->width;\n" + SPACE "assert(UINT32_MAX / width >= 10 && UINT32_MAX / height >= 10);\n" + SPACE "for (int i = 0; i < 4; i++)\n" + SPACE SPACE "*VecU8_mat(&res, 0 + i) = (width >> (8 * i)) & 0xff;\n" + SPACE "for (int i = 0; i < 4; i++)\n" + SPACE SPACE "*VecU8_mat(&res, 4 + i) = (height >> (8 * i)) & 0xff;\n" + SPACE "memcpy(res.buf + 8, self->pixels.buf, len);\n" + SPACE "return res;\n" "}\n\n", tex, tex, memb)); /* Method _write_to_file * Aborts on failure */ VecU8_append_vec(&res, VecU8_fmt( "void %s_write_to_file(const %s* self, const char* path) {\n" - SPACE4 "VecU8 data = %s_to_bitmap_text(self);\n" - SPACE4 "write_whole_file_or_abort(path, VecU8_to_span(&data));\n" - SPACE4 "VecU8_drop(data);\n" + SPACE "VecU8 data = %s_to_bitmap_text(self);\n" + SPACE "write_whole_file_or_abort(path, VecU8_to_span(&data));\n" + SPACE "VecU8_drop(data);\n" "}\n\n", tex, tex, tex)); /* Result structure */ VecU8 g_resoftex = VecU8_fmt("Result%sOrSpanU8", tex); SpanU8 resoftex = VecU8_to_span(&g_resoftex); VecU8_append_vec(&res, VecU8_fmt( "typedef struct {\n" - SPACE4 "Result_variant variant;\n" - SPACE4 "union {\n" - SPACE4 SPACE4 "%s ok;\n" - SPACE4 SPACE4 "SpanU8 err;\n" - SPACE4 "};\n" + SPACE "Result_variant variant;\n" + SPACE "union {\n" + SPACE SPACE "%s ok;\n" + SPACE SPACE "SpanU8 err;\n" + SPACE "};\n" "} %s;\n\n", tex, resoftex)); /* Method _from_bitmap_text() * We assume that bytes are tightly packed in member type */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_from_bitmap_text(SpanU8 text) {\n" - SPACE4 "if (text.len < 8)\n" - SPACE4 SPACE4 "return (%s){.variant = Result_Err, .err = cstr(\"No header *crying emoji*\")};\n" - SPACE4 "size_t width = 0, height = 0;\n" - SPACE4 "for (int i = 0; i < 4; i++)\n" - SPACE4 SPACE4 "width |= (((size_t)*SpanU8_at(text, 0 + i)) << (8 * i));\n" - SPACE4 "for (int i = 0; i < 4; i++)\n" - SPACE4 SPACE4 "height |= (((size_t)*SpanU8_at(text, 4 + i)) << (8 * i));\n" - SPACE4 "if (SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10)\n" - SPACE4 SPACE4 "return (%s){.variant = Result_Err, .err = cstr(\"Image is too big\")};\n" - SPACE4 "size_t len = width * height * sizeof(%s);\n" - SPACE4 "if (text.len < 8 + len)\n" - SPACE4 SPACE4 "return (%s){.variant = Result_Err, .err = cstr(\"Texture size and file size mismatch\")};\n" - SPACE4 "%s res = %s_new(width, height);\n" - SPACE4 "memcpy(res.pixels.buf, text.data + 8, len);\n" - SPACE4 "return (%s){.variant = Result_Ok, .ok = res};\n" + SPACE "if (text.len < 8)\n" + SPACE SPACE "return (%s){.variant = Result_Err, .err = cstr(\"No header *crying emoji*\")};\n" + SPACE "size_t width = 0, height = 0;\n" + SPACE "for (int i = 0; i < 4; i++)\n" + SPACE SPACE "width |= (((size_t)*SpanU8_at(text, 0 + i)) << (8 * i));\n" + SPACE "for (int i = 0; i < 4; i++)\n" + SPACE SPACE "height |= (((size_t)*SpanU8_at(text, 4 + i)) << (8 * i));\n" + SPACE "if (SIZE_MAX / width / height < 100 || UINT32_MAX / width < 10 || UINT32_MAX / height < 10)\n" + SPACE SPACE "return (%s){.variant = Result_Err, .err = cstr(\"Image is too big\")};\n" + SPACE "size_t len = width * height * sizeof(%s);\n" + SPACE "if (text.len < 8 + len)\n" + SPACE SPACE "return (%s){.variant = Result_Err, .err = cstr(\"Texture size and file size mismatch\")};\n" + SPACE "%s res = %s_new(width, height);\n" + SPACE "memcpy(res.pixels.buf, text.data + 8, len);\n" + SPACE "return (%s){.variant = Result_Ok, .ok = res};\n" "}\n\n", resoftex, tex, resoftex, resoftex, memb, resoftex, tex, tex, resoftex)); /* Method _read_from_file */ VecU8_append_vec(&res, VecU8_fmt( "%s %s_read_from_file(const char* path) {\n" - SPACE4 "VecU8 data = read_whole_file_or_abort(path);\n" - SPACE4 "%s res = %s_from_bitmap_text(VecU8_to_span(&data));\n" - SPACE4 "if (res.variant != Result_Ok) {\n" - SPACE4 SPACE4 "fprintf(stderr, \"Tried loading bitmap texture from file, but encountered decoding error: \");\n" - SPACE4 SPACE4 "SpanU8_fprint(res.err, stderr);\n" - SPACE4 SPACE4 "abortf(\"\\n\");\n" - SPACE4 "}\n" - SPACE4 "VecU8_drop(data);\n" - SPACE4 "return res.ok;\n" + SPACE "VecU8 data = read_whole_file_or_abort(path);\n" + SPACE "%s res = %s_from_bitmap_text(VecU8_to_span(&data));\n" + SPACE "if (res.variant != Result_Ok) {\n" + SPACE SPACE "fprintf(stderr, \"Tried loading bitmap texture from file, but encountered decoding error: \");\n" + SPACE SPACE "SpanU8_fprint(res.err, stderr);\n" + SPACE SPACE "abortf(\"\\n\");\n" + SPACE "}\n" + SPACE "VecU8_drop(data);\n" + SPACE "return res.ok;\n" "}\n\n", tex, tex, resoftex, tex)); /* Method _is_inside() */ VecU8_append_vec(&res, VecU8_fmt( "bool %s_is_inside(const %s* self, S32 x, S32 y) {\n" - SPACE4 "return x >= 0 && y >= 0 && x < (S32)self->width && self->width * y + x < self->pixels.len;\n" + SPACE "return x >= 0 && y >= 0 && x < (S32)self->width && self->width * y + x < self->pixels.len;\n" "}\n\n", tex, tex)); VecU8_drop(g_resoftex); diff --git a/src/l1/codegen/codegen.h b/src/l1/codegen/codegen.h index 668ab60..61741f0 100644 --- a/src/l1/codegen/codegen.h +++ b/src/l1/codegen/codegen.h @@ -37,7 +37,7 @@ void finish_header(GeneratedHeader header) { VecU8_drop(header.result); } -#define SPACE4 " " +#define SPACE " " #define SPACE8 " " #define SPACE12 " " #define SPACE16 " " diff --git a/src/l1/codegen/util_template_inst.h b/src/l1/codegen/util_template_inst.h index 58a0314..9fc775d 100644 --- a/src/l1/codegen/util_template_inst.h +++ b/src/l1/codegen/util_template_inst.h @@ -11,9 +11,9 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive, SpanU8 VecT = VecU8_to_span(&g_VecT); VecU8 res = VecU8_fmt( "typedef struct {\n" - SPACE4 "%s* buf;\n" - SPACE4 "size_t len;\n" - SPACE4 "size_t capacity;\n" + SPACE "%s* buf;\n" + SPACE "size_t len;\n" + SPACE "size_t capacity;\n" "} %s;\n\n", T, VecT); VecU8_append_vec(&res, VecU8_fmt("#define %s_new() ((%s){ 0 })\n\n", VecT, VecT)); @@ -21,76 +21,76 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive, VecU8_append_vec(&res, VecU8_fmt("void %s_drop(%s self) {\n", VecT, VecT)); if (!primitive) { VecU8_append_vec(&res, VecU8_fmt( - SPACE4 "for (size_t i = 0; i < self.len; i++) \n" - SPACE4 SPACE4 "%s_drop(self.buf[i]);\n", T)); + SPACE "for (size_t i = 0; i < self.len; i++) \n" + SPACE SPACE "%s_drop(self.buf[i]);\n", T)); } VecU8_append_vec(&res, VecU8_fmt( - SPACE4 "free(self.buf);\n" + SPACE "free(self.buf);\n" "}\n\n")); VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_new_reserved(size_t n) {\n" - SPACE4 "return (%s){ .buf = safe_calloc(n, sizeof(%s)), .len = 0, .capacity = n };\n" + SPACE "return (%s){ .buf = safe_calloc(n, sizeof(%s)), .len = 0, .capacity = n };\n" "}\n\n", VecT, VecT, VecT, T)); VecU8_append_vec(&res, VecU8_fmt( "void %s_append(%s* self, %s el) {\n" - SPACE4 "size_t new_length = self->len + 1;\n" - SPACE4 "if (new_length > self->capacity) {\n" - SPACE4 SPACE4 "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n" - SPACE4 SPACE4 "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n" - SPACE4 SPACE4 "self->capacity = new_capacity;\n" - SPACE4 "}\n" - SPACE4 "self->buf[self->len] = el;\n" - SPACE4 "self->len = new_length;\n" + SPACE "size_t new_length = self->len + 1;\n" + SPACE "if (new_length > self->capacity) {\n" + SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n" + SPACE SPACE "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n" + SPACE SPACE "self->capacity = new_capacity;\n" + SPACE "}\n" + SPACE "self->buf[self->len] = el;\n" + SPACE "self->len = new_length;\n" "}\n\n", VecT, VecT, T, T)); VecU8_append_vec(&res, VecU8_fmt( "%s* %s_mat(%s* self, size_t i) {\n" - SPACE4 "assert(i < self->len);\n" - SPACE4 "return &self->buf[i];\n" + SPACE "assert(i < self->len);\n" + SPACE "return &self->buf[i];\n" "}\n\n", T, VecT, VecT)); VecU8_append_vec(&res, VecU8_fmt( "const %s* %s_at(const %s* self, size_t i) {\n" - SPACE4 "assert(i < self->len);\n" - SPACE4 "return &self->buf[i];\n" + SPACE "assert(i < self->len);\n" + SPACE "return &self->buf[i];\n" "}\n\n", T, VecT, VecT)); if (clonable) { VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_clone(const %s* self) {\n" - SPACE4 "%s res = (%s){.buf = safe_calloc(self->len, sizeof(%s)), .len = self->len, .capacity = self->len};\n", + SPACE "%s res = (%s){.buf = safe_calloc(self->len, sizeof(%s)), .len = self->len, .capacity = self->len};\n", VecT, VecT, VecT, VecT, VecT, T)); if (primitive) { - VecU8_append_vec(&res, VecU8_fmt(SPACE4 "memcpy(res.buf, self->buf, self->len * sizeof(%s));\n", T)); + VecU8_append_vec(&res, VecU8_fmt(SPACE "memcpy(res.buf, self->buf, self->len * sizeof(%s));\n", T)); } else { VecU8_append_vec(&res, VecU8_fmt( - SPACE4 "for (size_t i = 0; i < self->len; i++)\n" - SPACE4 SPACE4 "res.buf[i] = %s_clone(&self->buf[i]);\n", T)); + SPACE "for (size_t i = 0; i < self->len; i++)\n" + SPACE SPACE "res.buf[i] = %s_clone(&self->buf[i]);\n", T)); } - VecU8_append_span(&res, cstr(SPACE4 "return res;\n}\n\n")); + VecU8_append_span(&res, cstr(SPACE "return res;\n}\n\n")); } VecU8_append_vec(&res, VecU8_fmt( "void %s_append_vec(%s* self, %s b) {\n" - SPACE4 "size_t new_length = self->len + b.len;\n" - SPACE4 "if (new_length > self->capacity) {\n" - SPACE4 SPACE4 "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n" - SPACE4 SPACE4 "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n" - SPACE4 SPACE4 "self->capacity = new_capacity;\n" - SPACE4 "}\n" - SPACE4 "for (size_t i = 0; i < b.len; i++){\n" - SPACE4 SPACE4 "self->buf[self->len + i] = b.buf[i];\n" - SPACE4 "}\n" - SPACE4 "self->len = new_length;\n" - SPACE4 "free(b.buf);\n" + SPACE "size_t new_length = self->len + b.len;\n" + SPACE "if (new_length > self->capacity) {\n" + SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n" + SPACE SPACE "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n" + SPACE SPACE "self->capacity = new_capacity;\n" + SPACE "}\n" + SPACE "for (size_t i = 0; i < b.len; i++){\n" + SPACE SPACE "self->buf[self->len + i] = b.buf[i];\n" + SPACE "}\n" + SPACE "self->len = new_length;\n" + SPACE "free(b.buf);\n" "}\n\n", VecT, VecT, VecT, T)); if (primitive) { VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_new_zeroinit(size_t len) {\n" - SPACE4 "return (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" + SPACE "return (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" "}\n\n", VecT, VecT, VecT, T)); } @@ -106,61 +106,61 @@ NODISCARD VecU8 generate_VecT_trivmove_extended_methods(SpanU8 T, bool primitive VecU8_append_vec(&res, VecU8_fmt( "%s%s %s_pop(%s* self) {\n" - SPACE4 "assert(self->len > 0);\n" - SPACE4 "self->len--;\n" - SPACE4 "return self->buf[self->len];\n" + SPACE "assert(self->len > 0);\n" + SPACE "self->len--;\n" + SPACE "return self->buf[self->len];\n" "}\n\n", primitive ? cstr("") : cstr("NODISCARD "), T, VecT, VecT)); if (!primitive) { VecU8_append_vec(&res, VecU8_fmt( "void %s_pop_and_drop(%s* self) {\n" - SPACE4 "assert(self->len > 0);\n" - SPACE4 "%s_drop(self->buf[self->len - 1]);\n" - SPACE4 "self->len--;\n" + SPACE "assert(self->len > 0);\n" + SPACE "%s_drop(self->buf[self->len - 1]);\n" + SPACE "self->len--;\n" "}\n\n", VecT, VecT, T)); } VecU8_append_vec(&res, VecU8_fmt( "%s%s %s_unordered_pop(%s* self, size_t ind) {\n" - SPACE4 "assert(ind < self->len);\n" - SPACE4 "%s res = self->buf[ind];\n" - SPACE4 "self->buf[ind] = self->buf[self->len - 1];\n" - SPACE4 "self->len--;\n" - SPACE4 "return res;\n" + SPACE "assert(ind < self->len);\n" + SPACE "%s res = self->buf[ind];\n" + SPACE "self->buf[ind] = self->buf[self->len - 1];\n" + SPACE "self->len--;\n" + SPACE "return res;\n" "}\n\n", primitive ? cstr("") : cstr("NODISCARD "), T, VecT, VecT, T)); if (!primitive) { VecU8_append_vec(&res, VecU8_fmt( "void %s_unordered_pop_and_drop(%s* self, size_t ind) {\n" - SPACE4 "assert(ind < self->len);\n" - SPACE4 "%s_drop(self->buf[ind]);\n" - SPACE4 "self->buf[ind] = self->buf[self->len - 1];\n" - SPACE4 "self->len--;\n" + SPACE "assert(ind < self->len);\n" + SPACE "%s_drop(self->buf[ind]);\n" + SPACE "self->buf[ind] = self->buf[self->len - 1];\n" + SPACE "self->len--;\n" "}\n\n", VecT, VecT, T)); } VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_swap_with_empty(%s* cell) {\n" - SPACE4 "%s val = *cell;\n" - SPACE4 "*cell = (%s){NULL, 0, 0};\n" - SPACE4 "return val;\n" + SPACE "%s val = *cell;\n" + SPACE "*cell = (%s){NULL, 0, 0};\n" + SPACE "return val;\n" "}\n\n", VecT, VecT, VecT, VecT, VecT)); if (primitive) { VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_new_filled(size_t len, %s el) {\n" - SPACE4 "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" - SPACE4 "for (size_t i = 0; i < len; i++)\n" - SPACE4 SPACE4 "res.buf[i] = el;\n" - SPACE4 "return res;\n" + SPACE "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" + SPACE "for (size_t i = 0; i < len; i++)\n" + SPACE SPACE "res.buf[i] = el;\n" + SPACE "return res;\n" "}\n\n", VecT, VecT, T, VecT, VecT, T)); } else if (clonable) { VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_new_filled(size_t len, const %s* el) {\n" - SPACE4 "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" - SPACE4 "for (size_t i = 0; i < len; i++)\n" - SPACE4 SPACE4 "res.buf[i] = %s_clone(el);\n" - SPACE4 "return res;\n" + SPACE "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" + SPACE "for (size_t i = 0; i < len; i++)\n" + SPACE SPACE "res.buf[i] = %s_clone(el);\n" + SPACE "return res;\n" "}\n\n", VecT, VecT, T, VecT, VecT, T, T)); } @@ -174,18 +174,18 @@ NODISCARD VecU8 generate_VecT_equal_method(SpanU8 T, bool integer) { SpanU8 VecT = VecU8_to_span(&g_VecT); VecU8 res = VecU8_fmt( "bool %s_equal_%s(const %s* A, const %s* B) {\n" - SPACE4 "if (A->len != B->len)\n" - SPACE4 SPACE4 "return false;\n" - SPACE4 "for (size_t i = 0; i < A->len; i++) {\n", VecT, VecT, VecT, VecT); + SPACE "if (A->len != B->len)\n" + SPACE SPACE "return false;\n" + SPACE "for (size_t i = 0; i < A->len; i++) {\n", VecT, VecT, VecT, VecT); if (integer) { VecU8_append_span(&res, cstr(SPACE8 "if (A->buf[i] != B->buf[i])\n")); } else { VecU8_append_vec(&res, VecU8_fmt(SPACE8 "if (!%s_equal_%s(A->buf + i, B->buf + i))\n", T, T)); } VecU8_append_span(&res, cstr( - SPACE4 SPACE4 SPACE4 "return false;\n" - SPACE4 "}\n" - SPACE4 "return true;\n" + SPACE SPACE SPACE "return false;\n" + SPACE "}\n" + SPACE "return true;\n" "}\n\n" )); @@ -199,10 +199,10 @@ NODISCARD VecU8 generate_VecT_new_of_size_method(SpanU8 T) { SpanU8 VecT = VecU8_to_span(&g_VecT); VecU8 res = VecU8_fmt( "NODISCARD %s %s_new_of_size(size_t len) {\n" - SPACE4 "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" - SPACE4 "for (size_t i = 0; i < len; i++)\n" - SPACE4 SPACE4 "res.buf[i] = %s_new();\n" - SPACE4 "return res;\n" + SPACE "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" + SPACE "for (size_t i = 0; i < len; i++)\n" + SPACE SPACE "res.buf[i] = %s_new();\n" + SPACE "return res;\n" "}\n", VecT, VecT, VecT, VecT, T, T); VecU8_drop(g_VecT); @@ -213,7 +213,7 @@ NODISCARD VecU8 generate_VecT_new_of_size_method(SpanU8 T) { void codegen_append_some_span_equal_method(VecU8* res, SpanU8 SpanT) { VecU8_append_vec(res, VecU8_fmt( "bool %s_equal_%s(%s A, %s B) {\n" - SPACE4 "return A->data == B->data && A->len == B->len;\n" + SPACE "return A->data == B->data && A->len == B->len;\n" "}\n\n", SpanT, SpanT, SpanT, SpanT)); } @@ -221,8 +221,8 @@ void codegen_append_some_span_equal_method(VecU8* res, SpanU8 SpanT) { void codegen_append_some_span_struct(VecU8* res, SpanU8 T, SpanU8 SpanT, SpanU8 mod) { VecU8_append_vec(res, VecU8_fmt( "typedef struct {\n" - SPACE4 "%s%s* data;\n" - SPACE4 "size_t len;\n" + SPACE "%s%s* data;\n" + SPACE "size_t len;\n" "} %s;\n\n", mod, T, SpanT)); } @@ -230,8 +230,8 @@ void codegen_append_some_span_struct(VecU8* res, SpanU8 T, SpanU8 SpanT, SpanU8 void codegen_append_some_span_at_method(VecU8* res, SpanU8 T, SpanU8 SpanT, SpanU8 mod) { VecU8_append_vec(res, VecU8_fmt( "%s%s* %s_at(%s self, size_t i) {\n" - SPACE4 "assert(i < self.len);\n" - SPACE4 "return self.data + i;\n" + SPACE "assert(i < self.len);\n" + SPACE "return self.data + i;\n" "}\n\n", mod, T, SpanT, SpanT)); } @@ -240,8 +240,8 @@ void codegen_append_some_span_at_method(VecU8* res, SpanU8 T, SpanU8 SpanT, Span void codegen_append_some_span_span_method(VecU8* res, SpanU8 SpanT) { VecU8_append_vec(res, VecU8_fmt( "%s %s_span(%s self, size_t start, size_t len){\n" - SPACE4 "assert(start < SIZE_MAX - len && start + len <= self.len);\n" - SPACE4 "return (%s){.data = self.data + start, .len = len};\n" + SPACE "assert(start < SIZE_MAX - len && start + len <= self.len);\n" + SPACE "return (%s){.data = self.data + start, .len = len};\n" "}\n\n", SpanT, SpanT, SpanT, SpanT)); } @@ -269,7 +269,7 @@ NODISCARD VecU8 generate_SpanT_struct_and_methods( if (add_mutable) { VecU8_append_vec(&res, VecU8_fmt( "%s %s_to_%s(%s self) {\n" - SPACE4 "return (%s){.data = self.data, .len = self.len};\n" + SPACE "return (%s){.data = self.data, .len = self.len};\n" "}\n\n", SpanT, MutSpanT, SpanT, MutSpanT, SpanT)); } codegen_append_some_span_at_method(&res, T, SpanT, cstr("const ")); @@ -285,18 +285,18 @@ NODISCARD VecU8 generate_SpanT_struct_and_methods( assert(add_mutable); VecU8_append_vec(&res, VecU8_fmt( "int %s_qcompare(const void* a, const void* b) {\n" - SPACE4 "const %s* A = a;\n" - SPACE4 "const %s* B = b;\n", T, T, T)); + SPACE "const %s* A = a;\n" + SPACE "const %s* B = b;\n", T, T, T)); if (integer) { - VecU8_append_span(&res, cstr(SPACE4 "return (int)(B < A) - (int)(A < B);\n")); + VecU8_append_span(&res, cstr(SPACE "return (int)(B < A) - (int)(A < B);\n")); } else { VecU8_append_vec(&res, VecU8_fmt( - SPACE4 "return (int)%s_less_%s(B, A) - (int)%s_less_%s(A, B);\n", T, T, T, T)); + SPACE "return (int)%s_less_%s(B, A) - (int)%s_less_%s(A, B);\n", T, T, T, T)); } VecU8_append_vec(&res, VecU8_fmt( "}\n\n" "void %s_sort(%s self) {\n" - SPACE4 "qsort(self.data, self.len, sizeof(%s), %s_qcompare);\n" + SPACE "qsort(self.data, self.len, sizeof(%s), %s_qcompare);\n" "}\n\n", MutSpanT, MutSpanT, T, T)); } @@ -320,63 +320,63 @@ NODISCARD VecU8 generate_SpanT_VecT_trivmove_collab(SpanU8 T, bool primitive, bo if (clonable) { VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_from_span(%s src){\n" - SPACE4 "%s res = (%s){ .buf = safe_calloc(src.len, sizeof(%s)), .len = src.len, .capacity = src.len };\n", + SPACE "%s res = (%s){ .buf = safe_calloc(src.len, sizeof(%s)), .len = src.len, .capacity = src.len };\n", VecT, VecT, SpanT, VecT, VecT, T)); if (primitive) { VecU8_append_vec(&res, VecU8_fmt( - SPACE4 "memcpy(res.buf, src.data, src.len * sizeof(%s));\n", T)); + SPACE "memcpy(res.buf, src.data, src.len * sizeof(%s));\n", T)); } else { VecU8_append_vec(&res, VecU8_fmt( - SPACE4 "for (size_t i = 0; i < src.len; i++)\n" + SPACE "for (size_t i = 0; i < src.len; i++)\n" SPACE8 "res.buf[i] = %s_clone(&src.data[i]);\n", T)); } - VecU8_append_span(&res, cstr(SPACE4 "return res;\n}\n\n")); + VecU8_append_span(&res, cstr(SPACE "return res;\n}\n\n")); } VecU8_append_vec(&res, VecU8_fmt( "%s %s_to_span(const %s* vec){\n" - SPACE4 "return (%s){vec->buf, vec->len};\n" + SPACE "return (%s){vec->buf, vec->len};\n" "}\n\n", SpanT, VecT, VecT, SpanT)); if (add_mutable) { VecU8_append_vec(&res, VecU8_fmt( "%s %s_to_mspan(%s* vec){\n" - SPACE4 "return (%s){vec->buf, vec->len};\n" + SPACE "return (%s){vec->buf, vec->len};\n" "}\n\n", MutSpanT, VecT, VecT, MutSpanT)); } if (clonable) { VecU8_append_vec(&res, VecU8_fmt( "void %s_append_span(%s* self, %s b) {\n" - SPACE4 "size_t new_length = self->len + b.len;\n" - SPACE4 "if (new_length > self->capacity) {\n" - SPACE4 SPACE4 "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n" - SPACE4 SPACE4 "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n" - SPACE4 SPACE4 "self->capacity = new_capacity;\n" - SPACE4 "}\n", VecT, VecT, SpanT, T)); + SPACE "size_t new_length = self->len + b.len;\n" + SPACE "if (new_length > self->capacity) {\n" + SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n" + SPACE SPACE "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n" + SPACE SPACE "self->capacity = new_capacity;\n" + SPACE "}\n", VecT, VecT, SpanT, T)); if (primitive) { VecU8_append_vec(&res, VecU8_fmt( - SPACE4 "memcpy(self->buf + self->len, b.data, b.len * sizeof(%s));\n", T)); + SPACE "memcpy(self->buf + self->len, b.data, b.len * sizeof(%s));\n", T)); } else { VecU8_append_vec(&res, VecU8_fmt( - SPACE4 "for (size_t i = 0; i < b.len; i++)\n" - SPACE4 SPACE4 "self->buf[self->len + i] = %s_clone(&b.data[i]);\n", T)); + SPACE "for (size_t i = 0; i < b.len; i++)\n" + SPACE SPACE "self->buf[self->len + i] = %s_clone(&b.data[i]);\n", T)); } VecU8_append_span(&res, cstr( - SPACE4 "self->len = new_length;\n" + SPACE "self->len = new_length;\n" "}\n\n")); } if (add_extended) { VecU8_append_vec(&res, VecU8_fmt( "%s %s_span(const %s* vec, size_t start, size_t len) {\n" - SPACE4 "assert(start < SIZE_MAX - len && start + len <= vec->len);\n" - SPACE4 "return (%s){.data = vec->buf + start, .len = len};\n" + SPACE "assert(start < SIZE_MAX - len && start + len <= vec->len);\n" + SPACE "return (%s){.data = vec->buf + start, .len = len};\n" "}\n\n", SpanT, VecT, VecT, SpanT)); if (add_mutable) { VecU8_append_vec(&res, VecU8_fmt( "%s %s_mspan(%s* vec, size_t start, size_t len) {\n" - SPACE4 "assert(start < SIZE_MAX - len && start + len <= vec->len);\n" - SPACE4 "return (%s){.data = vec->buf + start, .len = len};\n" + SPACE "assert(start < SIZE_MAX - len && start + len <= vec->len);\n" + SPACE "return (%s){.data = vec->buf + start, .len = len};\n" "}\n\n", MutSpanT, VecT, VecT, MutSpanT)); } } @@ -578,40 +578,40 @@ NODISCARD VecU8 generate_OptionT_struct_and_methods(option_template_instantiatio if (op.t_ptr) { VecU8_append_vec(&res, VecU8_fmt("typedef %s %s;\n", op.T, OptionT)); VecU8_append_vec(&res, VecU8_fmt("#define None_%s() NULL\n", op.T)); - VecU8_append_vec(&res, VecU8_fmt("%s Some_%s(%s ref) {\n" SPACE4 "return ref;\n}\n\n", OptionT, op.T, op.T)); + VecU8_append_vec(&res, VecU8_fmt("%s Some_%s(%s ref) {\n" SPACE "return ref;\n}\n\n", OptionT, op.T, op.T)); VecU8_append_vec(&res, VecU8_fmt( "%s %s_expect(%s self) {\n" - SPACE4 "return self;\n" + SPACE "return self;\n" "}\n\n", op.T, OptionT, OptionT)); } else { VecU8_append_vec(&res, VecU8_fmt( "typedef struct {\n" - SPACE4 "Option_variant variant;\n" - SPACE4 "%s some;\n" + SPACE "Option_variant variant;\n" + SPACE "%s some;\n" "} %s;\n\n", op.T, OptionT)); VecU8_append_vec(&res, VecU8_fmt("#define None_%s() (%s){ .variant = Option_None }\n\n", op.T, OptionT)); VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s Some_%s(%s obj) {\n" - SPACE4 "return (%s){ .variant = Option_Some, .some = obj };\n" + SPACE "return (%s){ .variant = Option_Some, .some = obj };\n" "}\n\n", OptionT, op.T, op.T, OptionT)); VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_expect(%s self){\n" - SPACE4 "if (self.variant == Option_None)\n" - SPACE4 SPACE4 "abortf(\"Expected something in %s got None\\n\");\n" - SPACE4 "return self.some;\n" + SPACE "if (self.variant == Option_None)\n" + SPACE SPACE "abortf(\"Expected something in %s got None\\n\");\n" + SPACE "return self.some;\n" "}\n\n", op.T, OptionT, OptionT, OptionT)); if (!op.t_primitive) { VecU8_append_vec(&res, VecU8_fmt( "void %s_drop(%s self) {\n" - SPACE4 "if (self.variant == Option_None)\n" - SPACE4 SPACE4 "%s_drop(self.some);\n" + SPACE "if (self.variant == Option_None)\n" + SPACE SPACE "%s_drop(self.some);\n" "}\n\n", OptionT, OptionT, op.T)); if (op.t_clonable) { VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_clone(const %s* self) {\n" - SPACE4 "if (self->variant == Option_None)\n" - SPACE4 SPACE4 "return (%s) { .variant = Option_None };\n" - SPACE4 "return (%s){ .variant = Option_Some, .some = %s_clone(&self->some) };\n" + SPACE "if (self->variant == Option_None)\n" + SPACE SPACE "return (%s) { .variant = Option_None };\n" + SPACE "return (%s){ .variant = Option_Some, .some = %s_clone(&self->some) };\n" "}\n\n", OptionT, OptionT, OptionT, OptionT, OptionT, op.T)); } } diff --git a/src/l1_5/anne/codegen.c b/src/l1_5/anne/codegen.c index d25788d..71ce5d6 100644 --- a/src/l1_5/anne/codegen.c +++ b/src/l1_5/anne/codegen.c @@ -2,12 +2,14 @@ #include "marie/clipping.h" #include "liza.h" +#include "l1_5_templ_very_base.h" int main() { mkdir_nofail("l1_5"); mkdir_nofail("l1_5/marie"); generate_marie_clipping_header(); generate_l1_5_liza_headers(); + generate_l1_5_template_instantiation_for_base_types(); finish_layer(cstr("l1_5")); return 0; } diff --git a/src/l1_5/anne/l1_5_templ_very_base.h b/src/l1_5/anne/l1_5_templ_very_base.h new file mode 100644 index 0000000..127e91f --- /dev/null +++ b/src/l1_5/anne/l1_5_templ_very_base.h @@ -0,0 +1,8 @@ +#ifndef prototype1_src_l1_5_anne_l1_5_templ_very_base_h +#define prototype1_src_l1_5_anne_l1_5_templ_very_base_h + +void generate_l1_5_template_instantiation_for_base_types(){ + +} + +#endif \ No newline at end of file diff --git a/src/l1_5/anne/marie/clipping.h b/src/l1_5/anne/marie/clipping.h index f55f914..1101660 100644 --- a/src/l1_5/anne/marie/clipping.h +++ b/src/l1_5/anne/marie/clipping.h @@ -144,7 +144,7 @@ int mod3_dec(int x) { void generate_func_clip_triang_on_triang_case_where_some_vertex_stuck(VecU8* res, char tC, char tT, bool tables_turned) { /* Case where all 3 vertices of tT are inside tC */ - VecU8_append_span(res, cstr(SPACE4 "if (")); + VecU8_append_span(res, cstr(SPACE "if (")); for (int cs = 0; cs < 3; cs++) { for (int tv = 0; tv < 3; tv++) { if (cs != 0 || tv != 0) @@ -155,11 +155,11 @@ void generate_func_clip_triang_on_triang_case_where_some_vertex_stuck(VecU8* res VecU8_append_span(res, cstr(") {\n" SPACE8)); append_triangle_registration_stmt(res, get_firstborn_vertex_stmt(tT, 0), get_firstborn_vertex_stmt(tT, 1), get_firstborn_vertex_stmt(tT, 2)); - VecU8_append_span(res, cstr(SPACE8 "return;\n" SPACE4 "}\n\n")); + VecU8_append_span(res, cstr(SPACE8 "return;\n" SPACE "}\n\n")); /* Cases where two vertices of tT are inside tC, but one is outside */ for (int ti = 0; ti < 3; ti++) { - VecU8_append_span(res, cstr(SPACE4 "if (")); + VecU8_append_span(res, cstr(SPACE "if (")); int TA = mod3_inc(ti); int TB = mod3_inc(TA); for (int j = 1; j <= 2; j++) { @@ -216,14 +216,14 @@ void generate_func_clip_triang_on_triang_case_where_some_vertex_stuck(VecU8* res } VecU8_append_span(res, cstr(SPACE8 "}\n")); } - VecU8_append_span(res, cstr(SPACE4 "}\n\n")); + VecU8_append_span(res, cstr(SPACE "}\n\n")); } /* Case where one vertice of tT is inside tC, but other two are outside tC */ for (int pl = 0; pl < 3; pl++) { int TA = mod3_inc(pl); int TB = mod3_inc(TA); - VecU8_append_span(res, cstr(SPACE4 "if (")); + VecU8_append_span(res, cstr(SPACE "if (")); for (int cb = 0; cb < 3; cb++) { if (cb) VecU8_append_span(res, cstr(" && ")); @@ -298,7 +298,7 @@ void generate_func_clip_triang_on_triang_case_where_some_vertex_stuck(VecU8* res } VecU8_append_span(res, cstr(SPACE8 "}\n")); } - VecU8_append_span(res, cstr(SPACE4 "}\n\n")); + VecU8_append_span(res, cstr(SPACE "}\n\n")); } } @@ -306,7 +306,7 @@ void generate_func_clip_triang_on_triang_case_where_some_vertex_stuck(VecU8* res void generate_func_clip_triang_on_triang_case_boring(VecU8* res) { /* Star of David case */ for (int cb = 0; cb < 3; cb++) { - VecU8_append_span(res, cstr(SPACE4 "if (")); + VecU8_append_span(res, cstr(SPACE "if (")); for (int i = 0; i < 3; i++) { if (i) VecU8_append_span(res, cstr(" && ")); @@ -325,12 +325,12 @@ void generate_func_clip_triang_on_triang_case_boring(VecU8* res) { VecU8_append_span(res, cstr(SPACE8 "for (int i = 0; i < 4; i++)\n" SPACE12 "VecMarieTriangle_append(pile, (MarieTriangle){hex[i], hex[i + 1], hex[5]});\n")); } - VecU8_append_span(res, cstr(SPACE4 "}\n")); + VecU8_append_span(res, cstr(SPACE "}\n")); } /* Wedge cases */ for (int cf = 0; cf < 3; cf++) { for (int ti = 0; ti < 3; ti++){ - VecU8_append_span(res, cstr(SPACE4 "if (")); + VecU8_append_span(res, cstr(SPACE "if (")); append_on_the_left_stmt(res, 'T', ti, 'T', mod3_dec(ti), 'C', cf); VecU8_append_span(res, cstr(" && ")); append_on_the_right_stmt(res, 'T', mod3_inc(ti), 'T', mod3_dec(ti), 'C', (cf + 2) % 3); @@ -380,7 +380,7 @@ void generate_func_clip_triang_on_triang_case_boring(VecU8* res) { } VecU8_append_span(res, cstr(SPACE8 "}\n")); } - VecU8_append_span(res, cstr(SPACE4 "}\n")); + VecU8_append_span(res, cstr(SPACE "}\n")); } } @@ -390,7 +390,7 @@ NODISCARD VecU8 generate_func_clip_ccw_triang_with_ccw_triang_append_to_Vec() { VecU8 res = VecU8_from_cstr( "void marie_clip_ccw_triang_with_ccw_triang_append_to_Vec(MarieTriangle C, MarieTriangle T, VecMarieTriangle* pile) {\n"); for (int ord = 0; ord < 18; ord++) { - VecU8_append_vec(&res, VecU8_format(SPACE4 "float M%d = marie_surface(", ord)); + VecU8_append_vec(&res, VecU8_format(SPACE "float M%d = marie_surface(", ord)); for (int a = 0; a < 3; a++) { if (a) VecU8_append_span(&res, cstr(", ")); 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 ae46a72..e903ee9 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 @@ -3,26 +3,66 @@ #include "all_set_map_templ_util_inst.h" -// VecU8 codegen_rb_tree_NOT_EQUAL(set_instantiation_op op, SpanU8 A, SpanU8 B){ -// return op.t_integer ? VecU8_fmt("%s != %s", A, B) : VecU8_fmt("!%s_equal_%s(%s, %s)", op.T, op.T, A, B); -// } -// -// VecU8 codegen_rb_tree_LESS(set_instantiation_op op, SpanU8 A, SpanU8 B){ -// return op.t_integer ? VecU8_fmt("A < B", A, B) : VecU8_fmt("%s_less_%s(%s, %s)", op.T, op.T, A, B); -// } - /* When key is given by value into some method of Buff_RBTreeSet */ -NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiation_op op, SpanU8 node_id_var_name){ +NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiation_op op){ if (op.t_integer) - return VecU8_fmt("self->el.buf[%s - 1] != key", node_id_var_name); - return VecU8_fmt("!%s_equal_%s(&self->el.buf[%s - 1], &key)", op.T, op.T, node_id_var_name); + return VecU8_fmt("self->el.buf[cur - 1] != key"); + return VecU8_fmt("!%s_equal_%s(&self->el.buf[cur - 1], &key)", op.T, op.T); } /* When key is given by value into some method of Buff_RBTreeSet */ -NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op op, SpanU8 node_id_var_name){ +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[%s - 1]", node_id_var_name); - return VecU8_fmt("%s_less_%s(&key, &self->el.buf[%s - 1])", op.T, op.T, node_id_var_name); + return VecU8_fmt("key < self->el.buf[cur - 1]"); + return VecU8_fmt("%s_less_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); +} + +/* When key is given by a pointer into some method of Buff_RBTreeSet */ +NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op op){ + if (op.t_integer) + return VecU8_fmt("self->el.buf[cur - 1] == key"); + return VecU8_fmt("%s_equal_%s(&self->el.buf[cur - 1], key)", op.T, op.T); +} + +/* When key is given by a pointer into some method of Buff_RBTreeSet */ +NODISCARD VecU8 codegen_rb_tree_set_key_ref_LESS_element(set_instantiation_op op){ + if (op.t_integer) + return VecU8_fmt("self->el.buf[cur - 1] < key"); + return VecU8_fmt("%s_less_%s(key, &self->el.buf[cur - 1])", op.T, op.T); +} + +/* When method returns constant pointer to found key (wrapped in Option) we will use this type + * Ofcourse, it can turn out that it is not generated. So be careful and generate it by yourself + */ +NODISCARD VecU8 codegen_rb_tree_set_option_returned_ref_t(set_instantiation_op op){ + /* Constant pointer to an integer is an integer */ + return op.t_integer ? VecU8_fmt("Option%s", op.T) : VecU8_fmt("OptionRef%s", op.T); +} + +/* Suppose some method returns pointer to key (ofc wrapped in option). And we found what to return + * we return it from self->el array */ +NODISCARD VecU8 codegen_rb_tree_set_some_ref_t(set_instantiation_op op, SpanU8 index_var_name){ + if (op.t_integer) + return VecU8_fmt("Some_%s(self->el[%s - 1])", op.T, index_var_name); + return VecU8_fmt("Some_Ref%s(&self->el[%s - 1])", op.T, index_var_name); +} + +/* Suppose some method returns pointer to key (ofc wrapped in option). But this time we found nothing */ +NODISCARD VecU8 codegen_rb_tree_set_none_ref_t(set_instantiation_op op, SpanU8 index_var_name){ + if (op.t_integer) + return VecU8_fmt("Some_%s()", op.T, index_var_name); + return VecU8_fmt("Some_Ref%s()", op.T, index_var_name); +} + +/* Suppose some method returns an owned key (by value, ofc wrapped in option). If we DID found something, + * we construct Option_Some */ +NODISCARD VecU8 codegen_rb_tree_some_t(set_instantiation_op op, SpanU8 val_giving_expr){ + return VecU8_fmt("Some_%s(%s)", op.T, val_giving_expr); +} + +/* Suppose some method returns an owned key (by value, ofc wrapped in option). But this time we found nothing */ +NODISCARD VecU8 codegen_rb_tree_none_t(set_instantiation_op op, SpanU8 val_giving_expr){ + return VecU8_fmt("None_%s(%s)", op.T, val_giving_expr); } /* src/l1_5/core/rb_tree_node.h is a dependency of all instantiations of rb_tree_set template @@ -31,68 +71,112 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op NODISCARD VecU8 generate_rb_tree_set_template_instantiation(set_instantiation_op op){ set_instantiation_op_fix(&op); VecU8 res = VecU8_new(); - VecU8 set = VecU8_fmt("BuffRBTree_Set%s", op.T); + VecU8 g_set = VecU8_fmt("BuffRBTree_Set%s", op.T); + SpanU8 set = VecU8_to_span(&g_set); VecU8_append_vec(&res, VecU8_fmt( "typedef struct {\n" - SPACE4 "VecRBTreeNode tree;\n" - SPACE4 "U64 root;\n" - SPACE4 "Vec%s" - "} %s\n\n", op.T, VecU8_to_span(&set))); + SPACE "VecRBTreeNode tree;\n" + SPACE "U64 root;\n" + SPACE "Vec%s" + "} %s\n\n", op.T, set)); VecU8_append_vec(&res, VecU8_fmt( "void %s_drop(%s self) {\n" - SPACE4 "VecRBTreeNode_drop(self->tree);\n" - SPACE4 "Vec%s_drop(self->el);\n" - "}\n\n", VecU8_to_span(&set), VecU8_to_span(&set), op.T)); + SPACE "VecRBTreeNode_drop(self->tree);\n" + SPACE "Vec%s_drop(self->el);\n" + "}\n\n", set, set, op.T)); /* Method insert does not try to replace the existing element with equal key, * it returns true if insertion was done, false it collision happened and key was not inserted */ VecU8_append_vec(&res, VecU8_fmt( - "bool %s_insert(%s* self, %s key) {\n" - SPACE4 "if (self->root == 0) {\n" - SPACE4 SPACE4 "assert(self->tree.len == 1);\n" - SPACE4 SPACE4 "VecRBTreeNode_append(&self->tree, (RBTreeNode){.color = RBTree_black});\n" - SPACE4 SPACE4 "Vec%s_append(&self->el, key);\n" - SPACE4 SPACE4 "self->root = 1;\n" - SPACE4 SPACE4 "return true;\n" - SPACE4 "}\n" - SPACE4 "U64 cur = self->root;\n" - SPACE4 "while (%v) {\n" - SPACE4 SPACE4 "if (%v) {\n" - SPACE4 SPACE4 SPACE4 "if (self->tree.buf[cur].left != 0) {\n" - SPACE4 SPACE4 SPACE4 SPACE4 "cur = self->tree.buf[cur].left\n" - SPACE4 SPACE4 SPACE4 "} else { \n" - /* We are inserting to the left of cur */ - SPACE4 SPACE4 SPACE4 SPACE4 "U64 n = self->tree.len;\n" - SPACE4 SPACE4 SPACE4 SPACE4 "VecRBTreeNode_append(&self->tree, (RBTreeeNode){.parent = cur, .color = RBTree_red});\n" - SPACE4 SPACE4 SPACE4 SPACE4 "self->tree.buf[cur].left = n;\n" - SPACE4 SPACE4 SPACE4 SPACE4 "RBTree_fix_after_insert(&self->tree, &self->root, n);\n" - SPACE4 SPACE4 SPACE4 SPACE4 "return true;\n" - SPACE4 SPACE4 SPACE4 "}\n" - SPACE4 SPACE4 "} else {\n" - SPACE4 SPACE4 SPACE4 "if (self->tree.buf[cur].right != 0) {\n" - SPACE4 SPACE4 SPACE4 SPACE4 "cur = self->tree.buf[cur].right\n" - SPACE4 SPACE4 SPACE4 "} else {\n" - /* We are inserting to the right of cur */ - SPACE4 SPACE4 SPACE4 SPACE4 "U64 n = self->tree.len;\n" - SPACE4 SPACE4 SPACE4 SPACE4 "VecRBTreeNode_append(&self->tree, (RBTreeeNode){.parent = cur, .color = RBTree_red});\n" - SPACE4 SPACE4 SPACE4 SPACE4 "self->tree.buf[cur].right = n;\n" - SPACE4 SPACE4 SPACE4 SPACE4 "RBTree_fix_after_insert(&self->tree, &self->root, n);\n" - SPACE4 SPACE4 SPACE4 SPACE4 "return true;\n" - SPACE4 SPACE4 SPACE4 "}\n" - SPACE4 SPACE4 "}\n" - SPACE4 "}\n" - SPACE4 "return false;\n" - "}\n\n", - VecU8_to_span(&set), VecU8_to_span(&set), op.T, - codegen_rb_tree_set_key_value_NOT_EQUAL_element(op, cstr("cur")), - codegen_rb_tree_set_key_value_LESS_element(op, cstr("cur")) - )); + "bool %s_insert(%s* self, %s key) {\n" + SPACE "if (self->root == 0) {\n" + SPACE SPACE "assert(self->tree.len == 1);\n" + SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeNode){.color = RBTree_black});\n" + SPACE SPACE "Vec%s_append(&self->el, key);\n" + SPACE SPACE "self->root = 1;\n" + SPACE SPACE "return true;\n" + SPACE "}\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (%v) {\n" + SPACE SPACE "if (%v) {\n" + SPACE SPACE SPACE "if (self->tree.buf[cur].left != 0) {\n" + SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].left\n" + SPACE SPACE SPACE "} else { \n" + /* We are inserting to the left of cur */ + SPACE SPACE SPACE SPACE "U64 n = self->tree.len;\n" + SPACE SPACE SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeeNode){.parent = cur, .color = RBTree_red});\n" + SPACE SPACE SPACE SPACE "self->tree.buf[cur].left = n;\n" + SPACE SPACE SPACE SPACE "RBTree_fix_after_insert(self->tree.buf, &self->root, n);\n" + SPACE SPACE SPACE SPACE "return true;\n" + SPACE SPACE SPACE "}\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "if (self->tree.buf[cur].right != 0) {\n" + SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].right\n" + SPACE SPACE SPACE "} else {\n" + /* We are inserting to the right of cur */ + SPACE SPACE SPACE SPACE "U64 n = self->tree.len;\n" + SPACE SPACE SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeeNode){.parent = cur, .color = RBTree_red});\n" + SPACE SPACE SPACE SPACE "self->tree.buf[cur].right = n;\n" + SPACE SPACE SPACE SPACE "RBTree_fix_after_insert(self->tree.buf, &self->root, n);\n" + SPACE SPACE SPACE SPACE "return true;\n" + SPACE SPACE SPACE "}\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return false;\n" + "}\n\n", + set, set, op.T, + codegen_rb_tree_set_key_value_NOT_EQUAL_element(op), + codegen_rb_tree_set_key_value_LESS_element(op) + )); - // VecU8_append_vec(&res, VecU8_fmt( - // "")); + VecU8_append_vec(&res, VecU8_fmt( + "bool %s_erase(%s* self, const %s* key) {\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (true){\n" + SPACE SPACE "if (cur == 0)\n" + SPACE SPACE SPACE "return false;\n" + SPACE SPACE "if (%v)\n" + SPACE SPACE SPACE "break;\n" + SPACE SPACE "if (%v)\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 "}\n" + SPACE "U64 z = cur;\n" + SPACE "U64 y = (self->tree.buf[z].left == 0 || ) ? z : RBTree_minimum_in_subtree(&self->tree);\n" + SPACE "U64 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].z;\n" + SPACE "U64 py = self->tree[y].parent;\n" // May be null + SPACE "self->tree.buf[x] = self->tree.buf[y].parent;\n" + SPACE "if (py == 0)\n" + SPACE SPACE "self->root = x;\n" + SPACE "else if (self->tree.buf[py].left == y)\n" + SPACE SPACE "self->tree.buf[py].left = x;\n" + SPACE "else" + SPACE SPACE "self->tree.buf[py].right = x;\n" + SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" + SPACE "if (z != y)\n" + SPACE SPACE "RBTree_steal_neighbours(z, y);\n" + SPACE "U64 L = self->el.len;\n" /* self->tree.len - 1 */ + SPACE "RBTree_steal_neighbours(L, z);\n" + SPACE "self->tree.len--;\n" + SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" + SPACE "self->el.len--;\n" + SPACE "if (y_org_clr)" + SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" + SPACE "return true;\n" + "}\n\n", + set, set, op.T, + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); - VecU8_drop(set); + // todo: continue from here. Implement method _pop_and_substitute() + + // todo: implement contains method + + // todo: implment _find and _at methods. All the other methods are secondary in importance + VecU8_drop(g_set); return res; } diff --git a/src/l1_5/codegen/trait_wrap_boil.h b/src/l1_5/codegen/trait_wrap_boil.h index a20a63b..0c9dded 100644 --- a/src/l1_5/codegen/trait_wrap_boil.h +++ b/src/l1_5/codegen/trait_wrap_boil.h @@ -28,7 +28,7 @@ NODISCARD VecU8 generate_trait_table_structure(NamedTraitDefRecordRef trait){ // todo: add iteration macro for (size_t i = 0; i < trait.methods.len; i++) { NamedMethodSignatureRecordRef method = *SpanNamedMethodSignatureRecordRef_at(trait.methods, i); - VecU8_append_vec(&res, VecU8_fmt(SPACE4 "%s (*%s)(", method.return_type, method.name)); + VecU8_append_vec(&res, VecU8_fmt(SPACE "%s (*%s)(", method.return_type, method.name)); for (size_t p = 0; p < method.params.len; p++) { NamedVariableRecordRef param = *SpanNamedVariableRecordRef_at(method.params, p); if (p) diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h index 2872b0b..d7c0450 100644 --- a/src/l1_5/core/rb_tree_node.h +++ b/src/l1_5/core/rb_tree_node.h @@ -104,4 +104,107 @@ void RBTree_fix_after_insert(RBTreeNode* tree, U64* root, U64 me){ tree[me].color = RBTree_black; } +/* fr index will be forgotten. to fields will be overwritten (all fields replaced by fr's values) + * If you need the old values of `to` position, you better save them on stack */ +void RBTree_steal_neighbours(RBTreeNode* tree, U64* root, U64 fr, U64 to){ + if (tree[fr].parent == 0) + *root = to; + else if (tree[tree[fr].parent].left == fr) + tree[tree[fr].parent].left = to; + else + tree[tree[fr].parent].right = to; + tree[tree[fr].left].parent = to; + tree[tree[fr].right].parent = to; + tree[to] = tree[fr]; +} + +/* helper function (used in _delete, _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){ + assert(s != 0); + while (tree[s].left != 0) + s = tree[s].left; + return s; +} + +void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ + assert(tree[*root].parent == 0); + while (me != *root && tree[me].color == RBTree_black) { + U64 mom = tree[me].parent; + if (me == tree[mom].left) { /* We are on the left */ + U64 sister = tree[mom].right; + if (tree[sister].color == RBTree_red) { /* Case 1 */ + tree[mom].color = RBTree_red; + tree[sister].color = RBTree_black; + RBTree_left_rotate(tree, root, mom); + /* Reassignation required */ + sister = tree[mom].right; + } + /* Cases 2,3,4 (every instance of red-black tree has an itchy substring in source code containing 2,3,4) */ + assert(sister != 0); + U64 nephew_firstborn = tree[sister].left; + U64 nephew_benjamin = tree[sister].right; + if (tree[nephew_firstborn].color == RBTree_black && tree[nephew_benjamin].color == RBTree_black) { + /* Case 2 */ + tree[sister].color = RBTree_red; + me = mom; + continue; + } + /* Cases 3,4 */ + if (tree[nephew_benjamin].right) { + /* Case 3 */ + tree[nephew_firstborn].color = RBTree_black; + tree[sister].color = RBTree_red; + RBTree_right_rotate(tree, root, sister); + /* Reassignation required */ + nephew_benjamin = sister; + sister = nephew_firstborn; + nephew_firstborn = tree[sister].left; + } + /* Case 4 */ + tree[sister].color = tree[mom].color; + tree[mom].color = RBTree_black; + tree[nephew_benjamin].color = RBTree_red; + me = *root; + } else if (me == tree[mom].right) { /* We are on the right */ + U64 sister = tree[mom].left; + if (tree[sister].color == RBTree_red) { /* Case 1 */ + tree[mom].color = RBTree_red; + tree[sister].color = RBTree_black; + RBTree_right_rotate(tree, root, mom); + /* Reassignation required */ + sister = tree[mom].left; + } + /* Cases 2,3,4 (every instance of red-black tree has an itchy substring in source code containing 2,3,4) */ + assert(sister != 0); + U64 nephew_firstborn = tree[sister].left; + U64 nephew_benjamin = tree[sister].right; + if (tree[nephew_firstborn].color == RBTree_black && tree[nephew_benjamin].color == RBTree_black) { + /* Case 2 */ + tree[sister].color = RBTree_red; + me = mom; + continue; + } + /* Cases 3,4 */ + if (tree[nephew_firstborn].left) { + /* Case 3 */ + tree[nephew_benjamin].color = RBTree_black; + tree[sister].color = RBTree_red; + RBTree_left_rotate(tree, root, sister); + /* Reassignation required */ + nephew_firstborn = sister; + sister = nephew_benjamin; + nephew_benjamin = tree[sister].right; + } + /* Case 4 */ + tree[sister].color = tree[mom].color; + tree[mom].color = RBTree_black; + tree[nephew_firstborn].color = RBTree_red; + me = *root; + } + } + tree[me].color = RBTree_black; +} + #endif diff --git a/src/l2/tests/t0.c b/src/l2/tests/t0.c new file mode 100644 index 0000000..a74e630 --- /dev/null +++ b/src/l2/tests/t0.c @@ -0,0 +1,3 @@ +int main(){ + +} \ No newline at end of file From bcc20b2f6e15df4d92bd2671b6408494ec3a52fa Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Sat, 20 Sep 2025 00:15:46 +0300 Subject: [PATCH 4/9] _insert(), _pop_substitute(), _erase_substitute() + INSTANTIATION for SetT template --- CMakeLists.txt | 6 +- src/l1/anne/util_temp_very_base.h | 8 +- src/l1/codegen/codegen.h | 14 ++ src/l1_5/anne/l1_5_templ_very_base.h | 14 +- .../codegen/rb_tree_set_map_template_inst.h | 225 +++++++++++++----- src/l2/tests/data_structures/t0.c | 5 + src/l2/tests/t0.c | 3 - 7 files changed, 201 insertions(+), 74 deletions(-) create mode 100644 src/l2/tests/data_structures/t0.c delete mode 100644 src/l2/tests/t0.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 70daa25..27fea5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,5 @@ add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) #add_executable(0_play_test src/l3/tests/p0.c) #target_link_libraries(0_play_test -lncurses) # -## Recursively collect all .h files in the src directory. -#file(GLOB_RECURSE HEADER_FILES "${CMAKE_SOURCE_DIR}/src/*.h") -## Do not build utku -#add_executable(utka src/l1/tests/t0.c ${HEADER_FILES}) + +add_executable(l2t0 src/l2/tests/data_structures/t0.c) \ No newline at end of file diff --git a/src/l1/anne/util_temp_very_base.h b/src/l1/anne/util_temp_very_base.h index 22ad5bc..095ddb2 100644 --- a/src/l1/anne/util_temp_very_base.h +++ b/src/l1/anne/util_temp_very_base.h @@ -3,12 +3,14 @@ #include "../codegen/util_template_inst.h" +// todo: split VecAndSpan_int_primitives into multiple files (one file per integer type) + /* These headers are guarded */ void generate_util_temp_very_base_headers() { { GeneratedHeader head = begin_header(cstr("l1/VecAndSpan_int_primitives.h")); VecU8_append_span(&head.result, cstr("#include \"../../src/l1/core/util.h\"\n\n")); - SpanU8 T[4] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")}; + SpanU8 T[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64"), cstr("S64")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { VecU8_append_vec(&head.result, generate_util_templates_instantiation((util_templates_instantiation_options){ .T = T[i], @@ -22,7 +24,7 @@ void generate_util_temp_very_base_headers() { { GeneratedHeader head = begin_header(cstr("l1/Option_int_primitives.h")); VecU8_append_span(&head.result, cstr("#include \"../../src/l1/core/util.h\"\n\n")); - SpanU8 T[4] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")}; + SpanU8 T[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64"), cstr("S64")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { VecU8_append_vec(&head.result, generate_OptionT_struct_and_methods((option_template_instantiation_op){ .T = T[i], .t_integer = true, .t_primitive = true @@ -33,7 +35,7 @@ void generate_util_temp_very_base_headers() { { GeneratedHeader head = begin_header(cstr("l1/VecAndSpan_Vec_int_primitives.h")); VecU8_append_span(&head.result, cstr("#include \"VecAndSpan_int_primitives.h\"\n\n")); - SpanU8 T[4] = {cstr("VecU8"), cstr("VecU16"), cstr("VecU32"), cstr("VecU64")}; + SpanU8 T[] = {cstr("VecU8"), cstr("VecU16"), cstr("VecU32"), cstr("VecU64")}; for (size_t i = 0; i < ARRAY_SIZE(T); i++) { VecU8_append_vec(&head.result, generate_util_templates_instantiation((util_templates_instantiation_options){ .T = T[i], .t_clonable = true, .vec = true, .vec_extended = true, diff --git a/src/l1/codegen/codegen.h b/src/l1/codegen/codegen.h index 61741f0..75850a1 100644 --- a/src/l1/codegen/codegen.h +++ b/src/l1/codegen/codegen.h @@ -71,4 +71,18 @@ NODISCARD VecU8 codegen_T_ref_less_T_ref(SpanU8 T, bool t_integer, VecU8 a, VecU return VecU8_fmt("%s_equal_%s(%v, %v)", T, T, a, b); } +NODISCARD VecU8 prepend_spaces_to_SpanU8_lines(SpanU8 lines, int tabulation){ + VecU8 res = VecU8_new(); + if (lines.len > 0) + for (int j = 0; j < tabulation; j++) + VecU8_append_span(&res, cstr(SPACE)); + for (size_t i = 0; i < lines.len; i++) { + VecU8_append(&res, lines.data[i]); + if (lines.data[i] == '\n' && i + 1 < lines.len) + for (int j = 0; j < tabulation; j++) + VecU8_append_span(&res, cstr(SPACE)); + } + return res; +} + #endif 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 127e91f..798b527 100644 --- a/src/l1_5/anne/l1_5_templ_very_base.h +++ b/src/l1_5/anne/l1_5_templ_very_base.h @@ -1,8 +1,18 @@ #ifndef prototype1_src_l1_5_anne_l1_5_templ_very_base_h #define prototype1_src_l1_5_anne_l1_5_templ_very_base_h -void generate_l1_5_template_instantiation_for_base_types(){ +#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 dep = cstr( + "#include \"../l1/VecAndSpan_int_primitives.h\"\n" + "#include \"../l1/Option_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}); } -#endif \ No newline at end of file +#endif 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 e903ee9..7974e5b 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 @@ -48,27 +48,109 @@ NODISCARD VecU8 codegen_rb_tree_set_some_ref_t(set_instantiation_op op, SpanU8 i } /* Suppose some method returns pointer to key (ofc wrapped in option). But this time we found nothing */ -NODISCARD VecU8 codegen_rb_tree_set_none_ref_t(set_instantiation_op op, SpanU8 index_var_name){ +NODISCARD VecU8 codegen_rb_tree_set_none_ref_t(set_instantiation_op op){ if (op.t_integer) - return VecU8_fmt("Some_%s()", op.T, index_var_name); - return VecU8_fmt("Some_Ref%s()", op.T, index_var_name); + return VecU8_fmt("Some_%s()", op.T); + return VecU8_fmt("Some_Ref%s()", op.T); +} + +NODISCARD VecU8 codegen_rb_tree_set_option_returned_value_t(set_instantiation_op op){ + return VecU8_fmt("Option%s", op.T); } /* Suppose some method returns an owned key (by value, ofc wrapped in option). If we DID found something, * we construct Option_Some */ -NODISCARD VecU8 codegen_rb_tree_some_t(set_instantiation_op op, SpanU8 val_giving_expr){ +NODISCARD VecU8 codegen_rb_tree_set_some_t(set_instantiation_op op, SpanU8 val_giving_expr){ return VecU8_fmt("Some_%s(%s)", op.T, val_giving_expr); } /* Suppose some method returns an owned key (by value, ofc wrapped in option). But this time we found nothing */ -NODISCARD VecU8 codegen_rb_tree_none_t(set_instantiation_op op, SpanU8 val_giving_expr){ - return VecU8_fmt("None_%s(%s)", op.T, val_giving_expr); +NODISCARD VecU8 codegen_rb_tree_set_none_t(set_instantiation_op op){ + return VecU8_fmt("None_%s()", op.T); +} + +/* Suppose some method (like _erase() or _pop(), or _find(), or _at(), takes constant reference to key T + * This function tells how to write type of this argument. Basically it is needed to take into account that + * integer is better than pointer to integer. (Though, notice that _pop family of methods don't exist for + * sets of integers + */ +NODISCARD VecU8 codegen_rb_tree_set_taking_ref_t_argument(set_instantiation_op op){ + return !op.t_integer ? VecU8_fmt("const %s*", op.T) : VecU8_from_span(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( + VecU8* result, set_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); + VecU8 Tc_on_left = prepend_spaces_to_SpanU8_lines(VecU8_to_span(&Tc), 4); + VecU8 Tc_on_right = prepend_spaces_to_SpanU8_lines(VecU8_to_span(&Tc), 4); + VecU8 Fc_exists = prepend_spaces_to_SpanU8_lines(VecU8_to_span(&Fc), 1); + VecU8_drop(Tc); + VecU8_drop(Fc); + + VecU8_append_vec(result, VecU8_fmt( + "%v %s_%s(%s* self, %s key) {\n" /* set, set, op.T */ + SPACE "if (self->root == 0) {\n" + SPACE SPACE "assert(self->tree.len == 1);\n" + SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeNode){.color = RBTree_black});\n" + SPACE SPACE "Vec%s_append(&self->el, key);\n" /* op.T */ + SPACE SPACE "self->root = 1;\n" + "%v" /* Tc_root */ + /* Should have returned by now in Tc*/ + SPACE "}\n" + SPACE "U64 cur = self->root;\n" + SPACE "while (%v) {\n" /* el[cur] != key */ + SPACE SPACE "if (%v) {\n" /* key < el[cur] */ + SPACE SPACE SPACE "if (self->tree.buf[cur].left != 0) {\n" + SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n" + SPACE SPACE SPACE "} else { \n" + /* We are inserting to the left of cur */ + SPACE SPACE SPACE SPACE "U64 n = self->tree.len;\n" + SPACE SPACE SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeNode){.parent = cur, .color = RBTree_red});\n" + SPACE SPACE SPACE SPACE "self->tree.buf[cur].left = n;\n" + SPACE SPACE SPACE SPACE "RBTree_fix_after_insert(self->tree.buf, &self->root, n);\n" + SPACE SPACE SPACE SPACE "Vec%s_append(&self->el, key);\n" /* op.T */ + "%v" /* Tc_on_left */ + /* Should have returned by now in Tc*/ + SPACE SPACE SPACE "}\n" + SPACE SPACE "} else {\n" + SPACE SPACE SPACE "if (self->tree.buf[cur].right != 0) {\n" + SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" + SPACE SPACE SPACE "} else {\n" + /* We are inserting to the right of cur */ + SPACE SPACE SPACE SPACE "U64 n = self->tree.len;\n" + SPACE SPACE SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeNode){.parent = cur, .color = RBTree_red});\n" + SPACE SPACE SPACE SPACE "self->tree.buf[cur].right = n;\n" + SPACE SPACE SPACE SPACE "RBTree_fix_after_insert(self->tree.buf, &self->root, n);\n" + SPACE SPACE SPACE SPACE "Vec%s_append(&self->el, key);\n" /* op.T */ + "%v" /* Tc_on_right */ + /* Should have returned by now in Tc*/ + SPACE SPACE SPACE "}\n" + SPACE SPACE "}\n" + SPACE "}\n" + "%v" /* Fc_exists */ + /* Should have returned by now in Tc*/ + "}\n\n", + RT, set, method_name, set, op.T, op.T, Tc_root, + codegen_rb_tree_set_key_value_NOT_EQUAL_element(op), + codegen_rb_tree_set_key_value_LESS_element(op), + op.T, Tc_on_left, op.T, Tc_on_right, Fc_exists + )); +} + +void codegen_append_rb_tree_set_erase_kind_method( + VecU8* result, set_instantiation_op op, SpanU8 set, SpanU8 method_name, + VecU8 Fc, VecU8 Tc_z_available, VecU8 Tc_returning + ){ + // todo: move deletion here } /* 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_rb_tree_set_template_instantiation(set_instantiation_op op){ +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); @@ -77,61 +159,51 @@ NODISCARD VecU8 generate_rb_tree_set_template_instantiation(set_instantiation_op "typedef struct {\n" SPACE "VecRBTreeNode tree;\n" SPACE "U64 root;\n" - SPACE "Vec%s" - "} %s\n\n", op.T, set)); + SPACE "Vec%s el;\n" + "} %s;\n\n", op.T, set)); VecU8_append_vec(&res, VecU8_fmt( "void %s_drop(%s self) {\n" - SPACE "VecRBTreeNode_drop(self->tree);\n" - SPACE "Vec%s_drop(self->el);\n" + SPACE "VecRBTreeNode_drop(self.tree);\n" + SPACE "Vec%s_drop(self.el);\n" "}\n\n", set, set, op.T)); - /* Method insert does not try to replace the existing element with equal key, - * it returns true if insertion was done, false it collision happened and key was not inserted */ - VecU8_append_vec(&res, VecU8_fmt( - "bool %s_insert(%s* self, %s key) {\n" - SPACE "if (self->root == 0) {\n" - SPACE SPACE "assert(self->tree.len == 1);\n" - SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeNode){.color = RBTree_black});\n" - SPACE SPACE "Vec%s_append(&self->el, key);\n" - SPACE SPACE "self->root = 1;\n" - SPACE SPACE "return true;\n" - SPACE "}\n" - SPACE "U64 cur = self->root;\n" - SPACE "while (%v) {\n" - SPACE SPACE "if (%v) {\n" - SPACE SPACE SPACE "if (self->tree.buf[cur].left != 0) {\n" - SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].left\n" - SPACE SPACE SPACE "} else { \n" - /* We are inserting to the left of cur */ - SPACE SPACE SPACE SPACE "U64 n = self->tree.len;\n" - SPACE SPACE SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeeNode){.parent = cur, .color = RBTree_red});\n" - SPACE SPACE SPACE SPACE "self->tree.buf[cur].left = n;\n" - SPACE SPACE SPACE SPACE "RBTree_fix_after_insert(self->tree.buf, &self->root, n);\n" - SPACE SPACE SPACE SPACE "return true;\n" - SPACE SPACE SPACE "}\n" - SPACE SPACE "} else {\n" - SPACE SPACE SPACE "if (self->tree.buf[cur].right != 0) {\n" - SPACE SPACE SPACE SPACE "cur = self->tree.buf[cur].right\n" - SPACE SPACE SPACE "} else {\n" - /* We are inserting to the right of cur */ - SPACE SPACE SPACE SPACE "U64 n = self->tree.len;\n" - SPACE SPACE SPACE SPACE "VecRBTreeNode_append(&self->tree, (RBTreeeNode){.parent = cur, .color = RBTree_red});\n" - SPACE SPACE SPACE SPACE "self->tree.buf[cur].right = n;\n" - SPACE SPACE SPACE SPACE "RBTree_fix_after_insert(self->tree.buf, &self->root, n);\n" - SPACE SPACE SPACE SPACE "return true;\n" - SPACE SPACE SPACE "}\n" - SPACE SPACE "}\n" - SPACE "}\n" - SPACE "return false;\n" - "}\n\n", - set, set, op.T, - codegen_rb_tree_set_key_value_NOT_EQUAL_element(op), - codegen_rb_tree_set_key_value_LESS_element(op) - )); + /* 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_rb_tree_set_insert_kind_method(&res, op, set, cstr("insert"), vcstr("bool"), + vcstr("return true;\n"), + op.t_integer ? + vcstr("return false;\n") : + VecU8_fmt( + "%s_drop(key);\n" /* op.T */ + "return false;\n", + op.T)); + + /* Method _erase_substitute() is a mole bald version of _insert() method. It will substitute + * previous element with equal key it it was found. It still returns true if no conflict has happened, though */ + codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("erase_substitute"), vcstr("bool"), + vcstr("return true;\n"), + op.t_integer ? + vcstr("return false;\n") : + VecU8_fmt( + "%s_drop(self->el.buf[cur - 1]);\n" + "self->el.buf[cur - 1] = key;\n" + "return false;\n" + )); + + if (!op.t_integer) { + codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("pop_substitute"), + codegen_rb_tree_set_option_returned_value_t(op), + VecU8_fmt("return %v;\n", codegen_rb_tree_set_none_t(op)), + VecU8_fmt( + "%s old = self->el.buf[cur - 1];\n" /* op.T */ + "self->el.buf[cur - 1] = key;\n" + "return %v;", /* Some_T(old) */ + op.T, codegen_rb_tree_set_some_t(op, cstr("old")))); + } VecU8_append_vec(&res, VecU8_fmt( - "bool %s_erase(%s* self, const %s* key) {\n" + "bool %s_erase(%s* self, %v key) {\n" /* set, codegen_rb_tree_set_taking_ref_t_argument */ SPACE "U64 cur = self->root;\n" SPACE "while (true){\n" SPACE SPACE "if (cur == 0)\n" @@ -144,10 +216,10 @@ NODISCARD VecU8 generate_rb_tree_set_template_instantiation(set_instantiation_op SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n" SPACE "}\n" SPACE "U64 z = cur;\n" - SPACE "U64 y = (self->tree.buf[z].left == 0 || ) ? z : RBTree_minimum_in_subtree(&self->tree);\n" - SPACE "U64 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].z;\n" - SPACE "U64 py = self->tree[y].parent;\n" // May be null - SPACE "self->tree.buf[x] = self->tree.buf[y].parent;\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 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].right;\n" + SPACE "U64 py = self->tree.buf[y].parent;\n" // May be null + SPACE "self->tree.buf[x].parent = self->tree.buf[y].parent;\n" SPACE "if (py == 0)\n" SPACE SPACE "self->root = x;\n" SPACE "else if (self->tree.buf[py].left == y)\n" @@ -156,9 +228,9 @@ NODISCARD VecU8 generate_rb_tree_set_template_instantiation(set_instantiation_op SPACE SPACE "self->tree.buf[py].right = x;\n" SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" SPACE "if (z != y)\n" - SPACE SPACE "RBTree_steal_neighbours(z, y);\n" + SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\n" SPACE "U64 L = self->el.len;\n" /* self->tree.len - 1 */ - SPACE "RBTree_steal_neighbours(L, z);\n" + SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" SPACE "self->tree.len--;\n" SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" SPACE "self->el.len--;\n" @@ -166,7 +238,7 @@ NODISCARD VecU8 generate_rb_tree_set_template_instantiation(set_instantiation_op SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" SPACE "return true;\n" "}\n\n", - set, set, op.T, + 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) )); @@ -180,4 +252,33 @@ NODISCARD VecU8 generate_rb_tree_set_template_instantiation(set_instantiation_op return res; } + +void generate_rb_tree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, option_template_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); + write_whole_file_or_abort((const char*)nt_path.buf, VecU8_to_span(&text)); + VecU8_drop(nt_path); + VecU8_drop(text); +} + +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); + 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/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_rb_tree_Set_template_instantiation(op)); + finish_header(head); +} + #endif \ No newline at end of file diff --git a/src/l2/tests/data_structures/t0.c b/src/l2/tests/data_structures/t0.c new file mode 100644 index 0000000..6c2af0c --- /dev/null +++ b/src/l2/tests/data_structures/t0.c @@ -0,0 +1,5 @@ +#include "../../../../gen/l1_5/BuffRBTree_SetS64.h" + +int main() { + return 0; +} diff --git a/src/l2/tests/t0.c b/src/l2/tests/t0.c deleted file mode 100644 index a74e630..0000000 --- a/src/l2/tests/t0.c +++ /dev/null @@ -1,3 +0,0 @@ -int main(){ - -} \ No newline at end of file From 36ef29cff1d7385e46ba3d2e11199fbc5f18bdbf Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Sun, 21 Sep 2025 16:02:16 +0300 Subject: [PATCH 5/9] Tests for insertion passed + written _find(), _at() methods --- .../codegen/rb_tree_set_map_template_inst.h | 96 +++++++--- src/l1_5/core/rb_tree_node.h | 6 +- src/l2/tests/data_structures/t0.c | 172 ++++++++++++++++++ 3 files changed, 250 insertions(+), 24 deletions(-) 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 7974e5b..496e4b9 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 @@ -6,8 +6,8 @@ /* When key is given by value into some method of Buff_RBTreeSet */ NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiation_op op){ if (op.t_integer) - return VecU8_fmt("self->el.buf[cur - 1] != key"); - return VecU8_fmt("!%s_equal_%s(&self->el.buf[cur - 1], &key)", op.T, op.T); + return VecU8_fmt("key != self->el.buf[cur - 1]"); + return VecU8_fmt("!%s_equal_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); } /* When key is given by value into some method of Buff_RBTreeSet */ @@ -17,17 +17,25 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op return VecU8_fmt("%s_less_%s(&key, &self->el.buf[cur - 1])", op.T, op.T); } +/* When key is given by ref into some method of Buff_RBTreeSet + * Ofk when op.T is integer, argument is still taken by a value */ +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]"); + return VecU8_fmt("!%s_equal_%s(key, &self->el.buf[cur - 1])", op.T, op.T); +} + /* When key is given by a pointer into some method of Buff_RBTreeSet */ NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op op){ if (op.t_integer) - return VecU8_fmt("self->el.buf[cur - 1] == key"); - return VecU8_fmt("%s_equal_%s(&self->el.buf[cur - 1], key)", op.T, op.T); + return VecU8_fmt("key == self->el.buf[cur - 1]"); + return VecU8_fmt("%s_equal_%s(ref, &self->el.buf[cur - 1])", op.T, op.T); } /* When key is given by a pointer into some method of Buff_RBTreeSet */ NODISCARD VecU8 codegen_rb_tree_set_key_ref_LESS_element(set_instantiation_op op){ if (op.t_integer) - return VecU8_fmt("self->el.buf[cur - 1] < key"); + return VecU8_fmt("key < self->el.buf[cur - 1]"); return VecU8_fmt("%s_less_%s(key, &self->el.buf[cur - 1])", op.T, op.T); } @@ -162,6 +170,11 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op SPACE "Vec%s el;\n" "} %s;\n\n", op.T, set)); + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s %s_new() {\n" + SPACE "return (%s){.tree = VecRBTreeNode_new_zeroinit(1), .root = 0, .el = Vec%s_new()};\n" + "}\n\n", set, set, set, op.T)); + VecU8_append_vec(&res, VecU8_fmt( "void %s_drop(%s self) {\n" SPACE "VecRBTreeNode_drop(self.tree);\n" @@ -179,19 +192,21 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op "return false;\n", op.T)); - /* Method _erase_substitute() is a mole bald version of _insert() method. It will substitute - * previous element with equal key it it was found. It still returns true if no conflict has happened, though */ - codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("erase_substitute"), vcstr("bool"), - vcstr("return true;\n"), - op.t_integer ? - vcstr("return false;\n") : - VecU8_fmt( - "%s_drop(self->el.buf[cur - 1]);\n" - "self->el.buf[cur - 1] = key;\n" - "return false;\n" - )); - if (!op.t_integer) { + /* Method _erase_substitute() is a more bald version of _insert() method. It will substitute + * previous element with equal key it it was found. It still returns true if no conflict has happened, though */ + codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("erase_substitute"), vcstr("bool"), + vcstr("return true;\n"), + op.t_integer ? + vcstr("return false;\n") : + VecU8_fmt( + "%s_drop(self->el.buf[cur - 1]);\n" + "self->el.buf[cur - 1] = key;\n" + "return false;\n" + )); + + /* Method _pop_substitute() is just like _erase_substitute(), but it returns a previous key + * that was overthrown after collision. Wrapped in option, ofcourse */ codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("pop_substitute"), codegen_rb_tree_set_option_returned_value_t(op), VecU8_fmt("return %v;\n", codegen_rb_tree_set_none_t(op)), @@ -224,7 +239,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op SPACE SPACE "self->root = x;\n" SPACE "else if (self->tree.buf[py].left == y)\n" SPACE SPACE "self->tree.buf[py].left = x;\n" - SPACE "else" + SPACE "else\n" SPACE SPACE "self->tree.buf[py].right = x;\n" SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" SPACE "if (z != y)\n" @@ -234,7 +249,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op SPACE "self->tree.len--;\n" SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" SPACE "self->el.len--;\n" - SPACE "if (y_org_clr)" + SPACE "if (y_org_clr)\n" SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" SPACE "return true;\n" "}\n\n", @@ -243,11 +258,50 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op codegen_rb_tree_set_key_ref_LESS_element(op) )); + VecU8_append_vec(&res, VecU8_fmt( + "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 */ + 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 cur;\n" + "}\n\n", + set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_NOT_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op) + )); + + if (!op.t_integer) { + VecU8_append_vec(&res, VecU8_fmt( + "%v %s_at(const %s* self, %v key) {\n" /* option_returned_ref_t, set, set, taking_ref_t_argument */ + SPACE "U64 cur = self->root;\n" + SPACE "while (cur != 0) {\n" + SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "return %v;\n" /* some_ref_t */ + 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 "cur = self->tree.buf[cur].right;\n" + SPACE SPACE "}\n" + SPACE "}\n" + SPACE "return %v;\n" /* none_ref_t */ + "}\n\n", + codegen_rb_tree_set_option_returned_ref_t(op), set, set, codegen_rb_tree_set_taking_ref_t_argument(op), + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_some_ref_t(op, cstr("cur")), + codegen_rb_tree_set_key_ref_LESS_element(op), + codegen_rb_tree_set_none_ref_t(op) + )); + } + // todo: continue from here. Implement method _pop_and_substitute() - // todo: implement contains method + // todo: All the other methods are secondary in importance - // todo: implment _find and _at methods. All the other methods are secondary in importance VecU8_drop(g_set); return res; } diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h index d7c0450..d39aa16 100644 --- a/src/l1_5/core/rb_tree_node.h +++ b/src/l1_5/core/rb_tree_node.h @@ -27,7 +27,7 @@ void RBTree_left_rotate(RBTreeNode* tree, U64* root, U64 x){ tree[tree[x].right].parent = x; tree[y].parent = tree[x].parent; - if (tree[y].parent != 0) { + if (tree[y].parent == 0) { *root = y; } else if (x == tree[tree[x].parent].left) { tree[tree[x].parent].left = y; @@ -47,7 +47,7 @@ void RBTree_right_rotate(RBTreeNode* tree, U64* root, U64 x){ tree[tree[x].left].parent = x; tree[y].parent = tree[x].parent; - if (tree[y].parent != 0) { + if (tree[y].parent == 0) { *root = y; } else if (x == tree[tree[x].parent].right) { tree[tree[x].parent].right = y; @@ -66,7 +66,7 @@ void RBTree_fix_after_insert(RBTreeNode* tree, U64* root, U64 me){ if (mom == 0) break; if (tree[mom].color == RBTree_black) - break; + return; U64 grandma = tree[mom].parent; U64 aunt = tree[grandma].left == mom ? tree[grandma].right : tree[grandma].left; assert(aunt != mom); diff --git a/src/l2/tests/data_structures/t0.c b/src/l2/tests/data_structures/t0.c index 6c2af0c..d5b8535 100644 --- a/src/l2/tests/data_structures/t0.c +++ b/src/l2/tests/data_structures/t0.c @@ -1,5 +1,177 @@ #include "../../../../gen/l1_5/BuffRBTree_SetS64.h" +void assert_structure_h_dfs(const VecRBTreeNode* tree, U64 x, VecU8* f){ + if (x == 0) + return; + if (*VecU8_at(f, x - 1) != 0) + assert(false); + *VecU8_mat(f, x - 1) = 1; + assert_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->left, f); + assert_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->right, f); +} + +U32 assert_structure_h_dfs_2(RBTreeNode* tree, U64 x){ + if (x == 0) { + return 0; + } + U32 a = assert_structure_h_dfs_2(tree, tree[x].left); + U32 b = assert_structure_h_dfs_2(tree, tree[x].right); + assert(a == b); + return a + (tree[x].color == RBTree_black ? 1 : 0); +} + +void assert_structure(const BuffRBTree_SetS64* self){ + assert(self->tree.len == self->el.len + 1); + assert(self->root < self->tree.len); + if (self->tree.len > 1) { + assert(self->root != 0); + } + VecU8 f = VecU8_new_zeroinit(self->tree.len - 1); + assert_structure_h_dfs(&self->tree, self->root, &f); + for (size_t i = 0; i < self->tree.len - 1; i++) { + assert(*VecU8_at(&f, i)); + } + VecU8_drop(f); /* f invalidated */ + for (size_t v = 1; v < self->tree.len; v++) { + if (v == self->root) { + assert(self->tree.buf[v].parent == 0); + } else { + assert(self->tree.buf[v].parent != 0); + } + assert(self->tree.buf[v].parent < self->tree.len); + assert(self->tree.buf[v].left < self->tree.len); + assert(self->tree.buf[v].right < self->tree.len); + if (self->tree.buf[v].left != 0) { + assert(self->tree.buf[self->tree.buf[v].left].parent == v); + assert(self->el.buf[self->tree.buf[v].left - 1] < self->el.buf[v - 1]); + } + if (self->tree.buf[v].right != 0) { + assert(self->tree.buf[self->tree.buf[v].right].parent == v); + assert(self->el.buf[v - 1] < self->el.buf[self->tree.buf[v].right - 1]); + } + } + + /* Checking coloring */ + assert(self->tree.buf[0].color == RBTree_black); + if (self->root != 0) + assert(self->tree.buf[self->root].color == RBTree_black); + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].color == RBTree_red) { + assert(self->tree.buf[self->tree.buf[v].left].color == RBTree_black); + assert(self->tree.buf[self->tree.buf[v].right].color == RBTree_black); + } + } + assert_structure_h_dfs_2(self->tree.buf, self->root); +} + +void insert_only(){ + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + assert_structure(&set); + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + bool ret = BuffRBTree_SetS64_insert(&set, 42); + assert(ret); + assert_structure(&set); + assert(set.el.len == 1); + assert(set.root == 1); + BuffRBTree_SetS64_drop(set); + } + { + bool ret; + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + ret = BuffRBTree_SetS64_insert(&set, 42); + assert(ret); + assert_structure(&set); + ret = BuffRBTree_SetS64_insert(&set, 69); + assert(ret); + assert_structure(&set); + assert(set.el.len == 2); + BuffRBTree_SetS64_drop(set); + } + { + bool ret; + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + ret = BuffRBTree_SetS64_insert(&set, 70); + assert(ret); + assert_structure(&set); + ret = BuffRBTree_SetS64_insert(&set, 50); + assert(ret); + assert_structure(&set); + assert(set.el.len == 2); + BuffRBTree_SetS64_drop(set); + } + { + bool ret; + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + ret = BuffRBTree_SetS64_insert(&set, 1); + assert(ret); + assert_structure(&set); + ret = BuffRBTree_SetS64_insert(&set, 2); + assert(ret); + assert_structure(&set); + ret = BuffRBTree_SetS64_insert(&set, 3); + assert(ret); + assert_structure(&set); + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + for (S64 i = 10; i < 100; i++) { + bool ret = BuffRBTree_SetS64_insert(&set, i); + assert(ret); + assert_structure(&set); + } + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + for (S64 i = 99; i >= 10; i--) { + bool ret = BuffRBTree_SetS64_insert(&set, i); + assert(ret); + assert_structure(&set); + } + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + for (S64 i = 10; i < 100; i++) { + bool ret = BuffRBTree_SetS64_insert(&set, i); + assert(ret); + assert_structure(&set); + bool ret2 = BuffRBTree_SetS64_insert(&set, 1000 - i); + assert(ret2); + assert_structure(&set); + } + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + // BuffRBTree_SetS64_erase_substitute() + BuffRBTree_SetS64_drop(set); + } +} + +void insert_and_then_find(){ + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + for (S64 p = 0; p < 100; p++) { + bool ret = BuffRBTree_SetS64_insert(&set, 2 * p); + assert(ret); + assert_structure(&set); + for (S64 i = 0; i <= p; i++) { + U64 ret1 = BuffRBTree_SetS64_find(&set, 2 * i); + assert(ret1); + U64 ret2 = BuffRBTree_SetS64_find(&set, 2 * i + 1); + assert(ret2 == 0); + } + } + BuffRBTree_SetS64_drop(set); +} + int main() { + insert_only(); + insert_and_then_find(); return 0; } From 0a35394a2e65d42644a8647e138b296a2849a54a Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Sun, 21 Sep 2025 16:44:07 +0300 Subject: [PATCH 6/9] All max priority methods written --- src/l1_5/anne/l1_5_templ_very_base.h | 3 +- .../codegen/rb_tree_set_map_template_inst.h | 110 +++++++++++------- 2 files changed, 68 insertions(+), 45 deletions(-) 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 798b527..479b283 100644 --- a/src/l1_5/anne/l1_5_templ_very_base.h +++ b/src/l1_5/anne/l1_5_templ_very_base.h @@ -7,8 +7,7 @@ void generate_l1_5_template_instantiation_for_base_types(){ SpanU8 l = cstr("l1_5"); SpanU8 ns = cstr(""); SpanU8 dep = cstr( - "#include \"../l1/VecAndSpan_int_primitives.h\"\n" - "#include \"../l1/Option_int_primitives.h\"" + "#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}); 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 496e4b9..561e19e 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 @@ -149,10 +149,61 @@ void codegen_append_rb_tree_set_insert_kind_method( } void codegen_append_rb_tree_set_erase_kind_method( - VecU8* result, set_instantiation_op op, SpanU8 set, SpanU8 method_name, - VecU8 Fc, VecU8 Tc_z_available, VecU8 Tc_returning + VecU8* result, set_instantiation_op op, SpanU8 set, SpanU8 method_name, VecU8 RT, + VecU8 Fc, VecU8 Tc_cur_available, VecU8 Tc_returning ){ - // todo: move deletion here + VecU8 not_found_case = prepend_spaces_to_SpanU8_lines(VecU8_to_span(&Fc), 3); + VecU8 saving_prev = prepend_spaces_to_SpanU8_lines(VecU8_to_span(&Tc_cur_available), 1); + VecU8 ret_found_case = prepend_spaces_to_SpanU8_lines(VecU8_to_span(&Tc_returning), 1); + VecU8_drop(Fc); + VecU8_drop(Tc_cur_available); + VecU8_drop(Tc_returning); + + VecU8_append_vec(result, VecU8_fmt( + "%v %s_%s(%s* self, %v key) {\n" /* RT, set, method_name, set, taking_ref_t_argument */ + SPACE "U64 cur = self->root;\n" + SPACE "while (true){\n" + SPACE SPACE "if (cur == 0) {\n" + "%v" /* not_found_case */ + SPACE SPACE "}\n" + SPACE SPACE "if (%v)\n" /* key_ref_EQUAL_element */ + SPACE SPACE SPACE "break;\n" + SPACE SPACE "if (%v)\n" /* key_ref_LESS_element */ + 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 "}\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 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].right;\n" + SPACE "U64 py = self->tree.buf[y].parent;\n" // May be null + SPACE "self->tree.buf[x].parent = self->tree.buf[y].parent;\n" + SPACE "if (py == 0)\n" + SPACE SPACE "self->root = x;\n" + SPACE "else if (self->tree.buf[py].left == y)\n" + SPACE SPACE "self->tree.buf[py].left = x;\n" + SPACE "else\n" + SPACE SPACE "self->tree.buf[py].right = x;\n" + SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" + SPACE "if (z != y)\n" + SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\n" + SPACE "U64 L = self->el.len;\n" /* self->tree.len - 1 */ + SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" + SPACE "self->tree.len--;\n" + SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" + SPACE "self->el.len--;\n" + SPACE "if (y_org_clr)\n" + SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" + "%v" /* ret_found_case */ + "}\n\n", + RT, set, method_name, set, codegen_rb_tree_set_taking_ref_t_argument(op), + not_found_case, + codegen_rb_tree_set_key_ref_EQUAL_element(op), + codegen_rb_tree_set_key_ref_LESS_element(op), + saving_prev, + ret_found_case + )); } /* src/l1_5/core/rb_tree_node.h is a dependency of all instantiations of rb_tree_set template @@ -217,46 +268,19 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op op.T, codegen_rb_tree_set_some_t(op, cstr("old")))); } - VecU8_append_vec(&res, VecU8_fmt( - "bool %s_erase(%s* self, %v key) {\n" /* set, codegen_rb_tree_set_taking_ref_t_argument */ - SPACE "U64 cur = self->root;\n" - SPACE "while (true){\n" - SPACE SPACE "if (cur == 0)\n" - SPACE SPACE SPACE "return false;\n" - SPACE SPACE "if (%v)\n" - SPACE SPACE SPACE "break;\n" - SPACE SPACE "if (%v)\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 "}\n" - 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 x = self->tree.buf[y].left != 0 ? self->tree.buf[y].left : self->tree.buf[y].right;\n" - SPACE "U64 py = self->tree.buf[y].parent;\n" // May be null - SPACE "self->tree.buf[x].parent = self->tree.buf[y].parent;\n" - SPACE "if (py == 0)\n" - SPACE SPACE "self->root = x;\n" - SPACE "else if (self->tree.buf[py].left == y)\n" - SPACE SPACE "self->tree.buf[py].left = x;\n" - SPACE "else\n" - SPACE SPACE "self->tree.buf[py].right = x;\n" - SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" - SPACE "if (z != y)\n" - SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\n" - SPACE "U64 L = self->el.len;\n" /* self->tree.len - 1 */ - SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" - SPACE "self->tree.len--;\n" - SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" - SPACE "self->el.len--;\n" - SPACE "if (y_org_clr)\n" - SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" - SPACE "return true;\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) - )); + codegen_append_rb_tree_set_erase_kind_method(&res, op, set, cstr("erase"), vcstr("bool"), + vcstr("return false;\n"), + op.t_primitive ? vcstr("") : VecU8_fmt("%s_drop(self->el.buf[cur - 1]);\n", op.T), + vcstr("return true;\n")); + + if (!op.t_integer) { + codegen_append_rb_tree_set_erase_kind_method(&res, op, set, cstr("pop"), + codegen_rb_tree_set_option_returned_value_t(op), + VecU8_fmt("return %v;\n", codegen_rb_tree_set_none_t(op)), + VecU8_fmt("%s saved = self->el[cur - 1];\n", op.T), + VecU8_fmt("return %v;\n", codegen_rb_tree_set_some_t(op, cstr("saved"))) + ); + } VecU8_append_vec(&res, VecU8_fmt( "U64 %s_find(const %s* self, %v key) {\n" /* set, set taking_ref_t_argument */ From ccba6112fa6f27b0ca33f38e19cc9af83fdfe35d Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Mon, 22 Sep 2025 22:09:12 +0300 Subject: [PATCH 7/9] fixed some bugs, wrote some tests. Still need to write rb tree graphvizization for better gaming --- .gitignore | 4 +- CMakeLists.txt | 4 +- Makefile | 10 +- shell.nix | 5 +- src/l1/core/VecU8_as_str.h | 22 +- src/l1/core/util.h | 2 + src/l1/system/creating_child_proc.h | 18 ++ src/l1_4/tests/t2.c | 41 ++++ .../codegen/rb_tree_set_map_template_inst.h | 57 ++++- src/l1_5/core/rb_tree_node.h | 12 +- src/l1_5/core/stringop.h | 10 - src/l2/tests/data_structures/t0.c | 195 ++++++++++++------ src/l2/tests/r0/r0.c | 17 +- 13 files changed, 298 insertions(+), 99 deletions(-) create mode 100644 src/l1/system/creating_child_proc.h create mode 100644 src/l1_4/tests/t2.c diff --git a/.gitignore b/.gitignore index 50f6faf..c04f2fa 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ vgcore.* *.xcf *_NORMAL.png *_TEMPLATE.png -/out \ No newline at end of file +/out +GRAPH*.dot +GRAPH*.png \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 27fea5c..dda56d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,8 @@ add_compile_options(-fno-trapping-math) #add_executable(0_test src/l1_4/tests/t0.c) #add_executable(1_test src/l1_4/tests/t1.c) # +add_executable(l1_4_t2 src/l1_4/tests/t2.c) + add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) # #add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c @@ -56,4 +58,4 @@ add_executable(codegen_l1_5 src/l1_5/anne/codegen.c) #target_link_libraries(0_play_test -lncurses) # -add_executable(l2t0 src/l2/tests/data_structures/t0.c) \ No newline at end of file +add_executable(l2t0 src/l2/tests/data_structures/t0.c) diff --git a/Makefile b/Makefile index 91d9d48..1e52fb4 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,15 @@ xdg_shell_private := gen/l_wl_protocols/xdg-shell-private.c l_wl_protocols := gen/l_wl_protocols/xdg-shell-client.h $(xdg_shell_private) +out/l2/t0: src/l2/tests/data_structures/t0.c $(HEADERS_gen_l1_5) + mkdir -p out/l2 + $(cc) $(cflags) -o $@ $< + +.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) mkdir -p out/l2 $(cc) $(cflags) -o $@ $< $(xdg_shell_private) -lvulkan -lm -lxkbcommon -lwayland-client -lpng @@ -101,4 +110,3 @@ run_r3: out/l2/r3 .PHONY: clean clean: rm -rf gen out - diff --git a/shell.nix b/shell.nix index 92fc387..8fdb217 100644 --- a/shell.nix +++ b/shell.nix @@ -12,7 +12,8 @@ let libs = (with pkgs; [ libpng ]); in pkgs.mkShell { - buildInputs = with pkgs; [ + buildInputs = with pkgs; [ + graphviz pipewire shaderc gnumake @@ -28,6 +29,6 @@ pkgs.mkShell { shellHook = '' export VK_LAYER_PATH="${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d" echo Day ruined. - ''; +''; } diff --git a/src/l1/core/VecU8_as_str.h b/src/l1/core/VecU8_as_str.h index d40a992..d80ec43 100644 --- a/src/l1/core/VecU8_as_str.h +++ b/src/l1/core/VecU8_as_str.h @@ -78,7 +78,7 @@ void S64_stringification_into_buf(S64 x, VecU8* targ){ if (x == 0) { VecU8_append(targ, '0'); } else if (x == -9223372036854775807L-1) { - VecU8_append_span(targ, cstr("-9223372036854775807")); + VecU8_append_span(targ, cstr("-9223372036854775808")); } else { if (x < 0) { VecU8_append(targ, '-'); @@ -97,7 +97,7 @@ void S64_stringification_into_buf(S64 x, VecU8* targ){ *right = *left; *left = t; left++; - right++; + right--; } } } @@ -130,7 +130,7 @@ void U64_stringification_into_buf(U64 x, VecU8* targ){ *right = *left; *left = t; left++; - right++; + right--; } } } @@ -156,7 +156,7 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) { /* We had not taken ownership of YET (will take it the next iteration) */ VecU8 vs = va_arg(args, VecU8); k += vs.len; - } else if (*ch == 's') { + } else if (*ch == 'i') { S64 x = va_arg(args, S64); k += S64_stringification_get_length(x); } else if (*ch == 'u') { @@ -186,7 +186,7 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) { } else if (*ch == 'v') { VecU8 vs = va_arg(args, VecU8); VecU8_append_vec(&res, vs); /* Moved ownership of vs argument */ - } else if (*ch == 's') { + } else if (*ch == 'i') { S64 x = va_arg(args, S64); S64_stringification_into_buf(x, &res); } else if (*ch == 'u') { @@ -203,4 +203,16 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) { return res; } +// todo: generate a special span method to check equality of contents +bool strings_in_spans_equal(SpanU8 a, SpanU8 b) { + if (a.len != b.len) + return false; + for (size_t i = 0; i < a.len; i++) { + if (*SpanU8_at(a, i) != *SpanU8_at(b, i)) + return false; + } + return true; +} + + #endif diff --git a/src/l1/core/util.h b/src/l1/core/util.h index 1e99f56..dfe2826 100644 --- a/src/l1/core/util.h +++ b/src/l1/core/util.h @@ -85,4 +85,6 @@ typedef struct { U32 height; } SizeOfRectangleU32; +#define check(expr) if (!(expr)) { abortf("Assertion failed at %s : %d : " #expr "\n", __FILE__, __LINE__); } + #endif diff --git a/src/l1/system/creating_child_proc.h b/src/l1/system/creating_child_proc.h new file mode 100644 index 0000000..a651e8e --- /dev/null +++ b/src/l1/system/creating_child_proc.h @@ -0,0 +1,18 @@ +#ifndef prototype1_src_l1_system_creating_child_proc_h +#define prototype1_src_l1_system_creating_child_proc_h + +#include "../core/util.h" + +void calling_system_func_nofail(const char* command) { + int ret = system(command); + if (ret == -1) { + abortf("system() failed\n"); + } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { + abortf("Error: command exited with code %d\n", WEXITSTATUS(ret)); + } else if (!WIFEXITED(ret)) { + abortf("Error: command terminated abnormally\n"); + } +} + + +#endif \ No newline at end of file diff --git a/src/l1_4/tests/t2.c b/src/l1_4/tests/t2.c new file mode 100644 index 0000000..0016d01 --- /dev/null +++ b/src/l1_4/tests/t2.c @@ -0,0 +1,41 @@ +#include "../../l1/core/VecU8_as_str.h" + +int main(){ + { + VecU8 res = VecU8_fmt("%i", 0); + check(strings_in_spans_equal(VecU8_to_span(&res), cstr("0"))); + VecU8_drop(res); + } + { + VecU8 res = VecU8_fmt("%i%i%i%i", -1LL, 0LL, 44LL, -231LL); + check(strings_in_spans_equal(VecU8_to_span(&res), cstr("-1044-231"))); + VecU8_drop(res); + } + { + VecU8 res = VecU8_fmt("%i", 44LL); + check(strings_in_spans_equal(VecU8_to_span(&res), cstr("44"))); + VecU8_drop(res); + } + { + VecU8 res = VecU8_fmt("%u", 44ULL); + check(strings_in_spans_equal(VecU8_to_span(&res), cstr("44"))); + VecU8_drop(res); + } + { + VecU8 res = VecU8_fmt("%u %i", 18446744073709551615ULL, -1LL); + check(strings_in_spans_equal(VecU8_to_span(&res), cstr("18446744073709551615 -1"))); + VecU8_drop(res); + } + { + VecU8 res = VecU8_fmt("%i %i", 9223372036854775807LL, -9223372036854775807LL-1); + check(strings_in_spans_equal(VecU8_to_span(&res), cstr("9223372036854775807 -9223372036854775808"))); + VecU8_drop(res); + } + { + VecU8 vec2 = vcstr("vec2"); + VecU8 res = VecU8_fmt("%i %v %i", -1230LL, vec2, 1340LL); + check(strings_in_spans_equal(VecU8_to_span(&res), cstr("-1230 vec2 1340"))); + VecU8_drop(res); + } + return 0; +} \ No newline at end of file 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 561e19e..0da914d 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 @@ -177,6 +177,7 @@ void codegen_append_rb_tree_set_erase_kind_method( 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 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 py = self->tree.buf[y].parent;\n" // May be null SPACE "self->tree.buf[x].parent = self->tree.buf[y].parent;\n" SPACE "if (py == 0)\n" @@ -189,11 +190,15 @@ void codegen_append_rb_tree_set_erase_kind_method( SPACE "if (z != y)\n" SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\n" SPACE "U64 L = self->el.len;\n" /* self->tree.len - 1 */ - SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" + SPACE "if (L != z){\n" + SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" + SPACE SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" + SPACE SPACE "if (L == x)\n" + SPACE SPACE SPACE "x = z;\n" + SPACE "}\n" SPACE "self->tree.len--;\n" - SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" SPACE "self->el.len--;\n" - SPACE "if (y_org_clr)\n" + SPACE "if (y_org_clr == RBTree_black)\n" SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" "%v" /* ret_found_case */ "}\n\n", @@ -322,6 +327,52 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op )); } + VecU8_append_vec(&res, VecU8_fmt( + "NODISCARD %s %s_clone(const %s* self){\n" + SPACE "return (%s){.tree = VecRBTreeNode_clone(&self->tree), .root = self->root,\n" + SPACE SPACE "Vec%s_clone(&self->el)};\n" + "}\n\n", set, set, set, set, op.T)); + + 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 "while (true) {\n" + SPACE SPACE "U64 p = self->tree.buf[x].parent;\n" + SPACE SPACE "if (p == 0)\n" + SPACE SPACE SPACE "return 0;\n" + SPACE SPACE "if (self->tree.buf[p].left == x)\n" + SPACE SPACE SPACE "return p;\n" + SPACE SPACE "x = p;\n" + SPACE "}\n" + "}\n\n", set, set)); + + 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" + SPACE "if (self->tree.buf[x].left != 0)\n" + SPACE SPACE "return RBTree_maximum_in_subtree(self->tree.buf, self->tree.buf[x].left);\n" + SPACE "while (true) {\n" + SPACE SPACE "U64 p = self->tree.buf[x].parent;\n" + SPACE SPACE "if (p == 0)\n" + SPACE SPACE SPACE "return 0;\n" + SPACE SPACE "if (self->tree.buf[p].right == x)\n" + SPACE SPACE SPACE "return p;\n" + SPACE SPACE "x = p;\n" + SPACE "}\n" + "}\n\n", set, set)); + + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_min(const %s* self) {\n" + SPACE "return self->root != 0 ? RBTree_minimum_in_subtree(self->tree.buf, self->root) : 0;\n" + "}\n\n", set, set)); + + VecU8_append_vec(&res, VecU8_fmt( + "U64 %s_find_max(const %s* self) {\n" + 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() // todo: All the other methods are secondary in importance diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h index d39aa16..a7d46d6 100644 --- a/src/l1_5/core/rb_tree_node.h +++ b/src/l1_5/core/rb_tree_node.h @@ -118,7 +118,7 @@ void RBTree_steal_neighbours(RBTreeNode* tree, U64* root, U64 fr, U64 to){ tree[to] = tree[fr]; } -/* helper function (used in _delete, _find_min methods). It is assumed that s is not null. +/* 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){ @@ -128,6 +128,16 @@ U64 RBTree_minimum_in_subtree(RBTreeNode* tree, U64 s){ return 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){ + assert(s != 0); + while (tree[s].right != 0) + s = tree[s].right; + return s; +} + void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ assert(tree[*root].parent == 0); while (me != *root && tree[me].color == RBTree_black) { diff --git a/src/l1_5/core/stringop.h b/src/l1_5/core/stringop.h index e59cd43..b4719b9 100644 --- a/src/l1_5/core/stringop.h +++ b/src/l1_5/core/stringop.h @@ -27,16 +27,6 @@ bool string_contains_string_ignorecase(SpanU8 str1, SpanU8 str2) { return false; } -bool strings_in_spans_equal(SpanU8 a, SpanU8 b) { - if (a.len != b.len) - return false; - for (size_t i = 0; i < a.len; i++) { - if (*SpanU8_at(a, i) != *SpanU8_at(b, i)) - return false; - } - return true; -} - bool is_string_in_string_vec(SpanU8 a, const VecVecU8* B) { for (size_t i = 0; i < B->len; i++) { if (strings_in_spans_equal(a, VecU8_to_span(VecVecU8_at(B, i)))) diff --git a/src/l2/tests/data_structures/t0.c b/src/l2/tests/data_structures/t0.c index d5b8535..1c06a03 100644 --- a/src/l2/tests/data_structures/t0.c +++ b/src/l2/tests/data_structures/t0.c @@ -1,128 +1,150 @@ #include "../../../../gen/l1_5/BuffRBTree_SetS64.h" +#include "../../../l1/core/VecU8_as_str.h" +#include "../../../l1/system/fileio.h" -void assert_structure_h_dfs(const VecRBTreeNode* tree, U64 x, VecU8* f){ +void check_structure_h_dfs(const VecRBTreeNode* tree, U64 x, VecU8* f){ if (x == 0) return; if (*VecU8_at(f, x - 1) != 0) - assert(false); + check(false); *VecU8_mat(f, x - 1) = 1; - assert_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->left, f); - assert_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->right, f); + check_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->left, f); + check_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->right, f); } -U32 assert_structure_h_dfs_2(RBTreeNode* tree, U64 x){ +U32 check_structure_h_dfs_2(RBTreeNode* tree, U64 x){ if (x == 0) { return 0; } - U32 a = assert_structure_h_dfs_2(tree, tree[x].left); - U32 b = assert_structure_h_dfs_2(tree, tree[x].right); - assert(a == b); + U32 a = check_structure_h_dfs_2(tree, tree[x].left); + U32 b = check_structure_h_dfs_2(tree, tree[x].right); + check(a == b); return a + (tree[x].color == RBTree_black ? 1 : 0); } -void assert_structure(const BuffRBTree_SetS64* self){ - assert(self->tree.len == self->el.len + 1); - assert(self->root < self->tree.len); +void check_structure(const BuffRBTree_SetS64* self){ + check(self->tree.len == self->el.len + 1); + check(self->root < self->tree.len); if (self->tree.len > 1) { - assert(self->root != 0); + check(self->root != 0); } VecU8 f = VecU8_new_zeroinit(self->tree.len - 1); - assert_structure_h_dfs(&self->tree, self->root, &f); + check_structure_h_dfs(&self->tree, self->root, &f); for (size_t i = 0; i < self->tree.len - 1; i++) { - assert(*VecU8_at(&f, i)); + check(*VecU8_at(&f, i)); } VecU8_drop(f); /* f invalidated */ for (size_t v = 1; v < self->tree.len; v++) { if (v == self->root) { - assert(self->tree.buf[v].parent == 0); + check(self->tree.buf[v].parent == 0); } else { - assert(self->tree.buf[v].parent != 0); + check(self->tree.buf[v].parent != 0); } - assert(self->tree.buf[v].parent < self->tree.len); - assert(self->tree.buf[v].left < self->tree.len); - assert(self->tree.buf[v].right < self->tree.len); + check(self->tree.buf[v].parent < self->tree.len); + check(self->tree.buf[v].left < self->tree.len); + check(self->tree.buf[v].right < self->tree.len); if (self->tree.buf[v].left != 0) { - assert(self->tree.buf[self->tree.buf[v].left].parent == v); - assert(self->el.buf[self->tree.buf[v].left - 1] < self->el.buf[v - 1]); + check(self->tree.buf[self->tree.buf[v].left].parent == v); + check(self->el.buf[self->tree.buf[v].left - 1] < self->el.buf[v - 1]); } if (self->tree.buf[v].right != 0) { - assert(self->tree.buf[self->tree.buf[v].right].parent == v); - assert(self->el.buf[v - 1] < self->el.buf[self->tree.buf[v].right - 1]); + check(self->tree.buf[self->tree.buf[v].right].parent == v); + check(self->el.buf[v - 1] < self->el.buf[self->tree.buf[v].right - 1]); } } /* Checking coloring */ - assert(self->tree.buf[0].color == RBTree_black); + check(self->tree.buf[0].color == RBTree_black); if (self->root != 0) - assert(self->tree.buf[self->root].color == RBTree_black); + check(self->tree.buf[self->root].color == RBTree_black); for (size_t v = 1; v < self->tree.len; v++) { if (self->tree.buf[v].color == RBTree_red) { - assert(self->tree.buf[self->tree.buf[v].left].color == RBTree_black); - assert(self->tree.buf[self->tree.buf[v].right].color == RBTree_black); + check(self->tree.buf[self->tree.buf[v].left].color == RBTree_black); + check(self->tree.buf[self->tree.buf[v].right].color == RBTree_black); } } - assert_structure_h_dfs_2(self->tree.buf, self->root); + check_structure_h_dfs_2(self->tree.buf, self->root); +} + +void save_tree_to_file(const BuffRBTree_SetS64* set, SpanU8 name){ + check_structure(set); + VecU8 graph = VecU8_new(); + VecU8_append_span(&graph, cstr( + "digraph rbtree {\n" + " fontsize = 20\n" + " rankdir = TB\n" + " bgcolor = \"lightgray\"\n" + " node [fontname = \"Arial\"];\n")); + for (size_t i = 1; i < set->tree.len; i++) { + VecU8_append_vec(&graph, VecU8_fmt(" v%s")); + } + VecU8_append_span(&graph, cstr("}\n")); + + VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.dot%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); } void insert_only(){ { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); - assert_structure(&set); + check_structure(&set); BuffRBTree_SetS64_drop(set); } { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); bool ret = BuffRBTree_SetS64_insert(&set, 42); - assert(ret); - assert_structure(&set); - assert(set.el.len == 1); - assert(set.root == 1); + check(ret); + check_structure(&set); + check(set.el.len == 1); + check(set.root == 1); BuffRBTree_SetS64_drop(set); } { bool ret; BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 42); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); ret = BuffRBTree_SetS64_insert(&set, 69); - assert(ret); - assert_structure(&set); - assert(set.el.len == 2); + check(ret); + check_structure(&set); + check(set.el.len == 2); BuffRBTree_SetS64_drop(set); } { bool ret; BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 70); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); ret = BuffRBTree_SetS64_insert(&set, 50); - assert(ret); - assert_structure(&set); - assert(set.el.len == 2); + check(ret); + check_structure(&set); + check(set.el.len == 2); BuffRBTree_SetS64_drop(set); } { bool ret; BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 1); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); ret = BuffRBTree_SetS64_insert(&set, 2); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); ret = BuffRBTree_SetS64_insert(&set, 3); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); BuffRBTree_SetS64_drop(set); } { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); for (S64 i = 10; i < 100; i++) { bool ret = BuffRBTree_SetS64_insert(&set, i); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); } BuffRBTree_SetS64_drop(set); } @@ -130,8 +152,8 @@ void insert_only(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); for (S64 i = 99; i >= 10; i--) { bool ret = BuffRBTree_SetS64_insert(&set, i); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); } BuffRBTree_SetS64_drop(set); } @@ -139,11 +161,11 @@ void insert_only(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); for (S64 i = 10; i < 100; i++) { bool ret = BuffRBTree_SetS64_insert(&set, i); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); bool ret2 = BuffRBTree_SetS64_insert(&set, 1000 - i); - assert(ret2); - assert_structure(&set); + check(ret2); + check_structure(&set); } BuffRBTree_SetS64_drop(set); } @@ -158,20 +180,71 @@ void insert_and_then_find(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); for (S64 p = 0; p < 100; p++) { bool ret = BuffRBTree_SetS64_insert(&set, 2 * p); - assert(ret); - assert_structure(&set); + check(ret); + check_structure(&set); for (S64 i = 0; i <= p; i++) { U64 ret1 = BuffRBTree_SetS64_find(&set, 2 * i); - assert(ret1); + check(ret1); U64 ret2 = BuffRBTree_SetS64_find(&set, 2 * i + 1); - assert(ret2 == 0); + check(ret2 == 0); } } BuffRBTree_SetS64_drop(set); } +void insert_and_delete(){ + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + check(BuffRBTree_SetS64_insert(&set, 1)) + check_structure(&set); + check(BuffRBTree_SetS64_find(&set, 1)); + check(BuffRBTree_SetS64_erase(&set, 1)); + check_structure(&set); + check(!BuffRBTree_SetS64_find(&set, 1)); + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + check(BuffRBTree_SetS64_insert(&set, 1)) + check_structure(&set); + check(BuffRBTree_SetS64_insert(&set, 2)) + check_structure(&set); + check(BuffRBTree_SetS64_erase(&set, 2)); + check_structure(&set); + check(BuffRBTree_SetS64_find(&set, 1)); + check(!BuffRBTree_SetS64_find(&set, 2)); + check(BuffRBTree_SetS64_erase(&set, 1)); + check_structure(&set); + check(!BuffRBTree_SetS64_find(&set, 1)); + check(!BuffRBTree_SetS64_find(&set, 2)); + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + check(BuffRBTree_SetS64_insert(&set, 1)) + check_structure(&set); + check(BuffRBTree_SetS64_insert(&set, 2)) + check_structure(&set); + check(BuffRBTree_SetS64_erase(&set, 1)); + check_structure(&set); + check(!BuffRBTree_SetS64_find(&set, 1)); + check(BuffRBTree_SetS64_find(&set, 2)); + + check(!BuffRBTree_SetS64_erase(&set, 1)); + check(!BuffRBTree_SetS64_find(&set, 1)); + check(BuffRBTree_SetS64_find(&set, 2)); + check(BuffRBTree_SetS64_erase(&set, 2)); + check_structure(&set); + check(!BuffRBTree_SetS64_find(&set, 1)); + check(!BuffRBTree_SetS64_find(&set, 2)); + BuffRBTree_SetS64_drop(set); + } + +} + int main() { insert_only(); insert_and_then_find(); + insert_and_delete(); return 0; } diff --git a/src/l2/tests/r0/r0.c b/src/l2/tests/r0/r0.c index e47d1cc..dd6c4f7 100644 --- a/src/l2/tests/r0/r0.c +++ b/src/l2/tests/r0/r0.c @@ -9,7 +9,7 @@ #include "../../../l1/system/fsmanip.h" #include "../../../../gen/l_wl_protocols/xdg-shell-client.h" #include - +#include "../../../l1/system/creating_child_proc.h" #include "../../margaret/png_pixel_masses.h" // todo: generate this structure in l2 @@ -1625,27 +1625,16 @@ static const struct wl_callback_listener main_h_wl_surface_frame_listener = { -void calling_system_func(const char* command) { - int ret = system(command); - if (ret == -1) { - abortf("system() failed\n"); - } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { - abortf("Error: command exited with code %d\n", WEXITSTATUS(ret)); - } else if (!WIFEXITED(ret)) { - abortf("Error: command terminated abnormally\n"); - } -} - void compile_shader_dir(SpanU8 name) { mkdir_nofail("shaders/spv"); VecU8 spv_shader_dir_name = VecU8_fmt("shaders/spv/%s%c", name, 0); mkdir_nofail((CSTR)spv_shader_dir_name.buf); VecU8_drop(spv_shader_dir_name); VecU8 vert_cmd = VecU8_fmt("glslc -o shaders/spv/%s/vert.spv shaders/glsl/%s/%s.vert%c", name, name, name, 0); - calling_system_func((CSTR)vert_cmd.buf); + calling_system_func_nofail((CSTR)vert_cmd.buf); VecU8_drop(vert_cmd); VecU8 frag_cmd = VecU8_fmt("glslc -o shaders/spv/%s/frag.spv shaders/glsl/%s/%s.frag%c", name, name, name, 0); - calling_system_func((CSTR)frag_cmd.buf); + calling_system_func_nofail((CSTR)frag_cmd.buf); VecU8_drop(frag_cmd); } From 4e5a7a8920eb0e284be2628a602a5e131c8bbb58 Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Tue, 23 Sep 2025 19:29:58 +0300 Subject: [PATCH 8/9] I WROTE THE GODDAMN RED BLACK TREE SET (tested only for T=S64 though). IT EVEN TOOK ME LESS THAN 2 WEEKS. --- .gitignore | 2 +- src/l1/core/int_primitives.h | 1 + .../codegen/rb_tree_set_map_template_inst.h | 26 +- src/l1_5/core/rb_tree_node.h | 10 +- src/l2/tests/data_structures/t0.c | 337 ++++++++++++++++-- 5 files changed, 328 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index c04f2fa..fa9c71a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,5 @@ vgcore.* *_NORMAL.png *_TEMPLATE.png /out -GRAPH*.dot +GRAPH*.gv GRAPH*.png \ No newline at end of file diff --git a/src/l1/core/int_primitives.h b/src/l1/core/int_primitives.h index d576eca..03f48cf 100644 --- a/src/l1/core/int_primitives.h +++ b/src/l1/core/int_primitives.h @@ -22,6 +22,7 @@ int_minmax_function_Definition(U8) int_minmax_function_Definition(U32) int_minmax_function_Definition(S32) int_minmax_function_Definition(U64) +int_minmax_function_Definition(S64) int_minmax_function_Definition(float) int_minmax_function_Definition(double) 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 0da914d..cd26652 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 @@ -178,29 +178,35 @@ void codegen_append_rb_tree_set_erase_kind_method( 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 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 py = self->tree.buf[y].parent;\n" // May be null - SPACE "self->tree.buf[x].parent = self->tree.buf[y].parent;\n" - SPACE "if (py == 0)\n" + SPACE "U64 x_adopter = self->tree.buf[y].parent;\n" + SPACE "self->tree.buf[x].parent = x_adopter;\n" + SPACE "if (x_adopter == 0)\n" SPACE SPACE "self->root = x;\n" - SPACE "else if (self->tree.buf[py].left == y)\n" - SPACE SPACE "self->tree.buf[py].left = x;\n" + SPACE "else if (self->tree.buf[x_adopter].left == y)\n" + SPACE SPACE "self->tree.buf[x_adopter].left = x;\n" SPACE "else\n" - SPACE SPACE "self->tree.buf[py].right = x;\n" + SPACE SPACE "self->tree.buf[x_adopter].right = x;\n" SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n" - SPACE "if (z != y)\n" + SPACE "if (z != y) {\n" SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\n" - SPACE "U64 L = self->el.len;\n" /* self->tree.len - 1 */ - SPACE "if (L != z){\n" + SPACE SPACE "if (x_adopter == z)\n" + SPACE SPACE SPACE "x_adopter = y;\n" + SPACE "}\n" + SPACE "U64 L = self->el.len;\n" + SPACE "if (L != z) {\n" SPACE SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, L, z);\n" SPACE SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n" SPACE SPACE "if (L == x)\n" SPACE SPACE SPACE "x = z;\n" + SPACE SPACE "else if (L == x_adopter) \n" + SPACE SPACE SPACE "x_adopter = z;\n" SPACE "}\n" + SPACE "self->tree.buf[x].parent = x_adopter;\n" SPACE "self->tree.len--;\n" SPACE "self->el.len--;\n" SPACE "if (y_org_clr == RBTree_black)\n" SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n" - "%v" /* ret_found_case */ + "%v" /* ret_found_case */ "}\n\n", RT, set, method_name, set, codegen_rb_tree_set_taking_ref_t_argument(op), not_found_case, diff --git a/src/l1_5/core/rb_tree_node.h b/src/l1_5/core/rb_tree_node.h index a7d46d6..44771f0 100644 --- a/src/l1_5/core/rb_tree_node.h +++ b/src/l1_5/core/rb_tree_node.h @@ -162,7 +162,7 @@ void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ continue; } /* Cases 3,4 */ - if (tree[nephew_benjamin].right) { + if (tree[nephew_benjamin].color == RBTree_black) { /* Case 3 */ tree[nephew_firstborn].color = RBTree_black; tree[sister].color = RBTree_red; @@ -175,7 +175,8 @@ void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ /* Case 4 */ tree[sister].color = tree[mom].color; tree[mom].color = RBTree_black; - tree[nephew_benjamin].color = RBTree_red; + tree[nephew_benjamin].color = RBTree_black; + RBTree_left_rotate(tree, root, mom); me = *root; } else if (me == tree[mom].right) { /* We are on the right */ U64 sister = tree[mom].left; @@ -197,7 +198,7 @@ void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ continue; } /* Cases 3,4 */ - if (tree[nephew_firstborn].left) { + if (tree[nephew_firstborn].color == RBTree_black) { /* Case 3 */ tree[nephew_benjamin].color = RBTree_black; tree[sister].color = RBTree_red; @@ -210,7 +211,8 @@ void RBTree_fix_after_delete(RBTreeNode* tree, U64* root, U64 me){ /* Case 4 */ tree[sister].color = tree[mom].color; tree[mom].color = RBTree_black; - tree[nephew_firstborn].color = RBTree_red; + tree[nephew_firstborn].color = RBTree_black; + RBTree_right_rotate(tree, root, mom); me = *root; } } diff --git a/src/l2/tests/data_structures/t0.c b/src/l2/tests/data_structures/t0.c index 1c06a03..e2629b2 100644 --- a/src/l2/tests/data_structures/t0.c +++ b/src/l2/tests/data_structures/t0.c @@ -1,6 +1,9 @@ #include "../../../../gen/l1_5/BuffRBTree_SetS64.h" +#include "../../../../gen/l1/VecAndSpan_int_primitives.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" void check_structure_h_dfs(const VecRBTreeNode* tree, U64 x, VecU8* f){ if (x == 0) @@ -22,7 +25,31 @@ U32 check_structure_h_dfs_2(RBTreeNode* tree, U64 x){ return a + (tree[x].color == RBTree_black ? 1 : 0); } -void check_structure(const BuffRBTree_SetS64* self){ +S64 min_key_in_subtree(const BuffRBTree_SetS64* self, U64 x){ + assert(x != 0 && x < self->tree.len); + S64 ans = self->el.buf[x - 1]; + if (self->tree.buf[x].left != 0) { + ans = MIN_S64(ans, min_key_in_subtree(self, self->tree.buf[x].left)); + } + if (self->tree.buf[x].right != 0) { + ans = MIN_S64(ans, min_key_in_subtree(self, self->tree.buf[x].right)); + } + return ans; +} + +S64 max_key_in_subtree(const BuffRBTree_SetS64* self, U64 x){ + assert(x != 0 && x < self->tree.len); + S64 ans = self->el.buf[x - 1]; + if (self->tree.buf[x].left != 0) { + ans = MAX_S64(ans, max_key_in_subtree(self, self->tree.buf[x].left)); + } + if (self->tree.buf[x].right != 0) { + ans = MAX_S64(ans, max_key_in_subtree(self, self->tree.buf[x].right)); + } + return ans; +} + +void check_only_structure(const BuffRBTree_SetS64* self){ check(self->tree.len == self->el.len + 1); check(self->root < self->tree.len); if (self->tree.len > 1) { @@ -45,13 +72,15 @@ void check_structure(const BuffRBTree_SetS64* self){ check(self->tree.buf[v].right < self->tree.len); if (self->tree.buf[v].left != 0) { check(self->tree.buf[self->tree.buf[v].left].parent == v); - check(self->el.buf[self->tree.buf[v].left - 1] < self->el.buf[v - 1]); } if (self->tree.buf[v].right != 0) { check(self->tree.buf[self->tree.buf[v].right].parent == v); - check(self->el.buf[v - 1] < self->el.buf[self->tree.buf[v].right - 1]); } } +} + +void check_correctness(const BuffRBTree_SetS64* self){ + check_only_structure(self); /* Checking coloring */ check(self->tree.buf[0].color == RBTree_black); @@ -64,39 +93,118 @@ void check_structure(const BuffRBTree_SetS64* self){ } } check_structure_h_dfs_2(self->tree.buf, self->root); + + /* checking keys, but better */ + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + check(self->el.buf[self->tree.buf[v].left - 1] < self->el.buf[v - 1]); + } + if (self->tree.buf[v].right != 0) { + check(self->el.buf[v - 1] < self->el.buf[self->tree.buf[v].right - 1]); + } + } + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + check(max_key_in_subtree(self, self->tree.buf[v].left) < self->el.buf[v - 1]); + } + if (self->tree.buf[v].right != 0) { + check(self->el.buf[v - 1] < min_key_in_subtree(self, self->tree.buf[v].right)); + } + } } void save_tree_to_file(const BuffRBTree_SetS64* set, SpanU8 name){ - check_structure(set); + check_only_structure(set); + + VecS64 ranked_node_to_rb_node = VecS64_new_reserved(set->el.len); + { + VecS64 bfs_nxt = VecS64_new(); + VecS64 bfs = VecS64_new(); + if (set->root != 0) + VecS64_append(&bfs_nxt, (S64)set->root); + while (bfs_nxt.len > 0) { + VecS64 t = bfs_nxt; + bfs_nxt = bfs; + bfs = t; + for (size_t j = 0; j < bfs.len; j++) { + S64 cur = *VecS64_at(&bfs, j); + assert(cur != 0); + VecS64_append(&ranked_node_to_rb_node, cur); + if (cur < 0) + continue; + if (set->tree.buf[cur].left != 0) + VecS64_append(&bfs_nxt, (S64)set->tree.buf[cur].left); + else if (set->tree.buf[cur].right != 0) + VecS64_append(&bfs_nxt, -cur); + if (set->tree.buf[cur].right != 0) + VecS64_append(&bfs_nxt, (S64)set->tree.buf[cur].right); + else if (set->tree.buf[cur].left != 0) + VecS64_append(&bfs_nxt, -cur); + } + bfs.len = 0; + } + } VecU8 graph = VecU8_new(); VecU8_append_span(&graph, cstr( "digraph rbtree {\n" " fontsize = 20\n" " rankdir = TB\n" " bgcolor = \"lightgray\"\n" - " node [fontname = \"Arial\"];\n")); - for (size_t i = 1; i < set->tree.len; i++) { - VecU8_append_vec(&graph, VecU8_fmt(" v%s")); + " node [fontname = \"Arial\", style=\"rounded,filled\", shape=circle];\n")); + for (U64 j = 0; j < ranked_node_to_rb_node.len; j++) { + S64 cur = ranked_node_to_rb_node.buf[j]; + assert(cur != 0); + if (cur < 0) { + VecU8_append_vec(&graph, VecU8_fmt(" n_%i [style=invis, label=\"\"]\n", -cur)); + continue; + } + U64 i = (U64)cur; + VecU8_append_vec(&graph, VecU8_fmt( + " v%u [label=%i, xlabel=<%u>, color=%s, fontcolor=%s]\n", + i, set->el.buf[i - 1], + set->tree.buf[i].color == RBTree_black ? cstr("black") : cstr("red"), i, + set->tree.buf[i].color == RBTree_black ? cstr("black") : cstr("red"), + set->tree.buf[i].color == RBTree_black ? cstr("white") : cstr("black"))); + } + VecU8_append_span(&graph, cstr("\n")); + for (U64 j = 0; j < ranked_node_to_rb_node.len; j++) { + S64 cur = ranked_node_to_rb_node.buf[j]; + if (cur < 0) + continue; + U64 i = (U64)cur; + if (set->tree.buf[i].left != 0) { + VecU8_append_vec(&graph, VecU8_fmt(" v%u -> v%u [weight=2]\n", i, set->tree.buf[i].left)); + } else if (set->tree.buf[i].right != 0) { + VecU8_append_vec(&graph, VecU8_fmt(" v%u -> n_%u [style=invis, weight=3]\n", i, i)); + } + if (set->tree.buf[i].right != 0) { + VecU8_append_vec(&graph, VecU8_fmt(" v%u -> v%u [weight=2]\n", i, set->tree.buf[i].right)); + } else if (set->tree.buf[i].left != 0) { + VecU8_append_vec(&graph, VecU8_fmt(" v%u -> n_%u [style=invis, weight=3]\n", i, i)); + } } VecU8_append_span(&graph, cstr("}\n")); - - VecU8 dot_filename_nt = VecU8_fmt("GRAPHS/GRAPH_%s.dot%c", name, 0); + 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(){ { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); - check_structure(&set); + check_correctness(&set); BuffRBTree_SetS64_drop(set); } { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); bool ret = BuffRBTree_SetS64_insert(&set, 42); check(ret); - check_structure(&set); + check_correctness(&set); check(set.el.len == 1); check(set.root == 1); BuffRBTree_SetS64_drop(set); @@ -106,10 +214,10 @@ void insert_only(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 42); check(ret); - check_structure(&set); + check_correctness(&set); ret = BuffRBTree_SetS64_insert(&set, 69); check(ret); - check_structure(&set); + check_correctness(&set); check(set.el.len == 2); BuffRBTree_SetS64_drop(set); } @@ -118,10 +226,10 @@ void insert_only(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 70); check(ret); - check_structure(&set); + check_correctness(&set); ret = BuffRBTree_SetS64_insert(&set, 50); check(ret); - check_structure(&set); + check_correctness(&set); check(set.el.len == 2); BuffRBTree_SetS64_drop(set); } @@ -130,13 +238,13 @@ void insert_only(){ BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); ret = BuffRBTree_SetS64_insert(&set, 1); check(ret); - check_structure(&set); + check_correctness(&set); ret = BuffRBTree_SetS64_insert(&set, 2); check(ret); - check_structure(&set); + check_correctness(&set); ret = BuffRBTree_SetS64_insert(&set, 3); check(ret); - check_structure(&set); + check_correctness(&set); BuffRBTree_SetS64_drop(set); } { @@ -144,7 +252,7 @@ void insert_only(){ for (S64 i = 10; i < 100; i++) { bool ret = BuffRBTree_SetS64_insert(&set, i); check(ret); - check_structure(&set); + check_correctness(&set); } BuffRBTree_SetS64_drop(set); } @@ -153,7 +261,7 @@ void insert_only(){ for (S64 i = 99; i >= 10; i--) { bool ret = BuffRBTree_SetS64_insert(&set, i); check(ret); - check_structure(&set); + check_correctness(&set); } BuffRBTree_SetS64_drop(set); } @@ -162,10 +270,10 @@ void insert_only(){ for (S64 i = 10; i < 100; i++) { bool ret = BuffRBTree_SetS64_insert(&set, i); check(ret); - check_structure(&set); + check_correctness(&set); bool ret2 = BuffRBTree_SetS64_insert(&set, 1000 - i); check(ret2); - check_structure(&set); + check_correctness(&set); } BuffRBTree_SetS64_drop(set); } @@ -181,7 +289,7 @@ void insert_and_then_find(){ for (S64 p = 0; p < 100; p++) { bool ret = BuffRBTree_SetS64_insert(&set, 2 * p); check(ret); - check_structure(&set); + check_correctness(&set); for (S64 i = 0; i <= p; i++) { U64 ret1 = BuffRBTree_SetS64_find(&set, 2 * i); check(ret1); @@ -196,25 +304,25 @@ void insert_and_delete(){ { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); check(BuffRBTree_SetS64_insert(&set, 1)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_find(&set, 1)); check(BuffRBTree_SetS64_erase(&set, 1)); - check_structure(&set); + check_correctness(&set); check(!BuffRBTree_SetS64_find(&set, 1)); BuffRBTree_SetS64_drop(set); } { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); check(BuffRBTree_SetS64_insert(&set, 1)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_insert(&set, 2)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_erase(&set, 2)); - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_find(&set, 1)); check(!BuffRBTree_SetS64_find(&set, 2)); check(BuffRBTree_SetS64_erase(&set, 1)); - check_structure(&set); + check_correctness(&set); check(!BuffRBTree_SetS64_find(&set, 1)); check(!BuffRBTree_SetS64_find(&set, 2)); BuffRBTree_SetS64_drop(set); @@ -222,11 +330,11 @@ void insert_and_delete(){ { BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); check(BuffRBTree_SetS64_insert(&set, 1)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_insert(&set, 2)) - check_structure(&set); + check_correctness(&set); check(BuffRBTree_SetS64_erase(&set, 1)); - check_structure(&set); + check_correctness(&set); check(!BuffRBTree_SetS64_find(&set, 1)); check(BuffRBTree_SetS64_find(&set, 2)); @@ -234,17 +342,180 @@ void insert_and_delete(){ check(!BuffRBTree_SetS64_find(&set, 1)); check(BuffRBTree_SetS64_find(&set, 2)); check(BuffRBTree_SetS64_erase(&set, 2)); - check_structure(&set); + check_correctness(&set); check(!BuffRBTree_SetS64_find(&set, 1)); check(!BuffRBTree_SetS64_find(&set, 2)); BuffRBTree_SetS64_drop(set); } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + for (S64 i = -120; i < 1000; i += 10) { + check(BuffRBTree_SetS64_insert(&set, i)) + check_correctness(&set); + } + // save_tree_to_file(&set, cstr("tree")); + BuffRBTree_SetS64_drop(set); + } + { + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + check(BuffRBTree_SetS64_insert(&set, 1)) + check_correctness(&set); + check(BuffRBTree_SetS64_insert(&set, 2)) + check_correctness(&set); + check(BuffRBTree_SetS64_insert(&set, 3)) + check_correctness(&set); + // save_tree_to_file(&set, cstr("trio")); + check(BuffRBTree_SetS64_erase(&set, 2)); + check_correctness(&set); + // save_tree_to_file(&set, cstr("duo")); + BuffRBTree_SetS64_drop(set); + } +} + +void MutSpanS64_shuffle(MutSpanS64 span){ + if (span.len <= 1) + return; + for (size_t i = span.len-1; i > 0; i--) { + size_t j = rand() % (i + 1); + S64 temp = span.data[i]; + span.data[i] = span.data[j]; + span.data[j] = temp; + } +} + +VecS64 gen_cool_sequence(S64 i){ + VecS64 res = VecS64_new_reserved(i); + for (S64 j = 0; j < i; j++) { + VecS64_append(&res, (j + 1) * 10); + } + MutSpanS64_shuffle(VecS64_to_mspan(&res)); + return res; +} + +void chaos(){ + for (int i = 1; i < 100; i++) { + srand(i); + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + VecS64 seq_to_insert = gen_cool_sequence(i); + for (int j = 0; j < i; j++) { + S64 to_insert = seq_to_insert.buf[j]; + BuffRBTree_SetS64_insert(&set, to_insert); + check_correctness(&set); + } + assert(set.el.len == (size_t)i); + // save_tree_to_file(&set, cstr("last_good")); + S64 to_delete = (rand() % i + 1) * 10; + printf("Started deleting from i=%d\n", i); + check(BuffRBTree_SetS64_erase(&set, to_delete)); + printf("Deleted from i=%d\n", i); + check_only_structure(&set); + // save_tree_to_file(&set, cstr("fucked_tree")); + check_correctness(&set); + VecS64_drop(seq_to_insert); + BuffRBTree_SetS64_drop(set); + } +} + +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}; + VecS64 el = VecS64_new_reserved(3); + VecS64_append(&el, 300); + VecS64_append(&el, 100); + VecS64_append(&el, 200); + set = (BuffRBTree_SetS64){.tree = tree, .root = 3, .el = el}; + } + check_correctness(&set); + check(BuffRBTree_SetS64_erase(&set, 300)); + check_correctness(&set); + BuffRBTree_SetS64_drop(set); +} + +void absolute_chaos(){ + for (int i = 1; i < 100; i++) { + srand(i); + BuffRBTree_SetS64 set = BuffRBTree_SetS64_new(); + VecS64 seq_to_insert = gen_cool_sequence(i); + for (int j = 0; j < i; j++) { + S64 to_insert = seq_to_insert.buf[j]; + check(BuffRBTree_SetS64_insert(&set, to_insert)); + check_correctness(&set); + } + printf("Filled chaos with i = %d\n", i); + // save_tree_to_file(&set, cstr("i_3")); + assert(set.el.len == (size_t)i); + VecS64 seq_to_erase = gen_cool_sequence(i); + for (int j = 0; j < i; j++) { + S64 to_erase = seq_to_erase.buf[j]; + check(BuffRBTree_SetS64_erase(&set, to_erase)); + check_correctness(&set); + } + printf("Emptied chaos with i = %d\n", i); + assert(set.el.len == 0); + VecS64_drop(seq_to_insert); + VecS64_drop(seq_to_erase); + BuffRBTree_SetS64_drop(set); + } +} + +void stress(){ + printf("Prepare for some real stress\n"); + for (int s = 2; s < 1000; s++) { + srand(s); + BuffRBTree_SetS64 set = BuffRBTree_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(BuffRBTree_SetS64_insert(&set, v)); + } 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(BuffRBTree_SetS64_erase(&set, v)); + } + /* We did something */ + check(real_set.len == set.el.len); + for (size_t j = 0; j < real_set.len; j++) { + check(BuffRBTree_SetS64_find(&set, real_set.buf[j]) != 0); + } + for (size_t j = 0; j < complementary_set.len; j++) { + check(BuffRBTree_SetS64_find(&set, complementary_set.buf[j]) == 0); + } + } + VecS64_drop(real_set); + BuffRBTree_SetS64_drop(set); + printf("Seed s=%d passed test\n", s); + } } int main() { insert_only(); insert_and_then_find(); insert_and_delete(); + chaos(); + triple_black(); + absolute_chaos(); + stress(); return 0; } From bec39703f6eb9178f0ca988a6d26f10b9108f2fc Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Tue, 23 Sep 2025 20:14:26 +0300 Subject: [PATCH 9/9] AAAAAAA --- src/l2/tests/data_structures/t0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/l2/tests/data_structures/t0.c b/src/l2/tests/data_structures/t0.c index e2629b2..1d2d1aa 100644 --- a/src/l2/tests/data_structures/t0.c +++ b/src/l2/tests/data_structures/t0.c @@ -504,6 +504,7 @@ void stress(){ } } VecS64_drop(real_set); + VecS64_drop(complementary_set); BuffRBTree_SetS64_drop(set); printf("Seed s=%d passed test\n", s); }