more fixes and start with rts
authorMart Lubbers <mart@martlubbers.net>
Wed, 10 Mar 2021 14:55:24 +0000 (15:55 +0100)
committerMart Lubbers <mart@martlubbers.net>
Wed, 10 Mar 2021 14:55:24 +0000 (15:55 +0100)
Makefile
ast.c
genc.c
rts/rts.c [new file with mode: 0644]
rts/rts.h [new file with mode: 0644]
sem.c
sem/hm.c
sem/hm.h
splc.c
util.c

index 1600f4c..b5092d1 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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 <stdint.h>\n"
-               "#include <stdlib.h>\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; i<ast->ndecls; i++) {
                fprintf(cout, "\n");
                decl_genc(ast->decls[i], cout);
diff --git a/rts/rts.c b/rts/rts.c
new file mode 100644 (file)
index 0000000..b5aa329
--- /dev/null
+++ b/rts/rts.c
@@ -0,0 +1,38 @@
+#include "rts.h"
+#include <stdlib.h>
+
+#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 (file)
index 0000000..521a7ce
--- /dev/null
+++ b/rts/rts.h
@@ -0,0 +1,12 @@
+#ifndef SPLC_RTS_H
+#define SPLC_RTS_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#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 (file)
--- 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; i<ast->ndecls && !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;
 }
index fbdfc4d..923eb8f 100644 (file)
--- 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;
index d035e4c..eab8cb9 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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';