From 981c4d763cd6194d32b38704ae0c4f2883a74a62 Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Thu, 11 Mar 2021 07:39:26 +0100 Subject: [PATCH] print function generation --- .gitignore | 1 + ast.c | 11 +++++++++- ast.h | 1 + genc.c | 34 ++++++++++++++++++++++++++++- rts/rts.c | 13 +++++++++++ rts/rts.h | 4 ++++ sem.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ sem/hm.c | 2 ++ type.c | 2 +- type.h | 1 + 10 files changed, 129 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 43faf05..afb708d 100644 --- a/.gitignore +++ b/.gitignore @@ -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 --- 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 --- 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 --- a/genc.c +++ b/genc.c @@ -1,4 +1,5 @@ #include +#include #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)) diff --git a/rts/rts.c b/rts/rts.c index b5aa329..c34cdf5 100644 --- a/rts/rts.c +++ b/rts/rts.c @@ -1,5 +1,6 @@ #include "rts.h" #include +#include #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"); +} diff --git a/rts/rts.h b/rts/rts.h index 521a7ce..5de6bb9 100644 --- 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 --- 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; ibody); + } AIEND subst_free(s0); } diff --git a/sem/hm.c b/sem/hm.c index 923eb8f..000abcd 100644 --- 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 --- 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 --- 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; -- 2.20.1