From: Mart Lubbers Date: Fri, 12 Feb 2021 14:15:54 +0000 (+0100) Subject: strongly connected components X-Git-Url: https://git.martlubbers.net/?a=commitdiff_plain;h=d46412a29fa0ed4d3f892ce47c9d00f3c5c8218f;p=ccc.git strongly connected components --- diff --git a/Makefile b/Makefile index 949b3e8..fe1880a 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CFLAGS+=-Wall -Wextra -std=c99 -pedantic -D_XOPEN_SOURCE=700 -ggdb YFLAGS+=-d --locations -v --defines=parse.h LFLAGS+=--header-file=scan.h -OBJECTS:=scan.o parse.o ast.o util.o list.o type.o genc.o scc.o +OBJECTS:=scan.o parse.o ast.o util.o list.o type.o genc.o scc.o tarjan.o all: splc splc: $(OBJECTS) diff --git a/ast.c b/ast.c index 72af738..bb8a541 100644 --- a/ast.c +++ b/ast.c @@ -36,20 +36,23 @@ struct vardecl *vardecl(struct type *type, char *ident, struct expr *expr) res->expr = expr; return res; } - -struct decl *decl_fun(char *ident, struct list *args, struct list *atypes, +struct fundecl *fundecl(char *ident, struct list *args, struct list *atypes, struct type *rtype, struct list *body) +{ + struct fundecl *res = safe_malloc(sizeof(struct fundecl)); + res->ident = ident; + res->args = (char **)list_to_array(args, &res->nargs, true); + res->atypes = (struct type **)list_to_array(atypes, &res->natypes, true); + res->rtype = rtype; + res->body = (struct stmt **)list_to_array(body, &res->nbody, true); + return res; +} + +struct decl *decl_fun(struct fundecl *fundecl) { struct decl *res = safe_malloc(sizeof(struct decl)); res->type = dfundecl; - res->data.dfun.ident = ident; - res->data.dfun.args = (char **) - list_to_array(args, &res->data.dfun.nargs, true); - res->data.dfun.atypes = (struct type **) - list_to_array(atypes, &res->data.dfun.natypes, true); - res->data.dfun.rtype = rtype; - res->data.dfun.body = (struct stmt **) - list_to_array(body, &res->data.dfun.nbody, true); + res->data.dfun = fundecl; return res; } @@ -305,39 +308,46 @@ void vardecl_print(struct vardecl *decl, int indent, FILE *out) safe_fprintf(out, ";\n"); } +void fundecl_print(struct fundecl *decl, FILE *out) +{ + safe_fprintf(out, "%s (", decl->ident); + for (int i = 0; inargs; i++) { + safe_fprintf(out, "%s", decl->args[i]); + if (i < decl->nargs - 1) + safe_fprintf(out, ", "); + } + safe_fprintf(out, ")"); + if (decl->rtype != NULL) { + safe_fprintf(out, " :: "); + for (int i = 0; inatypes; i++) { + type_print(decl->atypes[i], out); + safe_fprintf(out, " "); + } + safe_fprintf(out, "-> "); + type_print(decl->rtype, out); + } + safe_fprintf(out, " {\n"); + for (int i = 0; inbody; i++) + stmt_print(decl->body[i], 1, out); + safe_fprintf(out, "}\n"); +} + void decl_print(struct decl *decl, FILE *out) { if (decl == NULL) return; switch(decl->type) { case dfundecl: - safe_fprintf(out, "%s (", decl->data.dfun.ident); - for (int i = 0; idata.dfun.nargs; i++) { - safe_fprintf(out, "%s", decl->data.dfun.args[i]); - if (i < decl->data.dfun.nargs - 1) - safe_fprintf(out, ", "); - } - safe_fprintf(out, ")"); - if (decl->data.dfun.rtype != NULL) { - safe_fprintf(out, " :: "); - for (int i = 0; idata.dfun.natypes; i++) { - type_print(decl->data.dfun.atypes[i], out); - safe_fprintf(out, " "); - } - safe_fprintf(out, "-> "); - type_print(decl->data.dfun.rtype, out); - } - safe_fprintf(out, " {\n"); - for (int i = 0; idata.dfun.nbody; i++) - stmt_print(decl->data.dfun.body[i], 1, out); - safe_fprintf(out, "}\n"); + fundecl_print(decl->data.dfun, out); break; case dvardecl: vardecl_print(decl->data.dvar, 0, out); break; - case dcomponent: - for (int i = 0; idata.dcomponent.ndecls; i++) - decl_print(decl, out); + case dcomp: + fprintf(out, "//<<data.dcomp.ndecls; i++) + fundecl_print(decl->data.dcomp.decls[i], out); + fprintf(out, "//>>>comp\n"); break; default: die("Unsupported decl node\n"); @@ -515,28 +525,34 @@ void vardecl_free(struct vardecl *decl) free(decl); } +void fundecl_free(struct fundecl *decl) +{ + free(decl->ident); + for (int i = 0; inargs; i++) + free(decl->args[i]); + free(decl->args); + for (int i = 0; inatypes; i++) + type_free(decl->atypes[i]); + free(decl->atypes); + type_free(decl->rtype); + for (int i = 0; inbody; i++) + stmt_free(decl->body[i]); + free(decl->body); + free(decl); +} + void decl_free(struct decl *decl) { if (decl == NULL) return; switch(decl->type) { - case dcomponent: - for (int i = 0; idata.dcomponent.ndecls; i++) - decl_free(decl->data.dcomponent.decls[i]); - free(decl->data.dcomponent.decls); + case dcomp: + for (int i = 0; idata.dcomp.ndecls; i++) + fundecl_free(decl->data.dcomp.decls[i]); + free(decl->data.dcomp.decls); break; case dfundecl: - free(decl->data.dfun.ident); - for (int i = 0; idata.dfun.nargs; i++) - free(decl->data.dfun.args[i]); - free(decl->data.dfun.args); - for (int i = 0; idata.dfun.natypes; i++) - type_free(decl->data.dfun.atypes[i]); - free(decl->data.dfun.atypes); - type_free(decl->data.dfun.rtype); - for (int i = 0; idata.dfun.nbody; i++) - stmt_free(decl->data.dfun.body[i]); - free(decl->data.dfun.body); + fundecl_free(decl->data.dfun); break; case dvardecl: vardecl_free(decl->data.dvar); diff --git a/ast.h b/ast.h index bea8b7c..db69333 100644 --- a/ast.h +++ b/ast.h @@ -21,6 +21,16 @@ struct vardecl { char *ident; struct expr *expr; }; +struct fundecl { + char *ident; + int nargs; + char **args; + int natypes; + struct type **atypes; + struct type *rtype; + int nbody; + struct stmt **body; +}; enum basictype {btbool, btchar, btint, btvoid}; struct type { @@ -37,22 +47,14 @@ struct type { }; struct decl { - enum {dcomponent, dfundecl, dvardecl} type; + //NOTE: DON'T CHANGE THIS ORDER + enum {dcomp, dvardecl, dfundecl} type; union { struct { int ndecls; - struct decl **decls; - } dcomponent; - struct { - char *ident; - int nargs; - char **args; - int natypes; - struct type **atypes; - struct type *rtype; - int nbody; - struct stmt **body; - } dfun; + struct fundecl **decls; + } dcomp; + struct fundecl *dfun; struct vardecl *dvar; } data; }; @@ -132,9 +134,10 @@ struct expr { struct ast *ast(struct list *decls); struct vardecl *vardecl(struct type *type, char *ident, struct expr *expr); - -struct decl *decl_fun(char *ident, struct list *args, struct list *atypes, +struct fundecl *fundecl(char *ident, struct list *args, struct list *atypes, struct type *rtype, struct list *body); + +struct decl *decl_fun(struct fundecl *fundecl); struct decl *decl_var(struct vardecl *vardecl); struct stmt *stmt_assign(char *ident, struct list *fields, struct expr *expr); @@ -162,6 +165,7 @@ struct type *type_var(char *ident); void ast_print(struct ast *, FILE *out); void vardecl_print(struct vardecl *decl, int indent, FILE *out); +void fundecl_print(struct fundecl *decl, FILE *out); void decl_print(struct decl *ast, FILE *out); void stmt_print(struct stmt *ast, int indent, FILE *out); void expr_print(struct expr *ast, FILE *out); @@ -169,6 +173,7 @@ void type_print(struct type *type, FILE *out); void ast_free(struct ast *); void vardecl_free(struct vardecl *decl); +void fundecl_free(struct fundecl *fundecl); void decl_free(struct decl *ast); void stmt_free(struct stmt *ast); void expr_free(struct expr *ast); diff --git a/genc.c b/genc.c index 617bcf6..5ebfa29 100644 --- a/genc.c +++ b/genc.c @@ -176,38 +176,43 @@ void stmt_genc(struct stmt *stmt, int indent, FILE *cout) } } +void fundecl_genc(struct fundecl *decl, FILE *cout) +{ + type_genc(decl->rtype, cout); + safe_fprintf(cout, "%s (", decl->ident); + for (int i = 0; inargs; i++) { + if (i < decl->natypes) + die("function with unmatched type\n"); + safe_fprintf(cout, "%s", decl->args[i]); + if (i < decl->nargs - 1) + safe_fprintf(cout, ", "); + } + safe_fprintf(cout, ") /*"); + if (decl->rtype != NULL) { + safe_fprintf(cout, " :: "); + for (int i = 0; inatypes; i++) { + type_print(decl->atypes[i], cout); + safe_fprintf(cout, " "); + } + safe_fprintf(cout, "-> "); + type_print(decl->rtype, cout); + } + safe_fprintf(cout, "*/ {\n"); + for (int i = 0; inbody; i++) + stmt_genc(decl->body[i], 1, cout); + safe_fprintf(cout, "}\n"); +} + void decl_genc(struct decl *decl, FILE *cout) { switch (decl->type) { - case dcomponent: + case dcomp: //TODO generate prototypes? - for (int i = 0; idata.dcomponent.ndecls; i++) - decl_genc(decl->data.dcomponent.decls[i], cout); + for (int i = 0; idata.dcomp.ndecls; i++) + fundecl_genc(decl->data.dcomp.decls[i], cout); break; case dfundecl: - type_genc(decl->data.dfun.rtype, cout); - safe_fprintf(cout, "%s (", decl->data.dfun.ident); - for (int i = 0; idata.dfun.nargs; i++) { - if (i < decl->data.dfun.natypes) - die("function with unmatched type\n"); - safe_fprintf(cout, "%s", decl->data.dfun.args[i]); - if (i < decl->data.dfun.nargs - 1) - safe_fprintf(cout, ", "); - } - safe_fprintf(cout, ") /*"); - if (decl->data.dfun.rtype != NULL) { - safe_fprintf(cout, " :: "); - for (int i = 0; idata.dfun.natypes; i++) { - type_print(decl->data.dfun.atypes[i], cout); - safe_fprintf(cout, " "); - } - safe_fprintf(cout, "-> "); - type_print(decl->data.dfun.rtype, cout); - } - safe_fprintf(cout, "*/ {\n"); - for (int i = 0; idata.dfun.nbody; i++) - stmt_genc(decl->data.dfun.body[i], 1, cout); - safe_fprintf(cout, "}\n"); + fundecl_genc(decl->data.dfun, cout); break; case dvardecl: vardecl_genc(decl->data.dvar, 0, cout); diff --git a/parse.y b/parse.y index 8a8dca7..29fa0ca 100644 --- a/parse.y +++ b/parse.y @@ -29,7 +29,7 @@ int yywrap() struct stmt *stmt; struct list *list; struct vardecl *vardecl; - struct decl *decl; + struct fundecl *fundecl; struct type *type; char *ident; } @@ -52,12 +52,12 @@ int yywrap() %right POWER %type start -%type fundecl %type expr %type args body decls fargs field fnargs nargs funtype bbody %type stmt %type type ftype %type vardecl +%type fundecl %% @@ -65,7 +65,7 @@ start : decls { *result = ast($1); } ; decls : /* empty */ { $$ = NULL; } | decls vardecl { $$ = list_cons(decl_var($2), $1); } - | decls fundecl { $$ = list_cons($2, $1); } + | decls fundecl { $$ = list_cons(decl_fun($2), $1); } ; vardecl : VAR IDENT ASSIGN expr SEMICOLON { $$ = vardecl(NULL, $2, $4); } @@ -73,9 +73,9 @@ vardecl ; fundecl : IDENT BOPEN args BCLOSE COPEN body CCLOSE - { $$ = decl_fun($1, $3, NULL, NULL, $6); } + { $$ = fundecl($1, $3, NULL, NULL, $6); } | IDENT BOPEN args BCLOSE CONS CONS funtype ARROW ftype COPEN body CCLOSE - { $$ = decl_fun($1, $3, $7, $9, $11); } + { $$ = fundecl($1, $3, $7, $9, $11); } ; funtype : /* empty */ { $$ = NULL; } diff --git a/scc.c b/scc.c index a3743e2..bf8a8b4 100644 --- a/scc.c +++ b/scc.c @@ -1,130 +1,160 @@ -#include -#include -#include +#include #include +#include "ast.h" #include "list.h" -#include "util.h" -#include "scc.h" +#include "tarjan.h" -struct node { - int lowlink; - int index; - bool onStack; - void *data; -}; - -int ptrcmp(const void *l, const void *r) +int iddeclcmp(const void *l, const void *r) { - return ((ptrdiff_t)((struct node *)l)->data) - -((ptrdiff_t)((struct node *)r)->data); + return strcmp((char *)l, (*(struct decl **)r)->data.dfun->ident); } -int nodecmp(const void *l, const void *r) +struct list *edges_expr(int ndecls, struct decl **decls, void *parent, + struct expr *expr, struct list *l) { - return ((ptrdiff_t)l) -((ptrdiff_t)((struct node *)r)->data); + if (expr == NULL) + return l; + switch(expr->type) { + case ebinop: + l = edges_expr(ndecls, decls, parent, expr->data.ebinop.l, l); + l = edges_expr(ndecls, decls, parent, expr->data.ebinop.r, l); + break; + case ebool: + break; + case echar: + break; + case efuncall: + for(int i = 0; idata.efuncall.nargs; i++) + l = edges_expr(ndecls, decls, parent, + expr->data.efuncall.args[i], l); + struct decl **to = bsearch(expr->data.efuncall.ident, decls, + ndecls, sizeof(struct decl *), iddeclcmp); + if (to == NULL) { + fprintf(stderr, "calling an unknown function\n"); + } else { + struct edge *edge = safe_malloc(sizeof(struct edge)); + edge->from = parent; + edge->to = (void *)*to; + l = list_cons(edge, l); + } + break; + case eint: + break; + case eident: + break; + case enil: + break; + case etuple: + l = edges_expr(ndecls, decls, parent, + expr->data.etuple.left, l); + l = edges_expr(ndecls, decls, parent, + expr->data.etuple.right, l); + break; + case estring: + break; + case eunop: + l = edges_expr(ndecls, decls, parent, expr->data.eunop.l, l); + break; + default: + die("Unsupported expr node\n"); + } + return l; } -struct components *strongconnect(struct node *v, struct node **stack, int *sp, - int *index, int nedges, struct edge *edges, struct components *components) +struct list *edges_stmt(int ndecls, struct decl **decls, void *parent, + struct stmt *stmt, struct list *l) { - struct node *w; - v->index = *index; - v->lowlink = *index; - (*index)++; - stack[(*sp)++] = v; - v->onStack = true; - - for (int i = 0; iindex == -1) { - components = strongconnect(w, stack, sp, index, - nedges, edges, components); - } else if (w->onStack) { - v->lowlink = min(v->lowlink, w->index); - } + switch(stmt->type) { + case sassign: + l = edges_expr(ndecls, decls, parent, + stmt->data.sassign.expr, l); + break; + case sif: + l = edges_expr(ndecls, decls, parent, stmt->data.sif.pred, l); + for (int i = 0; idata.sif.nthen; i++) + l = edges_stmt(ndecls, decls, parent, + stmt->data.sif.then[i], l); + for (int i = 0; idata.sif.nels; i++) + l = edges_stmt(ndecls, decls, parent, + stmt->data.sif.els[i], l); + break; + case sreturn: + l = edges_expr(ndecls, decls, parent, stmt->data.sreturn, l); + break; + case sexpr: + l = edges_expr(ndecls, decls, parent, stmt->data.sexpr, l); + break; + case svardecl: + l = edges_expr(ndecls, decls, parent, + stmt->data.svardecl->expr, l); + break; + case swhile: + l = edges_expr(ndecls, decls, parent, + stmt->data.swhile.pred, l); + for (int i = 0; idata.swhile.nbody; i++) + l = edges_stmt(ndecls, decls, parent, + stmt->data.swhile.body[i], l); + break; + default: + die("Unsupported stmt node\n"); } + return l; +} - if (v->lowlink == v->index) { - struct list *res = NULL; - do { - w = stack[--*sp]; - w->onStack = false; - res = list_cons(w->data, res); - } while (w != v); - struct components *ng = safe_malloc(sizeof(struct components)); - ng->next = components; - ng->nodes = list_to_array(res, &ng->nnodes, false); - components = ng; - } - return components; +int declcmp(const void *l, const void *r) +{ + return (*(struct decl **)l)->type - (*(struct decl **)r)->type; } -struct components *scc(int nnodes, void **nodedata, int nedges, struct edge *edgedata) +struct ast *ast_scc(struct ast *ast) { - struct components *res = NULL; - struct node *nodes = safe_malloc(nnodes*sizeof(struct node)); - for (int i = 0; idecls, ast->ndecls, sizeof(struct decl *), declcmp); + //Index of the first function + int ffun; + for (ffun = 0; ffunndecls; ffun++) + if (ast->decls[ffun]->type == dfundecl) + break; + //Number of functions + int nfun = ast->ndecls-ffun; - struct edge *edges = safe_malloc(nedges*sizeof(struct edge)); - for (int i = 0; idecls+ffun; + struct list *edges = NULL; + for (int i = 0; idata.dfun->nbody; j++) + edges = edges_stmt(nfun, fundecls, fundecls[i], + fundecls[i]->data.dfun->body[j], edges); + int nedges; + struct edge **edgedata = (struct edge **) + list_to_array(edges, &nedges, false); + + // Do tarjan's and convert back into the declaration list + struct components *cs = scc(nfun, (void **)fundecls, nedges, edgedata); + int i = ffun; + FOREACHCOMP(c, cs) { + struct decl *d = safe_malloc(sizeof(struct decl)); + if (c->nnodes > 1) { + d->type = dcomp; + d->data.dcomp.ndecls = c->nnodes; + d->data.dcomp.decls = safe_malloc( + c->nnodes*sizeof(struct fundecl *)); + for (int i = 0; innodes; i++) + d->data.dcomp.decls[i] = + ((struct decl *)c->nodes[i])->data.dfun; + } else { + d->type = dfundecl; + d->data.dfun = ((struct decl *)c->nodes[0])->data.dfun; } - edges[i] = (struct edge){.from=from, .to=to}; + ast->decls[i++] = d; } + ast->ndecls = i; - struct node **stack = safe_malloc(nnodes*sizeof(struct node *)); - int sp = 0; - int index = 0; - for (int i = 0; i < nnodes; i++) - if (nodes[i].index == -1) - res = strongconnect(&nodes[i], stack, &sp, &index, - nedges, edges, res); -end: - free(stack); - free(nodes); - free(edges); - return res; -} - -void components_free(struct components *cs, void (*freefun)(void *)) -{ - while (cs != NULL) { - if (freefun != NULL) - for (int i = 0; innodes; i++) - freefun(cs->nodes[i]); - free(cs->nodes); - struct components *t = cs->next; - free(cs); - cs = t; - } + //Cleanup + for (int i = 0; innodes; i++) -// fprintf(stderr, "%d, ", c->nodes[i]); -// fprintf(stderr, "\n"); -// } -// components_free(cs, NULL); -//} diff --git a/scc.h b/scc.h index 2392556..919e440 100644 --- a/scc.h +++ b/scc.h @@ -1,37 +1,9 @@ #ifndef SCC_H #define SCC_H -struct edge { - void *from; - void *to; -}; +#include "ast.h" -struct components { - int nnodes; - void **nodes; - struct components *next; -}; -#define FOREACHCOMP(x, l) for(struct components *x = l; x != NULL; x = x->next) - -/** - * Calculate the strongly connected components using Tarjan's algorithm: - * en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm - * - * Returns NULL when there are invalid edges - * - * @param number of nodes - * @param data of the nodes - * @param number of edges - * @param data of edges - */ -struct components *scc(int nnodes, void **nodedata, int nedges, struct edge *edgedata); - -/** - * Free a list of components - * - * @param cs components - * @param freefun function to free the data with, if NULL, data isn't freed - */ -void components_free(struct components *cs, void (*freefun)(void *)); +// Split up the AST in strongly connected components +struct ast *ast_scc(struct ast *ast); #endif diff --git a/splc.c b/splc.c index bee929a..aeb2e89 100644 --- a/splc.c +++ b/splc.c @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) free(cfile); switch(lang) { case langc: - genc(result, cout); +// genc(result, cout); break; default: die("unsupported language\n"); diff --git a/tarjan.c b/tarjan.c new file mode 100644 index 0000000..5ac7e2d --- /dev/null +++ b/tarjan.c @@ -0,0 +1,131 @@ +#include +#include + +#include "util.h" + +struct edge { + void *from; + void *to; +}; + +struct components { + int nnodes; + void **nodes; + struct components *next; +}; + +struct node { + int lowlink; + int index; + bool onStack; + void *data; +}; + +static int ptrcmp(const void *l, const void *r) +{ + return (ptrdiff_t)((struct node *)l)->data + - (ptrdiff_t)((struct node *)r)->data; +} + +static int nodecmp(const void *l, const void *r) +{ + return (ptrdiff_t)l -(ptrdiff_t)((struct node *)r)->data; +} + +struct components *strongconnect(struct node *v, struct node **stack, int *sp, + int *index, int nedges, struct edge *edges, + struct components *res, struct components **tail) +{ + struct node *w; + v->index = *index; + v->lowlink = *index; + (*index)++; + stack[(*sp)++] = v; + v->onStack = true; + + for (int i = 0; iindex == -1) + res = strongconnect(w, stack, sp, index, + nedges, edges, res, tail); + else if (w->onStack) + v->lowlink = min(v->lowlink, w->index); + } + + if (v->lowlink == v->index) { + struct components *ng = safe_malloc(sizeof(struct components)); + if (*tail == NULL) + res = ng; + else + (*tail)->next = ng; + *tail = ng; + ng->next = NULL; + ng->nnodes = *sp; + do { + w = stack[--(*sp)]; + w->onStack = false; + } while (w != v); + ng->nnodes -= *sp; + ng->nodes = safe_malloc(ng->nnodes*sizeof(void *)); + for (int i = 0; innodes; i++) + ng->nodes[i] = stack[*sp+i]->data; + } + return res; +} + +#define nsearch(key)\ + bsearch(key, nodes, nnodes, sizeof(struct node), nodecmp);\ + if (key == NULL) {\ + fprintf(stderr, "edge references unknown node\n");\ + goto end;\ + }\ + +struct components *scc(int nnodes, void **nodedata, int nedges, struct edge **edgedata) +{ + //Create nodes + struct node *nodes = safe_malloc(nnodes*sizeof(struct node)); + for (int i = 0; ifrom); + struct node *to = nsearch(edgedata[i]->to); + edges[i] = (struct edge){.from=from, .to=to}; + } + + //Tarjan's + struct components *res = NULL, *tail = NULL; + struct node **stack = safe_malloc(nnodes*sizeof(struct node *)); + int sp = 0; + int index = 0; + for (int i = 0; i < nnodes; i++) { + if (nodes[i].index == -1) + res = strongconnect(&nodes[i], stack, &sp, &index, + nedges, edges, res, &tail); + } + free(stack); +end: + free(nodes); + free(edges); + return res; +} + +void components_free(struct components *cs, void (*freefun)(void *)) +{ + while (cs != NULL) { + if (freefun != NULL) + for (int i = 0; innodes; i++) + freefun(cs->nodes[i]); + free(cs->nodes); + struct components *t = cs->next; + free(cs); + cs = t; + } +} diff --git a/tarjan.h b/tarjan.h new file mode 100644 index 0000000..b2a8fbb --- /dev/null +++ b/tarjan.h @@ -0,0 +1,38 @@ +#ifndef SCC_H +#define SCC_H + +struct edge { + void *from; + void *to; +}; + +struct components { + int nnodes; + void **nodes; + struct components *next; +}; + +#define FOREACHCOMP(x, l) for(struct components *x = l; x != NULL; x = x->next) + +/** + * Calculate the strongly connected components using Tarjan's algorithm: + * en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + * + * Returns NULL when there are invalid edges + * + * @param number of nodes + * @param data of the nodes + * @param number of edges + * @param data of edges + */ +struct components *scc(int nn, void **nodes, int ne, struct edge **edges); + +/** + * Free a list of components + * + * @param cs components + * @param freefun function to free the data with, if NULL, data isn't freed + */ +void components_free(struct components *cs, void (*freefun)(void *)); + +#endif diff --git a/type.c b/type.c index 3325de8..0cf22e1 100644 --- a/type.c +++ b/type.c @@ -1,3 +1,8 @@ +#include +#include + +#include "list.h" +#include "scc.h" #include "ast.h" void type_error(const char *msg, ...) @@ -37,7 +42,7 @@ struct vardecl *type_vardecl(struct vardecl *vardecl) struct decl *type_decl(struct decl *decl) { switch (decl->type) { - case dcomponent: + case dcomp: fprintf(stderr, "type_decl:component unsupported\n"); break; case dfundecl: @@ -52,6 +57,8 @@ struct decl *type_decl(struct decl *decl) struct ast *type(struct ast *ast) { + ast = ast_scc(ast); + for (int i = 0; indecls; i++) { if (ast->decls[i]->type == dvardecl) { //Check globals @@ -61,4 +68,3 @@ struct ast *type(struct ast *ast) } return ast; } -