diff --git a/CMakeLists.txt b/CMakeLists.txt index b18c824..2c6fe60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,13 @@ cmake_minimum_required(VERSION 3.30) -project(prototype1 C) +project(prototype1 C CXX) #include_directories(${CMAKE_SOURCE_DIR}) set(CMAKE_C_FLAGS "-Wno-unused-parameter \ -Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type \ --std=c99 -g -ggdb -O0") +set(CMAKE_CXX_FLAGS "-Wno-unused-parameter \ + -Wall -Wextra -Werror=return-type \ + --std=c++20 -g -ggdb -O0") execute_process( COMMAND pkg-config --cflags libpipewire-0.3 @@ -66,3 +69,11 @@ target_link_libraries(l2_tex_gen -lm -lpng) add_executable(l3_r4 src/l3/r4/r4.c gen/l_wl_protocols/xdg-shell-private.c) target_link_libraries(l3_r4 -lvulkan -lwayland-client -lm -lxkbcommon -lpng -lfreetype) + +add_executable(codegen_l1_allie_cpp src/l1/allie_cpp/anne/codegen.cpp) + +add_executable(l3_r4c + src/l3/r4/r4c.cpp + src/l2/allie_cpp/glue.c + gen/l_wl_protocols/xdg-shell-private.c) +target_link_libraries(l3_r4c -lvulkan -lwayland-client -lm -lxkbcommon -lpng -lfreetype) diff --git a/Makefile b/Makefile index cbc3d05..72e7bfe 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ HEADERS_gen_l2 := gen/l2/dorothy.txt HEADERS_src_l3 := $(HEADERS_gen_l2) $(call find_headers,l3) cflags := -Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type -Wno-unused-parameter \ - --std=c99 -g -ggdb -O0 \ + --std=c99 -g -ggdb -O0 -D_FORTIFY_SOURCE=0 \ -fno-trapping-math -D_POSIX_C_SOURCE=200112L -D_GNU_SOURCE cc := gcc @@ -132,22 +132,6 @@ out/l2/r3: src/l2/tests/r3/r3.c $(HEADERS_src_l2) $(l_wl_protocols) run_r3: out/l2/r3 ./out/l2/r3 -# Whoever needs this will also need out/l_wl_protocols -out/l2/allie.o: src/l2/allie/allie.c $(HEADERS_src_l2) $(xdg_shell_client_h) gen/l_adele/dorothy.txt $(HEADERS_gen_l2) - mkdir -p out/l2 - $(cc) $(cflags) -o $@ -c $< -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype - -full_allie_obj := out/l2/allie.o $(xdg_shell_private_o) - -out/l3/r4: src/l3/r4/R4.hs src/l2/allie/Allie.hs $(full_allie_obj) - mkdir -p out/l3 - ghc -isrc/l2/allie -hidir out/l3/ -odir out/l3 -o $@ $< $(full_allie_obj) \ - -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype - -.PHONY: run_r4 -run_r4: out/l3/r4 - ./out/l3/r4 - out/l3/r4b: src/l3/r4/r4.c $(HEADERS_src_l3) $(l_wl_protocols) $(ASSETS_gen_l_adele) mkdir -p out/l3 $(cc) $(cflags) -o $@ $< $(xdg_shell_private_c) -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype @@ -158,4 +142,78 @@ run_r4b: out/l3/r4b .PHONY: clean clean: - rm -rf gen out \ No newline at end of file + rm -rf gen out + +# ======================= Daria ВСЁ =========================== +# ============================================================= +# ------------------------------------------------------------- + +# ------------------------------------------------------------- +# ============================================================= +# ====================== ПЛЮСЫ ================================ + +find_hpp_cpp = $(shell find src/$(1) -type f -name '*.hpp' ) + +HEADERS_src_l1_allie_cpp := $(call find_hpp_cpp,l1/allie_cpp) + +cxx_cpp := g++ +cxxflags_cpp := -Wall -Wextra -Werror=return-type -Wno-unused-parameter \ + --std=c++20 -g -ggdb -O0 -D_FORTIFY_SOURCE=0 \ + -fno-trapping-math -D_POSIX_C_SOURCE=200112L -D_GNU_SOURCE + +out/l1/allie_cpp/codegen: src/l1/allie_cpp/anne/codegen.cpp $(HEADERS_src_l1_allie_cpp) + mkdir -p out/l1/allie_cpp + $(cxx_cpp) $(cxxflags_cpp) -o $@ $< + +gen/l1/allie_cpp/dorothy.txt: out/l1/allie_cpp/codegen + mkdir -p gen + cd gen && ../out/l1/allie_cpp/codegen + +out/l2/allie_cpp/glue.o: src/l2/allie_cpp/glue.c $(HEADERS_src_l2) $(xdg_shell_client_h) gen/l_adele/dorothy.txt $(HEADERS_gen_l2) + mkdir -p out/l2/allie_cpp/ + $(cc) $(cflags) -o $@ -c $< -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype + +full_allie_cpp_obj := out/l2/allie_cpp/glue.o $(xdg_shell_private_o) + +# todo: add a call to a function that obtains all .hpp files from l2/allie_cpp +out/l3/allie_cpp/r4c: src/l3/r4/r4c.cpp src/l1/allie_cpp/anne/utils.hpp \ + src/l2/allie_cpp/alice.hpp $(full_allie_cpp_obj) + mkdir -p out/l3/allie_cpp + $(cxx_cpp) $(cxxflags_cpp) -o $@ $< $(full_allie_cpp_obj) \ + -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype + +.PHONY: run_r4c +run_r4c: out/l3/allie_cpp/r4c + ./out/l3/allie_cpp/r4c + +# ======================== ПЛЮСЫ ВСЁ ========================== +# ============================================================= +# ------------------------------------------------------------- + +# ------------------------------------------------------------- +# ============================================================= +# ========================== ХАСКЕЛЬ ========================== + +find_haskell_hs = $(shell find src/$(1) -type f -name '*.hs' ) + +# Whoever needs this will also need out/l_wl_protocols +out/l2/allie_hs/glue.o: src/l2/allie_hs/glue.c $(HEADERS_src_l2) $(xdg_shell_client_h) gen/l_adele/dorothy.txt $(HEADERS_gen_l2) + mkdir -p out/l2/allie_hs/ + $(cc) $(cflags) -o $@ -c $< -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype + +full_allie_hs_obj := out/l2/allie_hs/glue.o $(xdg_shell_private_o) + +# todo: write a function that gets all .hs files from l2/allie_hs. Call it +out/l3/allie_hs/r4: src/l3/r4/R4.hs src/l2/allie_hs/Alice.hs \ + src/l2/allie_hs/Geom.hs $(full_allie_hs_obj) + mkdir -p out/l3/allie_hs + ghc -isrc/l2/allie_hs -hidir out/l3/ -odir out/l3 -o $@ $< $(full_allie_hs_obj) \ + -lvulkan -lm -lxkbcommon -lwayland-client -lpng -lfreetype + +.PHONY: run_r4 +run_r4: out/l3/allie_hs/r4 + ./out/l3/allie_hs/r4 + +# ========================== ХАСКЕЛЬ ВСЁ ====================== +# ============================================================= +# ------------------------------------------------------------- diff --git a/src/l1/allie_cpp/anne/codegen.cpp b/src/l1/allie_cpp/anne/codegen.cpp new file mode 100644 index 0000000..91051d8 --- /dev/null +++ b/src/l1/allie_cpp/anne/codegen.cpp @@ -0,0 +1,7 @@ +#include "geom.hpp" + +int main() { + l1_generate_geom_hpp(); + touch_file("l1/allie_cpp/dorothy.txt"); + return 0; +} diff --git a/src/l1/allie_cpp/anne/geom.hpp b/src/l1/allie_cpp/anne/geom.hpp new file mode 100644 index 0000000..cc378bc --- /dev/null +++ b/src/l1/allie_cpp/anne/geom.hpp @@ -0,0 +1,533 @@ +#pragma once + +#include "../codegen.hpp" + +#include +#include +#include +#include +#include +#include + +/* This file is vibecoded. It requires more rewriting */ + +inline constexpr std::array kGeomFieldNames = {"x", "y", "z", "w"}; + +struct GeomVecFamilySpec { + std::string_view prefix; + std::string_view scalar; + bool geometric_methods; +}; + +struct GeomMatFamilySpec { + std::string_view mat_prefix; + std::string_view vec_prefix; + std::string_view scalar; +}; + +template +concept GeomIndexCallable = + requires(F&& f) { + std::invoke(std::forward(f), int{}); + }; + +template +concept GeomIndexStringCallable = + requires(F&& f) { + { std::invoke(std::forward(f), int{}) } -> std::convertible_to; + }; + +template +concept GeomIndexPairStringCallable = + requires(F&& f) { + { std::invoke(std::forward(f), int{}, int{}) } -> std::convertible_to; + }; + +template +inline void geom_append_joined(std::string& out, int count, std::string_view separator, F&& emit_one) { + for (int i = 0; i < count; ++i) { + if (i > 0) { + out += separator; + } + emit_one(i); + } +} + +inline std::string_view geom_field_name(int index) { + return kGeomFieldNames[index]; +} + +inline std::string geom_vec_name(std::string_view prefix, int n) { + return std::string(prefix) + std::to_string(n); +} + +inline std::string geom_mat_name(std::string_view prefix, int cols, int rows) { + if (cols == rows) { + return std::string(prefix) + std::to_string(cols); + } + return std::string(prefix) + std::to_string(cols) + "x" + std::to_string(rows); +} + +template +inline void geom_append_constructor_call(std::string& out, std::string_view type_name, int count, F&& arg_expression) { + out += std::string(type_name); + out += "("; + geom_append_joined(out, count, ", ", [&](int index) { + out += arg_expression(index); + }); + out += ")"; +} + +template +inline void geom_append_vector_return(std::string& out, std::string_view vec_name, int count, F&& component_expression) { + out += " return "; + geom_append_constructor_call(out, vec_name, count, component_expression); + out += ";\n"; +} + +template +inline void geom_append_matrix_return( + std::string& out, + std::string_view mat_name, + std::string_view vec_name, + int cols, + int rows, + F&& component_expression) { + out += " return "; + out += std::string(mat_name); + out += "("; + geom_append_joined(out, cols, ", ", [&](int col) { + geom_append_constructor_call(out, vec_name, rows, [&](int row) { + return component_expression(col, row); + }); + }); + out += ");\n"; +} + +template +inline void geom_append_matrix_column_return(std::string& out, std::string_view mat_name, int cols, F&& column_expression) { + out += " return "; + geom_append_constructor_call(out, mat_name, cols, column_expression); + out += ";\n"; +} + +inline void geom_append_vector_family(std::string& out, GeomVecFamilySpec spec, int n) { + const std::string vec_name = geom_vec_name(spec.prefix, n); + + out += "struct " + vec_name + " {\n"; + for (int i = 0; i < n; ++i) { + out += " " + std::string(spec.scalar) + " " + std::string(geom_field_name(i)) + ";\n"; + } + out += "\n"; + out += " constexpr " + vec_name + "() noexcept = default;\n"; + out += " constexpr " + vec_name + "("; + geom_append_joined(out, n, ", ", [&](int index) { + out += std::string(spec.scalar) + " " + std::string(geom_field_name(index)); + }); + out += ") noexcept : "; + geom_append_joined(out, n, ", ", [&](int index) { + const std::string field = std::string(geom_field_name(index)); + out += field + "(" + field + ")"; + }); + out += " {}\n"; + out += "};\n\n"; + + out += "inline " + vec_name + " operator+(" + vec_name + " A, " + vec_name + " B) noexcept {\n"; + geom_append_vector_return(out, vec_name, n, [&](int index) { + const std::string field = std::string(geom_field_name(index)); + return "A." + field + " + B." + field; + }); + out += "}\n\n"; + + out += "inline " + vec_name + " operator-(" + vec_name + " A, " + vec_name + " B) noexcept {\n"; + geom_append_vector_return(out, vec_name, n, [&](int index) { + const std::string field = std::string(geom_field_name(index)); + return "A." + field + " - B." + field; + }); + out += "}\n\n"; + + out += "inline " + vec_name + " operator-(" + vec_name + " A) noexcept {\n"; + geom_append_vector_return(out, vec_name, n, [&](int index) { + return "-A." + std::string(geom_field_name(index)); + }); + out += "}\n\n"; + + out += "inline " + vec_name + " operator*(" + vec_name + " A, " + std::string(spec.scalar) + " B) noexcept {\n"; + geom_append_vector_return(out, vec_name, n, [&](int index) { + return "A." + std::string(geom_field_name(index)) + " * B"; + }); + out += "}\n\n"; + + out += "inline " + vec_name + " operator*(" + std::string(spec.scalar) + " A, " + vec_name + " B) noexcept {\n"; + out += " return B * A;\n}\n\n"; + + out += "inline " + vec_name + " operator/(" + vec_name + " A, " + std::string(spec.scalar) + " B) noexcept {\n"; + geom_append_vector_return(out, vec_name, n, [&](int index) { + return "A." + std::string(geom_field_name(index)) + " / B"; + }); + out += "}\n\n"; + + out += "inline " + vec_name + " operator*(" + vec_name + " A, " + vec_name + " B) noexcept {\n"; + geom_append_vector_return(out, vec_name, n, [&](int index) { + const std::string field = std::string(geom_field_name(index)); + return "A." + field + " * B." + field; + }); + out += "}\n\n"; + + out += "inline " + std::string(spec.scalar) + " dot(" + vec_name + " A, " + vec_name + " B) noexcept {\n"; + out += " return " + [&]() { + std::string expression; + geom_append_joined(expression, n, " + ", [&](int index) { + const std::string field = std::string(geom_field_name(index)); + expression += "A." + field + " * B." + field; + }); + return expression; + }() + ";\n}\n\n"; + + if (spec.geometric_methods) { + out += "inline " + std::string(spec.scalar) + " length(" + vec_name + " A) noexcept {\n"; + out += " return std::sqrt(dot(A, A));\n}\n\n"; + + out += "inline " + vec_name + " normalize(" + vec_name + " A) noexcept {\n"; + out += " return A / length(A);\n}\n\n"; + + if (n == 3) { + out += "inline " + vec_name + " cross(" + vec_name + " A, " + vec_name + " B) noexcept {\n"; + geom_append_vector_return(out, vec_name, 3, [&](int index) { + if (index == 0) { + return "A.y * B.z - A.z * B.y"; + } + if (index == 1) { + return "-A.x * B.z + A.z * B.x"; + } + return "A.x * B.y - A.y * B.x"; + }); + out += "}\n\n"; + } + } +} + +inline void geom_append_vector_and_one(std::string& out, GeomVecFamilySpec spec, int n) { + const std::string vec_name = geom_vec_name(spec.prefix, n); + const std::string vec_next = geom_vec_name(spec.prefix, n + 1); + + out += "inline " + vec_next + " and_one(" + vec_name + " A) noexcept {\n"; + geom_append_vector_return(out, vec_next, n + 1, [&](int index) { + if (index == n) { + return std::string("1"); + } + return "A." + std::string(geom_field_name(index)); + }); + out += "}\n\n"; +} + +inline void geom_append_matrix_struct(std::string& out, GeomMatFamilySpec spec, int cols, int rows) { + const std::string mat_name = geom_mat_name(spec.mat_prefix, cols, rows); + const std::string vec_rows = geom_vec_name(spec.vec_prefix, rows); + + out += "struct " + mat_name + " {\n"; + for (int col = 0; col < cols; ++col) { + out += " " + vec_rows + " " + std::string(geom_field_name(col)) + ";\n"; + } + out += "\n"; + out += " constexpr " + mat_name + "() noexcept = default;\n"; + out += " constexpr " + mat_name + "("; + geom_append_joined(out, cols, ", ", [&](int col) { + out += vec_rows + " " + std::string(geom_field_name(col)); + }); + out += ") noexcept : "; + geom_append_joined(out, cols, ", ", [&](int col) { + const std::string field = std::string(geom_field_name(col)); + out += field + "(" + field + ")"; + }); + out += " {}\n"; + out += "};\n\n"; +} + +inline void geom_append_matrix_new(std::string& out, GeomMatFamilySpec spec, int cols, int rows) { + const std::string mat_name = geom_mat_name(spec.mat_prefix, cols, rows); + const std::string vec_rows = geom_vec_name(spec.vec_prefix, rows); + + out += "inline " + mat_name + " " + mat_name + "_new("; + bool first = true; + for (int row = 0; row < rows; ++row) { + for (int col = 0; col < cols; ++col) { + if (!first) { + out += ", "; + } + first = false; + out += std::string(spec.scalar) + " "; + out += std::string(geom_field_name(col)); + out += std::string(geom_field_name(row)); + } + } + out += ") noexcept {\n"; + geom_append_matrix_return(out, mat_name, vec_rows, cols, rows, [&](int col, int row) { + return std::string(geom_field_name(col)) + std::string(geom_field_name(row)); + }); + out += "}\n\n"; +} + +inline void geom_append_matrix_base_operators(std::string& out, GeomMatFamilySpec spec, int cols, int rows) { + const std::string mat_name = geom_mat_name(spec.mat_prefix, cols, rows); + const std::string scalar = std::string(spec.scalar); + const std::string vec_cols = geom_vec_name(spec.vec_prefix, cols); + const std::string vec_rows = geom_vec_name(spec.vec_prefix, rows); + + out += "inline " + mat_name + " operator+(" + mat_name + " A, " + mat_name + " B) noexcept {\n"; + geom_append_matrix_column_return(out, mat_name, cols, [&](int col) { + const std::string field = std::string(geom_field_name(col)); + return "A." + field + " + B." + field; + }); + out += "}\n\n"; + + out += "inline " + mat_name + " operator-(" + mat_name + " A, " + mat_name + " B) noexcept {\n"; + geom_append_matrix_column_return(out, mat_name, cols, [&](int col) { + const std::string field = std::string(geom_field_name(col)); + return "A." + field + " - B." + field; + }); + out += "}\n\n"; + + out += "inline " + mat_name + " operator-(" + mat_name + " A) noexcept {\n"; + geom_append_matrix_column_return(out, mat_name, cols, [&](int col) { + return "-A." + std::string(geom_field_name(col)); + }); + out += "}\n\n"; + + out += "inline " + mat_name + " operator*(" + mat_name + " A, " + scalar + " B) noexcept {\n"; + geom_append_matrix_column_return(out, mat_name, cols, [&](int col) { + return "A." + std::string(geom_field_name(col)) + " * B"; + }); + out += "}\n\n"; + + out += "inline " + mat_name + " operator*(" + scalar + " A, " + mat_name + " B) noexcept {\n"; + out += " return B * A;\n}\n\n"; + + out += "inline " + mat_name + " operator/(" + mat_name + " A, " + scalar + " B) noexcept {\n"; + geom_append_matrix_column_return(out, mat_name, cols, [&](int col) { + return "A." + std::string(geom_field_name(col)) + " / B"; + }); + out += "}\n\n"; + + out += "inline " + vec_rows + " operator*(" + mat_name + " A, " + vec_cols + " B) noexcept {\n"; + geom_append_vector_return(out, vec_rows, rows, [&](int row) { + std::string expression; + geom_append_joined(expression, cols, " + ", [&](int col) { + expression += "A." + std::string(geom_field_name(col)); + expression += "."; + expression += std::string(geom_field_name(row)); + expression += " * B."; + expression += std::string(geom_field_name(col)); + }); + return expression; + }); + out += "}\n\n"; +} + +inline void geom_append_matrix_transpose(std::string& out, GeomMatFamilySpec spec, int cols, int rows) { + const std::string mat_name = geom_mat_name(spec.mat_prefix, cols, rows); + const std::string mat_transposed = geom_mat_name(spec.mat_prefix, rows, cols); + const std::string vec_cols = geom_vec_name(spec.vec_prefix, cols); + + out += "inline " + mat_transposed + " transpose(" + mat_name + " A) noexcept {\n"; + geom_append_matrix_return(out, mat_transposed, vec_cols, rows, cols, [&](int new_col, int new_row) { + return "A." + std::string(geom_field_name(new_row)) + "." + std::string(geom_field_name(new_col)); + }); + out += "}\n\n"; +} + +inline void geom_append_square_identity(std::string& out, GeomMatFamilySpec spec, int n) { + const std::string mat_name = geom_mat_name(spec.mat_prefix, n, n); + const std::string vec_name = geom_vec_name(spec.vec_prefix, n); + + out += "inline constexpr " + mat_name + " " + mat_name + "_E = "; + geom_append_constructor_call(out, mat_name, n, [&](int col) { + std::string column; + geom_append_constructor_call(column, vec_name, n, [&](int row) { + return std::string(col == row ? "1" : "0"); + }); + return column; + }); + out += ";\n\n"; +} + +inline void geom_append_square_outer_product(std::string& out, GeomMatFamilySpec spec, int n) { + const std::string mat_name = geom_mat_name(spec.mat_prefix, n, n); + const std::string vec_name = geom_vec_name(spec.vec_prefix, n); + + out += "inline " + mat_name + " outer_product(" + vec_name + " v) noexcept {\n"; + geom_append_matrix_return(out, mat_name, vec_name, n, n, [&](int col, int row) { + const std::string col_field = std::string(geom_field_name(col)); + return "v." + col_field + " * v." + std::string(geom_field_name(row)); + }); + out += "}\n\n"; + + out += "inline " + mat_name + " " + mat_name + "_new_for_proj(" + vec_name + " v) noexcept {\n"; + out += " return outer_product(v);\n}\n\n"; +} + +inline void geom_append_matrix_times_matrix(std::string& out, GeomMatFamilySpec spec, int n, int m, int k) { + const std::string left_name = geom_mat_name(spec.mat_prefix, n, m); + const std::string right_name = geom_mat_name(spec.mat_prefix, k, n); + const std::string result_name = geom_mat_name(spec.mat_prefix, k, m); + const std::string vec_m = geom_vec_name(spec.vec_prefix, m); + + out += "inline " + result_name + " operator*(" + left_name + " A, " + right_name + " B) noexcept {\n"; + geom_append_matrix_return(out, result_name, vec_m, k, m, [&](int result_col, int result_row) { + std::string expression; + geom_append_joined(expression, n, " + ", [&](int inner) { + expression += "A." + std::string(geom_field_name(inner)); + expression += "."; + expression += std::string(geom_field_name(result_row)); + expression += " * B."; + expression += std::string(geom_field_name(result_col)); + expression += "."; + expression += std::string(geom_field_name(inner)); + }); + return expression; + }); + out += "}\n\n"; +} + +inline void geom_append_det_function(std::string& out, GeomMatFamilySpec spec, int n) { + const std::string mat_name = geom_mat_name(spec.mat_prefix, n, n); + const std::string scalar = std::string(spec.scalar); + + out += "inline " + scalar + " det(" + mat_name + " a) noexcept {\n"; + out += " return " + [&]() { + std::string expression; + if (n == 2) { + expression = "a.x.x * a.y.y - a.x.y * a.y.x"; + return expression; + } + geom_append_joined(expression, n, "\n ", [&](int i) { + if (i > 0) { + expression += ""; + } + for (int j = 0; j < n; ++j) { + if (j == i) { + continue; + } + const int k = (n == 3) ? (3 - i - j) : -1; + if (n == 3) { + const bool minus = + (((i > j) ? 1 : 0) + ((j > k) ? 1 : 0) + ((i > k) ? 1 : 0)) % 2 != 0; + if (!expression.empty()) { + expression += " "; + } + expression += minus ? "-" : "+"; + expression += " a.x."; + expression += std::string(geom_field_name(i)); + expression += " * a.y."; + expression += std::string(geom_field_name(j)); + expression += " * a.z."; + expression += std::string(geom_field_name(k)); + } + } + if (n == 4) { + for (int j = 0; j < 4; ++j) { + if (j == i) { + continue; + } + for (int k = 0; k < 4; ++k) { + if (k == i || k == j) { + continue; + } + const int u = 6 - i - j - k; + const bool minus = + (((i > j) ? 1 : 0) + ((j > k) ? 1 : 0) + ((i > k) ? 1 : 0) + + ((i > u) ? 1 : 0) + ((j > u) ? 1 : 0) + ((k > u) ? 1 : 0)) % 2 != 0; + if (!expression.empty()) { + expression += " "; + } + expression += minus ? "-" : "+"; + expression += " a.x."; + expression += std::string(geom_field_name(i)); + expression += " * a.y."; + expression += std::string(geom_field_name(j)); + expression += " * a.z."; + expression += std::string(geom_field_name(k)); + expression += " * a.w."; + expression += std::string(geom_field_name(u)); + } + } + } + }); + return expression; + }() + ";\n}\n\n"; +} + +inline std::string geom_build_hpp() { + std::string out; + out.reserve(131072); + + out += "#pragma once\n"; + out += "/* Automatically generated file. Do not edit it. */\n\n"; + out += "#include \n"; + out += "#include \n\n"; + + constexpr std::array vec_specs = {{ + {"cvec", "std::uint8_t", false}, + {"uvec", "std::uint32_t", false}, + {"s64vec", "std::int64_t", false}, + {"ivec", "std::int32_t", false}, + {"vec", "float", true}, + {"dvec", "double", true}, + }}; + + for (const GeomVecFamilySpec& spec : vec_specs) { + for (int n = 2; n <= 4; ++n) { + geom_append_vector_family(out, spec, n); + } + if (spec.geometric_methods) { + for (int n = 2; n <= 3; ++n) { + geom_append_vector_and_one(out, spec, n); + } + } + } + + for (int n = 2; n <= 4; ++n) { + out += "using s32vec" + std::to_string(n) + " = ivec" + std::to_string(n) + ";\n"; + } + out += "\n"; + + constexpr std::array mat_specs = {{ + {"mat", "vec", "float"}, + {"s64mat", "s64vec", "std::int64_t"}, + }}; + + for (const GeomMatFamilySpec& spec : mat_specs) { + for (int cols = 2; cols <= 4; ++cols) { + for (int rows = 2; rows <= 4; ++rows) { + geom_append_matrix_struct(out, spec, cols, rows); + geom_append_matrix_new(out, spec, cols, rows); + geom_append_matrix_base_operators(out, spec, cols, rows); + } + } + for (int cols = 2; cols <= 4; ++cols) { + for (int rows = 2; rows <= 4; ++rows) { + geom_append_matrix_transpose(out, spec, cols, rows); + } + } + for (int n = 2; n <= 4; ++n) { + geom_append_square_identity(out, spec, n); + geom_append_square_outer_product(out, spec, n); + } + for (int n = 2; n <= 4; ++n) { + for (int m = 2; m <= 4; ++m) { + for (int k = 2; k <= 4; ++k) { + geom_append_matrix_times_matrix(out, spec, n, m, k); + } + } + } + for (int n = 2; n <= 4; ++n) { + geom_append_det_function(out, spec, n); + } + } + + return out; +} + +inline void l1_generate_geom_hpp() { + write_text_file("l1/allie_cpp/geom.hpp", geom_build_hpp()); +} diff --git a/src/l1/allie_cpp/anne/utils.hpp b/src/l1/allie_cpp/anne/utils.hpp new file mode 100644 index 0000000..c54d015 --- /dev/null +++ b/src/l1/allie_cpp/anne/utils.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef uint8_t U8; +typedef uint16_t U16; +typedef uint32_t U32; +typedef uint64_t U64; +typedef int8_t S8; +typedef int16_t S16; +typedef int32_t S32; +typedef int64_t S64; + +struct allie_SpanU8 { + const U8* data; + U64 len; + + explicit allie_SpanU8(std::string_view cpp_span): data(reinterpret_cast(cpp_span.data())), len(cpp_span.size()){} +}; + +struct allie_VecU8 { + const U8* buf; + U64 len; +}; + +struct U32Segment { + U32 start; + U32 len; +}; + +struct allie_VecU32Segment { + U32Segment* buf; + U64 len; + U64 capacity; +}; + +#define ALLIE_CPP_OPAQUE(T) \ +void* opa; \ +T& operator=(T&)=delete; \ +T(T&)=delete; \ +T& operator=(T&& other) noexcept { \ +std::swap(opa, other.opa); \ +return *this; \ +} \ +T(T&& other) noexcept: opa(other.opa){ \ +other.opa = NULL; \ +} + +void* safe_malloc(size_t n) { + void* res = malloc(n); + if (!res) { + std::fprintf(stderr, "Allocation failure"); + abort(); + } + return res; +} + +void* safe_calloc(size_t nmemb, size_t size) { + void* res = calloc(nmemb, size); + if (!res) { + std::fprintf(stderr, "Calloc died"); + abort(); + } + return res; +} diff --git a/src/l1/allie_cpp/codegen.hpp b/src/l1/allie_cpp/codegen.hpp new file mode 100644 index 0000000..f786da7 --- /dev/null +++ b/src/l1/allie_cpp/codegen.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include +#include +#include + +inline void write_text_file(std::string_view path_string, std::string_view text) { + const std::filesystem::path path(path_string); + std::ofstream out(path); + if (!out) { + throw std::runtime_error("failed to open " + path.string()); + } + out << text; +} + +inline void touch_file(std::string_view path_string) { + write_text_file(path_string, ""); +} diff --git a/src/l2/alice/engine.h b/src/l2/alice/engine.h index e4d766f..78b46ec 100644 --- a/src/l2/alice/engine.h +++ b/src/l2/alice/engine.h @@ -621,6 +621,7 @@ void alice_default_callback_on_another_frame(void* d, float fl){} typedef struct Alice Alice; typedef struct{ + void* guest; /* guest data, button, button action (wl_pointer_button_state) */ void (*on_wl_pointer_button)(void*, U32, U32); /* guest data, keysym, key action (wl_keyboard_key_state) */ @@ -691,7 +692,7 @@ typedef struct { struct Alice { AliceCallbacks callbacks; - void* guest; + AliceWaylandApp wl; MargaretInstanceAndItsDebug instance_and_debug; @@ -1087,7 +1088,7 @@ void alice_frame_drawing(Alice* alice) { } margaret_reset_and_begin_command_buffer(alice->compute_command_buf); - alice->callbacks.on_another_frame(alice->guest, (float)(alice->wl.cur_frame_time - alice->wl.last_frame_time) / 1000); + alice->callbacks.on_another_frame(alice->callbacks.guest, (float)(alice->wl.cur_frame_time - alice->wl.last_frame_time) / 1000); AliceScene__another_frame(alice); // LucyGlyphCache_another_frame(&alice->lucy_cache); lucy cache has no business here... Well, maybe later MutRefWidget_draw_prepare(alice->overlay_ui_root, (uvec2){win_width, win_height}); @@ -1283,7 +1284,7 @@ static void alice_mainloop_h_wl_keyboard_key( } else if (keysym < 0x80 && key_action == WL_KEYBOARD_KEY_STATE_PRESSED) { alice->wl.first_0x80_keys[keysym] = true; } - alice->callbacks.on_wl_keyboard_key(alice->guest, keysym, key_action); + alice->callbacks.on_wl_keyboard_key(alice->callbacks.guest, keysym, key_action); if (key_action == WL_KEYBOARD_KEY_STATE_RELEASED) { if (keysym == XKB_KEY_1) { } else if (keysym == XKB_KEY_2) { @@ -1342,7 +1343,7 @@ static void alice_mainloop_h_wl_pointer_button( void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t btn_action ) { Alice* alice = data; - alice->callbacks.on_wl_pointer_button(alice->guest, button, btn_action); + alice->callbacks.on_wl_pointer_button(alice->callbacks.guest, button, btn_action); } static void alice_mainloop_h_wl_pointer_axis( @@ -1934,7 +1935,9 @@ void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) { alice->callbacks.on_wl_pointer_button = callbacks->on_wl_pointer_button, alice->callbacks.on_wl_keyboard_key = callbacks->on_wl_keyboard_key; alice->callbacks.on_another_frame = callbacks->on_another_frame; + alice->callbacks.guest = callbacks->guest; printf("ENTERING WAYLAND MAINLOOP\n"); + alice->wl.closed = false; while (wl_display_dispatch(alice->wl.wl_display) >= 0) { if (alice->wl.closed) break; @@ -1980,5 +1983,21 @@ void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) { // if (alice->wl.wl_seat) // wl_seat_destroy(alice->wl.wl_seat); // wl_registry_destroy(alice->wl.wl_registry); - wl_display_disconnect(alice->wl.wl_display); + // wl_display_disconnect(alice->wl.wl_display); } + +/* Direct alice methods */ + +LucyFace* Alice_new_LucyFace(Alice* alice, VecU8 path) { + return LucyFace_new(alice->ft_library, &alice->lucy_cache, path); +} + +void Alice_lucy_cache_add_glyphs(Alice* alice, VecLucyGlyphCachingRequest req){ + LucyGlyphCache_add_glyphs(&alice->lucy_cache, req); +} + +void Alice_lucy_renderer_add_simple_label(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs, + vec4 color, S32 additional_y_advance, SpanU8 text, ivec2 start_pos + ) { + LucyRenderer_add_simple_label(&alice->lucy_renderer, ffs, color, additional_y_advance, text, start_pos); +} \ No newline at end of file diff --git a/src/l2/allie_cpp/alice.hpp b/src/l2/allie_cpp/alice.hpp new file mode 100644 index 0000000..c4327bb --- /dev/null +++ b/src/l2/allie_cpp/alice.hpp @@ -0,0 +1,106 @@ +#include "../../l1/allie_cpp/anne/utils.hpp" + +#include "../../../gen/l1/allie_cpp/geom.hpp" + +#include +#include + +/* Actually it is RBTreeNodeLucyFaceFixedSize */ +struct LucyFaceFixedSize { + ALLIE_CPP_OPAQUE(LucyFaceFixedSize) + /* For internal use, don't actually use it */ + explicit LucyFaceFixedSize(void* new_opa) noexcept : opa(new_opa) {} + /* Need to implement */ + ~LucyFaceFixedSize() = default; +}; + +struct allie_LucyGlyphCachingRequest { + void* sized_face; + allie_VecU32Segment codepoint_ranges; +}; + +struct allie_VecLucyGlyphCachingRequest { + allie_LucyGlyphCachingRequest* buf; + U64 len; + U64 capacity; +}; + +struct LucyGlyphCachingRequest { + LucyFaceFixedSize& sized_face; + std::vector codepoint_ranges; +}; + +extern "C" { + void* allie_LucyFace_of_size(void* self, U32 size); +} + +struct LucyFace { + ALLIE_CPP_OPAQUE(LucyFace) + /* For internal use, don't actually use it */ + explicit LucyFace(void* new_opa) noexcept : opa(new_opa) {} + /* I just don't have it right now */ + ~LucyFace() = default; + + LucyFaceFixedSize of_size(U32 size) noexcept { + return LucyFaceFixedSize{allie_LucyFace_of_size(opa, size)}; + } +}; + +struct Alice; + +struct AliceCallbacks { + void* guest; + /* guest data, button, button action (wl_pointer_button_state) */ + void (*on_wl_pointer_button)(void*, U32, U32); + /* guest data, keysym, key action (wl_keyboard_key_state) */ + void (*on_wl_keyboard_key)(void*, U32, U32); + void (*on_another_frame)(void*, float); +}; + +extern "C" { + void* allie_Alice_new(); + void allie_Alice_mainloop(void*, const AliceCallbacks*); + void* allie_Alice_new_LucyFace(void* alice, allie_SpanU8 path); + void allie_Alice_lucy_cache_add_glyphs(void* alice, allie_VecLucyGlyphCachingRequest req); + void allie_Alice_lucy_renderer_add_simple_label(void* alice, void* ffs, + vec4 color, S32 additional_y_advance, allie_SpanU8 text, ivec2 start_pos); +} + +/* You are supposed to pass */ +struct Alice { + ALLIE_CPP_OPAQUE(Alice) + Alice() noexcept: opa(allie_Alice_new()){} + ~Alice() { + // todo: do something about it + } + + void mainloop(const AliceCallbacks& callbacks) noexcept { + allie_Alice_mainloop(opa, &callbacks); + } + + LucyFace new_lucy_face (std::string_view path) noexcept { + return LucyFace{allie_Alice_new_LucyFace(opa, allie_SpanU8(path))}; + } + + void lucy_cache_add_glyphs(std::vector&& reqs) { + allie_VecLucyGlyphCachingRequest a_reqs{}; + a_reqs.len = a_reqs.capacity = reqs.size(); + a_reqs.buf = static_cast( safe_malloc(reqs.size() * sizeof(allie_LucyGlyphCachingRequest) )); + for (U64 i = 0; i < reqs.size(); i++) { + allie_LucyGlyphCachingRequest& a_r = a_reqs.buf[i]; + LucyGlyphCachingRequest& r = reqs[i]; + a_r.sized_face = r.sized_face.opa; + a_r.codepoint_ranges.len = a_r.codepoint_ranges.capacity = r.codepoint_ranges.size(); + a_r.codepoint_ranges.buf = static_cast(safe_malloc( r.codepoint_ranges.size() * sizeof(U32Segment) )); + memcpy(a_r.codepoint_ranges.buf, r.codepoint_ranges.data(), r.codepoint_ranges.size() * sizeof(U32Segment) ); + } + allie_Alice_lucy_cache_add_glyphs(opa, a_reqs); + } + + void lucy_renderer_add_simple_label(LucyFaceFixedSize& ffs, + vec4 color, S32 additional_y_advance,std::string_view text, ivec2 start_pos + ) noexcept { + allie_Alice_lucy_renderer_add_simple_label(opa, ffs.opa, + color, additional_y_advance, allie_SpanU8(text), start_pos); + } +}; diff --git a/src/l2/allie_cpp/glue.c b/src/l2/allie_cpp/glue.c new file mode 100644 index 0000000..cf78cc4 --- /dev/null +++ b/src/l2/allie_cpp/glue.c @@ -0,0 +1,32 @@ +#include "../alice/engine.h" + +Alice* allie_Alice_new(){ + return Alice_new(); +} + +void allie_Alice_mainloop(Alice* self, const AliceCallbacks* callbacks) { + Alice_mainloop(self, callbacks); +} + +void allie_Alice_drop(Alice* self) { + // todo: implment +} + +LucyFace* allie_Alice_new_LucyFace(Alice* alice, SpanU8 path) { + return Alice_new_LucyFace(alice, VecU8_from_span(path)); +} + + +RBTreeNodeLucyFaceFixedSize* allie_LucyFace_of_size(LucyFace* self, U32 size) { + return LucyFace_of_size(self, size); +} + +void allie_Alice_lucy_cache_add_glyphs(Alice* alice, VecLucyGlyphCachingRequest req) { + Alice_lucy_cache_add_glyphs(alice, req); +} + +void allie_Alice_lucy_renderer_add_simple_label(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs, + vec4 color, S32 additional_y_advance, SpanU8 text, ivec2 start_pos + ) { + Alice_lucy_renderer_add_simple_label(alice, ffs, color, additional_y_advance, text, start_pos); +} diff --git a/src/l2/allie/Allie.hs b/src/l2/allie_hs/Alice.hs similarity index 100% rename from src/l2/allie/Allie.hs rename to src/l2/allie_hs/Alice.hs diff --git a/src/l2/allie/Geom.hs b/src/l2/allie_hs/Geom.hs similarity index 100% rename from src/l2/allie/Geom.hs rename to src/l2/allie_hs/Geom.hs diff --git a/src/l2/allie/allie.c b/src/l2/allie_hs/glue.c similarity index 98% rename from src/l2/allie/allie.c rename to src/l2/allie_hs/glue.c index e4bb8cf..3b2f345 100644 --- a/src/l2/allie/allie.c +++ b/src/l2/allie_hs/glue.c @@ -20,6 +20,7 @@ RBTreeNodeLucyFaceFixedSize* allie_alice_lucy_face_of_size(LucyFace* face, U32 h return LucyFace_of_size(face, height); } +// todo: rewrite this too /* lol */ void allie_lucy_face_add_glyphs(RBTreeNodeLucyFaceFixedSize* face_fs, U32 start, U32 seg_len){ VecLucyGlyphCachingRequest lucy_requests = VecLucyGlyphCachingRequest_new(); @@ -28,7 +29,7 @@ void allie_lucy_face_add_glyphs(RBTreeNodeLucyFaceFixedSize* face_fs, U32 start, VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){ .sized_face = face_fs, .codepoint_ranges = ranges_needed, }); - LucyGlyphCache_add_glyphs(lucy_requests); + // LucyGlyphCache_add_glyphs(lucy_requests, ); } void allie_alice_clear_text(Alice* alice){ diff --git a/src/l2/lucy/glyph_cache.h b/src/l2/lucy/glyph_cache.h index 135bb96..ad5a5ce 100644 --- a/src/l2/lucy/glyph_cache.h +++ b/src/l2/lucy/glyph_cache.h @@ -202,10 +202,7 @@ void LucyGlyphCache_add_glyphs__close_img( }, 0, NULL); } -void LucyGlyphCache_add_glyphs(VecLucyGlyphCachingRequest requests_for_faces){ - if (requests_for_faces.len == 0) - return; - LucyGlyphCache* cache = requests_for_faces.buf[0].sized_face->value.p->p; +void LucyGlyphCache_add_glyphs(LucyGlyphCache* cache, VecLucyGlyphCachingRequest requests_for_faces){ for (size_t fi = 0; fi < requests_for_faces.len; fi++) { assert(cache == requests_for_faces.buf[fi].sized_face->value.p->p); } diff --git a/src/l2/lucy/glyph_render.h b/src/l2/lucy/glyph_render.h index 0de639b..b4b11e2 100644 --- a/src/l2/lucy/glyph_render.h +++ b/src/l2/lucy/glyph_render.h @@ -129,7 +129,7 @@ void LucyRenderer_draw_char_glyph(LucyRenderer* self, vec4 color, ivec2 pos, Luc */ void LucyRenderer_add_simple_label( LucyRenderer* self, RBTreeNodeLucyFaceFixedSize* ffs, vec4 color, - U32 additional_y_advance, SpanU8 text, ivec2 start_pos + S32 additional_y_advance, SpanU8 text, ivec2 start_pos ){ self->need_to_transfer = true; U32 font_height = ffs->key; @@ -138,7 +138,7 @@ void LucyRenderer_add_simple_label( while (text.len > 0) { U32 codepoint = SpanU8_decode_as_utf8(&text); if (codepoint == (U32)'\n') { - pos = (ivec2){start_pos.x, pos.y + (S32)font_height + (S32)additional_y_advance}; + pos = (ivec2){start_pos.x, pos.y + (S32)font_height + additional_y_advance}; continue; } BufRBTree_MapU32ToLucyStoredGlyph *glyphs = &ffs->value.glyphs; diff --git a/src/l3/r4/r4.c b/src/l3/r4/r4.c index 620cf0f..c49c9bd 100644 --- a/src/l3/r4/r4.c +++ b/src/l3/r4/r4.c @@ -304,7 +304,7 @@ void main_h_on_another_frame(void* data, float fl){ if (st->hits_count > 0) { VecU8_append_fmt(&text, "You hit ROA %u times\n", st->hits_count); } - LucyRenderer_add_simple_label(&alice->lucy_renderer, st->font_face_of_size_40, (vec4){0, 0, 0, 1}, 0, + Alice_lucy_renderer_add_simple_label(alice, st->font_face_of_size_40, (vec4){0, 0, 0, 1}, 0, VecU8_to_span(&text), (ivec2){10, 10}); VecU8_drop(text); } @@ -314,10 +314,8 @@ void run_app(){ st.hero_pos = (vec3){0, 0.81f, 0}; Alice* alice = Alice_new(); st.alice = alice; - st.alice->guest = &st; - st.font_face = LucyFace_new(st.alice->ft_library, &st.alice->lucy_cache, - vcstr("./src/l3/fonts/DMSerifText-Regular.ttf")); + st.font_face = Alice_new_LucyFace(alice, vcstr("./src/l3/fonts/DMSerifText-Regular.ttf")); st.font_face_of_size_40 = LucyFace_of_size(st.font_face, 40); VecLucyGlyphCachingRequest lucy_requests = VecLucyGlyphCachingRequest_new(); VecU32Segment ranges_needed = VecU32Segment_new(); @@ -325,16 +323,16 @@ void run_app(){ VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){ .sized_face = st.font_face_of_size_40, .codepoint_ranges = ranges_needed, }); - LucyGlyphCache_add_glyphs(lucy_requests); + Alice_lucy_cache_add_glyphs(alice, lucy_requests); lucy_requests = VecLucyGlyphCachingRequest_new(); ranges_needed = VecU32Segment_new(); VecU32Segment_append(&ranges_needed, (U32Segment){.start = 0x430, .len = 0x44f - 0x430 + 1}); VecLucyGlyphCachingRequest_append(&lucy_requests, (LucyGlyphCachingRequest){ .sized_face = st.font_face_of_size_40, .codepoint_ranges = ranges_needed, }); + Alice_lucy_cache_add_glyphs(alice, lucy_requests); - LucyGlyphCache_add_glyphs(lucy_requests); - LucyRenderer_add_simple_label(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0, + Alice_lucy_renderer_add_simple_label(alice, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0, cstr("..."), (ivec2){10, 10}); /* Recursion depth is 2 */ @@ -417,6 +415,7 @@ void run_app(){ st.bullets_stuck_on_ROA = Vecvec3_new(); Alice_mainloop(st.alice, &(AliceCallbacks){ + .guest = &st, .on_wl_pointer_button = main_h_on_wl_pointer_button, .on_wl_keyboard_key = main_h_on_wl_keyboard_key, .on_another_frame = main_h_on_another_frame, diff --git a/src/l3/r4/r4c.cpp b/src/l3/r4/r4c.cpp new file mode 100644 index 0000000..e9bf21a --- /dev/null +++ b/src/l3/r4/r4c.cpp @@ -0,0 +1,54 @@ +#include "../../l2/allie_cpp/alice.hpp" +#include "../../../gen/l1/allie_cpp/geom.hpp" +#include +#include + +template +using unique = std::unique_ptr; + +struct AppMem { + float gr = 0; +}; + +struct R4C_State { + unique alice; + unique face; + unique sized_face; + + AppMem app; +}; + +vec4 funky_color(float time) { + return vec4{(sinf(0.95f * time + 0.6f) + 1) / 2, (sinf(0.233f * time + 0.2f) + 1) / 2, (sinf(1.433f * time) + 1) / 2, 1}; +} + +void main_h_on_another_frame(void* data, float fl) { + R4C_State& st = *(R4C_State*)data; + Alice& alice = *st.alice; + LucyFaceFixedSize& ffs = *st.sized_face; + st.app.gr += fl; + alice.lucy_renderer_add_simple_label(ffs, funky_color(st.app.gr), 0, "Hello from C++", ivec2(500, 50)); +} + +void main_h_on_wl_keyboard_key(void* data, U32 keysym, U32 act) { + +} + +void main_h_on_wl_pointer_button(void* data, U32 button, U32 act) { + +} + +int main() { + R4C_State st{}; + st.alice = std::make_unique(); + st.face = std::make_unique(st.alice->new_lucy_face("./src/l3/fonts/DMSerifText-Regular.ttf")); + st.sized_face = std::make_unique(st.face->of_size(40)); + st.alice->lucy_cache_add_glyphs({LucyGlyphCachingRequest{*st.sized_face, {{ .start = 32, .len = 126 - 32 + 1 }}}}); + st.alice->mainloop({ + .guest = &st, + .on_wl_pointer_button = main_h_on_wl_pointer_button, + .on_wl_keyboard_key = main_h_on_wl_keyboard_key, + .on_another_frame = main_h_on_another_frame, + }); + return 0; +} \ No newline at end of file