--- /dev/null
+#include <string.h>
+
+#include "sem.h"
+#include "gen.h"
+#include "gen/c.h"
+#include "gen/ssm.h"
+
+void overloaded_type(YYLTYPE loc, 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");
+ overloaded_type(loc, type->data.tlist, cout);
+ break;
+ case ttuple:
+ safe_fprintf(cout, "t");
+ overloaded_type(loc, type->data.ttuple.l, cout);
+ overloaded_type(loc, type->data.ttuple.r, cout);
+ safe_fprintf(cout, "t");
+ break;
+ case tvar:
+ type_error(loc, true, "cannot print overloaded types???");
+ break;
+ }
+}
+
+static int type_cmpv(const void *l, const void *r)
+{
+ return type_cmp((struct type *)l, *(void **)r);
+}
+
+static void call_register(struct array *st, struct type *type)
+{
+ *st = array_binsert(type, *st, type_cmpv);
+ switch(type->type) {
+ case tlist:
+ call_register(st, type->data.tlist);
+ break;
+ case ttuple:
+ call_register(st, type->data.ttuple.l);
+ call_register(st, type->data.ttuple.r);
+ break;
+ default:
+ break;
+ }
+}
+
+static void ol_expr(struct overload *st, struct expr *expr)
+{
+ switch(expr->type) {
+ case ebinop:
+ if (expr->data.ebinop.op == eq || expr->data.ebinop.op == neq)
+ call_register(&st->eq, expr->data.ebinop.type);
+ ol_expr(st, expr->data.ebinop.l);
+ ol_expr(st, expr->data.ebinop.r);
+ break;
+ case efuncall:
+ if (strcmp(expr->data.efuncall.ident, "print") == 0)
+ call_register(&st->print, expr->data.efuncall.type);
+ ARRAY_ITER(struct expr *, e, i, expr->data.efuncall.args)
+ ol_expr(st, e);
+ AIEND
+ break;
+ case etuple:
+ ol_expr(st, expr->data.etuple.left);
+ ol_expr(st, expr->data.etuple.right);
+ break;
+ case eunop:
+ ol_expr(st, expr->data.eunop.l);
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void ol_body(struct overload *st, struct array body);
+static void ol_stmt(struct overload *st, struct stmt *stmt)
+{
+ switch(stmt->type) {
+ case sassign:
+ ol_expr(st, stmt->data.sassign.expr);
+ break;
+ case sif:
+ ol_expr(st, stmt->data.sif.pred);
+ ol_body(st, stmt->data.sif.then);
+ ol_body(st, stmt->data.sif.els);
+ break;
+ case sreturn:
+ if (stmt->data.sreturn != NULL)
+ ol_expr(st, stmt->data.sreturn);
+ break;
+ case sexpr:
+ ol_expr(st, stmt->data.sexpr);
+ break;
+ case svardecl:
+ ol_expr(st, stmt->data.svardecl->expr);
+ break;
+ case swhile:
+ ol_expr(st, stmt->data.swhile.pred);
+ ol_body(st, stmt->data.swhile.body);
+ break;
+ default:
+ die("Unsupported stmt node\n");
+ }
+
+}
+
+static void ol_body(struct overload *st, struct array body)
+{
+ ARRAY_ITER(struct stmt *, s, i, body)
+ ol_stmt(st, s);
+ AIEND
+}
+
+void gen(struct ast *res, enum lang lang, FILE *cout)
+{
+ struct overload st = { .print=array_null, .eq=array_null };
+ for (int i = 0; i<res->ndecls; i++) {
+ struct decl *decl = res->decls[i];
+ switch(decl->type) {
+ case dcomp:
+ ARRAY_ITER(struct fundecl *, d, i, decl->data.dcomp)
+ ol_body(&st, d->body);
+ AIEND
+ break;
+ case dfundecl:
+ break;
+ case dvardecl:
+ ol_expr(&st, decl->data.dvar->expr);
+ break;
+ }
+ }
+
+ switch(lang) {
+ case c:
+ genc(res, st, cout);
+ break;
+ case ssm:
+ genssm(res, st, cout);
+ break;
+ default:
+ die("unsupported language\n");
+ }
+ array_free(st.print, NULL);
+ array_free(st.eq, NULL);
+}
#include <string.h>
#include <stdlib.h>
-#include "ast.h"
-#include "sem.h"
+#include "../ast.h"
+#include "../sem.h"
+#include "../gen.h"
struct gencst {
struct array printtypes; // struct type *
safe_fprintf(cout, ")");
}
-static int type_cmpv(const void *l, const void *r)
-{
- return type_cmp((struct type *)l, *(void **)r);
-}
-
-static void call_print_register(struct gencst *st, struct type *type)
-{
- st->printtypes = array_binsert(type, st->printtypes, type_cmpv);
- switch(type->type) {
- case tlist:
- call_print_register(st, type->data.tlist);
- break;
- case ttuple:
- call_print_register(st, type->data.ttuple.l);
- call_print_register(st, type->data.ttuple.r);
- break;
- default:
- break;
- }
-}
-
-static void call_print_type(YYLTYPE loc, 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(loc, type->data.tlist, cout);
- break;
- case ttuple:
- safe_fprintf(cout, "t");
- call_print_type(loc, type->data.ttuple.l, cout);
- call_print_type(loc, type->data.ttuple.r, cout);
- safe_fprintf(cout, "t");
- break;
- case tvar:
- type_error(loc, true, "cannot print overloaded types???");
- break;
- }
-}
-
static void expr_genc(struct gencst *st, struct expr *expr, FILE *cout)
{
char buf[] = "\\x55";
return;
switch(expr->type) {
case ebinop:
- if (expr->data.ebinop.op == cons) {
+ if (expr->data.ebinop.op == eq || expr->data.ebinop.op == neq) {
+ if (expr->data.ebinop.op == neq)
+ safe_fprintf(cout, "!");
+ safe_fprintf(cout, "eq_");
+ overloaded_type(expr->loc, expr->data.ebinop.type, cout);
+ safe_fprintf(cout, "(");
+ expr_genc(st, expr->data.ebinop.l, cout);
+ safe_fprintf(cout, ",");
+ expr_genc(st, expr->data.ebinop.r, cout);
+ safe_fprintf(cout, ")");
+ } else if (expr->data.ebinop.op == cons) {
binop_genc(st, "splc_cons", expr->data.ebinop.l,
expr->data.ebinop.r, cout);
} else if (expr->data.ebinop.op == power) {
case efuncall:
if (strcmp(expr->data.efuncall.ident, "print") == 0) {
safe_fprintf(cout, "print_");
- call_print_register(st, expr->data.efuncall.type);
- call_print_type(expr->loc, expr->data.efuncall.type, cout);
+ overloaded_type(expr->loc, expr->data.efuncall.type, cout);
} else {
safe_fprintf(cout, "%s", expr->data.efuncall.ident);
}
}
}
-static void generate_print_body(struct type *type, FILE *cout)
+static void generate_eq(struct type *type, FILE *cout)
{
+ if (type->type == tbasic)
+ return;
+
+ safe_fprintf(cout, "WORD eq_");
YYLTYPE loc;
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, "(");
+ type_genc(type, cout);
+ safe_fprintf(cout, "x, ");
+ type_genc(type, cout);
+ safe_fprintf(cout, "y) {\n");
switch(type->type) {
- case tbasic:
- safe_fprintf(cout, "\tprint_");
- call_print_type(loc, type, cout);
- safe_fprintf(cout, ");\n");
+ case tlist:
+ safe_fprintf(cout, "\twhile(t != NULL) {\n");
+ safe_fprintf(cout, "\t\tif (!eq_");
+ overloaded_type(loc, type->data.tlist, cout);
+ safe_fprintf(cout, "(x->hd, y->hd));\n");
+ safe_fprintf(cout, "\t\t\treturn false;\n");
+ safe_fprintf(cout, "\t\tt = t->tl;\n");
+ safe_fprintf(cout, "\t}\n");
+ safe_fprintf(cout, "\treturn true;\n");
+ break;
+ case ttuple:
+ safe_fprintf(cout, "\treturn eq_");
+ overloaded_type(loc, type->data.ttuple.l, cout);
+ safe_fprintf(cout, "(x->fst, y->fst)");
+ safe_fprintf(cout, " && eq_");
+ overloaded_type(loc, type->data.ttuple.r, cout);
+ safe_fprintf(cout, "(x->snd, y->snd);");
break;
+ default:
+ die("cannot compare anything else than tuples and lists");
+ }
+ safe_fprintf(cout, "\n}\n");
+}
+
+static void generate_print(struct type *type, FILE *cout)
+{
+ if (type->type == tbasic)
+ return;
+
+ safe_fprintf(cout, "void print_");
+ YYLTYPE loc;
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, "(");
+ type_genc(type, cout);
+ safe_fprintf(cout, " t) {\n");
+ switch(type->type) {
case tlist:
safe_fprintf(cout, "\tprintf(\"[\");\n");
safe_fprintf(cout, "\twhile(t != NULL) {\n");
safe_fprintf(cout, "\t\tprint_");
- call_print_type(loc, type->data.tlist, cout);
+ overloaded_type(loc, type->data.tlist, cout);
safe_fprintf(cout, "(t->hd);\n");
- safe_fprintf(cout, "\t\tif (t->tl != NULL) printf(\", \");\n");
+ safe_fprintf(cout, "\t\tif (t->tl != NULL)\n");
+ safe_fprintf(cout, "\t\t\tprintf(\", \");\n");
safe_fprintf(cout, "\t\tt = t->tl;\n");
safe_fprintf(cout, "\t}\n");
safe_fprintf(cout, "\tprintf(\"]\");\n");
case ttuple:
safe_fprintf(cout, "\tprintf(\"(\");\n");
safe_fprintf(cout, "\tprint_");
- call_print_type(loc, type->data.ttuple.l, cout);
+ overloaded_type(loc, type->data.ttuple.l, cout);
safe_fprintf(cout, "(t->fst);\n");
safe_fprintf(cout, "\tprintf(\",\");\n");
safe_fprintf(cout, "\tprint_");
- call_print_type(loc, type->data.ttuple.r, cout);
+ overloaded_type(loc, type->data.ttuple.r, cout);
safe_fprintf(cout, "(t->snd);\n");
safe_fprintf(cout, "\tprintf(\")\");\n");
break;
default:
+ die("cannot print anything else than tuples and lists");
break;
}
-}
-
-static void generate_print(struct type *type, FILE *cout)
-{
- if (type->type == tbasic)
- return;
-
- safe_fprintf(cout, "void print_");
- YYLTYPE loc;
- call_print_type(loc, type, cout);
- safe_fprintf(cout, "(");
- type_genc(type, cout);
- safe_fprintf(cout, " t) {\n");
- generate_print_body(type, cout);
safe_fprintf(cout, "}\n");
}
-void genc(struct ast *ast, FILE *cout)
+void genc(struct ast *ast, struct overload ol, FILE *cout)
{
+ //Header
safe_fprintf(cout, "#include \"rts.h\"\n");
+
+ //Overloaded functions
+ ARRAY_ITER(struct type *, t, i, ol.print) {
+ generate_print(t, cout);
+ } AIEND
+ ARRAY_ITER(struct type *, t, i, ol.eq) {
+ generate_eq(t, cout);
+ } AIEND
+
+ //Code
struct gencst st = {.printtypes = array_null};
for (int i = 0; i<ast->ndecls; i++) {
safe_fprintf(cout, "\n");
decl_genc(&st, ast->decls[i], cout);
}
- ARRAY_ITER(struct type *, t, i, st.printtypes) {
- generate_print(t, cout);
- } AIEND
- array_free(st.printtypes, NULL);
}
--- /dev/null
+#include <string.h>
+
+#include "../ast.h"
+#include "../sem.h"
+#include "../gen.h"
+
+struct genssmst {
+ int fresh;
+};
+
+static const char *unop_instr[] = { [inverse] = "not", [negate] = "neg" };
+static const char *binop_instr[] = {
+ [binor] = "or", [binand] = "and", [eq] = "eq", [neq] = "ne",
+ [leq] = "le", [le] = "lt", [geq] = "ge", [ge] = "gt", [cons] = ":",
+ [plus] = "add", [minus] = "sub", [times] = "mul", [divide] = "div",
+ [modulo] = "mod", [power] = "^",
+};
+
+static void generate_eq(struct type *type, FILE *cout)
+{
+ YYLTYPE loc;
+ safe_fprintf(cout, "eq");
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, ":\n");
+ safe_fprintf(cout, "link 0\n");
+ switch(type->type) {
+ case tbasic:
+ safe_fprintf(cout, "bsr eq");
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, "\n");
+ safe_fprintf(cout, "ajs -2\n");
+ break;
+ case tlist:
+ die("list equality not implemented yet\n");
+ break;
+ case ttuple:
+ safe_fprintf(cout, "ldl -2\nldh -1\n");
+ safe_fprintf(cout, "ldl -3\nldh -1\n");
+ safe_fprintf(cout, "eq\n");
+ //Compare left
+ safe_fprintf(cout, "brf eq");
+ overloaded_type(loc, type->data.ttuple.l, cout);
+ safe_fprintf(cout, "e\n");
+ safe_fprintf(cout, "ldl -2\nldh 0\n");
+ safe_fprintf(cout, "ldl -3\nldh 0\n");
+ safe_fprintf(cout, "bsr eq\n");
+ overloaded_type(loc, type->data.ttuple.l, cout);
+ safe_fprintf(cout, "\najs -2\n");
+ safe_fprintf(cout, "ldr RR2\n");
+ safe_fprintf(cout, "brf eq");
+ overloaded_type(loc, type->data.ttuple.l, cout);
+ safe_fprintf(cout, "e\n");
+ safe_fprintf(cout, "ldc -1\n");
+ safe_fprintf(cout, "str RR\n");
+ safe_fprintf(cout, "unlink\n");
+ safe_fprintf(cout, "ret\n");
+ //Return false
+ safe_fprintf(cout, "eq");
+ overloaded_type(loc, type->data.ttuple.l, cout);
+ safe_fprintf(cout, "e:\n");
+ safe_fprintf(cout, "ldc 0\n");
+ safe_fprintf(cout, "str RR\n");
+ break;
+ default:
+ break;
+ }
+ safe_fprintf(cout, "unlink\n");
+ safe_fprintf(cout, "ret\n");
+}
+static void generate_print(struct type *type, FILE *cout)
+{
+ YYLTYPE loc;
+ safe_fprintf(cout, "print");
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, ":\n");
+ safe_fprintf(cout, "link 0\n");
+ switch(type->type) {
+ case tbasic:
+ safe_fprintf(cout, "bsr print");
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, "\n");
+ safe_fprintf(cout, "ajs -1\n");
+ break;
+ case tlist:
+ //Print [
+ safe_fprintf(cout, "ldc 91\ntrap 1\n");
+ safe_fprintf(cout, "print");
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, "b:\n");
+ safe_fprintf(cout, "ldl -2\n");
+ //Check if null
+ safe_fprintf(cout, "ldc 0\n");
+ safe_fprintf(cout, "eq\n");
+ safe_fprintf(cout, "brt print");
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, "e\n");
+ //Print element
+ safe_fprintf(cout, "ldl -2\n");
+ safe_fprintf(cout, "ldh -1\n");
+ safe_fprintf(cout, "bsr print");
+ overloaded_type(loc, type->data.ttuple.l, cout);
+ safe_fprintf(cout, "\n");
+ safe_fprintf(cout, "ajs -1\n");
+ safe_fprintf(cout, "ldl -2\n");
+ safe_fprintf(cout, "ldh 0\n");
+ safe_fprintf(cout, "stl -2\n");
+ //Print space
+ safe_fprintf(cout, "ldc 44\ntrap 1\n");
+ safe_fprintf(cout, "ldc 32\ntrap 1\n");
+ safe_fprintf(cout, "bra print");
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, "b\n");
+ //End label
+ safe_fprintf(cout, "print");
+ overloaded_type(loc, type, cout);
+ safe_fprintf(cout, "e:\n");
+ //Print ]
+ safe_fprintf(cout, "ldc 93\ntrap 1\n");
+ break;
+ case ttuple:
+ safe_fprintf(cout, "ldc 40\ntrap 1\n");
+ safe_fprintf(cout, "ldl -2\nldh -1\n");
+ safe_fprintf(cout, "bsr print");
+ overloaded_type(loc, type->data.ttuple.l, cout);
+ safe_fprintf(cout, "\n");
+ safe_fprintf(cout, "ajs -1\n");
+ safe_fprintf(cout, "ldc 44\ntrap 1\n");
+ safe_fprintf(cout, "ldl -2\nldh 0\n");
+ safe_fprintf(cout, "bsr print");
+ overloaded_type(loc, type->data.ttuple.r, cout);
+ safe_fprintf(cout, "\n");
+ safe_fprintf(cout, "ajs -1\n");
+ safe_fprintf(cout, "ldc 41\ntrap 1\n");
+ break;
+ default:
+ break;
+ }
+ safe_fprintf(cout, "unlink\n");
+ safe_fprintf(cout, "ret\n");
+}
+
+static void call_print_type(YYLTYPE loc, 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(loc, type->data.tlist, cout);
+ break;
+ case ttuple:
+ safe_fprintf(cout, "t");
+ call_print_type(loc, type->data.ttuple.l, cout);
+ call_print_type(loc, type->data.ttuple.r, cout);
+ safe_fprintf(cout, "t");
+ break;
+ case tvar:
+ type_error(loc, true, "cannot print overloaded types???");
+ break;
+ }
+}
+
+//static void generate_print_body(struct type *type, FILE *cout)
+//{
+// YYLTYPE loc;
+// switch(type->type) {
+// case tbasic:
+// safe_fprintf(cout, "\tprint_");
+// call_print_type(loc, type, cout);
+// safe_fprintf(cout, ");\n");
+// break;
+// case tlist:
+// safe_fprintf(cout, "\tprintf(\"[\");\n");
+// safe_fprintf(cout, "\twhile(t != NULL) {\n");
+// safe_fprintf(cout, "\t\tprint_");
+// call_print_type(loc, type->data.tlist, cout);
+// safe_fprintf(cout, "(t->hd);\n");
+// safe_fprintf(cout, "\t\tif (t->tl != NULL) printf(\", \");\n");
+// safe_fprintf(cout, "\t\tt = t->tl;\n");
+// safe_fprintf(cout, "\t}\n");
+// safe_fprintf(cout, "\tprintf(\"]\");\n");
+// break;
+// case ttuple:
+// safe_fprintf(cout, "\tprintf(\"(\");\n");
+// safe_fprintf(cout, "\tprint_");
+// call_print_type(loc, type->data.ttuple.l, cout);
+// safe_fprintf(cout, "(t->fst);\n");
+// safe_fprintf(cout, "\tprintf(\",\");\n");
+// safe_fprintf(cout, "\tprint_");
+// call_print_type(loc, type->data.ttuple.r, cout);
+// safe_fprintf(cout, "(t->snd);\n");
+// safe_fprintf(cout, "\tprintf(\")\");\n");
+// break;
+// default:
+// break;
+// }
+//}
+
+//static void generate_print(struct type *type, FILE *cout)
+//{
+// if (type->type == tbasic)
+// return;
+//
+// safe_fprintf(cout, "void print_");
+// YYLTYPE loc;
+// call_print_type(loc, type, cout);
+// safe_fprintf(cout, "(");
+// type_genc(type, cout);
+// safe_fprintf(cout, " t) {\n");
+// generate_print_body(type, cout);
+// safe_fprintf(cout, "}\n");
+//}
+static void expr_genssm(struct genssmst *st, struct expr *expr, FILE *cout)
+{
+ switch(expr->type) {
+ case ebinop:
+ expr_genssm(st, expr->data.ebinop.l, cout);
+ expr_genssm(st, expr->data.ebinop.r, cout);
+ if (expr->data.ebinop.op == eq || expr->data.ebinop.op == neq) {
+ safe_fprintf(cout, "bsr eq");
+ overloaded_type(expr->loc, expr->data.ebinop.type, cout);
+ safe_fprintf(cout, "\n");
+ safe_fprintf(cout, "ajs -2\n");
+ safe_fprintf(cout, "ldr RR\n");
+ if (expr->data.ebinop.op == neq)
+ safe_fprintf(cout, "neg\n");
+
+ } else if (expr->data.ebinop.op == cons) {
+ safe_fprintf(cout, "stmh 2\n");
+ } else if (expr->data.ebinop.op == power) {
+ safe_fprintf(cout, "bsr pow\n");
+ safe_fprintf(cout, "ajs -2\n");
+ safe_fprintf(cout, "ldr RR\n");
+ } else {
+ safe_fprintf(cout, "%s\n", binop_instr[expr->data.ebinop.op]);
+ }
+ break;
+ case ebool:
+ safe_fprintf(cout, "ldc %d\n", expr->data.ebool ? "-1" : "1");
+ break;
+ case echar:
+ safe_fprintf(cout, "ldc %d\n", expr->data.echar);
+ break;
+ case efuncall:
+ ARRAY_ITER(struct expr *, e, i, expr->data.efuncall.args)
+ expr_genssm(st, e, cout);
+ AIEND
+ if (strcmp(expr->data.efuncall.ident, "print") == 0) {
+ safe_fprintf(cout, "bsr print");
+// call_print_register(st, expr->data.efuncall.type);
+ call_print_type(expr->loc, expr->data.efuncall.type, cout);
+ safe_fprintf(cout, "\n");
+ } else {
+ safe_fprintf(cout, "bsr %s\n", expr->data.efuncall.ident);
+ safe_fprintf(cout, "ajs -%u\n",
+ ARRAY_SIZE(expr->data.efuncall.args));
+ }
+ break;
+ case eint:
+ safe_fprintf(cout, "ldc %d\n", expr->data.eint);
+ break;
+ //case eident:
+ // safe_fprintf(cout, "%s", expr->data.eident);
+ // break;
+ case enil:
+ safe_fprintf(cout, "ldc 0\n");
+ break;
+ case etuple:
+ expr_genssm(st, expr->data.etuple.left, cout);
+ expr_genssm(st, expr->data.etuple.right, cout);
+ safe_fprintf(cout, "stmh 2\n");
+ 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:
+ expr_genssm(st, expr->data.eunop.l, cout);
+ safe_fprintf(cout, "%s\n", unop_instr[expr->data.eunop.op]);
+ break;
+ default:
+ die("Unknown expression node\n");
+ }
+}
+
+static void stmt_genssm(struct genssmst *st, struct stmt *stmt, FILE *cout);
+static void body_genssm(struct genssmst *st, struct array body, FILE *cout)
+{
+ ARRAY_ITER(struct stmt *, s, i, body)
+ stmt_genssm(st, s, cout);
+ AIEND
+}
+
+static void stmt_genssm(struct genssmst *st, struct stmt *stmt, FILE *cout)
+{
+ switch(stmt->type) {
+ case sassign:
+// pindent(indent, cout);
+// safe_fprintf(cout, "%s", stmt->data.sassign.ident);
+// ARRAY_ITER(char *, f, i, stmt->data.sassign.fields)
+// safe_fprintf(cout, "->%s", f);
+// AIEND
+// safe_fprintf(cout, " = ");
+// expr_genabc(st, stmt->data.sassign.expr, cout);
+// safe_fprintf(cout, ";\n");
+ break;
+ case sif:
+ expr_genssm(st, stmt->data.sif.pred, cout);
+ safe_fprintf(cout, "brf _else%d\n", st->fresh);
+ body_genssm(st, stmt->data.sif.then, cout);
+ safe_fprintf(cout, "bra _endif%d\n", st->fresh);
+ safe_fprintf(cout, "_else%d:\n", st->fresh);
+ body_genssm(st, stmt->data.sif.els, cout);
+ safe_fprintf(cout, "_endif%d: \n", st->fresh++);
+ break;
+ case sreturn:
+ if (stmt->data.sreturn != NULL) {
+ expr_genssm(st, stmt->data.sreturn, cout);
+ safe_fprintf(cout, "str RR\n");
+ }
+ break;
+ case sexpr:
+ expr_genssm(st, stmt->data.sexpr, cout);
+ safe_fprintf(cout, "ajs -1\n");
+ break;
+ case svardecl:
+// vardecl_genc(st, stmt->data.svardecl, indent, cout);
+ break;
+ case swhile:
+ safe_fprintf(cout, "_while%d: \n", st->fresh);
+ expr_genssm(st, stmt->data.sif.pred, cout);
+ safe_fprintf(cout, "brf _endwhile%d\n", st->fresh);
+ body_genssm(st, stmt->data.swhile.body, cout);
+ safe_fprintf(cout, "bra _while%d\n", st->fresh);
+ safe_fprintf(cout, "_endwhile%d: \n", st->fresh++);
+ break;
+ default:
+ die("Unsupported stmt node\n");
+ }
+}
+
+
+static void vardecl_genssm(struct genssmst *st, struct vardecl *vardecl, FILE *cout)
+{
+ //TODO add to dictionary
+ expr_genssm(st, vardecl->expr, cout);
+}
+
+static void fundecl_genssm(struct genssmst *st, struct fundecl *decl, FILE *cout)
+{
+ safe_fprintf(cout, "%s: link 0\n", decl->ident);
+ //TODO add args to dictionary
+ body_genssm(st, decl->body, cout);
+ safe_fprintf(cout, "unlink\n");
+ safe_fprintf(cout, "ret\n");
+}
+
+void genssm(struct ast *ast, struct overload ol, FILE *cout)
+{
+ //Header
+ safe_fprintf(cout, "ldrr R5 R1\n");
+ struct genssmst st = { .fresh=0 };
+ for (int i = 0; i<ast->ndecls; i++)
+ if (ast->decls[i]->type == dvardecl)
+ vardecl_genssm(&st, ast->decls[i]->data.dvar, cout);
+ safe_fprintf(cout, "bsr main\n");
+ safe_fprintf(cout, "halt\n");
+
+ //Generate overloaded functions
+ ARRAY_ITER(struct type *, t, i, ol.print)
+ if (t->type != tbasic)
+ generate_print(t, cout);
+ AIEND
+ ARRAY_ITER(struct type *, t, i, ol.eq)
+ if (t->type != tbasic)
+ generate_eq(t, cout);
+ AIEND
+
+ //Generate code
+ for (int i = 0; i<ast->ndecls; i++)
+ if (ast->decls[i]->type == dcomp)
+ ARRAY_ITER(struct fundecl *, d, j, ast->decls[i]->data.dcomp)
+ fundecl_genssm(&st, d, cout);
+ AIEND
+ FILE *rts = fopen("rts.ssm", "r");
+ if (rts == NULL)
+ pdie("fopen");
+ #define BSIZE 1024
+ char buf[BSIZE];
+ size_t r;
+ do {
+ r = fread(buf, 1, BSIZE, rts);
+ if (r != BSIZE && ferror(rts) != 0)
+ pdie("fread");
+ if (fwrite(buf, 1, r, cout) != r)
+ pdie("fwrite");
+ } while(r == BSIZE);
+ if (fclose(rts) != 0)
+ pdie("fclose");
+}