/* * NAME: optimizer.c * DESCRIPTION: perform optimizations to a MOO AST before compilation */ # include <moo/tokens.h> # define PROTO(elt) static mixed *o_##elt##(mixed *ast) # define OPTIMIZE(ast, elt) o_##elt##(ast) PROTO(program); PROTO(if); PROTO(for); PROTO(while); PROTO(fork); PROTO(return); PROTO(expression); PROTO(list); PROTO(lvalue); /* * NAME: main() * DESCRIPTION: perform optimizations */ mixed *main(mixed *ast) { # if 1 return ast; # else return OPTIMIZE(ast, program); # endif } # if 0 /* optimizer proper */ PROTO(program) { int i, sz, tag; mixed *new; new = allocate(sz = sizeof(ast)); for (i = 0; i < sz; ++i) { switch (TAG(ast[i])) { case TOK_IF: new[i] = OPTIMIZE(ast[i], if); break; case TOK_FOR: new[i] = OPTIMIZE(ast[i], for); break; case TOK_WHILE: new[i] = OPTIMIZE(ast[i], while); break; case TOK_FORK: new[i] = OPTIMIZE(ast[i], fork); break; case TOK_RETURN: new[i] = OPTIMIZE(ast[i], return); break; default: /* expression */ new[i] = OPTIMIZE(ast[i], expression); tag = TAG(new[i]); if (tag == TOK_LIT_NUM || tag == TOK_LIT_STR || tag == TOK_LIT_OBJ || tag == TOK_LIT_ERR || tag == TOK_LIT_FLT) new[i] = ({ TOK_NOP }); } } return new; } PROTO(expression) { mixed *new; int i, sz; switch (TAG(ast)) { case TOK_LIT_NUM: case TOK_LIT_STR: case TOK_LIT_OBJ: case TOK_LIT_ERR: case TOK_LIT_FLT: return ast; case TOK_LBRACE: return OPTIMIZE(ast[1], list); case TOK_PLUS: new = ({ TOK_PLUS, OPTIMIZE(ast[1], expression), OPTIMIZE(ast[2], expression) }); switch (TAG(new[1])) { case TOK_LIT_NUM: if (TAG(new[2]) == TOK_LIT_NUM) return ({ TOK_LIT_NUM, new[1][1] + new[2][1] }); if (TAG(new[2]) == TOK_LIT_FLT) return ({ TOK_LIT_FLT, (float) new[1][1] + new[2][1] }); return new; case TOK_LIT_STR: if (TAG(new[2]) == TOK_LIT_STR) return ({ TOK_LIT_STR, new[1][1] + new[2][1] }); return ast; case TOK_LIT_FLT: if (TAG(new[2]) == TOK_LIT_FLT) return ({ TOK_LIT_FLT, new[1][1] + new[2][1] }); if (TAG(new[2]) == TOK_LIT_NUM) return ({ TOK_LIT_FLT, new[1][1] + (float) new[2][1] }); return ast; default: return ast; } case TOK_MINUS: new = ({ TOK_MINUS, OPTIMIZE( switch (TAG(ast[1])) { case TOK_LIT_NUM: if (TAG(ast[2]) == TOK_LIT_NUM) return ({ TOK_LIT_NUM, ast[1][1] - ast[2][1] }); if (TAG(ast[2]) == TOK_LIT_FLT) return ({ TOK_LIT_FLT, (float) ast[1][1] - ast[2][1] }); return ast; case TOK_LIT_FLT: if (TAG(ast[2]) == TOK_LIT_FLT) return ({ TOK_LIT_FLT, ast[1][1] - ast[2][1] }); if (TAG(ast[2]) == TOK_LIT_NUM) return ({ TOK_LIT_FLT, ast[1][1] - (float) ast[2][1] }); return ast; default: return ast; } case TOK_TIMES: switch (TAG(ast[1])) { case TOK_LIT_NUM: if (TAG(ast[2]) == TOK_LIT_NUM) return ({ TOK_LIT_NUM, ast[1][1] - ast[2][1] }); if (TAG(ast[2]) == TOK_LIT_FLT) return ({ TOK_LIT_FLT, (float) ast[1][1] - ast[2][1] }); return ast; case TOK_LIT_FLT: if (TAG(ast[2]) == TOK_LIT_FLT) return ({ TOK_LIT_FLT, ast[1][1] - ast[2][1] }); if (TAG(ast[2]) == TOK_LIT_NUM) return ({ TOK_LIT_FLT, ast[1][1] - (float) ast[2][1] }); return ast; default: return ast; } } } # endif