--- /dev/null
+#include <stdbool.h>
+
+#include "ast.h"
+
+#define gdie(msg) { fprintf(stderr, "%s", msg); return 1; }
+
+int expr_genc(struct expr *expr, FILE *cout);
+
+void binop_genc(char *fun, struct expr *l, struct expr *r, FILE *cout)
+{
+ safe_fprintf(cout, "%s(", fun);
+ expr_genc(l, cout);
+ safe_fprintf(cout, ", ");
+ expr_genc(r, cout);
+ safe_fprintf(cout, ")");
+}
+
+int expr_genc(struct expr *expr, FILE *cout)
+{
+ int r = 0;
+ char buf[] = "\\x55";
+ if (expr == NULL)
+ return 0;
+ switch(expr->type) {
+ case ebinop:
+ if (expr->type == ebinop && expr->data.ebinop.op == cons) {
+ binop_genc("splc_cons", expr->data.ebinop.l,
+ expr->data.ebinop.r, cout);
+ } else if (expr->type == ebinop && expr->data.ebinop.op == power) {
+ binop_genc("splc_power", expr->data.ebinop.l,
+ expr->data.ebinop.r, cout);
+ } else {
+ safe_fprintf(cout, "(");
+ expr_genc(expr->data.ebinop.l, cout);
+ safe_fprintf(cout, "%s", binop_str[expr->data.ebinop.op]);
+ expr_genc(expr->data.ebinop.r, cout);
+ safe_fprintf(cout, ")");
+ }
+ break;
+ case ebool:
+ safe_fprintf(cout, "%s", expr->data.ebool ? "true" : "false");
+ break;
+ case echar:
+ safe_fprintf(cout, "'%s'",
+ escape_char(expr->data.echar, buf, false));
+ break;
+ case efuncall:
+ safe_fprintf(cout, "%s(", expr->data.efuncall.ident);
+ for(int i = 0; i<expr->data.efuncall.nargs; i++) {
+ expr_genc(expr->data.efuncall.args[i], cout);
+ if (i+1 < expr->data.efuncall.nargs)
+ safe_fprintf(cout, ", ");
+ }
+ safe_fprintf(cout, ")");
+ for (int i = 0; i<expr->data.efuncall.nfields; i++)
+ fprintf(cout, "->%s",
+ fieldspec_str[expr->data.efuncall.fields[i]]);
+ break;
+ case eint:
+ safe_fprintf(cout, "%d", expr->data.eint);
+ break;
+ case eident:
+ fprintf(cout, "%s", expr->data.eident.ident);
+ for (int i = 0; i<expr->data.eident.nfields; i++)
+ fprintf(cout, "->%s",
+ fieldspec_str[expr->data.eident.fields[i]]);
+ break;
+ case enil:
+ safe_fprintf(cout, "NULL");
+ break;
+ case etuple:
+ binop_genc("splc_tuple", expr->data.etuple.left,
+ expr->data.etuple.right, cout);
+ break;
+ case estring:
+ safe_fprintf(cout, "\"");
+ for (int i = 0; i<expr->data.estring.nchars; i++)
+ safe_fprintf(cout, "%s", escape_char(
+ expr->data.estring.chars[i], buf, true));
+ safe_fprintf(cout, "\"");
+ break;
+ case eunop:
+ safe_fprintf(cout, "(%s", unop_str[expr->data.eunop.op]);
+ expr_genc(expr->data.eunop.l, cout);
+ safe_fprintf(cout, ")");
+ break;
+ default:
+ die("Unknown expression node\n");
+ }
+ return r;
+}
+
+int type_genc(struct type *type, FILE *cout)
+{
+ if (type == NULL) {
+ 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");
+ }
+ }
+ return 0;
+}
+
+int vardecl_genc(struct vardecl *vardecl, int indent, FILE *cout)
+{
+ int r = 0;
+ if (vardecl == NULL)
+ return 0;
+ pindent(indent, cout);
+ type_genc(vardecl->type, cout);
+ fprintf(cout, "%s = ", vardecl->ident);
+ r = expr_genc(vardecl->expr, cout);
+ fprintf(cout, ";\n");
+ return r;
+}
+
+void stmt_genc(struct stmt *stmt, int indent, FILE *cout)
+{
+ if (stmt == NULL)
+ return;
+ switch(stmt->type) {
+ case sassign:
+ pindent(indent, cout);
+ fprintf(cout, "%s", stmt->data.sassign.ident);
+ for (int i = 0; i<stmt->data.sassign.nfields; i++)
+ fprintf(cout, "->%s", stmt->data.sassign.fields[i]);
+ safe_fprintf(cout, " = ");
+ expr_genc(stmt->data.sassign.expr, cout);
+ safe_fprintf(cout, ";\n");
+ break;
+ case sif:
+ pindent(indent, cout);
+ safe_fprintf(cout, "if (");
+ expr_genc(stmt->data.sif.pred, cout);
+ safe_fprintf(cout, ") {\n");
+ for (int i = 0; i<stmt->data.sif.nthen; i++)
+ stmt_genc(stmt->data.sif.then[i], indent+1, cout);
+ pindent(indent, cout);
+ safe_fprintf(cout, "} else {\n");
+ for (int i = 0; i<stmt->data.sif.nels; i++)
+ stmt_genc(stmt->data.sif.els[i], indent+1, cout);
+ pindent(indent, cout);
+ safe_fprintf(cout, "}\n");
+ break;
+ case sreturn:
+ pindent(indent, cout);
+ safe_fprintf(cout, "return ");
+ expr_genc(stmt->data.sreturn, cout);
+ safe_fprintf(cout, ";\n");
+ break;
+ case sexpr:
+ pindent(indent, cout);
+ expr_genc(stmt->data.sexpr, cout);
+ safe_fprintf(cout, ";\n");
+ break;
+ case svardecl:
+ vardecl_genc(stmt->data.svardecl, indent, cout);
+ break;
+ case swhile:
+ pindent(indent, cout);
+ safe_fprintf(cout, "while (");
+ expr_genc(stmt->data.swhile.pred, cout);
+ safe_fprintf(cout, ") {\n");
+ for (int i = 0; i<stmt->data.swhile.nbody; i++)
+ stmt_genc(stmt->data.swhile.body[i], indent+1, cout);
+ pindent(indent, cout);
+ safe_fprintf(cout, "}\n");
+ break;
+ default:
+ die("Unsupported stmt node\n");
+ }
+}
+
+int decl_genc(struct decl *decl, FILE *cout)
+{
+ switch (decl->type) {
+ 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);
+ safe_fprintf(cout, "%s", decl->data.dfun.args[i]);
+ if (i < decl->data.dfun.nargs - 1)
+ safe_fprintf(cout, ", ");
+ }
+ safe_fprintf(cout, ") /*");
+ if (decl->data.dfun.rtype != NULL) {
+ safe_fprintf(cout, " :: ");
+ for (int i = 0; i<decl->data.dfun.natypes; i++) {
+ type_print(decl->data.dfun.atypes[i], cout);
+ safe_fprintf(cout, " ");
+ }
+ safe_fprintf(cout, "-> ");
+ type_print(decl->data.dfun.rtype, cout);
+ }
+ safe_fprintf(cout, "*/ {\n");
+ for (int i = 0; i<decl->data.dfun.nbody; i++)
+ stmt_genc(decl->data.dfun.body[i], 1, cout);
+ safe_fprintf(cout, "}\n");
+ break;
+ case dvardecl:
+ return vardecl_genc(decl->data.dvar, 0, cout);
+ }
+ return 0;
+}
+
+int 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"
+ );
+ int r = 0;
+ for (int i = 0; i<ast->ndecls && r == 0; i++) {
+ fprintf(cout, "\n");
+ r = decl_genc(ast->decls[i], cout);
+ }
+ return r;
+}