From 597efe579140104a9a2b5653e86d050f7dde757a Mon Sep 17 00:00:00 2001 From: Lorenzo Torres Date: Thu, 4 Dec 2025 20:43:48 +0100 Subject: [PATCH] implemented topological sorting for type resolution --- examples/hello_world.l | 18 +++-- sema.c | 179 +++++++++++++++++++++++++++++++++++++---- sema.h | 14 ++-- 3 files changed, 179 insertions(+), 32 deletions(-) diff --git a/examples/hello_world.l b/examples/hello_world.l index 8eae4f8..52e3232 100644 --- a/examples/hello_world.l +++ b/examples/hello_world.l @@ -1,13 +1,19 @@ import std; -struct { - u32 a, - u32 b, -}; +struct b { + a b, +} -i32 main(usize argc, [*u8] argv) +struct c { + u32 b, +} + +struct a { + c b, +} + +i32 main(i32 argc, [*[*u8]] argv) { print("Hello world!\n"); - return 0; } diff --git a/sema.c b/sema.c index 729d720..e48ee5a 100644 --- a/sema.c +++ b/sema.c @@ -1,8 +1,25 @@ #define STB_DS_IMPLEMENTATION #include "sema.h" #include +#include +#include -static struct { char *key; type *value; } *types; +typedef struct _res_node { + struct _res_node **in; + struct _res_node **out; + type *value; +} res_node; + +typedef struct { res_node node; bool complete; } pair; + +static struct { char *key; pair *value; } *types; +static struct { char *key; type *value; } *type_reg; + +/* Print the error message and sync the parser. */ +static void error(ast_node *n, char *msg) +{ + printf("\x1b[31m\x1b[1merror\x1b[0m\x1b[1m:%ld:%ld:\x1b[0m %s\n", n->position.row, n->position.column, msg); +} static char *intern_string(sema *s, char *str, usize len) { @@ -12,7 +29,38 @@ static char *intern_string(sema *s, char *str, usize len) return ptr; } -static type *analyze_type(sema *s, ast_node *node) +static type *create_integer(sema *s, char *name, u8 bits, bool sign) +{ + type *t = arena_alloc(s->allocator, sizeof(type)); + t->tag = sign ? TYPE_INTEGER : TYPE_UINTEGER; + t->data.integer = bits; + + pair *graph_node = arena_alloc(s->allocator, sizeof(pair)); + graph_node->node.value = t; + graph_node->node.in = NULL; + graph_node->node.out = NULL; + + shput(types, name, graph_node); + return t; +} + +static type *create_float(sema *s, char *name, u8 bits) +{ + type *t = arena_alloc(s->allocator, sizeof(type)); + t->tag = TYPE_FLOAT; + t->data.flt = bits; + + pair *graph_node = arena_alloc(s->allocator, sizeof(pair)); + graph_node->node.value = t; + graph_node->node.in = NULL; + graph_node->node.out = NULL; + + shput(types, name, graph_node); + return t; +} + +/* https://en.wikipedia.org/wiki/Topological_sorting */ +static void order_type(sema *s, ast_node *node) { if (node->type == NODE_STRUCT || node->type == NODE_UNION) { type *t = arena_alloc(s->allocator, sizeof(type)); @@ -20,32 +68,118 @@ static type *analyze_type(sema *s, ast_node *node) t->data.structure.name = node->expr.structure.name; t->data.structure.name_len = node->expr.structure.name_len; t->data.structure.members = node->expr.structure.members; - shput(types, intern_string(s, t->data.structure.name, t->data.structure.name_len), t); - return t; + + pair *graph_node = shget(types, intern_string(s, node->expr.structure.name, node->expr.structure.name_len)); + + if (!graph_node) { + graph_node = arena_alloc(s->allocator, sizeof(pair)); + graph_node->node.value = t; + graph_node->node.in = NULL; + graph_node->node.out = NULL; + } else { + graph_node->complete = true; + } + + member *m = t->data.structure.members; + while (m) { + char *name = intern_string(s, m->name, m->name_len); + pair *p = shget(types, name); + if (!p) { + p = arena_alloc(s->allocator, sizeof(pair)); + p->complete = false; + p->node.out = NULL; + p->node.in = NULL; + shput(types, name, p); + } + + arrput(p->node.in, &graph_node->node); + arrput(graph_node->node.out, &p->node); + + m = m->next; + } + + shput(types, intern_string(s, t->data.structure.name, t->data.structure.name_len), graph_node); + } +} + +static void register_struct(sema *s, char *name, type *t) +{ + +} + +static void register_union(sema *s, char *name, type *t) +{ + +} + +static void register_type(sema *s, char *name, type *t) +{ + switch (t->tag) { + case TYPE_INTEGER: + case TYPE_UINTEGER: + t->size = t->data.integer / 8; + t->alignment = t->data.integer / 8; + break; + case TYPE_PTR: + t->size = 8; + t->alignment = 8; + break; + case TYPE_FLOAT: + t->size = t->data.flt / 8; + t->alignment = t->data.flt / 8; + break; + case TYPE_STRUCT: + register_struct(s, name, t); + break; } - if (node->type == NODE_ENUM) { - type *t = arena_alloc(s->allocator, sizeof(type)); - t->tag = TYPE_ENUM; - - t->data.enm.name = node->expr.enm.name; - t->data.enm.name_len = node->expr.enm.name_len; - t->data.enm.variants = node->expr.enm.variants; - shput(types, intern_string(s, t->data.enm.name, t->data.enm.name_len), t); - return t; - } - - return NULL; + shput(type_reg, name, t); } static void analyze_unit(sema *s, ast_node *node) { ast_node *current = node; while (current && current->type == NODE_UNIT) { - if (analyze_type(s, current)) goto end; + order_type(s, current->expr.unit_node.expr); end: current = current->expr.unit_node.next; } + + res_node **nodes = NULL; + res_node **ordered = NULL; + for (int i=0; i < shlen(types); i++) { + if (arrlen(types[i].value->node.in) == 0) { + arrput(nodes, &types[i].value->node); + } + } + + while (arrlen(nodes) > 0) { + res_node *n = nodes[0]; + arrdel(nodes, 0); + arrput(ordered, n); + while (arrlen(n->out) > 0) { + res_node *dep = n->out[0]; + arrdel(n->out, 0); + + for (int j=0; j < arrlen(dep->in); j++) { + if (dep->in[j] == n) { + arrdel(dep->in, j); + } + } + + if (arrlen(dep->in) == 0) { + arrput(nodes, dep); + } + } + } + + for (int i=0; i < arrlen(ordered); i++) { + type *t = ordered[i]->value; + if (t && (t->tag == TYPE_STRUCT || t->tag == TYPE_UNION)) { + char *name = intern_string(s, t->data.structure.name, t->data.structure.name_len); + register_type(s, name, t); + } + } } sema *sema_init(parser *p, arena *a) @@ -55,6 +189,17 @@ sema *sema_init(parser *p, arena *a) types = NULL; s->ast = p->ast; + register_type(s, "u8", create_integer(s, "u8", 8, false)); + register_type(s, "u16", create_integer(s, "u16", 16, false)); + register_type(s, "u32", create_integer(s, "u32", 32, false)); + register_type(s, "u64", create_integer(s, "u64", 64, false)); + register_type(s, "i8", create_integer(s, "i8", 8, true)); + register_type(s, "i16", create_integer(s, "i16", 16, true)); + register_type(s, "i32", create_integer(s, "i32", 32, true)); + register_type(s, "i64", create_integer(s, "i64", 64, true)); + register_type(s, "f32", create_float(s, "f32", 32)); + register_type(s, "f64", create_float(s, "f64", 64)); + analyze_unit(s, s->ast); return s; diff --git a/sema.h b/sema.h index fc67ea7..116fb53 100644 --- a/sema.h +++ b/sema.h @@ -8,14 +8,9 @@ typedef enum { TYPE_VOID, TYPE_PTR, - TYPE_I8, - TYPE_I16, - TYPE_I32, - TYPE_I64, - TYPE_U8, - TYPE_U16, - TYPE_U32, - TYPE_U64, + TYPE_FLOAT, + TYPE_INTEGER, + TYPE_UINTEGER, TYPE_STRUCT, TYPE_UNION, TYPE_ENUM, @@ -24,6 +19,8 @@ typedef enum { typedef struct _type { type_tag tag; + usize size; + usize alignment; union { u8 integer; u8 flt; // float @@ -40,7 +37,6 @@ typedef struct _type { struct { char *name; usize name_len; - usize alignment; member *members; } structure; struct {