meta refactorings

This commit is contained in:
Krzosa Karol
2025-01-20 11:00:33 +01:00
parent 6f53fa4db0
commit f221ccfcf9
10 changed files with 268 additions and 266 deletions

306
src/meta/meta_format.c Normal file
View File

@@ -0,0 +1,306 @@
typedef enum {
#define MT_AST_FLAG_XLIST \
X(ast_flag_null) \
X(ast_flag_string) \
X(ast_flag_integer) \
X(ast_flag_real) \
X(ast_flag_binary) \
X(ast_flag_enum) \
X(ast_flag_enum_member) \
X(ast_flag_struct) \
X(ast_flag_struct_member) \
X(ast_flag_var) \
X(ast_flag_type_name) \
X(ast_flag_type_pointer) \
X(ast_flag_type_array) \
X(ast_flag_dont_serialize) \
X(ast_flag_flag_enum) \
#define X(NAME) NAME,
MT_AST_FLAG_XLIST
#undef X
} ast_flag_t;
typedef struct ast_t ast_t;
struct ast_t {
ast_flag_t flags;
lex_t *pos;
ast_t *next;
ast_t *first;
ast_t *last;
i32 len;
s8_t string;
f64 real;
i64 integer;
};
fn s8_t s8_serial_ast_flag_t(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);
MT_AST_FLAG_XLIST
#undef X
s8_t result = sb8_serial_end(arena, sb);
ma_end_scratch(scratch);
return result;
}
fn ast_t *mt_create_ast(parser_t *par, lex_t *pos, ast_flag_t flags) {
ast_t *result = ma_push_type(par->arena, ast_t);
memset(result, 0, sizeof(ast_t));
result->flags = flags;
result->pos = pos;
return result;
}
fn void mt_ast_append(ast_t *parent, ast_t *node) {
SLLQ_APPEND(parent->first, parent->last, node);
parent->len += 1;
}
fn ast_t *mt_create_ast_binary(parser_t *par, lex_t *pos, ast_t *left, lex_kind_t op, ast_t *right) {
ast_t *result = mt_create_ast(par, pos, set_bit(ast_flag_string) | set_bit(ast_flag_binary) | set_bit(ast_flag_integer));
mt_ast_append(result, left);
mt_ast_append(result, right);
result->integer = op;
result->string = lex_kind_to_simple_s8(op);
return result;
}
fn ast_t *mt_parse_expr(parser_t *par);
fn ast_t *mt_parse_lit_expr(parser_t *par) {
lex_t *token = parser_next(par);
if (token->kind == lex_kind_integer) {
ast_t *result = mt_create_ast(par, token, set_bit(ast_flag_integer) | set_bit(ast_flag_string));
result->integer = token->integer;
result->string = token->string;
return result;
} else if (token->kind == lex_kind_real) {
ast_t *result = mt_create_ast(par, token, set_bit(ast_flag_real) | set_bit(ast_flag_string));
result->real = (double)token->real;
result->string = token->string;
return result;
} else if (token->kind == lex_kind_open_paren) {
ast_t *result = mt_parse_expr(par);
parser_expect(par, lex_kind_close_paren);
return result;
} else {
parser_panicf(token, "got invalid token of kind: %S while parsing expression", lex_kind_to_s8(token->kind));
return 0;
}
}
fn ast_t *mt_parse_mul_expr(parser_t *par) {
ast_t *left = mt_parse_lit_expr(par);
while (par->at->kind == lex_kind_multiply || par->at->kind == lex_kind_divide || par->at->kind == lex_kind_modulo) {
lex_t *op = parser_next(par);
left = mt_create_ast_binary(par, op, left, op->kind, mt_parse_lit_expr(par));
}
return left;
}
fn ast_t *mt_parse_add_expr(parser_t *par) {
ast_t *left = mt_parse_mul_expr(par);
while (par->at->kind == lex_kind_plus || par->at->kind == lex_kind_minus) {
lex_t *op = parser_next(par);
left = mt_create_ast_binary(par, op, left, op->kind, mt_parse_lit_expr(par));
}
return left;
}
fn ast_t *mt_parse_logical_and_expr(parser_t *par) {
ast_t *left = mt_parse_add_expr(par);
while (par->at->kind == lex_kind_or) {
lex_t *op = parser_next(par);
left = mt_create_ast_binary(par, op, left, op->kind, mt_parse_lit_expr(par));
}
return left;
}
fn ast_t *parse_logical_or_expr(parser_t *par) {
ast_t *left = mt_parse_logical_and_expr(par);
while (par->at->kind == lex_kind_or) {
lex_t *op = parser_next(par);
left = mt_create_ast_binary(par, op, left, op->kind, mt_parse_lit_expr(par));
}
return left;
}
fn ast_t *mt_parse_expr(parser_t *par) {
ast_t *expr = parse_logical_or_expr(par);
return expr;
}
fn ast_t *mt_parse_expr_str(ma_arena_t *arena, char *file_name, s8_t stream) {
lex_array_t tokens = lex_tokens(arena, file_name, stream);
parser_t *par = parser_make(arena, tokens.data);
ast_t *result = mt_parse_expr(par);
return result;
}
fn i64 mt_eval_const_expr(ast_t *expr) {
if (expr->flags & set_bit(ast_flag_integer)) {
return expr->integer;
} else if (expr->flags & set_bit(ast_flag_binary)) {
assert(expr->first != expr->last);
i64 left = mt_eval_const_expr(expr->first);
i64 right = mt_eval_const_expr(expr->last);
switch(expr->integer) {
case lex_kind_plus: return left + right;
case lex_kind_minus: return left - right;
case lex_kind_multiply: return left * right;
case lex_kind_divide: return left / right;
case lex_kind_modulo: return left % right;
case lex_kind_and: return left && right;
case lex_kind_or: return left || right;
default: parser_panicf(expr->pos, "unhandled binary operator: %S", lex_kind_to_s8(expr->integer));
}
} 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));
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, type_name, set_bit(ast_flag_type_name) | set_bit(ast_flag_string));
type->string = type_name->string;
while (parser_match(par, lex_kind_multiply)) {
ast_t *pointer = mt_create_ast(par, par->at, set_bit(ast_flag_type_pointer) | set_bit(ast_flag_string));
mt_ast_append(pointer, type);
pointer->string = s8_printf(par->arena, "%S*", type->string);
type = pointer;
}
*name = parser_expect(par, lex_kind_ident)->string;
while (parser_match(par, lex_kind_open_bracket)) {
ast_t *array = mt_create_ast(par, par->at, set_bit(ast_flag_type_array) | set_bit(ast_flag_string));
mt_ast_append(array, type);
lex_t *num = parser_match(par, lex_kind_integer);
if (num) {
array->flags |= set_bit(ast_flag_integer);
array->integer = (int)num->integer;
array->string = s8_printf(par->arena, "%S[%d]", type->string, (int)array->integer);
} else {
array->string = s8_printf(par->arena, "%S[]", type->string);
}
parser_expect(par, lex_kind_close_bracket);
type = array;
}
return type;
}
fn ast_t *mt_parse_decls(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 *result = mt_create_ast(par, par->at, set_bit(ast_flag_string));
result->string = s8_copy_char(arena, file);
for (;par->at->kind != lex_kind_eof;) {
lex_t *pos = par->at;
b32 matched = false;
b32 is_typedef = !!parser_matchi(par, s8_lit("typedef"));
if (is_typedef && parser_matchi(par, s8_lit("enum"))) {
ast_t *n = mt_create_ast(par, pos, set_bit(ast_flag_string) | set_bit(ast_flag_enum));
mt_ast_append(result, n);
parser_expect(par, lex_kind_open_brace);
while (par->at->kind == lex_kind_ident) {
lex_t *val = parser_expect(par, lex_kind_ident);
ast_t *mem = mt_create_ast(par, val, set_bit(ast_flag_enum_member) | set_bit(ast_flag_string));
mem->string = val->string;
mt_ast_append(n, mem);
// if (parser_match(par, lex_kind_assign)) {
// mt_parse_expr();
// }
if (!parser_match(par, lex_kind_comma)) break;
}
parser_expect(par, lex_kind_close_brace);
n->string = parser_expect(par, lex_kind_ident)->string;
parser_expect(par, lex_kind_semicolon);
if (parser_matchi(par, s8_lit("mt_tag")) && parser_expect(par, lex_kind_open_paren)) {
if (parser_expecti(par, s8_lit("flags"))) {
n->flags |= set_bit(ast_flag_flag_enum);
}
parser_expect(par, lex_kind_close_paren);
}
matched = true;
}
if (is_typedef && parser_matchi(par, s8_lit("struct"))) {
parser_match(par, lex_kind_ident);
parser_match(par, lex_kind_ident);
parser_match(par, lex_kind_semicolon);
matched = true;
}
if (parser_matchi(par, s8_lit("struct"))) {
ast_t *n = mt_create_ast(par, pos, set_bit(ast_flag_string) | set_bit(ast_flag_struct));
mt_ast_append(result, n);
n->string = parser_expect(par, lex_kind_ident)->string;
parser_expect(par, lex_kind_open_brace);
while (par->at->kind != lex_kind_close_brace) {
ast_t *mem = mt_create_ast(par, par->at, set_bit(ast_flag_struct_member) | set_bit(ast_flag_var) | set_bit(ast_flag_string));
mt_ast_append(n, mem);
ast_t *type = mt_parse_struct_mem(par, &mem->string);
mt_ast_append(mem, type);
parser_expect(par, lex_kind_semicolon);
if (parser_matchi(par, s8_lit("mt_tag")) && parser_expect(par, lex_kind_open_paren)) {
if (parser_expecti(par, s8_lit("dont_serialize"))) {
n->flags |= set_bit(ast_flag_dont_serialize);
}
parser_expect(par, lex_kind_close_paren);
}
}
parser_expect(par, lex_kind_close_brace);
parser_expect(par, lex_kind_semicolon);
matched = true;
}
if (!matched) parser_next(par);
}
return result;
}