From c692ce2b9dab198b364f4e389c1cb19de8965269 Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Wed, 10 Mar 2021 15:55:24 +0100 Subject: [PATCH] more fixes and start with rts --- Makefile | 2 +- ast.c | 2 +- genc.c | 59 ++++++++++++++++++------------------------------------- rts/rts.c | 38 +++++++++++++++++++++++++++++++++++ rts/rts.h | 12 +++++++++++ sem.c | 45 +++++++++++++++++++++++++++++++++--------- sem/hm.c | 8 ++++---- sem/hm.h | 1 - splc.c | 2 +- util.c | 6 +++--- 10 files changed, 115 insertions(+), 60 deletions(-) create mode 100644 rts/rts.c create mode 100644 rts/rts.h diff --git a/Makefile b/Makefile index 1600f4c..b5092d1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS+=-Wall -Wextra -Werror -std=c99 -pedantic -ggdb +CFLAGS+=-Wall -Wextra -Werror -std=c99 -pedantic -ggdb -O3 LDFLAGS+=-Wl,--gc-sections,--print-gc-sections YFLAGS+=--locations -Wno-yacc --defines=parse.h LFLAGS+=--header-file=scan.h diff --git a/ast.c b/ast.c index 5f9e26e..bc6f528 100644 --- a/ast.c +++ b/ast.c @@ -175,7 +175,7 @@ bool is_builtin(char *t) || strcmp(t, "print") == 0; } -struct expr *expr_funcall_real(char *ident, struct array args, YYLTYPE l) +static struct expr *expr_funcall_real(char *ident, struct array args, YYLTYPE l) { struct expr *res = xalloc(1, struct expr); res->loc = l; diff --git a/genc.c b/genc.c index 6acf9e1..9c6d8cf 100644 --- a/genc.c +++ b/genc.c @@ -86,7 +86,8 @@ void type_genc(struct type *type, FILE *cout) die("unresolved var type\n"); switch(type->type) { case tbasic: - fprintf(cout, "WORD "); + fprintf(cout, "%s ", + type->data.tbasic == btvoid ? "void" : "WORD"); break; case tlist: fprintf(cout, "struct splc_list *"); @@ -177,28 +178,25 @@ void stmt_genc(struct stmt *stmt, int indent, FILE *cout) } } -void fundecl_genc(struct fundecl *decl, FILE *cout) +void fundecl_sig(struct fundecl *decl, FILE *cout) { type_genc(decl->rtype, cout); safe_fprintf(cout, "%s (", decl->ident); ARRAY_ITER(char *, a, i, decl->args) { if (i >= ARRAY_SIZE(decl->atypes)) die("function with unmatched type\n"); + type_genc(ARRAY_EL(struct type *, decl->atypes, i), cout); safe_fprintf(cout, "%s", a); if (i < ARRAY_SIZE(decl->args) - 1) safe_fprintf(cout, ", "); } AIEND - safe_fprintf(cout, ") /*"); - if (decl->rtype != NULL) { - safe_fprintf(cout, " :: "); - ARRAY_ITER(struct type *, t, i, decl->atypes) { - type_print(t, cout); - safe_fprintf(cout, " "); - } AIEND - safe_fprintf(cout, "-> "); - type_print(decl->rtype, cout); - } - safe_fprintf(cout, "*/ {\n"); + safe_fprintf(cout, ")"); +} + +void fundecl_genc(struct fundecl *decl, FILE *cout) +{ + fundecl_sig(decl, cout); + safe_fprintf(cout, "{\n"); ARRAY_ITER(struct stmt *, s, i, decl->body) stmt_genc(s, 1, cout); AIEND @@ -209,13 +207,18 @@ void decl_genc(struct decl *decl, FILE *cout) { switch (decl->type) { case dcomp: - //TODO generate prototypes? + if (ARRAY_SIZE(decl->data.dcomp) > 1) { + ARRAY_ITER(struct fundecl *, d, i, decl->data.dcomp) + fundecl_sig(d, cout); + safe_fprintf(cout, ";\n"); + AIEND + } ARRAY_ITER(struct fundecl *, d, i, decl->data.dcomp) fundecl_genc(d, cout); AIEND break; case dfundecl: - fundecl_genc(decl->data.dfun, cout); + die("fundecls should be gone by now\n"); break; case dvardecl: vardecl_genc(decl->data.dvar, 0, cout); @@ -225,31 +228,7 @@ void decl_genc(struct decl *decl, FILE *cout) void genc(struct ast *ast, FILE *cout) { - fprintf(cout, - "#include \n" - "#include \n" - "#define WORD intptr_t\n" - "struct splc_tuple { WORD fst; WORD snd; };\n" - "struct splc_list { WORD hd; struct splc_list *tl; };\n" - "struct splc_tuple *splc_tuple(WORD fst, WORD snd) {\n" - "\tstruct splc_tuple *res = malloc(sizeof(splc_tuple));\n" - "\tres->fst = fst;\n" - "\tres->snd = snd;\n" - "\treturn res;\n" - "}\n" - "struct splc_list *splc_cons(WORD hd, struct splc_list *tl) {\n" - "\tstruct splc_list *res = malloc(sizeof(splc_tuple));\n" - "\tres->hd = hd;\n" - "\tres->tl = tl;\n" - "\treturn res;\n" - "}\n" - "WORD splc_power(WORD l, WORD r) {\n" - "\tWORD res = 1;\n" - "\twhile(l-- >= 0)\n" - "\t\tres *= r;\n" - "\treturn res;\n" - "}\n" - ); + fprintf(cout, "#include \"rts.h\"\n"); for (int i = 0; indecls; i++) { fprintf(cout, "\n"); decl_genc(ast->decls[i], cout); diff --git a/rts/rts.c b/rts/rts.c new file mode 100644 index 0000000..b5aa329 --- /dev/null +++ b/rts/rts.c @@ -0,0 +1,38 @@ +#include "rts.h" +#include + +#define REFC(ptr) (*(int *)((ptr)-1)) + +void *splc_malloc(size_t size) +{ + void *res = malloc(sizeof(void *)+size); + res++; + REFC(res) = 0; + return res; +} + +void splc_free(void *ptr) +{ + REFC(ptr)--; + if (REFC(ptr) == 0) + free(ptr-1); +} + +struct splc_tuple *splc_tuple(WORD fst, WORD snd) { + struct splc_tuple *res = splc_malloc(sizeof(splc_tuple)); + res->fst = fst; + res->snd = snd; + return res; +} +struct splc_list *splc_cons(WORD hd, struct splc_list *tl) { + struct splc_list *res = splc_malloc(sizeof(splc_tuple)); + res->hd = hd; + res->tl = tl; + return res; +} +WORD splc_power(WORD l, WORD r) { + WORD res = 1; + while(l-- >= 0) + res *= r; + return res; +} diff --git a/rts/rts.h b/rts/rts.h new file mode 100644 index 0000000..521a7ce --- /dev/null +++ b/rts/rts.h @@ -0,0 +1,12 @@ +#ifndef SPLC_RTS_H +#define SPLC_RTS_H + +#include +#include + +#define WORD intptr_t + +struct splc_tuple { WORD fst; WORD snd; }; +struct splc_list { WORD hd; struct splc_list *tl; }; + +#endif diff --git a/sem.c b/sem.c index ea77d8e..fbb9d48 100644 --- a/sem.c +++ b/sem.c @@ -19,7 +19,7 @@ void type_error(YYLTYPE l, bool d, const char *msg, ...) die(""); } -void check_expr_constant(struct expr *expr) +static void check_expr_constant(struct expr *expr) { switch (expr->type) { case ebinop: @@ -39,7 +39,7 @@ void check_expr_constant(struct expr *expr) } } -struct vardecl *type_vardecl(struct gamma *gamma, struct vardecl *vardecl) +static struct vardecl *type_vardecl(struct gamma *gamma, struct vardecl *vardecl) { struct type *t = vardecl->type == NULL ? gamma_fresh(gamma) : vardecl->type; @@ -53,7 +53,7 @@ struct vardecl *type_vardecl(struct gamma *gamma, struct vardecl *vardecl) return vardecl; } -void type_comp(struct gamma *gamma, struct array decl) +static void type_comp(struct gamma *gamma, struct array decl) { //Create a fresh variable for every function in the component struct type **fs = xalloc(ARRAY_SIZE(decl), struct type *); @@ -112,7 +112,7 @@ void type_comp(struct gamma *gamma, struct array decl) subst_free(s0); } -void gamma_preamble(struct gamma *gamma) +static void gamma_preamble(struct gamma *gamma) { struct type *t = type_arrow(type_tuple(type_var_str("a") , type_var_str("b")) ,type_var_str("a")); @@ -144,8 +144,8 @@ void gamma_preamble(struct gamma *gamma) type_free(t); } -bool check_return_stmt(struct stmt *stmt); -bool check_return_body(struct array body) +static bool check_return_stmt(struct stmt *stmt); +static bool check_return_body(struct array body) { ARRAY_ITER(struct stmt *, s, i, body) if (check_return_stmt(s)) @@ -155,7 +155,7 @@ bool check_return_body(struct array body) } -bool check_return_stmt(struct stmt *stmt) +static bool check_return_stmt(struct stmt *stmt) { switch (stmt->type) { case sassign: @@ -172,7 +172,7 @@ bool check_return_stmt(struct stmt *stmt) } } -void check_return_comp(struct array decl) +static void check_return_comp(struct array decl) { ARRAY_ITER(struct fundecl *, d, i, decl) { if (d->rtype->type == tbasic && d->rtype->data.tbasic == btvoid) @@ -183,7 +183,7 @@ void check_return_comp(struct array decl) } AIEND } -void add_return_if_none(struct array decl) +static void add_return_if_none(struct array decl) { ARRAY_ITER(struct fundecl *, d, i, decl) if (d->rtype == NULL && !check_return_body(d->body)) @@ -191,6 +191,19 @@ void add_return_if_none(struct array decl) AIEND } +bool checkmain (struct fundecl *d) +{ + fprintf(stderr, "%s\n", d->ident); + if (strcmp(d->ident, "main") == 0) { + if (ARRAY_SIZE(d->args) != 0) + type_error(d->loc, true, "main cannot have arguments"); + if (d->rtype->type != tbasic || d->rtype->data.tbasic != btvoid) + type_error(d->loc, true, "main must return void"); + return true; + } + return false; +} + struct ast *sem(struct ast *ast) { //Break up into strongly connected components @@ -222,5 +235,19 @@ struct ast *sem(struct ast *ast) } gamma_free(gamma); + //Check for a main function + bool found = false; + for (int i = 0; indecls && !found; i++) { + struct decl *decl = ast->decls[i]; + if (decl->type == dcomp) { + ARRAY_ITER(struct fundecl *, d, i, decl->data.dcomp) { + if ((found = checkmain(d))) + break; + } AIEND + } + } + if (!found) + type_error(ast->loc, true, "no main function found\n"); + return ast; } diff --git a/sem/hm.c b/sem/hm.c index fbdfc4d..923eb8f 100644 --- a/sem/hm.c +++ b/sem/hm.c @@ -8,7 +8,7 @@ #include "../sem.h" #include "../ast.h" -bool occurs_check(struct ident ident, struct type *r) +static bool occurs_check(struct ident ident, struct type *r) { int nftv = 0; struct ident *ftv = NULL; @@ -64,7 +64,7 @@ struct subst *unify(YYLTYPE loc, struct type *l, struct type *r) return NULL; } -struct subst *infer_binop(struct gamma *gamma, struct expr *l, struct expr *r, +static struct subst *infer_binop(struct gamma *gamma, struct expr *l, struct expr *r, struct type *a1, struct type *a2, struct type *rt, struct type *sigma) { struct subst *s1 = infer_expr(gamma, l, a1); @@ -74,7 +74,7 @@ struct subst *infer_binop(struct gamma *gamma, struct expr *l, struct expr *r, return subst_union(s4, s3); } -struct subst *infer_unop(struct gamma *gamma, struct expr *e, +static struct subst *infer_unop(struct gamma *gamma, struct expr *e, struct type *a, struct type *rt, struct type *sigma) { struct subst *s1 = infer_expr(gamma, e, a); @@ -195,7 +195,7 @@ struct subst *infer_expr(struct gamma *gamma, struct expr *expr, struct type *ty return NULL; } -struct subst *infer_body(struct gamma *gamma, struct array stmts, struct type *type) +static struct subst *infer_body(struct gamma *gamma, struct array stmts, struct type *type) { gamma_increment_scope(gamma); struct subst *s0 = subst_id(), *s1; diff --git a/sem/hm.h b/sem/hm.h index d035e4c..eab8cb9 100644 --- a/sem/hm.h +++ b/sem/hm.h @@ -9,7 +9,6 @@ struct ast *infer(struct ast *ast); -bool occurs_check(struct ident ident, struct type *r); struct subst *unify(YYLTYPE loc, struct type *l, struct type *r); struct subst *infer_expr(struct gamma *gamma, struct expr *expr, struct type *type); struct subst *infer_stmt(struct gamma *gamma, struct stmt *stmt, struct type *type); diff --git a/splc.c b/splc.c index 419d13a..834797d 100644 --- a/splc.c +++ b/splc.c @@ -93,7 +93,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/util.c b/util.c index cdc0d28..a95913a 100644 --- a/util.c +++ b/util.c @@ -7,7 +7,7 @@ #include "util.h" -int fromHex(char c) +static inline int fromHex(char c) { if (c >= '0' && c <= '9') return c-'0'; @@ -43,12 +43,12 @@ char *escape_char(char c, char *buf, bool str) return buf; } -bool isodigit(char c) +static inline bool isodigit(char c) { return c >= '0' && c <= '7'; } -int fromOctal(char c) +static inline int fromOctal(char c) { if (isodigit(c)) return c-'0'; -- 2.20.1