YFLAGS+=-d --locations -v --defines=parse.h
LFLAGS+=--header-file=scan.h
-OBJECTS:=scan.o parse.o ast.o util.o type.o genc.o
+OBJECTS:=scan.o parse.o ast.o util.o list.o type.o genc.o scc.o
all: splc
splc: $(OBJECTS)
if (ast == NULL)
return;
for (int i = 0; i<ast->ndecls; i++)
- decl_print(ast->decls[i], 0, out);
+ decl_print(ast->decls[i], out);
}
void vardecl_print(struct vardecl *decl, int indent, FILE *out)
safe_fprintf(out, ";\n");
}
-void decl_print(struct decl *decl, int indent, FILE *out)
+void decl_print(struct decl *decl, FILE *out)
{
if (decl == NULL)
return;
switch(decl->type) {
case dfundecl:
- pindent(indent, out);
safe_fprintf(out, "%s (", decl->data.dfun.ident);
for (int i = 0; i<decl->data.dfun.nargs; i++) {
safe_fprintf(out, "%s", decl->data.dfun.args[i]);
}
safe_fprintf(out, " {\n");
for (int i = 0; i<decl->data.dfun.nbody; i++)
- stmt_print(decl->data.dfun.body[i], indent+1, out);
- pindent(indent, out);
+ stmt_print(decl->data.dfun.body[i], 1, out);
safe_fprintf(out, "}\n");
break;
case dvardecl:
- vardecl_print(decl->data.dvar, indent, out);
+ vardecl_print(decl->data.dvar, 0, out);
+ break;
+ case dcomponent:
+ for (int i = 0; i<decl->data.dcomponent.ndecls; i++)
+ decl_print(decl, out);
break;
default:
die("Unsupported decl node\n");
if (decl == NULL)
return;
switch(decl->type) {
+ case dcomponent:
+ for (int i = 0; i<decl->data.dcomponent.ndecls; i++)
+ decl_free(decl->data.dcomponent.decls[i]);
+ free(decl->data.dcomponent.decls);
+ break;
case dfundecl:
free(decl->data.dfun.ident);
for (int i = 0; i<decl->data.dfun.nargs; i++)
};
struct decl {
- enum {dfundecl, dvardecl} type;
+ enum {dcomponent, dfundecl, dvardecl} type;
union {
+ struct {
+ int ndecls;
+ struct decl **decls;
+ } dcomponent;
struct {
char *ident;
int nargs;
void ast_print(struct ast *, FILE *out);
void vardecl_print(struct vardecl *decl, int indent, FILE *out);
-void decl_print(struct decl *ast, int indent, 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);
void type_print(struct type *type, FILE *out);
#include "ast.h"
-#define gdie(msg) { fprintf(stderr, "%s", msg); return 1; }
-
-int expr_genc(struct expr *expr, FILE *cout);
+void expr_genc(struct expr *expr, FILE *cout);
void binop_genc(char *fun, struct expr *l, struct expr *r, FILE *cout)
{
safe_fprintf(cout, ")");
}
-int expr_genc(struct expr *expr, FILE *cout)
+void expr_genc(struct expr *expr, FILE *cout)
{
- int r = 0;
char buf[] = "\\x55";
if (expr == NULL)
- return 0;
+ return;
switch(expr->type) {
case ebinop:
if (expr->type == ebinop && expr->data.ebinop.op == cons) {
default:
die("Unknown expression node\n");
}
- return r;
}
-int type_genc(struct type *type, FILE *cout)
+void type_genc(struct type *type, FILE *cout)
{
- if (type == NULL) {
+ if (type == NULL)
+ die("unresolved var type\n");
+ switch(type->type) {
+ case tbasic:
fprintf(cout, "WORD ");
- } else {
- switch(type->type) {
- case tbasic:
- fprintf(cout, "WORD ");
- break;
- case tlist:
- fprintf(cout, "struct splc_list *");
- break;
- case ttuple:
- fprintf(cout, "struct splc_tuple *");
- break;
- case tvar:
- fprintf(cout, "WORD ");
- break;
- default:
- die("Unsupported type node\n");
- }
+ break;
+ case tlist:
+ fprintf(cout, "struct splc_list *");
+ break;
+ case ttuple:
+ fprintf(cout, "struct splc_tuple *");
+ break;
+ case tvar:
+ fprintf(cout, "WORD ");
+ break;
+ default:
+ die("Unsupported type node\n");
}
- return 0;
}
-int vardecl_genc(struct vardecl *vardecl, int indent, FILE *cout)
+void vardecl_genc(struct vardecl *vardecl, int indent, FILE *cout)
{
- int r = 0;
if (vardecl == NULL)
- return 0;
+ return;
pindent(indent, cout);
type_genc(vardecl->type, cout);
fprintf(cout, "%s = ", vardecl->ident);
- r = expr_genc(vardecl->expr, cout);
+ expr_genc(vardecl->expr, cout);
fprintf(cout, ";\n");
- return r;
}
void stmt_genc(struct stmt *stmt, int indent, FILE *cout)
}
}
-int decl_genc(struct decl *decl, FILE *cout)
+void decl_genc(struct decl *decl, FILE *cout)
{
switch (decl->type) {
+ case dcomponent:
+ //TODO generate prototypes?
+ for (int i = 0; i<decl->data.dcomponent.ndecls; i++)
+ decl_genc(decl->data.dcomponent.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; i<decl->data.dfun.nargs; i++) {
if (i < decl->data.dfun.natypes)
- type_genc(decl->data.dfun.atypes[i], cout);
+ 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, "}\n");
break;
case dvardecl:
- return vardecl_genc(decl->data.dvar, 0, cout);
+ vardecl_genc(decl->data.dvar, 0, cout);
+ break;
}
- return 0;
}
-int genc(struct ast *ast, FILE *cout)
+void genc(struct ast *ast, FILE *cout)
{
fprintf(cout,
"#include <stdint.h>\n"
"\treturn res;\n"
"}\n"
);
- int r = 0;
- for (int i = 0; i<ast->ndecls && r == 0; i++) {
+ for (int i = 0; i<ast->ndecls; i++) {
fprintf(cout, "\n");
- r = decl_genc(ast->decls[i], cout);
+ decl_genc(ast->decls[i], cout);
}
- return r;
}
#ifndef GENC_H
#define GENC_H
-#include <stdbool.h>
#include <stdio.h>
#include "ast.h"
-int genc(struct ast *res, FILE *cout);
+void genc(struct ast *res, FILE *cout);
#endif
--- /dev/null
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "list.h"
+#include "util.h"
+
+struct list *list_append(void *el, struct list *head)
+{
+ if (head == NULL)
+ return list_cons(el, NULL);
+ struct list *tail = head;
+ while (tail->tail != NULL)
+ tail = tail->tail;
+ tail->tail = list_cons(el, NULL);
+ return head;
+}
+
+struct list *list_cons(void *el, struct list *tail)
+{
+ struct list *res = safe_malloc(sizeof(struct list));
+ res->el = el;
+ res->tail = tail;
+ return res;
+}
+
+void list_free(struct list *head, void (*freefun)(void *))
+{
+ while (head != NULL) {
+ struct list *t = head;
+ if (freefun != NULL)
+ freefun(head->el);
+ head = head->tail;
+ free(t);
+ }
+}
+
+void **list_to_array(struct list *list, int *num, bool reverse)
+{
+ int i = list_length(list);
+ *num = i;
+ void **ptr = safe_malloc(i*sizeof(void *));
+
+ struct list *r = list;
+ while(i > 0) {
+ if (reverse)
+ ptr[--i] = r->el;
+ else
+ ptr[*num-(--i)-1] = r->el;
+ struct list *t = r;
+ r = r->tail;
+ free(t);
+ }
+ return ptr;
+}
+
+int list_length(struct list *r)
+{
+ int i = 0;
+ FOREACH(e, r)
+ i++;
+ return i;
+}
--- /dev/null
+#ifndef LIST_H
+#define LIST_H
+
+#include <stdbool.h>
+
+#define FOREACH(x, l) for(struct list *x = l; x != NULL; x = x->tail)
+
+struct list {
+ void *el;
+ struct list *tail;
+};
+
+struct list *list_append(void *el, struct list *head);
+struct list *list_cons(void *el, struct list *tail);
+void list_free(struct list *head, void (*freefun)(void *));
+void **list_to_array(struct list *list, int *num, bool reverse);
+int list_length(struct list *head);
+
+#endif
--- /dev/null
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "list.h"
+#include "util.h"
+#include "scc.h"
+
+struct node {
+ int lowlink;
+ int index;
+ bool onStack;
+ void *data;
+};
+
+struct edge2 {
+ struct node *from;
+ struct node *to;
+};
+
+int ptrcmp(const void *l, const void *r)
+{
+ return ((ptrdiff_t)((struct node *)l)->data)
+ -((ptrdiff_t)((struct node *)r)->data);
+}
+
+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 edge2 *edges, struct components *components)
+{
+ struct node *w;
+ v->index = *index;
+ v->lowlink = *index;
+ (*index)++;
+ stack[(*sp)++] = v;
+ v->onStack = true;
+
+ for (int i = 0; i<nedges; i++) {
+ if (edges[i].from != v)
+ continue;
+ w = edges[i].to;
+ if (w->index == -1) {
+ components = strongconnect(w, stack, sp, index,
+ nedges, edges, components);
+ } else if (w->onStack) {
+ v->lowlink = min(v->lowlink, w->index);
+ }
+ }
+
+ 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;
+}
+
+struct components *scc(int nnodes, void **nodedata, int nedges, struct edge *edgedata)
+{
+ struct components *res = NULL;
+ struct node *nodes = safe_malloc(nnodes*sizeof(struct node));
+ for (int i = 0; i<nnodes; i++)
+ nodes[i] = (struct node){.lowlink=-1, .index=-1,
+ .onStack=false, .data=nodedata[i]};
+ qsort(nodes, nnodes, sizeof(struct node), ptrcmp);
+
+ struct edge2 *edges = safe_malloc(nedges*sizeof(struct edge2));
+ for (int i = 0; i<nedges; i++) {
+ struct node *from = bsearch(edgedata[i].from, nodes, nnodes,
+ sizeof(struct node), nodecmp);
+ if (from == NULL) {
+ fprintf(stderr, "edge from references unknown node\n");
+ goto end;
+ }
+ struct node *to = bsearch(edgedata[i].to, nodes, nnodes,
+ sizeof(struct node), nodecmp);
+ if (to == NULL) {
+ fprintf(stderr, "edge to references unknown node\n");
+ goto end;
+ }
+ edges[i] = (struct edge2){.from=from, .to=to};
+ }
+
+ 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; i<cs->nnodes; i++)
+ freefun(cs->nodes[i]);
+ free(cs->nodes);
+ struct components *t = cs->next;
+ free(cs);
+ cs = t;
+ }
+}
+//
+//int main ()
+//{
+// void *nodes[] = {(void *)1, (void *)2, (void *)3};
+// struct edge edges[] = {{(void *)1, (void *)2}, {(void *)2, (void *)1}};
+// struct components *cs = scc(3, &nodes[0], 2, &edges[0]);
+// FOREACHCOMP(c, cs) {
+// fprintf(stderr, "comp: ");
+// for (int i = 0; i<c->nnodes; i++)
+// fprintf(stderr, "%d, ", c->nodes[i]);
+// fprintf(stderr, "\n");
+// }
+// components_free(cs, NULL);
+//}
--- /dev/null
+#ifndef SCC_H
+#define SCC_H
+
+#include <stdbool.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 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 (*free)(void *));
+
+#endif
free(cfile);
switch(lang) {
case langc:
- r = genc(result, cout);
+ genc(result, cout);
break;
default:
die("unsupported language\n");
struct decl *type_decl(struct decl *decl)
{
switch (decl->type) {
+ case dcomponent:
+ fprintf(stderr, "type_decl:component unsupported\n");
+ break;
case dfundecl:
fprintf(stderr, "type_decl:fundecl unsupported\n");
break;
#include "util.h"
-struct list *list_cons(void *el, struct list *tail)
-{
- struct list *res = safe_malloc(sizeof(struct list));
- res->el = el;
- res->tail = tail;
- return res;
-}
-
-void list_free(struct list *head, void (*freefun)(void *))
-{
- while (head != NULL) {
- freefun(head->el);
- head = head->tail;
- }
-}
-
-void **list_to_array(struct list *list, int *num, bool reverse)
-{
- int i = list_length(list);
- *num = i;
- void **ptr = safe_malloc(i*sizeof(void *));
-
- struct list *r = list;
- while(i > 0) {
- if (reverse)
- ptr[--i] = r->el;
- else
- ptr[*num-(--i)] = r->el;
- struct list *t = r;
- r = r->tail;
- free(t);
- }
- return ptr;
-}
-
-int list_length(struct list *r)
-{
- int i = 0;
- while(r != NULL) {
- i++;
- r = r->tail;
- }
- return i;
-}
-
int fromHex(char c)
{
if (c >= '0' && c <= '9')
#include <stdbool.h>
#include <stdio.h>
-struct list { void *el; struct list *tail; };
-struct list *list_cons(void *el, struct list *tail);
-void list_free(struct list *head, void (*freefun)(void *));
-void **list_to_array(struct list *list, int *num, bool reverse);
-int list_length(struct list *head);
+#define min(x, y) ((x)<(y)?(x):(y))
void die(const char *msg, ...);
void pdie(const char *msg);