diff --git a/src/app/app.meta.c b/src/app/app.meta.c index 8dd9a34..7a3ac8a 100644 --- a/src/app/app.meta.c +++ b/src/app/app.meta.c @@ -2,7 +2,6 @@ void mt_app(ma_arena_t *arena) { sb8_t *h = sb8_serial_begin(arena); sb8_t *c = sb8_serial_begin(arena); - ast_t *keys = mtt_parse(arena, __FILE__, S8_CODE( // javascript filter out { name js1 js2 jf windows1 windows2 } @@ -89,7 +88,7 @@ void mt_app(ma_arena_t *arena) { c->indent += 1; { sb8_stmtf(c, "if (0) {}"); - for (mtt_iter_t it = mtt_iterate(c->arena, keys); mtt_is_valid(it); mtt_advance(&it)) { + for (ast_t *it = keys->first; it; it = it->next) { assert(mtt(it, "jf")->integer == 0 || mtt(it, "jf")->integer == 1); s8_t js[] = {mtts(it, "js1"), mtts(it, "js2")}; for (i32 i = 0; i < lengthof(js); i += 1) { @@ -111,7 +110,7 @@ void mt_app(ma_arena_t *arena) { sb8_stmtf(c, "switch(wparam) {"); c->indent += 1; { - for (mtt_iter_t it = mtt_iterate(c->arena, keys); mtt_is_valid(it); mtt_advance(&it)) { + for (ast_t *it = keys->first; it; it = it->next) { s8_t w[] = {mtts(it, "windows1"), mtts(it, "windows2")}; for (i32 i = 0; i < lengthof(w); i += 1) { if (s8_are_equal(w[i], s8_lit("XXX"))) continue; diff --git a/src/core/core_inc.h b/src/core/core_inc.h index 65526e0..a4c0840 100644 --- a/src/core/core_inc.h +++ b/src/core/core_inc.h @@ -6,10 +6,10 @@ #include "core_unicode.h" #include "core_arena.h" #include "core_string.h" -#include "core_lexer.h" #include "core_math.h" -#include "core_log.h" #include "core_type_info.h" +#include "core_lexer.h" +#include "core_log.h" #include "core_intrin.h" #include "core_platform.h" #include "core_hash_table.h" diff --git a/src/core/core_lexer.h b/src/core/core_lexer.h index c8ca19d..dfb2c9b 100644 --- a/src/core/core_lexer.h +++ b/src/core/core_lexer.h @@ -159,3 +159,18 @@ fn void parser_panicf(lex_t *token, const char *str, ...); fn void parser_eat_until(parser_t *par, lex_kind_t kind); fn void parser_eat_including(parser_t *par, lex_kind_t kind); +gb_read_only lex_t lex_null; + +gb_read_only type_member_t members__lex_kind_t[] = { +#define X(KIND, STR, SIMPLE) {.name = s8_const_lit("lex_kind_" #KIND), .value = KIND}, + LEX_KIND_XLIST +#undef X +}; +DEFINE_ENUM(lex_kind_t); + +gb_read_only type_member_t members__lex_suffix_t[] = { +#define X(KIND) {.name = s8_const_lit(#KIND), .value = KIND}, + LEX_SUFFIX_XLIST +#undef X +}; +DEFINE_ENUM(lex_suffix_t); diff --git a/src/core/core_log.h b/src/core/core_log.h index 1e8bc6b..4291e2b 100644 --- a/src/core/core_log.h +++ b/src/core/core_log.h @@ -1,22 +1,4 @@ -/* -** design: -** two modes of working: -** optional immediate dump to console -** optional store and retrieval data structure -** -** [ ] console -** [ ] silence very particular messages (use case: user tries to tokenize c code, -** cares only about particular decls, -** does not want to see error flood) -** [ ] graphical integrated into application -** [ ] little counter of unread warnings/errors, somewhere in the corner, that you can click on -** [ ] hierarchy which you can traverse, dive into things which interest you -** [ ] support for very arbitrary logs: "log_triangle", which would show debug points on screen -** -** -** -*/ -typedef enum { // AFTER_CHANGING: modify type_info and log_level_str +typedef enum { log_level_debug, log_level_info, log_level_warning, diff --git a/src/core/core_string.h b/src/core/core_string.h index 1c68119..9f5df61 100644 --- a/src/core/core_string.h +++ b/src/core/core_string.h @@ -33,6 +33,7 @@ struct sb8_t { // WARNING: remember to update typeinfo after editing this i32 indent; + void *user_data; }; typedef i32 s8_seek_t; diff --git a/src/core/core_type_info.h b/src/core/core_type_info.h index 27d76d5..b9e6119 100644 --- a/src/core/core_type_info.h +++ b/src/core/core_type_info.h @@ -20,6 +20,7 @@ enum { type_kind_usize, type_kind_int, type_kind_char, + type_kind_void, type_kind_pointer, type_kind_array, @@ -28,7 +29,7 @@ enum { type_kind_enum, type_kind_first_basic = type_kind_i8, - type_kind_last_basic = type_kind_char, + type_kind_last_basic = type_kind_void, }; typedef struct type_t type_t; @@ -101,6 +102,7 @@ gb_read_only type_t type__isize = {type_kind_isize, s8_const_lit("isize"), sizeo gb_read_only type_t type__usize = {type_kind_usize, s8_const_lit("usize"), sizeof(usize)}; gb_read_only type_t type__int = {type_kind_int, s8_const_lit("int"), sizeof(int)}; gb_read_only type_t type__char = {type_kind_char, s8_const_lit("char"), sizeof(char)}; +gb_read_only type_t type__void = {type_kind_void, s8_const_lit("void")}; gb_read_only type_t type__s8_t = { type_kind_struct, s8_const_lit("s8_t"), sizeof(s8_t), .count = 2, .members = (type_member_t[]){ @@ -146,7 +148,8 @@ gb_read_only type_t type__sb8_t = { type_kind_struct, s8_const_lit("sb8_t"), siz {s8_const_lit("arena"), &POINTER(ma_arena_t), .offset = offsetof(sb8_t, arena)}, {s8_const_lit("first"), &POINTER(sb8_node_t), .offset = offsetof(sb8_t, first)}, {s8_const_lit("last"), &POINTER(sb8_node_t), .offset = offsetof(sb8_t, last)}, - {s8_const_lit("indent"), &type__i32, .offset = offsetof(sb8_t, first)}, + {s8_const_lit("indent"), &type__i32, .offset = offsetof(sb8_t, indent)}, + {s8_const_lit("user_data"), &POINTER(void), .offset = offsetof(sb8_t, user_data)}, } }; @@ -353,26 +356,3 @@ gb_read_only type_member_t members__r1i64_t[] = { {s8_const_lit("x1"), &type__i64, .offset = offsetof(r1i64_t, x1)}, }; gb_read_only DEFINE_STRUCT(r1i64_t); - -gb_read_only type_member_t members__lex_kind_t[] = { -#define X(KIND, STR, SIMPLE) {.name = s8_const_lit("lex_kind_" #KIND), .value = KIND}, - LEX_KIND_XLIST -#undef X -}; -DEFINE_ENUM(lex_kind_t); - -gb_read_only type_member_t members__lex_suffix_t[] = { -#define X(KIND) {.name = s8_const_lit(#KIND), .value = KIND}, - LEX_SUFFIX_XLIST -#undef X -}; -DEFINE_ENUM(lex_suffix_t); - -gb_read_only type_member_t members__log_level_t[] = { - {.name = s8_const_lit("log_level_debug"), .value = log_level_debug}, - {.name = s8_const_lit("log_level_info"), .value = log_level_info}, - {.name = s8_const_lit("log_level_warning"), .value = log_level_warning}, - {.name = s8_const_lit("log_level_error"), .value = log_level_error}, - {.name = s8_const_lit("log_level_fatal"), .value = log_level_fatal}, -}; -DEFINE_ENUM(log_level_t); \ No newline at end of file diff --git a/src/meta/meta_format.c b/src/meta/meta_format.c index 1bdf889..65d0510 100644 --- a/src/meta/meta_format.c +++ b/src/meta/meta_format.c @@ -16,6 +16,7 @@ typedef enum { X(ast_flag_type_array) \ X(ast_flag_dont_serialize) \ X(ast_flag_flag_enum) \ + X(ast_flag_row) \ #define X(NAME) NAME, @@ -38,7 +39,7 @@ struct ast_t { i64 integer; }; -fn s8_t s8_serial_ast_flag_t(ma_arena_t *arena, ast_flag_t flag) { +fn s8_t mt_serial_ast_flag(ma_arena_t *arena, ast_flag_t flag) { ma_temp_t scratch = ma_begin_scratch1(arena); sb8_t *sb = sb8_serial_begin(scratch.arena); #define X(NAME) if (flag & set_bit(NAME)) sb8_printf(sb, #NAME); @@ -162,35 +163,12 @@ fn i64 mt_eval_const_expr(ast_t *expr) { } } else { ma_temp_t scratch = ma_begin_scratch(); - parser_panicf(expr->pos, "unhandled ast in const expression evaluation: %S", s8_serial_ast_flag_t(scratch.arena, expr->flags)); + parser_panicf(expr->pos, "unhandled ast in const expression evaluation: %S", mt_serial_ast_flag(scratch.arena, expr->flags)); ma_end_scratch(scratch); } return 0; } -#define test_expr(x) do {\ - lex_array_t tokens = lex_tokens(scratch.arena, "parser_test", s8_lit(#x));\ - parser_t *par = parser_make(scratch.arena, tokens.data);\ - ast_t *expr = mt_parse_expr(par);\ - assert(expr != NULL);\ - i64 value = mt_eval_const_expr(expr);\ - assert(value == x);\ -} while (0) - -fn void run_parser_test() { - ma_temp_t scratch = ma_begin_scratch(); - test_expr(32 + 2 + 5 + 5); - test_expr(32 - 2 + 5 - 5); - test_expr(2 * 2 / 4 * 5 + 2 + 3); - test_expr(2 * 5 * 5 / 2 + 2 - 1 - 1); - test_expr(2 * (5 * 5) / 2 + (2 - 1 - 1)); - test_expr((2 * (5 * 5) / (2)) + (2 - 1 - 1)); - test_expr(10 % 3); - test_expr(10 % 3 + 4 || 2); - test_expr(10 % 3 + 4 || 2 && (4 && 2) || 3 && 1 || 0); - ma_end_scratch(scratch); -} - fn ast_t *mt_parse_struct_mem(parser_t *par, s8_t *name) { lex_t *type_name = parser_expect(par, lex_kind_ident); ast_t *type = mt_create_ast(par->arena, type_name, set_bit(ast_flag_type_name) | set_bit(ast_flag_string)); diff --git a/src/meta/meta_table_format.c b/src/meta/meta_table_format.c index 7cc2840..5300bb0 100644 --- a/src/meta/meta_table_format.c +++ b/src/meta/meta_table_format.c @@ -26,73 +26,67 @@ fn void mtt__parse_row(parser_t *par, ast_t *parent) { } } +/* +** DATA: +** { windows linux macos } +** { win32 unix unix } +** { msvc gcc clang } +** +** AST (represented in key value format): +** table { +** row { +** windows { win32 } +** linux { unix } +** macos { unix } +** } +** row { +** windows { msvc } +** linux { gcc } +** macos { clang } +** } +** } +*/ fn ast_t *mtt_parse(ma_arena_t *arena, char *file, s8_t code) { lex_array_t tokens = lex_tokens(arena, file, code); parser_t *par = parser_make(arena, tokens.data); ast_t *table = mt_create_ast(arena, par->at, 0); - mtt__parse_row(par, table); + ast_t *name_row = mt_create_ast(arena, par->at, set_bit(ast_flag_row)); + mtt__parse_row(par, name_row); while (par->at->kind != lex_kind_eof) { - mtt__parse_row(par, table->first); + ast_t *row = mt_create_ast(arena, par->at, set_bit(ast_flag_row)); + mt_ast_append(table, row); + for (ast_t *it = name_row->first; it; it = it->next) { + ast_t *name_copy = mt_create_ast(arena, par->at, it->flags); + mt_ast_append(row, name_copy); + name_copy->string = it->string; + name_copy->real = it->real; + name_copy->integer = it->integer; + } + mtt__parse_row(par, row->first); } return table; } -fn ast_t *mtt_find_row(ast_t *table, char *name) { - s8_t name_string = s8_from_char(name); - for (ast_t *it = table->first; it; it = it->next) { - if (s8_are_equal(it->string, name_string)) return it; +fn ast_t *mtt_get(ast_t *row, s8_t name_string) { + for (ast_t *it = row->first; it; it = it->next) { + if (s8_are_equal(it->string, name_string)) return it->first; } return NULL; } -typedef struct mtt_iter_t mtt_iter_t; -struct mtt_iter_t { - ma_arena_t *arena; - ast_t **first_row; - ast_t **it; - i32 len; -}; - -fn mtt_iter_t mtt_iterate(ma_arena_t *arena, ast_t *table) { - mtt_iter_t iter = {arena}; - iter.len = table->len; - iter.first_row = ma_push_array(arena, ast_t *, iter.len); - iter.it = ma_push_array(arena, ast_t *, iter.len); - i32 i = 0; - for (ast_t *it = table->first; it; it = it->next) { - iter.it[i] = it->first; - iter.first_row[i] = it; - i += 1; - } - return iter; +fn s8_t mtt_gets(ast_t *row, s8_t name_string) { + ast_t *n = mtt_get(row, name_string); + return n->string; } -fn s8_t mttsi(mtt_iter_t iter, i32 idx) { - assert(idx >= 0 && idx < iter.len); - return iter.it[idx]->string; -} - -fn ast_t *mtt(mtt_iter_t iter, char *name) { +fn ast_t *mtt(ast_t *row, char *name) { s8_t name_string = s8_from_char(name); - for (i32 i = 0; i < iter.len; i += 1) { - if (s8_are_equal(iter.first_row[i]->string, name_string)) return iter.it[i]; - } - return NULL; + return mtt_get(row, name_string); } -fn s8_t mtts(mtt_iter_t iter, char *name) { - return mtt(iter, name)->string; -} - -fn void mtt_advance(mtt_iter_t *iter) { - for (i32 i = 0; i < iter->len; i += 1) { - iter->it[i] = iter->it[i]->next; - } -} - -fn b32 mtt_is_valid(mtt_iter_t iter) { - b32 result = iter.it[0] != NULL; - return result; +fn s8_t mtts(ast_t *row, char *name) { + ast_t *v = mtt(row, name); + return v->string; } fn void mtt_serialb(sb8_t *c, sb8_t *h, ast_t *table, s8_t decl) { @@ -101,7 +95,7 @@ fn void mtt_serialb(sb8_t *c, sb8_t *h, ast_t *table, s8_t decl) { /////////////////////////////// // enum typedef sb8_printf(h, "typedef enum {\n"); - for (mtt_iter_t it = mtt_iterate(c->arena, table); mtt_is_valid(it); mtt_advance(&it)) { + for (ast_t *it = table->first; it; it = it->next) { sb8_printf(h, "%S_%S", decl, mtts(it, "name")); sb8_printf(h, ",\n"); } @@ -116,15 +110,16 @@ fn void mtt_serialb(sb8_t *c, sb8_t *h, ast_t *table, s8_t decl) { sb8_stmtf(c, ".members = (type_member_t[]){"); c->indent += 1; { - for (mtt_iter_t it = mtt_iterate(c->arena, table); mtt_is_valid(it); mtt_advance(&it)) { + for (ast_t *it = table->first; it; it = it->next) { sb8_stmtf(c, "{.name = s8_const_lit(\"%S_%S\"), .value = %S_%S},", decl, mtts(it, "name"), decl, mtts(it, "name")); } } c->indent -= 1; sb8_stmtf(c, "},"); - sb8_stmtf(c, ".count = %d,", mtt_find_row(table, "name")->len); + sb8_stmtf(c, ".count = %d,", table->len); } c->indent -= 1; sb8_stmtf(c, "};"); } + diff --git a/src/ui/ui.meta.c b/src/ui/ui.meta.c index 76ec47e..c94b7ee 100644 --- a/src/ui/ui.meta.c +++ b/src/ui/ui.meta.c @@ -1,5 +1,70 @@ -void mt_test_replace(ma_arena_t *arena) { - ast_t *keys = mtt_parse(arena, __FILE__, S8_CODE( +fn ast_t *mt_ast_string(ma_arena_t *arena, s8_t string) { + ast_t *n = mt_create_ast(arena, &lex_null, set_bit(ast_flag_string)); + n->string = string; + return n; +} + +fn ast_t *mt_kv(ma_arena_t *arena, s8_t key, s8_t value) { + ast_t *n = mt_ast_string(arena, key); + mt_ast_append(n, mt_ast_string(arena, value)); + return n; +} + +fn s8_t mt_templatize_string(ma_arena_t *arena, s8_t string, lex_array_t tokens, ast_t *n) { + ma_temp_t scratch = ma_begin_scratch1(arena); + sb8_t *sb = sb8_serial_begin(scratch.arena); + parser_t *par = parser_make(arena, tokens.data); + + for (i64 i = 0; i < string.len;) { + if (par->at->str != string.str + i) { + sb8_append(sb, s8(string.str + i, 1)); + i += 1; + continue; + } + + lex_t *token = parser_next(par); i += token->len; + if (token->kind == lex_kind_tag && char_is_alphanumeric(string.str[i])) { + lex_t *ident = parser_expect(par, lex_kind_ident); i += ident->len; + sb8_append(sb, mtt_gets(n, ident->string)); + + } else { + sb8_append(sb, token->string); + } + } + + s8_t result = sb8_serial_end(arena, sb); + ma_end_scratch(scratch); + return result; +} + +fn s8_t mt_print(ma_arena_t *arena, ast_t *n, s8_t string) { + ma_temp_t scratch = ma_begin_scratch1(arena); + lex_array_t tokens = lex_tokens(scratch.arena, "mt_print", string); + string = mt_templatize_string(arena, string, tokens, n); + ma_end_scratch(scratch); + return string; +} + +fn s8_t mt_printf(ma_arena_t *arena, ast_t *n, char *str, ...) { + ma_temp_t scratch = ma_begin_scratch1(arena); + S8_FMT(scratch.arena, str, string); + s8_t result = mt_print(arena, n, string); + ma_end_scratch(scratch); + return result; +} + +fn s8_t mt_sbprintf(sb8_t *sb, char *str, ...) { + assert(sb->user_data); + ma_temp_t scratch = ma_begin_scratch1(sb->arena); + S8_FMT(scratch.arena, str, string); + s8_t result = mt_print(sb->arena, (ast_t *)sb->user_data, string); + sb8_append(sb, result); + ma_end_scratch(scratch); + return result; +} + +fn void mt_test_replace(ma_arena_t *arena) { + ast_t *table = mtt_parse(arena, __FILE__, S8_CODE( // javascript filter out { name js1 js2 jf windows1 windows2 } { null XXX XXX 1 XXX XXX } @@ -72,7 +137,12 @@ void mt_test_replace(ma_arena_t *arena) { { page_up PageUp XXX 1 VK_INSERT XXX } { page_down PageDown XXX 1 VK_PRIOR XXX } )); - + sb8_t *sb = sb8_serial_begin(arena); + for (ast_t *it = table->first; it; it = it->next) { + sb->user_data = it; + mt_sbprintf(sb, "@name = @windows1 @windows2\n"); + } + debugf("%S", sb8_serial_end(arena, sb)); } void mt_ui(ma_arena_t *arena) { @@ -169,7 +239,7 @@ void mt_ui(ma_arena_t *arena) { /// variables_t vars = serial_vars_from_struct(it, type(mt_ui_stacks_t)); - sb8_tmplf(h, "typedef struct node_type node_type; struct node_type { value_type value; node_type *next; };", vars); + sb8_tmplf(h, "typedef struct $node_type $node_type; struct $node_type { value_type value; $node_type *next; };", vars); //// diff --git a/todo.txt b/todo.txt index 5418303..8109f2b 100644 --- a/todo.txt +++ b/todo.txt @@ -30,6 +30,7 @@ [x] remove dates and time from core [ ] meta [ ] prototype something like templates, readable string generation + [ ] mt_tag syntax // f32 value; mt_tag(min = 0, min = 10) // mt_tag(something) [x] search for python snippets and execute meta.py script on that file [x] simplify logging!!!! [x] somehow index properly the meta files and ignore generated files