new table format, templating mt_printf
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
@@ -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));
|
||||
|
||||
@@ -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, "};");
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
////
|
||||
|
||||
|
||||
1
todo.txt
1
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
|
||||
|
||||
Reference in New Issue
Block a user