Just wrote basic json support. Had not tested yet. In fact, I haven't even finished debugging marie_triangulation algorithm. I am truly running out of time

This commit is contained in:
Андреев Григорий 2026-01-26 18:47:49 +03:00
parent 2c4252847d
commit 78fd9f0816
21 changed files with 772 additions and 204 deletions

View File

@ -59,6 +59,8 @@ target_link_libraries(r2c -lm)
#add_executable(l2t0 src/l2/tests/data_structures/t0.c)
#add_executable(l2t1 src/l2/tests/data_structures/t1.c)
add_executable(l2_t_parsing src/l2/tests/t_parsing.c)
add_executable(l2_tex_gen src/l2/anne/codegen.c)
target_link_libraries(l2_tex_gen -lm -lpng)

View File

@ -9,13 +9,13 @@ void generate_liza_l1_headers() {
mkdir_nofail("l1/eve/liza");
// 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});
.T = cstr("BoxLizaSound"), .vec = true}, false);
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("PlayingSound"), .vec_extended = true});
.T = cstr("PlayingSound"), .vec_extended = true}, false);
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("BoxLizaInstrument"), .vec = true});
.T = cstr("BoxLizaInstrument"), .vec = true}, false);
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("MyInstrument"), .vec = true});
.T = cstr("MyInstrument"), .vec = true}, false);
}
#endif

View File

@ -17,7 +17,7 @@ void generate_l1_lucy_headers(){
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("LucyPositionedStagingGlyph"), .vec = true, .sort = true,
});
}, false);
}
#endif

View File

@ -11,7 +11,7 @@ void generate_margaret_eve_for_vulkan_utils() {
mkdir_nofail("l1/eve/margaret");
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("MargaretScoredPhysicalDevice"), .t_primitive = true, .vec = true, .sort = true
});
}, false);
/* For l2/margaret/{ vulkan_img_claire.h , vulkan_buffer_claire.h } */
generate_eve_span_company_for_primitive(l, ns, cstr("MargaretIAFreeSegment"), true, false);

View File

@ -12,7 +12,6 @@ void generate_l1_headers_for_marie() {
generate_eve_span_company_for_primitive(l, ns, cstr("MarieTriangleAttr"), true, false);
/* shape_geom */
generate_eve_span_company_for_primitive(l, ns, cstr("MarieEarCuttingTriangulVertState"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MarieHoleConnectTriangStackFrame"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("MarieHoleAndVertexId"), true, false);
generate_eve_span_company_for_non_primitive_clonable(l, ns, cstr("VecMarieHoleAndVertexId"), true, false);
generate_eve_span_company_for_non_primitive_clonable(l, ns, cstr("VecVecMarieHoleAndVertexId"), true, false);

View File

@ -17,7 +17,7 @@ void generate_headers_for_r0_r1_r2_r3() {
SpanU8 ns = cstr("r2");
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("PlayingSound"), .vec_extended = true
});
}, false);
}
mkdir_nofail("l1/eve/ds_test");
{ /* This structure is needed for testing purposes only */

View File

@ -67,6 +67,13 @@ void generate_util_temp_very_base_headers() {
cstr("#include \"../../gen/l1/pixel_masses.h\"\n"), true, false);
generate_guarded_span_company_for_primitive(l, ns, cstr("KVPU64ToU64"), cstr(""), true, false);
/* Currently not clonable, because I forgot to implement clone for rbtree. todo: do this */
generate_util_templ_inst_eve_header(l, ns, (util_templates_instantiation_options){
.T = cstr("Json"), .t_clonable = false, .vec = true, .skip_declaration_gen = true}, true);
generate_Option_templ_inst_eve_header(l, ns,
(option_template_instantiation_op){.T = cstr("Json"), .t_clonable = false});
}
#endif

View File

@ -4,21 +4,30 @@
#include "codegen.h"
// todo: add macro that iterates over vector
// todo: add _less_ method
// todo: rewrite this crap
/* if !primitive, requires methods T_drop, and, if also clonable, requires method T_clone */
NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive, bool clonable) {
VecU8 g_VecT = VecU8_fmt("Vec%s", T);
SpanU8 VecT = VecU8_to_span(&g_VecT);
VecU8 res = VecU8_fmt(
"typedef struct {\n"
NODISCARD VecU8 generate_VecT_struct(SpanU8 T, bool skip_declaration_gen){
VecU8 res = VecU8_new();
if (!skip_declaration_gen) {
VecU8_append_vec(&res, VecU8_fmt("typedef struct Vec%s Vec%s;\n\n", T, T));
}
VecU8_append_vec(&res, VecU8_fmt(
"struct Vec%s {\n"
SPACE "%s* buf;\n"
SPACE "size_t len;\n"
SPACE "size_t capacity;\n"
"} %s;\n\n", T, VecT);
"};\n\n", T, T));
return res;
}
VecU8_append_vec(&res, VecU8_fmt("#define %s_new() ((%s){ 0 })\n\n", VecT, VecT));
/* if !primitive, requires methods T_drop, and, if also clonable, requires method T_clone */
NODISCARD VecU8 generate_VecT_base_methods(SpanU8 T, bool primitive, bool clonable) {
VecU8 res = VecU8_new();
VecU8_append_vec(&res, VecU8_fmt("void %s_drop(%s self) {\n", VecT, VecT));
VecU8_append_vec(&res, VecU8_fmt("#define Vec%s_new() ((Vec%s){ 0 })\n\n", T, T));
VecU8_append_vec(&res, VecU8_fmt("void Vec%s_drop(Vec%s self) {\n", T, T));
if (!primitive) {
VecU8_append_vec(&res, VecU8_fmt(
SPACE "for (size_t i = 0; i < self.len; i++) \n"
@ -29,12 +38,12 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
"}\n\n"));
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_reserved(size_t n) {\n"
SPACE "return (%s){ .buf = (%s*)safe_calloc(n, sizeof(%s)), .len = 0, .capacity = n };\n"
"}\n\n", VecT, VecT, VecT, T, T));
"NODISCARD Vec%s Vec%s_new_reserved(size_t n) {\n"
SPACE "return (Vec%s){ .buf = (%s*)safe_calloc(n, sizeof(%s)), .len = 0, .capacity = n };\n"
"}\n\n", T, T, T, T, T));
VecU8_append_vec(&res, VecU8_fmt(
"void %s_append(%s* self, %s el) {\n" /* VecT, VecT, T */
"void Vec%s_append(Vec%s* self, %s el) {\n" /* T, T, T */
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"
@ -43,26 +52,26 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
SPACE "}\n"
SPACE "self->buf[self->len] = el;\n"
SPACE "self->len = new_length;\n"
"}\n\n", VecT, VecT, T, T, T));
"}\n\n", T, T, T, T, T));
VecU8_append_vec(&res, VecU8_fmt(
"%s* %s_mat(%s* self, size_t i) {\n"
"%s* Vec%s_mat(Vec%s* self, size_t i) {\n"
SPACE "assert(i < self->len);\n"
SPACE "return &self->buf[i];\n"
"}\n\n", T, VecT, VecT));
"}\n\n", T, T, T));
VecU8_append_vec(&res, VecU8_fmt(
"const %s* %s_at(const %s* self, size_t i) {\n"
"const %s* Vec%s_at(const Vec%s* self, size_t i) {\n"
SPACE "assert(i < self->len);\n"
SPACE "return &self->buf[i];\n"
"}\n\n", T, VecT, VecT));
"}\n\n", T, T, T));
VecU8_append_vec(&res, VecU8_fmt(
"void %s_sink(%s* self, size_t new_len) {\n" /* VecT, VecT */
"void Vec%s_sink(Vec%s* self, size_t new_len) {\n" /* T, T */
SPACE "assert(new_len <= self->len);\n"
"%v" /* dropping */
SPACE "self->len = new_len;\n"
"}\n\n", VecT, VecT,
"}\n\n", T, T,
primitive ? vcstr("") : VecU8_fmt(
SPACE "for (size_t i = new_len; i < self->len; i++)\n"
SPACE SPACE "%s_drop(self->buf[i]);\n", /* T */
@ -70,9 +79,10 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
if (clonable) {
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_clone(const %s* self) {\n" /* VecT, VecT, VecT */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(self->len, sizeof(%s)), .len = self->len, .capacity = self->len};\n",
VecT, VecT, VecT, VecT, VecT, T, T));
"NODISCARD Vec%s Vec%s_clone(const Vec%s* self) {\n" /* T, T, T */
SPACE "Vec%s res = (Vec%s){.buf = (%s*)safe_calloc(self->len, sizeof(%s)),\n" /* T, T, T, T */
SPACE SPACE ".len = self->len, .capacity = self->len};\n",
T, T, T, T, T, T, T));
if (primitive) {
VecU8_append_vec(&res, VecU8_fmt(SPACE "memcpy(res.buf, self->buf, self->len * sizeof(%s));\n", T));
} else {
@ -84,7 +94,7 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
}
VecU8_append_vec(&res, VecU8_fmt(
"void %s_append_vec(%s* self, %s b) {\n" /* VecT, VecT, VecT */
"void Vec%s_append_vec(Vec%s* self, Vec%s b) {\n" /* T, T, 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"
@ -96,17 +106,16 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
SPACE "}\n"
SPACE "self->len = new_length;\n"
SPACE "free(b.buf);\n"
"}\n\n", VecT, VecT, VecT, T, T));
"}\n\n", T, T, T, T, T));
if (primitive) {
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_zeroinit(size_t len) {\n" /* VecT, VecT*/
SPACE "return (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, T, T */
"NODISCARD Vec%s Vec%s_new_zeroinit(size_t len) {\n" /* T, T */
SPACE "return (Vec%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* T, T, T */
"}\n\n",
VecT, VecT, VecT, T, T));
T, T, T, T, T));
}
VecU8_drop(g_VecT); // VecT invalidated too
return res;
}
@ -229,13 +238,16 @@ void codegen_append_some_span_equal_method(VecU8* res, SpanU8 SpanT) {
"}\n\n", SpanT, SpanT, SpanT, SpanT));
}
/* helper function. (SpanT, mod) is either (SpanT "const ") or (MutSpanT, "") */
void codegen_append_some_span_struct(VecU8* res, SpanU8 T, SpanU8 SpanT, SpanU8 mod) {
/* Helper function. (span_mod, mod) is in {("", "const "), ("Mut", "")} */
void codegen_append_some_span_struct(VecU8* res, SpanU8 T, SpanU8 span_mod, SpanU8 mod, bool skip_declaration_gen) {
if (!skip_declaration_gen) {
VecU8_append_vec(res, VecU8_fmt("typedef struct %sSpan%s %sSpan%s;\n\n", span_mod, T, span_mod, T));
}
VecU8_append_vec(res, VecU8_fmt(
"typedef struct {\n"
SPACE "%s%s* data;\n"
"struct %sSpan%s {\n" /* span_mod, T */
SPACE "%s%s* data;\n" /* mod, T */
SPACE "size_t len;\n"
"} %s;\n\n", mod, T, SpanT));
"};\n\n", span_mod, T, mod, T));
}
/* helper function. (SpanT, mod) is either (SpanT "const ") or (MutSpanT, "") */
@ -257,11 +269,19 @@ void codegen_append_some_span_span_method(VecU8* res, SpanU8 SpanT) {
"}\n\n", SpanT, SpanT, SpanT, SpanT));
}
NODISCARD VecU8 generate_SpanT_structures(SpanU8 T, bool add_mutable, bool skip_declaration_gen){
VecU8 res = VecU8_new();
codegen_append_some_span_struct(&res, T, cstr(""), cstr("const "), skip_declaration_gen);
if (add_mutable)
codegen_append_some_span_struct(&res, T, cstr("Mut"), cstr(""), skip_declaration_gen);
return res;
}
/* T must be sized. Option `add_sort` requires option `add_mutable` and method T_less
* add_mutable option generates MutSpanT.
* add_equal option generates equal method. add_extended option generated extended methods
*/
NODISCARD VecU8 generate_SpanT_struct_and_methods(
NODISCARD VecU8 generate_SpanT_base_methods(
SpanU8 T, bool integer, bool add_mutable, bool add_equal, bool add_extended
) {
VecU8 g_SpanT = VecU8_fmt("Span%s", T);
@ -270,9 +290,6 @@ NODISCARD VecU8 generate_SpanT_struct_and_methods(
SpanU8 MutSpanT = VecU8_to_span(&g_MutSpanT);
VecU8 res = VecU8_new();
codegen_append_some_span_struct(&res, T, SpanT, cstr("const "));
if (add_mutable)
codegen_append_some_span_struct(&res, T, MutSpanT, cstr(""));
if (add_equal) {
codegen_append_some_span_equal_method(&res, SpanT);
if (add_mutable)
@ -426,6 +443,8 @@ typedef struct {
bool sort;
bool collab_vec_span;
bool collab_vec_span_extended;
bool skip_declaration_gen;
} util_templates_instantiation_options;
void util_templates_instantiation_options_fix(util_templates_instantiation_options* op) {
@ -453,37 +472,50 @@ void util_templates_instantiation_options_fix(util_templates_instantiation_optio
assert(!op->t_primitive || op->t_clonable);
}
NODISCARD VecU8 generate_util_templates_instantiation(util_templates_instantiation_options op) {
NODISCARD VecU8 generate_util_templates_instantiation(util_templates_instantiation_options op,
bool generate_structures, bool generate_methods) {
VecU8 res = VecU8_new();
util_templates_instantiation_options_fix(&op);
if (op.vec) {
VecU8_append_vec(&res, generate_VecT_struct_and_base_methods(op.T, op.t_primitive, op.t_clonable));
if (generate_structures) {
if (op.vec) {
VecU8_append_vec(&res, generate_VecT_struct(op.T, op.skip_declaration_gen));
}
if (op.span) {
VecU8_append_vec(&res, generate_SpanT_structures(op.T, op.mut_span, op.skip_declaration_gen));
}
}
if (op.vec_extended) {
assert(op.vec);
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(op.T, op.t_integer));
}
if (op.vec_new_of_size) {
assert(op.vec);
VecU8_append_vec(&res, generate_VecT_new_of_size_method(op.T));
}
if (op.span) {
VecU8_append_vec(&res, generate_SpanT_struct_and_methods(op.T, op.t_integer, op.mut_span, false, op.span_extended));
}
if (op.sort) {
VecU8_append_vec(&res, generate_span_company_sort_methods(op.T, op.t_integer, op.mut_span, op.vec));
}
if (op.collab_vec_span) {
assert(op.vec && op.span);
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));
if (generate_methods) {
if (op.vec) {
VecU8_append_vec(&res, generate_VecT_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(op.T, op.t_primitive, op.t_clonable));
}
if (op.vec_equal) {
assert(op.vec);
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(op.T));
}
if (op.span) {
VecU8_append_vec(&res, generate_SpanT_base_methods(op.T, op.t_integer, op.mut_span, false, op.span_extended));
}
if (op.sort) {
VecU8_append_vec(&res, generate_span_company_sort_methods(op.T, op.t_integer, op.mut_span, op.vec));
}
if (op.collab_vec_span) {
assert(op.vec && op.span);
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;
}
/* Does not include .h postfix. .h postfix and `path` prefix have to be added by someone else */
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",
@ -491,38 +523,49 @@ NODISCARD VecU8 util_templates_instantiation_get_appropriate_filename(util_templ
(int)op.vec + (int)op.span > 1 ? cstr("_") : cstr(""), op.T);
}
void generate_util_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, util_templates_instantiation_options op) {
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_util_templates_instantiation(op),
util_templates_instantiation_get_appropriate_filename(op));
void generate_util_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, util_templates_instantiation_options op,
bool separate_struct_and_methods) {
if (separate_struct_and_methods) {
VecU8 name_for_structures = VecU8_fmt("%v_struct", util_templates_instantiation_get_appropriate_filename(op));
VecU8 name_for_methods = VecU8_fmt("%v_methods", util_templates_instantiation_get_appropriate_filename(op));
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_util_templates_instantiation(op, true, false),
name_for_structures);
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_util_templates_instantiation(op, false, true),
name_for_methods);
} else {
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_util_templates_instantiation(op, true, true),
util_templates_instantiation_get_appropriate_filename(op));
}
}
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, (util_templates_instantiation_options){
.T = T,
.t_primitive = true, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span
});
}, false);
}
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, (util_templates_instantiation_options){
.T = T,
.t_clonable = true, .vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span
});
}, false);
}
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, (util_templates_instantiation_options){
.T = T,
.vec = with_vector, .span = with_span, .collab_vec_span = with_vector && with_span
});
}, false);
}
void generate_util_templ_inst_guarded_header(
SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies, util_templates_instantiation_options op
) {
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, VecU8_fmt("%v%s\n",
codegen_include_relative_to_root(bonus_ns, cstr("src/l1/core/util.h")), dependencies),
generate_util_templates_instantiation(op), util_templates_instantiation_get_appropriate_filename(op));
generate_util_templates_instantiation(op, true, true), util_templates_instantiation_get_appropriate_filename(op));
}
void generate_guarded_span_company_for_primitive(
@ -552,6 +595,7 @@ void generate_guarded_span_company_for_non_primitive_non_clonable(
});
}
NODISCARD VecU8 get_ResultType_inst_name(SpanU8 OkT, SpanU8 ErrT){
bool ok_t_void = OkT.len == 0;
bool err_t_void = ErrT.len == 0;

View File

@ -102,6 +102,12 @@ void S64_stringification_into_buf(S64 x, VecU8* targ){
}
}
VecU8 S64_stringification(S64 x){
VecU8 res = VecU8_new();
S64_stringification_into_buf(x, &res);
return res;
}
size_t U64_stringification_get_length(U64 x){
if (x == 0)
return 1;
@ -135,6 +141,12 @@ void U64_stringification_into_buf(U64 x, VecU8* targ){
}
}
VecU8 U64_stringification(U64 x){
VecU8 res = VecU8_new();
U64_stringification_into_buf(x, &res);
return res;
}
/* %s - SpanU8
* %v - VecU8
* %u - U64
@ -253,11 +265,78 @@ U32 SpanU8_decode_as_utf8(SpanU8* rem){
}
bool SpanU8_is_prefix(SpanU8 a, SpanU8 str){
return str.len >= a.len && SpanU8_cont_equal(a, (SpanU8){str.data, a.len});
if (str.len < a.len)
return false;
for (size_t i = 0; i < a.len; i++) {
if (a.data[i] != str.data[i]) {
return false;
}
}
return true;
}
bool SpanU8_is_postfix(SpanU8 a, SpanU8 str){
return str.len >= a.len && SpanU8_cont_equal(a, (SpanU8){str.data + str.len - a.len, a.len});
if (str.len < a.len)
return false;
for (size_t i = 0; i < a.len; i++) {
if (a.data[i] != str.data[str.len - a.len + i]) {
return false;
}
}
return true;
}
// todo: automatically generate such methods for vectors of nice types
bool SpanU8_less_SpanU8(SpanU8 a, SpanU8 b){
size_t i = 0;
while (i < a.len && i < b.len) {
if (a.data[i] < b.data[i])
return true;
if (b.data[i] < a.data[i])
return false;
i++;
}
/* If i < b->len, then a is eigen-prefix of b, which means a < b
* Or... i < a->len, and this means b is eigen-prefix of a => a > b
* Or... a == b . Here we also return false */
return i < b.len;
}
bool VecU8_less_VecU8(const VecU8* a, const VecU8* b){
return SpanU8_less_SpanU8(VecU8_to_span(a), VecU8_to_span(b));
}
char digit_to_big_hex(U32 d){
assert(d < 16);
return d >= 10 ? (char)('A' + d - 10) : (char)('0' + d);
}
char digit_to_small_hex(U32 d){
assert(d < 16);
return d >= 10 ? (char)('a' + d - 10) : (char)('0' + d);
}
static_assert(0b11000000 == 0xC0 && 0b10000000 == 0x80 && 0b00111111 == 0x3F, "asdasda");
/* Some bytes (encoding codepoint U) will be appended to str. Utf-8 works only with codepoints below (1u << 24) */
void VecU8_encode_as_utf8(VecU8* str, U32 U){
if (U < (1u << 7)) {
VecU8_append(str, (U8)U);
} else if (U < (1u << 11)) {
VecU8_append_span(str, (SpanU8){(U8[]){
0xC0 | (U8)(U >> 6), 0x80 | (U8)(U & 0x3F)
}, 2});
} else if (U < (1u << 17)) {
VecU8_append_span(str, (SpanU8){(U8[]){
0xC0 | (U8)(U >> 12), 0x80 | (U8)((U >> 6) & 0x3F), (U8)(U & 0x3F)
}, 3});
} else {
/* U < (1u << 24) */
VecU8_append_span(str, (SpanU8){(U8[]){
0xC0 | (U8)(U >> 18), 0x80 | (U8)((U >> 12) & 0x3F), 0x80 | (U8)((U >> 6) & 0x3F), (U8)(U & 0x3F)
}, 4});
}
}
#endif

View File

@ -17,9 +17,16 @@ void generate_l1_5_template_instantiation_for_base_types(){
generate_rbtree_Set_templ_inst_guarded_header(l, ns, cstr(""), (set_instantiation_op){
.T = cstr("S64"), .t_integer = true }, true);
// todo: move vector declaration HERE
// todo: move vector declaration HERE (might wait)
generate_buf_rbtree_Map_templ_inst_guarded_header(l, ns, cstr("#include \"../../gen/l1/VecKVPU64ToU64.h\"\n"),
(map_instantiation_op){.K = cstr("U64"), .k_integer = true, .V = cstr("U64"), .v_integer = true,});
// todo: implement recursion for heap-allocated red-black tree, to make json dictionary clonable
generate_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
.K = cstr("VecU8"), .k_clonable = true,
.V = cstr("Json"), .v_clonable = false,
.skip_declaration_gen = true,
}, false, true);
}
#endif

View File

@ -9,7 +9,7 @@ void generate_l1_5_lucy_headers(){
generate_buf_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
.K = cstr("U32"), .k_integer = true, .V = cstr("LucyStoredGlyph"), .v_primitive = true});
generate_rbtree_Map_templ_inst_eve_header(l, ns, (map_instantiation_op){
.K = cstr("U32"), .k_integer = true, .V = cstr("LucyFaceFixedSize")}, true);
.K = cstr("U32"), .k_integer = true, .V = cstr("LucyFaceFixedSize")}, true, false);
}

View File

@ -46,6 +46,7 @@ typedef struct {
bool at, mat;
bool pop, pop_substitute;
bool skip_declaration_gen;
} map_instantiation_op;
void map_instantiation_op_fix(map_instantiation_op* self){
@ -67,7 +68,7 @@ void map_instantiation_op_fix(map_instantiation_op* self){
/* --- Sharing is caring --- */
/* Assuming A nd B are passed as intended */
/* Assuming A and B are passed as intended */
NODISCARD VecU8 codegen_rbtree_map__less(map_instantiation_op op, VecU8 A, VecU8 B){
if (op.guest_data_T.len > 0) {
assert(op.alternative_less.len > 0);
@ -77,7 +78,7 @@ NODISCARD VecU8 codegen_rbtree_map__less(map_instantiation_op op, VecU8 A, VecU8
return VecU8_fmt("%s(%v, %v)", op.alternative_less, A, B);
if (op.k_integer)
return VecU8_fmt("%v < %v", A, B);
return VecU8_fmt("%s_less_%s(%v %v)", op.K, op.K, A, B);
return VecU8_fmt("%s_less_%s(%v, %v)", op.K, op.K, A, B);
}
NODISCARD VecU8 codegen_rbtree_map__exp_passing_key_val(map_instantiation_op op){

View File

@ -18,14 +18,18 @@ NODISCARD VecU8 codegen_buf_rbtree_map__exp_passing_cur_key(map_instantiation_op
void codegen_append_buff_rbtree_map__structure_and_simplest_methods(
VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 TT
){
if (!op.skip_declaration_gen) {
VecU8_append_vec(res, VecU8_fmt("typedef struct %s %s;\n\n", set, set));
}
VecU8_append_vec(res, VecU8_fmt(
"typedef struct {\n"
"struct %s{\n"
SPACE "VecBufRBTreeNode tree;\n"
SPACE "U64 root;\n"
SPACE "Vec%s el;\n"
"%v"
"} %s;\n\n",
TT, op.guest_data_T.len > 0 ? VecU8_fmt(SPACE "%s guest;\n", op.guest_data_T) : vcstr(""), set));
"};\n\n",
set, TT, op.guest_data_T.len > 0 ? VecU8_fmt(SPACE "%s guest;\n", op.guest_data_T) : vcstr("")));
if (op.guest_data_T.len > 0) {
VecU8_append_vec(res, VecU8_fmt(

View File

@ -28,18 +28,22 @@ NODISCARD VecU8 codegen_rbtree_map__exp_passing_cur_key(map_instantiation_op op)
return VecU8_fmt("%s" "((%v*)cur)->key", op.k_integer ? cstr("") : cstr("&"), codegen_rbtree__node_struct_name(op));
}
void codegen_append_rbtree_map__structure_and_simplest_methods(
VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 TT
){
void codegen_append_rbtree_map__structure(VecU8* res, map_instantiation_op op, SpanU8 set){
if (!op.skip_declaration_gen) {
VecU8_append_vec(res, VecU8_fmt("typedef struct %s %s;\n\n", set, set));
}
VecU8_append_vec(res, VecU8_fmt(
"typedef struct {\n"
"struct %s {\n"
SPACE "RBTreeNode* root;\n"
SPACE "RBTreeNode* NIL;\n"
"%v" /* "" / guest field */
"} %s;\n\n",
op.guest_data_T.len == 0 ? vcstr("") : VecU8_fmt("%s guest;\n", op.guest_data_T),
set));
"};\n\n",
set,
op.guest_data_T.len == 0 ? vcstr("") : VecU8_fmt("%s guest;\n", op.guest_data_T)));
}
void codegen_append_rbtree_map__simplest_methods(VecU8* res, map_instantiation_op op, SpanU8 set, SpanU8 TT){
VecU8_append_vec(res, VecU8_fmt(
"NODISCARD %s %s_new(" "%v" ") {\n" /* set, set, "" / GT guest */
/* Only color field initialization is important (should be 0) */
@ -290,6 +294,12 @@ void codegen_append_rbtree_map__structure_and_simplest_methods(
"}\n\n",
set, set, codegen_rbtree_map__taking_ref_k_argument(op),
TT, set, set));
VecU8_append_vec(res, VecU8_fmt(
"bool %s_empty(const %s* self){\n" /* set, set */
SPACE "return self->root == self->NIL;\n"
"}\n\n",
set, set));
}
@ -312,7 +322,8 @@ NODISCARD VecU8 generate_rbtree_Set_template_instantiation(set_instantiation_op
VecU8 set_g = get_name_of_rbtree_set_structure(op);
if (generate_node_struct)
VecU8_append_vec(&res, codegen_rbtree__node_structure(map_op));
codegen_append_rbtree_map__structure_and_simplest_methods(&res, map_op, VecU8_to_span(&set_g), op.T);
codegen_append_rbtree_map__structure(&res, map_op, VecU8_to_span(&set_g));
codegen_append_rbtree_map__simplest_methods(&res, map_op, VecU8_to_span(&set_g), op.T);
VecU8_drop(set_g);
return res;
}
@ -340,7 +351,8 @@ NODISCARD VecU8 get_name_of_rbtree_map_structure(map_instantiation_op op){
return VecU8_fmt("RBTree_Map%sTo%s", op.K, op.V);
}
NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op op, bool generate_node_struct){
NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op op, bool generate_node_struct,
bool generate_map_struct, bool generate_methods){
map_instantiation_op_fix(&op);
VecU8 res = VecU8_new();
@ -351,73 +363,89 @@ NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op
if (generate_node_struct)
VecU8_append_vec(&res, codegen_rbtree__node_structure(op));
codegen_append_rbtree_map__structure_and_simplest_methods(&res, op, map, kvp);
if (generate_map_struct)
codegen_append_rbtree_map__structure(&res, op, map);
if (generate_methods) {
codegen_append_rbtree_map__simplest_methods(&res, op, map, kvp);
if (op.pop_substitute) {
VecU8_append_vec(&res, VecU8_fmt(
"%s" "Option%s %s_pop_substitute(%s* self, %s key, %s value) {\n" /* "" / NODISCARD , op.V, map, map, op.K, op.V */
/* Using unsafe method with conditional ownership transfer */
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key, value);\n" /* kvp, map */
SPACE "if (col == NULL) {\n"
SPACE SPACE "return None_%s();\n" /* op.V */
SPACE "} else {\n"
"%v" /* "" / dropping col->key */
SPACE SPACE "%s saved = col->value;\n" /* op.V */
SPACE SPACE "col->key = key;\n"
SPACE SPACE "col->value = value;\n"
SPACE SPACE "return Some_%s(saved);\n" /* op.V */
SPACE "}\n"
"}\n\n",
op.v_primitive ? cstr("") : cstr("NODISCARD "), op.V, map, map, op.K, op.V,
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE"%s_drop(col->key);\n", op.K),
op.V, op.V));
if (op.pop_substitute) {
VecU8_append_vec(&res, VecU8_fmt(
"%s" "Option%s %s_pop_substitute(%s* self, %s key, %s value) {\n" /* "" / NODISCARD , op.V, map, map, op.K, op.V */
/* Using unsafe method with conditional ownership transfer */
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key, value);\n" /* kvp, map */
SPACE "if (col == NULL) {\n"
SPACE SPACE "return None_%s();\n" /* op.V */
SPACE "} else {\n"
"%v" /* "" / dropping col->key */
SPACE SPACE "%s saved = col->value;\n" /* op.V */
SPACE SPACE "col->key = key;\n"
SPACE SPACE "col->value = value;\n"
SPACE SPACE "return Some_%s(saved);\n" /* op.V */
SPACE "}\n"
"}\n\n",
op.v_primitive ? cstr("") : cstr("NODISCARD "), op.V, map, map, op.K, op.V,
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE SPACE"%s_drop(col->key);\n", op.K),
op.V, op.V));
}
if (!op.v_primitive) {
VecU8_append_vec(&res, VecU8_fmt(
"bool %s_erase_substitute(%s* self, %s key, %s value) {\n" /* map, map, op.K, op.V */
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key, value);\n" /* kvp, map */
SPACE "if (col == NULL)\n"
SPACE SPACE "return true;\n"
"%v" "%v" /* "" / op.K_drop(col->key), "" / op.V_drop(col->value) */
SPACE "col->key = key;\n"
SPACE "col->value = value;\n"
SPACE "return false;\n"
"}\n\n",
map, map, op.K, op.V, kvp, map,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->value);\n", op.V)));
}
if (op.pop){
// todo: write _pop_by_it
// todo: rewrite pop using _pop_by_it
VecU8_append_vec(&res, VecU8_fmt(
"Option%s %s_pop(%s* self, %v key) {\n" /* op.V, map, map, taking_ref_k_argument */
SPACE "RBTreeNode_%s* v = %s_find(self, key);\n" /* kvp, map */
SPACE "if (v == NULL)\n"
SPACE SPACE "return None_%s();\n" /* op.V */
"%v" /* "" / op.K_drop(v->key) */
"%s saved = v->value;\n" /* op.V */
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, (RBTreeNode*)v);\n"
SPACE "free(v);\n"
SPACE "return Some_%s(saved);\n" /* op.V */
"}\n\n",
op.V, map, map, codegen_rbtree_map__taking_ref_k_argument(op),
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->key);\n", op.K),
op.V, op.V));
}
// todo: write generator for methods _at and _mat
}
if (!op.v_primitive) {
VecU8_append_vec(&res, VecU8_fmt(
"bool %s_erase_substitute(%s* self, %s key, %s value) {\n" /* map, map, op.K, op.V */
SPACE "RBTreeNode_%s* col = %s_try_insert(self, key, value);\n" /* kvp, map */
SPACE "if (col == NULL)\n"
SPACE SPACE "return true;\n"
"%v" "%v" /* "" / op.K_drop(col->key), "" / op.V_drop(col->value) */
SPACE "col->key = key;\n"
SPACE "col->value = value;\n"
SPACE "return false;\n"
"}\n\n",
map, map, op.K, op.V, kvp, map,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->key);\n", op.K),
op.v_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(col->value);\n", op.V)));
}
if (op.pop){
// todo: write _pop_by_it
// todo: rewrite pop using _pop_by_it
VecU8_append_vec(&res, VecU8_fmt(
"Option%s %s_pop(%s* self, %v key) {\n" /* op.V, map, map, taking_ref_k_argument */
SPACE "RBTreeNode_%s* v = %s_find(self, key);\n" /* kvp, map */
SPACE "if (v == NULL)\n"
SPACE SPACE "return None_%s();\n" /* op.V */
"%v" /* "" / op.K_drop(v->key) */
"%s saved = v->value;\n" /* op.V */
SPACE "RBTree_erase_empty_by_iter(&self->root, self->NIL, (RBTreeNode*)v);\n"
SPACE "free(v);\n"
SPACE "return Some_%s(saved);\n" /* op.V */
"}\n\n",
op.V, map, map, codegen_rbtree_map__taking_ref_k_argument(op),
kvp, map, op.V,
op.k_primitive ? vcstr("") : VecU8_fmt(SPACE "%s_drop(v->key);\n", op.K),
op.V, op.V));
}
// todo: write generator for methods _at and _mat
return res;
}
void generate_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op,
bool generate_node_struct) {
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
generate_rbtree_Map_template_instantiation(op, generate_node_struct), get_name_of_rbtree_map_structure(op));
bool generate_node_struct, bool separate_struct_and_methods) {
if (separate_struct_and_methods) {
assert(!generate_node_struct);
VecU8 name_for_struct = VecU8_fmt("%v_struct", get_name_of_rbtree_map_structure(op));
VecU8 name_for_method = VecU8_fmt("%v_method", get_name_of_rbtree_map_structure(op));
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
generate_rbtree_Map_template_instantiation(op, false, true, false),
name_for_struct);
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
generate_rbtree_Map_template_instantiation(op, false, false, true),
name_for_method);
} else {
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
generate_rbtree_Map_template_instantiation(op, generate_node_struct, true, true),
get_name_of_rbtree_map_structure(op));
}
}
void generate_rbtree_Map_templ_inst_guarded_header(
@ -426,8 +454,8 @@ void generate_rbtree_Map_templ_inst_guarded_header(
VecU8 all_dependencies = VecU8_fmt("%v%s",
codegen_include_relative_to_root(bonus_ns, cstr("src/l1_5/core/rb_tree_node.h")), dependencies);
generate_SOME_templ_inst_guarded_header(layer, bonus_ns, all_dependencies,
generate_rbtree_Map_template_instantiation(op, generate_node_struct), get_name_of_rbtree_map_structure(op));
generate_rbtree_Map_template_instantiation(op, generate_node_struct, true, true),
get_name_of_rbtree_map_structure(op));
}
#endif

View File

@ -4,17 +4,6 @@
#include "../../l1/core/VecU8_as_str.h"
#include <math.h>
void SpanU8_parsing_expect_char(SpanU8* rem, char ch){
if (rem->len == 0) {
abortf("Unexpected EOF. Syntax error\n");
}
if (*rem->data != (U8)ch) {
abortf("Expected %d, got %d. Syntax error\n", (int)(*rem->data), (int)ch);
}
rem->data++;
rem->len--;
}
/* if `expected` is prefix of `rem`, `rem` will be advanced by |`expected`| and true will be returned.
* Otherwise false is returned and `rem` is untouched */
bool SpanU8_parsing_try_read_prefix(SpanU8* rem, SpanU8 expected){
@ -29,13 +18,18 @@ bool SpanU8_parsing_try_read_prefix(SpanU8* rem, SpanU8 expected){
return false;
}
void SpanU8_parsing_skip_char(SpanU8* rem){
assert(rem->len > 0);
rem->data++;
rem->len--;
}
bool SpanU8_parsing_try_read_char(SpanU8* rem, char ch){
if (rem->len == 0) {
return false;
}
if (rem->data[0] == (U8)ch) {
rem->data++;
rem->len--;
SpanU8_parsing_skip_char(rem);
return true;
}
return false;
@ -50,19 +44,13 @@ void SpanU8_parsing_skip_entire_line(SpanU8* rem){
}
}
void SpanU8_parsing_skip_char(SpanU8* rem){
assert(rem->len > 0);
rem->data++;
rem->len--;
}
bool SpanU8_parsing_is_char_ahead(SpanU8* rem, char ch){
return rem->len > 0 ? rem->data[0] == (U8)ch : false;
}
/* Time to learn how to read integers */
/* returns positive on error, returns 0 on success */
/* Returns positive on error, 0 on success, rem_ret is untouched on error */
int SpanU8_read_U64(SpanU8* rem_ret, U64* res_ret){
SpanU8 rem = *rem_ret;
U64 x = 0;
@ -102,6 +90,7 @@ U64 SpanU64_expect_read_U64(SpanU8* rem){
return x;
}
/* Returns positive on error, 0 on success, rem_ret is untouched on error */
int SpanU8_read_S64(SpanU8* rem_ret, S64* ret){
SpanU8 rem = *rem_ret;
U64 x = 0;
@ -156,7 +145,7 @@ int SpanU8_read_S64(SpanU8* rem_ret, S64* ret){
}
/* returns positive int on error, 0 on success */
/* returns positive int on error, 0 on success, rem_ret is untouched on error */
int SpanU8_read_float(SpanU8* rem_ret, float* res_ret){
SpanU8 rem = *rem_ret;
@ -187,8 +176,10 @@ int SpanU8_read_float(SpanU8* rem_ret, float* res_ret){
res = (res * 10 + d);
}
saw_digit = true;
} else if (ch == 'e') {
} else if (ch == 'e' || ch == 'E') {
SpanU8_parsing_skip_char(&rem);
if (SpanU8_parsing_is_char_ahead(&rem, '+'))
SpanU8_parsing_skip_char(&rem);
S64 exp;
int ret = SpanU8_read_S64(&rem, &exp);
if (ret)
@ -227,4 +218,41 @@ float SpanU8_expect_read_float(SpanU8* rem){
return x;
}
void SpanU8_parsing_skip_spaces(SpanU8* rem){
while (rem->len) {
U8 ch = *rem->data;
if (!(ch == '\t' || ch == ' ' || ch == '\n' || ch == '\r'))
break;
SpanU8_parsing_skip_char(rem);
}
}
bool is_hex_char(char ch){
return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F');
}
static_assert('a' > 'A', "ASCII check");
static_assert('A' > '0', "ASCII check");
U32 char_to_hex_digit(char ch){
if (ch >= 'a')
return ch - 'a' + 10;
if (ch >= 'A')
return ch - 'A' + 10;
return ch - '0';
}
/* Should return true on success */
bool SpanU8_parsing_try_read_hex_digit(SpanU8* rem, U32* ret){
if (rem->len == 0)
return false;
char ch = (char)rem->data[0];
if (is_hex_char(ch)) {
*ret = char_to_hex_digit(ch);
SpanU8_parsing_skip_char(rem);
return true;
}
return false;
}
#endif

View File

@ -895,19 +895,19 @@ VecVecs64vec2 generate_funny_polygon(){
/* We are on l2 */
int gen_assets_for_r4() {
// mkdir_nofail("l2/models");
// mkdir_nofail("l2/textures");
// mkdir_nofail("l2/textures/r4");
// r4_asset_gen_generic_mesh_one_fourth_of_a_cylinder_2(10, 2, 6);
// alice_write_shiny_mesh_to_file(generate_shiny_cube((vec3){0.6f, 0.6f, 0.7f}), vcstr("l2/models/cube.AliceShinyMesh"));
// alice_write_shiny_mesh_to_file(generate_shiny_lamp(0.3f, 0.13f, 0.19f), vcstr("l2/models/lamp.AliceShinyMesh"));
// r4_asset_gen_generic_mesh_quad(10, 10, vcstr("l2/models/quad.AliceGenericMesh"));
// r4_asset_gen_generic_mesh_cylinder(200, 0.4f, 0.17f, 30, vcstr("l2/models/puck.AliceGenericMesh"),
// vcstr("l2/textures/puck_TEMPLATE.png"), vcstr("l2/textures/puck_NORMAL.png"));
// r4_asset_gen_generic_mesh_cylinder(100, 0.04f, 1.5f, 4, vcstr("l2/models/stick.AliceGenericMesh"),
// vcstr("l2/textures/stick_TEMPLATE.png"), vcstr("l2/textures/stick_NORMAL.png"));
// r4_generate_flat_normal_map(vcstr("l2/textures/flat_NORMAL.png"));
// generate_single_pixel_gray_tex(vcstr("l2/textures/no_SPECULAR.png"), 0);
mkdir_nofail("l2/models");
mkdir_nofail("l2/textures");
mkdir_nofail("l2/textures/r4");
r4_asset_gen_generic_mesh_one_fourth_of_a_cylinder_2(10, 2, 6);
alice_write_shiny_mesh_to_file(generate_shiny_cube((vec3){0.6f, 0.6f, 0.7f}), vcstr("l2/models/cube.AliceShinyMesh"));
alice_write_shiny_mesh_to_file(generate_shiny_lamp(0.3f, 0.13f, 0.19f), vcstr("l2/models/lamp.AliceShinyMesh"));
r4_asset_gen_generic_mesh_quad(10, 10, vcstr("l2/models/quad.AliceGenericMesh"));
r4_asset_gen_generic_mesh_cylinder(200, 0.4f, 0.17f, 30, vcstr("l2/models/puck.AliceGenericMesh"),
vcstr("l2/textures/puck_TEMPLATE.png"), vcstr("l2/textures/puck_NORMAL.png"));
r4_asset_gen_generic_mesh_cylinder(100, 0.04f, 1.5f, 4, vcstr("l2/models/stick.AliceGenericMesh"),
vcstr("l2/textures/stick_TEMPLATE.png"), vcstr("l2/textures/stick_NORMAL.png"));
r4_generate_flat_normal_map(vcstr("l2/textures/flat_NORMAL.png"));
generate_single_pixel_gray_tex(vcstr("l2/textures/no_SPECULAR.png"), 0);
{ /* Just a test */
VecVecs64vec2 P = generate_funny_polygon();
r4_asset_gen_generic_mesh_horizontal_polygon(&P, (mat3x2){.x.x = 1, .y.y = 1},

95
src/l2/core/json.h Normal file
View File

@ -0,0 +1,95 @@
#ifndef prototype1_src_l2_core_json_h
#define prototype1_src_l2_core_json_h
#include "../../l1/core/VecU8_as_str.h"
#include "../../l1_5/core/rb_tree_node.h"
typedef struct Json Json;
typedef struct VecJson VecJson;
typedef struct RBTree_MapVecU8ToJson RBTree_MapVecU8ToJson;
#include "../../../gen/l1/eve/VecJson_struct.h"
#include "../../../gen/l1_5/eve/RBTree_MapVecU8ToJson_struct.h"
typedef enum {
Json_integer,
Json_float,
Json_dict,
Json_arr,
Json_str,
Json_false,
Json_true,
Json_none,
} Json_variant;
struct Json{
Json_variant variant;
union {
S64 integer;
float float_num;
RBTree_MapVecU8ToJson dict;
VecJson arr;
VecU8 str;
};
};
typedef struct RBTreeNode_KVPVecU8ToJson {
RBTreeNode base;
VecU8 key;
Json value;
} RBTreeNode_KVPVecU8ToJson;
/* Pulling declarations of methods, defined below */
void VecJson_drop(VecJson self);
void RBTree_MapVecU8ToJson_drop(RBTree_MapVecU8ToJson self);
void Json_drop(Json self) {
if (self.variant == Json_str) {
VecU8_drop(self.str);
} else if (self.variant == Json_arr) {
VecJson_drop(self.arr);
} else if (self.variant == Json_dict) {
RBTree_MapVecU8ToJson_drop(self.dict);
}
}
#include "../../../gen/l1/eve/VecJson_methods.h"
#include "../../../gen/l1_5/eve/RBTree_MapVecU8ToJson_method.h"
Json Json_from_float(float x){
return (Json){.variant = Json_float, .float_num = x};
}
Json Json_from_int(S64 x){
return (Json){.variant = Json_float, .integer = x};
}
Json Json_from_VecU8(VecU8 x){
return (Json){.variant = Json_str, .str = x};
}
Json Json_from_SpanU8(SpanU8 x){
return (Json){.variant = Json_str, .str = VecU8_from_span(x)};
}
Json Json_from_bool(bool x){
return (Json){.variant = x ? Json_true : Json_false};
}
const Json Json_None = ((Json){.variant = Json_none});
const Json Json_True = ((Json){.variant = Json_true});
const Json Json_False = ((Json){.variant = Json_false});
Json Json_from_VecJson(VecJson arr){
return (Json){.variant = Json_arr, .arr = arr};
}
Json Json_from_MapVecU8ToJson(RBTree_MapVecU8ToJson dict){
return (Json){.variant = Json_dict, .dict = dict};
}
// Bonus
#include "../../../gen/l1/eve/OptionJson.h"
#endif

278
src/l2/core/json_encoded.h Normal file
View File

@ -0,0 +1,278 @@
#ifndef prototype1_src_l2_core_json_encoded_h
#define prototype1_src_l2_core_json_encoded_h
#include "../../l1_5/core/parsing_string.h"
#include "json.h"
void json_encoding_append_utf16(VecU8* res, U8 codepoint){
assert(codepoint < 32);
VecU8_append_span(res, cstr("\\u00"));
VecU8_append(res, digit_to_big_hex(codepoint >> 4));
VecU8_append(res, digit_to_big_hex(codepoint & 0xF));
}
/* Str is being encoded as JSON string literal */
void json_encoding_append_string(VecU8* res, const VecU8* str){
VecU8_append(res, '"');
for (size_t i = 0; i < str->len; i++) {
U8 ch = str->buf[i];
if (ch == '\t') {
VecU8_append_span(res, cstr("\\t"));
} else if (ch == '\n') {
VecU8_append_span(res, cstr("\\n"));
} else if (ch == '\r') {
VecU8_append_span(res, cstr("\\r"));
} else if (ch <= 31) {
json_encoding_append_utf16(res, ch);
} else if (ch == '\"') {
VecU8_append_span(res, cstr("\\\""));
} else if (ch == '\\') {
VecU8_append_span(res, cstr("\\\\"));
} else {
VecU8_append(res, ch);
}
}
VecU8_append(res, '"');
}
/* No prettyprinting */
void json_encoding_append_to_str(const Json* obj, VecU8* res){
if (obj->variant == Json_false) {
VecU8_append_span(res, cstr("false"));
} else if (obj->variant == Json_true) {
VecU8_append_span(res, cstr("true"));
} else if (obj->variant == Json_none) {
VecU8_append_span(res, cstr("none"));
} else if (obj->variant == Json_integer) {
S64_stringification_into_buf(obj->integer, res);
} else if (obj->variant == Json_float) {
VecU8_append_vec(res, VecU8_format("%f", obj->float_num));
} else if (obj->variant == Json_str) {
json_encoding_append_string(res, &obj->str);
} else if (obj->variant == Json_arr) {
VecU8_append(res, '[');
const VecJson* arr = &obj->arr;
for (size_t i = 0; i < arr->len; i++) {
if (i) {
VecU8_append_span(res, cstr(", "));
}
json_encoding_append_to_str(&arr->buf[i], res);
}
VecU8_append(res, ']');
} else if (obj->variant == Json_dict) {
VecU8_append(res, '{');
bool was = false;
for (RBTreeNode_KVPVecU8ToJson* it = RBTree_MapVecU8ToJson_find_min(&obj->dict); it;) {
if (was) {
VecU8_append_span(res, cstr(", "));
}
json_encoding_append_string(res, &it->key);
VecU8_append_span(res, cstr(": "));
json_encoding_append_to_str(&it->value, res);
was = true;
it = RBTree_MapVecU8ToJson_find_next(&obj->dict, it);
}
VecU8_append(res, '}');
}
}
/* json depth is w => Required stack depth is w frames */
VecU8 json_encode(const Json* obj){
VecU8 res = VecU8_new();
json_encoding_append_to_str(obj, &res);
return res;
}
/* Kids had their fun with json encoding. Now it's time for adults to enjoy some parsing */
OptionJson json_decoding_h_no_spaces(SpanU8* rem, U32 depth_rem);
OptionJson json_decoding_h(SpanU8* rem, U32 depth_rem){
SpanU8_parsing_skip_spaces(rem);
OptionJson x = json_decoding_h_no_spaces(rem, depth_rem);
SpanU8_parsing_skip_spaces(rem);
return x;
}
/* Returns positive on error, 0 on success */
int json_decoding_parse_string(SpanU8* rem, VecU8* ret_str){
if (!SpanU8_parsing_try_read_char(rem, '\"')) {
return 1;
}
VecU8 res = VecU8_new();
U16 prev_high_surrogate = 0;
while (true) {
if (rem->len == 0) {
VecU8_drop(res);
return 1;
}
U8 ch = rem->data[0];
SpanU8_parsing_skip_char(rem);
if (ch == '\"') {
*ret_str = res;
return 0;
}
if (ch == '\\') {
if (rem->len == 0) {
VecU8_drop(res);
return 2;
}
ch = rem->data[0];
SpanU8_parsing_skip_char(rem);
if (ch == '\"' || ch == '\\' || ch == '/') {
VecU8_append(&res, ch);
} else if (ch == 'b') {
VecU8_append(&res, '\b');
} else if (ch == 'f') {
VecU8_append(&res, '\f');
} else if (ch == 'n') {
VecU8_append(&res, '\b');
} else if (ch == 'r') {
VecU8_append(&res, '\r');
} else if (ch == 't') {
VecU8_append(&res, '\t');
} else if (ch == 'u') {
U16 cur_word = 0;
for (int i = 0; i < 4; i++) {
U32 d;
if (!SpanU8_parsing_try_read_hex_digit(rem, &d)) {
VecU8_drop(res);
return 3;
}
cur_word = (cur_word << 4) | (U16)d;
}
if (0xDC00 <= cur_word && cur_word < 0xE000) {
/* Low surrogate pair */
if (prev_high_surrogate == 0) {
VecU8_drop(res);
return 4;
}
U32 U = (U32)0x10000 + ((U32)(prev_high_surrogate - 0xD800) << 10) + (U32)(cur_word - 0xDC00);
VecU8_encode_as_utf8(&res, U);
prev_high_surrogate = 0;
} else if (0xD800 <= cur_word && cur_word < 0xDC00) {
/* High surrogate pair */
prev_high_surrogate = cur_word;
} else {
prev_high_surrogate = 0;
VecU8_encode_as_utf8(&res, (U32)cur_word);
}
} else {
VecU8_drop(res);
return 5;
}
} else {
/* We ignore illegal characters in string literals */
VecU8_append(&res, ch);
}
}
}
OptionJson json_decoding_h_no_spaces(SpanU8* rem, U32 depth_rem){
if (depth_rem == 0) {
return None_Json();
}
float fl_value;
int fl_code = SpanU8_read_float(rem, &fl_value);
if (fl_code == 0)
return Some_Json(Json_from_float(fl_value));
S64 int_value;
int int_code = SpanU8_read_S64(rem, &int_value);
if (int_code == 0)
return Some_Json(Json_from_int(int_value));
bool false_code = SpanU8_parsing_try_read_prefix(rem, cstr("false"));
if (false_code)
return Some_Json(Json_False);
bool true_code = SpanU8_parsing_try_read_prefix(rem, cstr("true"));
if (true_code)
return Some_Json(Json_True);
bool none_code = SpanU8_parsing_try_read_prefix(rem, cstr("none"));
if (none_code)
return Some_Json(Json_None);
if (SpanU8_parsing_is_char_ahead(rem, '\"')) {
VecU8 str;
int str_code = json_decoding_parse_string(rem, &str);
if (str_code) {
/* str is uninitialized on error */
return None_Json();
}
/* In case of success, str starts owning a VecU8 */
return Some_Json(Json_from_VecU8(str));
}
if (SpanU8_parsing_try_read_char(rem, '[')) {
SpanU8_parsing_skip_spaces(rem);
VecJson arr = VecJson_new();
while (true) {
if (SpanU8_parsing_try_read_char(rem, ']')) {
return Some_Json(Json_from_VecJson(arr));
}
if (arr.len > 0) {
if (!SpanU8_parsing_try_read_char(rem, ',')) {
VecJson_drop(arr);
return None_Json();
}
}
OptionJson x = json_decoding_h(rem, depth_rem - 1);
if (x.variant == Option_None) {
VecJson_drop(arr);
return None_Json();
}
VecJson_append(&arr, x.some);
}
}
if (SpanU8_parsing_try_read_char(rem, '{')) {
SpanU8_parsing_skip_spaces(rem);
RBTree_MapVecU8ToJson dict = RBTree_MapVecU8ToJson_new();
while (true) {
if (SpanU8_parsing_try_read_char(rem, '}')) {
return Some_Json(Json_from_MapVecU8ToJson(dict));
}
// todo: add _empty method to rb tree map
if (!RBTree_MapVecU8ToJson_empty(&dict)) {
if (!SpanU8_parsing_try_read_char(rem, ',')) {
RBTree_MapVecU8ToJson_drop(dict);
return None_Json();
}
VecU8 key;
int key_code = json_decoding_parse_string(rem, &key);
if (key_code) {
RBTree_MapVecU8ToJson_drop(dict);
return None_Json();
}
SpanU8_parsing_skip_spaces(rem);
if (!SpanU8_parsing_try_read_char(rem, ':')) {
RBTree_MapVecU8ToJson_drop(dict);
VecU8_drop(key);
return None_Json();
}
OptionJson x = json_decoding_h(rem, depth_rem - 1);
if (x.variant == Option_None) {
RBTree_MapVecU8ToJson_drop(dict);
VecU8_drop(key);
return None_Json();
}
bool iret = RBTree_MapVecU8ToJson_insert(&dict, key, x.some);
if (!iret) {
/* Two elements of dictionary share the same key. Very illegal */
RBTree_MapVecU8ToJson_drop(dict);
return None_Json();
}
}
}
}
return None_Json();
}
/* Given depth_allowed=w, maximum of w frames will be used on stack and the returned Json object will
* have a maximum depth of w */
OptionJson json_decode(SpanU8 text, U32 depth_allowed){
OptionJson x = json_decoding_h(&text, depth_allowed);
if (x.variant == Option_Some && text.len > 0) {
return None_Json();
}
return x;
}
#endif

View File

@ -137,17 +137,6 @@ VecU64 marie_polygon_ear_cutting_triangulation(Spans64vec2 P){
return triangles;
}
/* Recursion is dead. Recursion remains dead. And we have killed it.
* Used in hole-connecting triangulation algorithm */
typedef struct {
U64 hole_id;
U64 vertex_in_hole_id;
U64 progress;
U64 progress_in_starting_vertex;
} MarieHoleConnectTriangStackFrame;
#include "../../../gen/l1/eve/marie/VecMarieHoleConnectTriangStackFrame.h"
/* Used in hole-connecting triangulation algorithm */
typedef struct{
U64 hole_id;

6
src/l2/tests/t_parsing.c Normal file
View File

@ -0,0 +1,6 @@
#include "../core/json_encoded.h"
int main(){
return 0;
}

View File

@ -1,3 +1,4 @@
#include "../../l2/core/json.h"
#include "../../l2/allie/allie.c"
AliceGenericMeshPath AliceGenericMeshPath_for_log(SpanU8 root_dir, U64 w, U64 r, U64 k) {