print function generation
authorMart Lubbers <mart@martlubbers.net>
Thu, 11 Mar 2021 06:39:26 +0000 (07:39 +0100)
committerMart Lubbers <mart@martlubbers.net>
Thu, 11 Mar 2021 06:39:26 +0000 (07:39 +0100)
.gitignore
ast.c
ast.h
genc.c
rts/rts.c
rts/rts.h
sem.c
sem/hm.c
type.c
type.h

index 43faf05..afb708d 100644 (file)
@@ -4,6 +4,7 @@ scan.[ch]
 *.o
 y.output
 a.c
+a.out
 
 callgrind.out.*
 massif.out.*
diff --git a/ast.c b/ast.c
index bc6f528..8af8fe1 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -182,6 +182,7 @@ static struct expr *expr_funcall_real(char *ident, struct array args, YYLTYPE l)
        res->type = efuncall;
        res->data.efuncall.ident = ident;
        res->data.efuncall.args = args;
+       res->data.efuncall.type = NULL;
        return res;
 }
 
@@ -468,7 +469,13 @@ static void expr_print2(struct expr *expr, FILE *out, struct ctx ctx)
                        escape_char(expr->data.echar, buf, false));
                break;
        case efuncall:
-               safe_fprintf(out, "%s(", expr->data.efuncall.ident);
+               safe_fprintf(out, "%s", expr->data.efuncall.ident);
+               if (expr->data.efuncall.type != NULL) {
+                       safe_fprintf(out, " /* ");
+                       type_print(expr->data.efuncall.type, out);
+                       safe_fprintf(out, " */ ");
+               }
+               safe_fprintf(out, "(");
                ARRAY_ITER(struct expr *, e, i, expr->data.efuncall.args) {
                        expr_print2(e, out, nfctx);
                        if (i+1 < ARRAY_SIZE(expr->data.efuncall.args))
@@ -616,6 +623,8 @@ void expr_free(struct expr *expr)
                break;
        case efuncall:
                free(expr->data.efuncall.ident);
+               if (expr->data.efuncall.type != NULL)
+                       type_free(expr->data.efuncall.type);
                array_free(expr->data.efuncall.args, (void (*)(void *))expr_free);
                break;
        case eint:
diff --git a/ast.h b/ast.h
index 1a27550..4424dca 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -91,6 +91,7 @@ struct expr {
                struct {
                        char *ident;
                        struct array args; // struct expr *
+                       struct type *type; // type for overloaded functions
                } efuncall;
                int eint;
                char *eident;
diff --git a/genc.c b/genc.c
index 9c6d8cf..abf1ee3 100644 (file)
--- a/genc.c
+++ b/genc.c
@@ -1,4 +1,5 @@
 #include <stdbool.h>
+#include <string.h>
 
 #include "ast.h"
 
@@ -13,6 +14,31 @@ static void binop_genc(char *fun, struct expr *l, struct expr *r, FILE *cout)
        safe_fprintf(cout, ")");
 }
 
+static void call_print_type(struct type *type, FILE *cout)
+{
+       switch(type->type) {
+       case tarrow:
+               die("cannot print functions???");
+               break;
+       case tbasic:
+               safe_fprintf(cout, "%s", basictype_str[type->data.tbasic]);
+               break;
+       case tlist:
+               safe_fprintf(cout, "l");
+               call_print_type(type->data.tlist, cout);
+               break;
+       case ttuple:
+               safe_fprintf(cout, "t");
+               type_print(type->data.ttuple.l, cout);
+               type_print(type->data.ttuple.r, cout);
+               safe_fprintf(cout, "t");
+               break;
+       case tvar:
+               die("cannot print overloaded types???");
+               break;
+       }
+}
+
 void expr_genc(struct expr *expr, FILE *cout)
 {
        char buf[] = "\\x55";
@@ -42,7 +68,13 @@ void expr_genc(struct expr *expr, FILE *cout)
                        escape_char(expr->data.echar, buf, false));
                break;
        case efuncall:
-               safe_fprintf(cout, "%s(", expr->data.efuncall.ident);
+               if (strcmp(expr->data.efuncall.ident, "print") == 0) {
+                       fprintf(cout, "print_");
+                       call_print_type(expr->data.efuncall.type, cout);
+               } else {
+                       safe_fprintf(cout, "%s", expr->data.efuncall.ident);
+               }
+               safe_fprintf(cout, "(");
                ARRAY_ITER(struct expr *, e, i, expr->data.efuncall.args) {
                        expr_genc(e, cout);
                        if (i+1 < ARRAY_SIZE(expr->data.efuncall.args))
index b5aa329..c34cdf5 100644 (file)
--- a/rts/rts.c
+++ b/rts/rts.c
@@ -1,5 +1,6 @@
 #include "rts.h"
 #include <stdlib.h>
+#include <stdio.h>
 
 #define REFC(ptr) (*(int *)((ptr)-1))
 
@@ -36,3 +37,15 @@ WORD splc_power(WORD l, WORD r) {
                res *= r;
        return res;
 }
+void print_Int(WORD l)
+{
+       printf("%ld", l);
+}
+void print_Char(WORD l)
+{
+       printf("%c", l);
+}
+void print_Bool(WORD l)
+{
+       printf("%s", l ? "true" : "false");
+}
index 521a7ce..5de6bb9 100644 (file)
--- a/rts/rts.h
+++ b/rts/rts.h
@@ -9,4 +9,8 @@
 struct splc_tuple { WORD fst; WORD snd; };
 struct splc_list { WORD hd; struct splc_list *tl; };
 
+void print_Int(WORD l);
+void print_Char(WORD l);
+void print_Bool(WORD l);
+
 #endif
diff --git a/sem.c b/sem.c
index fbb9d48..510a77a 100644 (file)
--- a/sem.c
+++ b/sem.c
@@ -53,6 +53,64 @@ static struct vardecl *type_vardecl(struct gamma *gamma, struct vardecl *vardecl
        return vardecl;
 }
 
+static void patch_overload_stmt(struct subst *subst, struct stmt *s);
+static void patch_overload_body(struct subst *subst, struct array body)
+{
+       ARRAY_ITER(struct stmt *, s, j, body)
+               patch_overload_stmt(subst, s);
+       AIEND
+}
+
+static void patch_overload_expr(struct subst *subst, struct expr *expr)
+{
+       if (expr == NULL)
+               return;
+       switch (expr->type) {
+       case ebinop:
+               patch_overload_expr(subst, expr->data.ebinop.l);
+               patch_overload_expr(subst, expr->data.ebinop.r);
+               break;
+       case efuncall:
+               if (strcmp(expr->data.efuncall.ident, "print") == 0)
+                       expr->data.efuncall.type = subst_apply_t(subst,
+                               expr->data.efuncall.type);
+               break;
+       case etuple:
+               patch_overload_expr(subst, expr->data.etuple.left);
+               patch_overload_expr(subst, expr->data.etuple.right);
+               break;
+       default:
+               break;
+       }
+
+}
+static void patch_overload_stmt(struct subst *subst, struct stmt *stmt)
+{
+       switch (stmt->type) {
+       case sassign:
+               patch_overload_expr(subst, stmt->data.sassign.expr);
+               break;
+       case sif:
+               patch_overload_expr(subst, stmt->data.sif.pred);
+               patch_overload_body(subst, stmt->data.sif.then);
+               patch_overload_body(subst, stmt->data.sif.els);
+               break;
+       case sreturn:
+               patch_overload_expr(subst, stmt->data.sreturn);
+               break;
+       case sexpr:
+               patch_overload_expr(subst, stmt->data.sexpr);
+               break;
+       case svardecl:
+               patch_overload_expr(subst, stmt->data.svardecl->expr);
+               break;
+       case swhile:
+               patch_overload_expr(subst, stmt->data.swhile.pred);
+               patch_overload_body(subst, stmt->data.swhile.body);
+               break;
+       }
+}
+
 static void type_comp(struct gamma *gamma, struct array decl)
 {
        //Create a fresh variable for every function in the component
@@ -109,6 +167,11 @@ static void type_comp(struct gamma *gamma, struct array decl)
        for (size_t i = 0; i<ARRAY_SIZE(decl); i++)
                type_free(fs[i]);
        free(fs);
+
+       //Patch all overloaded functions
+       ARRAY_ITER(struct fundecl *, d, i, decl) {
+               patch_overload_body(s0, d->body);
+       } AIEND
        subst_free(s0);
 }
 
index 923eb8f..000abcd 100644 (file)
--- a/sem/hm.c
+++ b/sem/hm.c
@@ -155,6 +155,8 @@ struct subst *infer_expr(struct gamma *gamma, struct expr *expr, struct type *ty
                //Infer return type
                s1 = unify(expr->loc, t, type);
                s0 = subst_union(s1, s0);
+               if (strcmp(expr->data.efuncall.ident, "print") == 0)
+                       expr->data.efuncall.type = type_dup(ft->data.tarrow.l);
                type_free(ft);
                return s0;
        case eint:
diff --git a/type.c b/type.c
index 51ce1a0..29e20fc 100644 (file)
--- a/type.c
+++ b/type.c
@@ -5,7 +5,7 @@
 #include "type.h"
 #include "ident.h"
 
-static const char *basictype_str[] = {
+const char *basictype_str[] = {
        [btbool] = "Bool", [btchar] = "Char", [btint] = "Int",
        [btvoid] = "Void",
 };
diff --git a/type.h b/type.h
index f8655d1..e37ca1e 100644 (file)
--- a/type.h
+++ b/type.h
@@ -5,6 +5,7 @@
 #include "ast.h"
 #include "ident.h"
 
+extern const char *basictype_str[];
 enum basictype {btbool, btchar, btint, btvoid};
 struct type {
        enum {tarrow,tbasic,tlist,ttuple,tvar} type;