Compare commits

...

10 Commits

34 changed files with 1982 additions and 396 deletions

4
.gitignore vendored
View File

@ -11,4 +11,6 @@ vgcore.*
*.xcf
*_NORMAL.png
*_TEMPLATE.png
/out
/out
GRAPH*.gv
GRAPH*.png

View File

@ -31,30 +31,31 @@ add_compile_options(-fno-trapping-math)
#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(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)
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_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)
#
## 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)

View File

@ -53,23 +53,60 @@ 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/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
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

View File

@ -0,0 +1,89 @@
#import "../head.typ": *
#set page(footer: context {align(center, counter(page).display("1"))})
#set text(size: 1.2em)
#set par(first-line-indent: 16pt)
#align(center, heading(depth: 1)[Архитектура и стиль кода в prototype1 (Дарье)])
Для компиляции используется только сборочная система make.
Генерировать makefile с помощью shell-скрипта разрешено, просто в данный момент это не
практикуется.
Другие сборочные системы, вроде Cmake, Meson, скрипты на питоне, и.т.д.
есть мерзость. _Ты можешь обнаружить в корне репозитория `CmakeLists.txt` - он не
обязателен для компиляции, он лишь для тех, чья среда разработки требует cmake._
Ни одна строка кода не должна быть написана на C++. Дарья не требует
для функционирования компилятор C++. То, что почти все зависимости Дарьи
требуют компилятор C++ - очень досадное обстоятельство, но не причина отказываться
от них, ибо аналогов у них нет. Мы молчаливо осуждаем тех, кто написал компилятор
glsl на C++. Допускается использовать python, rust, haskell
для написания скриптов, вспомогательных для разработки Дарьи, но не обязательных
для запуска Дарьи. Допускается написание самых высших уровней Дарьи на
haskell и rust. Самые высшие уровни Дарьи это те, что лишь используют мощь
моего игрового движка для исключительно творческих целей. Сам же движок Дарьи
пишется на чистом C99. Я не называю ни одну зависимость Дарьи святой.
Тем не менее аналогов им я не знаю. Как бы тебе не был противен C, прийдётся
уж им пользоваться, на нём основан linux, без линукса Дарья не запускается. Нижние
уровни Дарьи декларируют фреймворк, сглаживающий большинство недостатков C.
Во всех файлах на C используется `snake_case` для именования функций,
`UpperCamelCase` для именования типов. Имя пространства имён не имеет
такого правила наименования, поскольку если оно встречается в имени
функции, используется правило наименования для функции, если внутри имени типа,
используется правило для типов. Имя пространства имён дописывается перед
именем символа, внутреннего для пространства имён, без всякого разделителя.
Пространств имён у меня не много. В Дарье есть система инстанциации шаблонов
для C. К имени шаблона справа дописываются аргументы инстанциации (но есть исключения).
`VecU64`, `OptionVkFormat`, `ResultTextureDataR8OrSpanU8` значат буквально то,
что они значат.
Я не морочусь с тонной объектных файлов при компиляции, ибо пишу код
исключительно в `.h` файлах, где декларация объединена с определением.
Если я компилирую исполняемый бинарник, код с функцией `main` имеет расширение
`.c`, он вбирает все те заголовочные файлы, что ему нужны. В заголовочных файлах
используются "хедер-гуарды". При компиляции весь весь код со всех файлов,
нужных исполняемой программе какбы склеивается воедино. Поэтому нельзя одно и то же
имя дважды в двух разных заголовках, используемых одной программой, даже если чисто
логически они независимы.
В корне репозитория находится главный `Makefile`, плюс необязательны
для сборки `shell.nix` для
людей нетрадиционной сексуальной ориентации, которые захотят воспользоваться
Дарьей. Весь остальной код лежит в папке `src` в обнимку с тестами. В процессе
компиляции дарья создаст папку `out`, куда будут помещены скомпилированные `cc`
исполняемые файлы и папку `gen`, куда будет помещён код на C,
сгенерированный самой Дарьей для последующей компиляции. Поскольку в Дарье
присутствует кодген, весь исходный код генерируемый код тоже) разграничен на уровни.
Уровни обозначают порядок компиляции. На низших уровнях сгенерированно кода цель
компиляции только одна - сам этот код. На низших уровнях исходного кода
есть цель для генерации кода генерируемого соответсвующего себе уровня,
а так же тесты исходного кода этого уровня и любого кода с предыдущих уровней.
Да, уровни располагаются в одном порядке. В их именазаложена числовая нумерация.
Есть, правда, исключения из этого правила, для уровней, у которых
нет исходного (только генерируемый код) и генерируемый код генерируется не Дарьей,
а зависимостью Дарьи.
Вот какие уровни есть в данный момент:
`l_wl_protocls` (написан не мной, не нумеруется), `l1`, `l1_4`, `l1_5`, `l2`
Весь код хранится в папках `src/<имя уровня>` и `gen/<имя уровня>`.
Код с более высокого уровня может использовать код с более низкого уровня.
Сгенерированный код с какого-то уровня может использовать исходный код
с этого же уровня, но исходный код не может использовать генерированный
код своего уровня. Тем не менее код,
генерирующий другой код, может быть осведомлён о существовании и содердании
более высоких слоёв, но только если он находится в специальной папке
`gen/l1vi`
Разберём что делает каждый уровень, что есть в данный момент в Дарье:
- `l_wl_protocols` -- из-за странного способа дистрибуции wayland-lib мы должны сами
генерировать код для неё.
- `l1` -- самый первый уровень. Тут определены все утилиты, которые не
потребовали кодгена. Так же исходный код `l` определяет типы и функции,
полезные при любой генерации кода. В утилитах `l1` так же есть
обёртки над базовыми обёртками над системными вызовами линукса.
Первый уроведь определяет самые главные шаблоны: `Vec<T>`, `Option<T>`,
`Span<T>`, `MutSpan<T>`, `Result<O>Or<E>`,

View File

@ -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.
'';
'';
}

View File

@ -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

View File

@ -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)

View File

@ -7,14 +7,15 @@ 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});
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});
// 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, (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

View File

@ -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

View File

@ -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<texdatat, SpanU8> 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);

View File

@ -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
});
}
}

View File

@ -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);
}

View File

@ -3,14 +3,17 @@
#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(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,
@ -21,10 +24,10 @@ 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_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);
@ -32,10 +35,11 @@ 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(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 +50,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);

View File

@ -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);

View File

@ -37,7 +37,7 @@ void finish_header(GeneratedHeader header) {
VecU8_drop(header.result);
}
#define SPACE4 " "
#define SPACE " "
#define SPACE8 " "
#define SPACE12 " "
#define SPACE16 " "
@ -48,4 +48,41 @@ 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);
}
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

View File

@ -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));
}
}
@ -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,107 @@ 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) {
option_template_instantiation_op_fix(&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" SPACE "return ref;\n}\n\n", OptionT, op.T, op.T));
VecU8_append_vec(&res, VecU8_fmt(
"%s %s_expect(%s self) {\n"
SPACE "return self;\n"
"}\n\n", op.T, OptionT, OptionT));
} else {
VecU8_append_vec(&res, VecU8_fmt(
"typedef struct {\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"
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"
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"
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"
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));
}
}
}
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

View File

@ -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("-9223372036854775808"));
} 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 == 'i') {
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 == 'i') {
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 {
@ -106,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

View File

@ -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)

View File

@ -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

View File

@ -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

41
src/l1_4/tests/t2.c Normal file
View File

@ -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;
}

View File

@ -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;
}

View File

@ -0,0 +1,17 @@
#ifndef prototype1_src_l1_5_anne_l1_5_templ_very_base_h
#define prototype1_src_l1_5_anne_l1_5_templ_very_base_h
#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\""
);
// 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

View File

@ -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(", "));

View File

@ -0,0 +1,27 @@
#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;
}
#endif

View File

@ -0,0 +1,419 @@
#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"
/* 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("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 */
NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op op){
if (op.t_integer)
return VecU8_fmt("key < self->el.buf[cur - 1]");
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("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("key < self->el.buf[cur - 1]");
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){
if (op.t_integer)
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_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_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 RT,
VecU8 Fc, VecU8 Tc_cur_available, VecU8 Tc_returning
){
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 "assert(x != y && x != z);\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[x_adopter].left == y)\n"
SPACE SPACE "self->tree.buf[x_adopter].left = x;\n"
SPACE "else\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 SPACE "RBTree_steal_neighbours(self->tree.buf, &self->root, z, y);\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 */
"}\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
* 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 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"
SPACE "VecRBTreeNode tree;\n"
SPACE "U64 root;\n"
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"
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 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));
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)),
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"))));
}
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 */
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)
));
}
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
VecU8_drop(g_set);
return res;
}
void generate_rb_tree_Set_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, option_template_instantiation_op op) {
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

View File

@ -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)

View File

@ -0,0 +1,222 @@
#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"
typedef enum {
RBTree_black = 0,
RBTree_red = 1,
} RBTreeColor;
typedef struct {
size_t left;
size_t right;
size_t parent;
/* 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)
return;
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;
}
/* 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 _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){
assert(s != 0);
while (tree[s].left != 0)
s = tree[s].left;
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) {
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].color == RBTree_black) {
/* 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_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;
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].color == RBTree_black) {
/* 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_black;
RBTree_right_rotate(tree, root, mom);
me = *root;
}
}
tree[me].color = RBTree_black;
}
#endif

View File

@ -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))))

View File

@ -22,7 +22,7 @@ typedef struct {
typedef struct {
void* r;
const LizaSound_Table* t;
} MutRefLizaSound;
} RefMutLizaSound;
/* Existence of Box<Trait> type implies that _drop method is virtual according to this trait */
typedef struct {

View File

@ -16,13 +16,19 @@
#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 <vulkan/vulkan_wayland.h>
// #include <vulkan/vulkan.h>

View File

@ -0,0 +1,522 @@
#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)
return;
if (*VecU8_at(f, x - 1) != 0)
check(false);
*VecU8_mat(f, x - 1) = 1;
check_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->left, f);
check_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->right, f);
}
U32 check_structure_h_dfs_2(RBTreeNode* tree, U64 x){
if (x == 0) {
return 0;
}
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);
}
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) {
check(self->root != 0);
}
VecU8 f = VecU8_new_zeroinit(self->tree.len - 1);
check_structure_h_dfs(&self->tree, self->root, &f);
for (size_t i = 0; i < self->tree.len - 1; 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) {
check(self->tree.buf[v].parent == 0);
} else {
check(self->tree.buf[v].parent != 0);
}
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) {
check(self->tree.buf[self->tree.buf[v].left].parent == v);
}
if (self->tree.buf[v].right != 0) {
check(self->tree.buf[self->tree.buf[v].right].parent == v);
}
}
}
void check_correctness(const BuffRBTree_SetS64* self){
check_only_structure(self);
/* Checking coloring */
check(self->tree.buf[0].color == RBTree_black);
if (self->root != 0)
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) {
check(self->tree.buf[self->tree.buf[v].left].color == RBTree_black);
check(self->tree.buf[self->tree.buf[v].right].color == RBTree_black);
}
}
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_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\", 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=<<FONT color='%s'>%u</FONT>>, 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"));
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_correctness(&set);
BuffRBTree_SetS64_drop(set);
}
{
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
bool ret = BuffRBTree_SetS64_insert(&set, 42);
check(ret);
check_correctness(&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);
check(ret);
check_correctness(&set);
ret = BuffRBTree_SetS64_insert(&set, 69);
check(ret);
check_correctness(&set);
check(set.el.len == 2);
BuffRBTree_SetS64_drop(set);
}
{
bool ret;
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
ret = BuffRBTree_SetS64_insert(&set, 70);
check(ret);
check_correctness(&set);
ret = BuffRBTree_SetS64_insert(&set, 50);
check(ret);
check_correctness(&set);
check(set.el.len == 2);
BuffRBTree_SetS64_drop(set);
}
{
bool ret;
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
ret = BuffRBTree_SetS64_insert(&set, 1);
check(ret);
check_correctness(&set);
ret = BuffRBTree_SetS64_insert(&set, 2);
check(ret);
check_correctness(&set);
ret = BuffRBTree_SetS64_insert(&set, 3);
check(ret);
check_correctness(&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);
check(ret);
check_correctness(&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);
check(ret);
check_correctness(&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);
check(ret);
check_correctness(&set);
bool ret2 = BuffRBTree_SetS64_insert(&set, 1000 - i);
check(ret2);
check_correctness(&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);
check(ret);
check_correctness(&set);
for (S64 i = 0; i <= p; i++) {
U64 ret1 = BuffRBTree_SetS64_find(&set, 2 * i);
check(ret1);
U64 ret2 = BuffRBTree_SetS64_find(&set, 2 * i + 1);
check(ret2 == 0);
}
}
BuffRBTree_SetS64_drop(set);
}
void insert_and_delete(){
{
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
check(BuffRBTree_SetS64_insert(&set, 1))
check_correctness(&set);
check(BuffRBTree_SetS64_find(&set, 1));
check(BuffRBTree_SetS64_erase(&set, 1));
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_correctness(&set);
check(BuffRBTree_SetS64_insert(&set, 2))
check_correctness(&set);
check(BuffRBTree_SetS64_erase(&set, 2));
check_correctness(&set);
check(BuffRBTree_SetS64_find(&set, 1));
check(!BuffRBTree_SetS64_find(&set, 2));
check(BuffRBTree_SetS64_erase(&set, 1));
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();
check(BuffRBTree_SetS64_insert(&set, 1))
check_correctness(&set);
check(BuffRBTree_SetS64_insert(&set, 2))
check_correctness(&set);
check(BuffRBTree_SetS64_erase(&set, 1));
check_correctness(&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_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);
VecS64_drop(complementary_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;
}

View File

@ -9,7 +9,7 @@
#include "../../../l1/system/fsmanip.h"
#include "../../../../gen/l_wl_protocols/xdg-shell-client.h"
#include <xkbcommon/xkbcommon.h>
#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);
}

View File

@ -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