implemented topological sorting for type resolution
This commit is contained in:
parent
e094049a0d
commit
597efe5791
3 changed files with 179 additions and 32 deletions
|
|
@ -1,13 +1,19 @@
|
||||||
import std;
|
import std;
|
||||||
|
|
||||||
struct {
|
struct b {
|
||||||
u32 a,
|
a b,
|
||||||
u32 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");
|
print("Hello world!\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
179
sema.c
179
sema.c
|
|
@ -1,8 +1,25 @@
|
||||||
#define STB_DS_IMPLEMENTATION
|
#define STB_DS_IMPLEMENTATION
|
||||||
#include "sema.h"
|
#include "sema.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
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)
|
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;
|
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) {
|
if (node->type == NODE_STRUCT || node->type == NODE_UNION) {
|
||||||
type *t = arena_alloc(s->allocator, sizeof(type));
|
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 = node->expr.structure.name;
|
||||||
t->data.structure.name_len = node->expr.structure.name_len;
|
t->data.structure.name_len = node->expr.structure.name_len;
|
||||||
t->data.structure.members = node->expr.structure.members;
|
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) {
|
shput(type_reg, name, t);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void analyze_unit(sema *s, ast_node *node)
|
static void analyze_unit(sema *s, ast_node *node)
|
||||||
{
|
{
|
||||||
ast_node *current = node;
|
ast_node *current = node;
|
||||||
while (current && current->type == NODE_UNIT) {
|
while (current && current->type == NODE_UNIT) {
|
||||||
if (analyze_type(s, current)) goto end;
|
order_type(s, current->expr.unit_node.expr);
|
||||||
end:
|
end:
|
||||||
current = current->expr.unit_node.next;
|
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)
|
sema *sema_init(parser *p, arena *a)
|
||||||
|
|
@ -55,6 +189,17 @@ sema *sema_init(parser *p, arena *a)
|
||||||
types = NULL;
|
types = NULL;
|
||||||
s->ast = p->ast;
|
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);
|
analyze_unit(s, s->ast);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
|
||||||
14
sema.h
14
sema.h
|
|
@ -8,14 +8,9 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TYPE_VOID,
|
TYPE_VOID,
|
||||||
TYPE_PTR,
|
TYPE_PTR,
|
||||||
TYPE_I8,
|
TYPE_FLOAT,
|
||||||
TYPE_I16,
|
TYPE_INTEGER,
|
||||||
TYPE_I32,
|
TYPE_UINTEGER,
|
||||||
TYPE_I64,
|
|
||||||
TYPE_U8,
|
|
||||||
TYPE_U16,
|
|
||||||
TYPE_U32,
|
|
||||||
TYPE_U64,
|
|
||||||
TYPE_STRUCT,
|
TYPE_STRUCT,
|
||||||
TYPE_UNION,
|
TYPE_UNION,
|
||||||
TYPE_ENUM,
|
TYPE_ENUM,
|
||||||
|
|
@ -24,6 +19,8 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct _type {
|
typedef struct _type {
|
||||||
type_tag tag;
|
type_tag tag;
|
||||||
|
usize size;
|
||||||
|
usize alignment;
|
||||||
union {
|
union {
|
||||||
u8 integer;
|
u8 integer;
|
||||||
u8 flt; // float
|
u8 flt; // float
|
||||||
|
|
@ -40,7 +37,6 @@ typedef struct _type {
|
||||||
struct {
|
struct {
|
||||||
char *name;
|
char *name;
|
||||||
usize name_len;
|
usize name_len;
|
||||||
usize alignment;
|
|
||||||
member *members;
|
member *members;
|
||||||
} structure;
|
} structure;
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue