diff options
Diffstat (limited to 'compile.c')
| -rw-r--r-- | compile.c | 121 |
1 files changed, 91 insertions, 30 deletions
@@ -18,19 +18,18 @@ CORD compile_type(type_ast_t *t) static inline CORD compile_statement(ast_t *ast) { - CORD code = compile(ast); switch (ast->tag) { - case If: case For: case While: case FunctionDef: - return code; + case If: case For: case While: case FunctionDef: case Return: case TypeDef: case Declare: case Assign: case UpdateAssign: + return compile(ast); default: - return CORD_cat(code, ";"); + return CORD_asprintf("(void)%r;", compile(ast)); } } CORD compile(ast_t *ast) { switch (ast->tag) { - case Nil: return "NULL"; + case Nil: return CORD_asprintf("(%r)NULL", compile_type(Match(ast, Nil)->type)); case Bool: return Match(ast, Bool)->b ? "true" : "false"; case Var: return Match(ast, Var)->var.name; case Int: return CORD_asprintf("((Int%ld_t)%ld)", Match(ast, Int)->precision, Match(ast, Int)->i); @@ -40,7 +39,7 @@ CORD compile(ast_t *ast) auto unop = Match(ast, UnaryOp); CORD expr = compile(unop->value); switch (unop->op) { - case UNOP_NOT: return CORD_cat("!", expr); + case UNOP_NOT: return CORD_asprintf("not(%r)", expr); case UNOP_NEGATIVE: return CORD_cat("-", expr); case UNOP_HEAP_ALLOCATE: return CORD_asprintf("__heap(%r)", expr); case UNOP_STACK_REFERENCE: return CORD_asprintf("__stack(%r)", expr); @@ -55,7 +54,8 @@ CORD compile(ast_t *ast) switch (binop->op) { case BINOP_MULT: return CORD_asprintf("(%r * %r)", lhs, rhs); case BINOP_DIVIDE: return CORD_asprintf("(%r / %r)", lhs, rhs); - case BINOP_MOD: return CORD_asprintf("(%r %% %r)", lhs, rhs); + case BINOP_MOD: return CORD_asprintf("mod(%r, %r)", lhs, rhs); + case BINOP_MOD1: return CORD_asprintf("mod1(%r, %r)", lhs, rhs); case BINOP_PLUS: return CORD_asprintf("(%r + %r)", lhs, rhs); case BINOP_MINUS: return CORD_asprintf("(%r - %r)", lhs, rhs); case BINOP_LSHIFT: return CORD_asprintf("(%r << %r)", lhs, rhs); @@ -66,8 +66,9 @@ CORD compile(ast_t *ast) case BINOP_LE: return CORD_asprintf("(%r <= %r)", lhs, rhs); case BINOP_GT: return CORD_asprintf("(%r > %r)", lhs, rhs); case BINOP_GE: return CORD_asprintf("(%r >= %r)", lhs, rhs); - case BINOP_AND: return CORD_asprintf("(%r && %r)", lhs, rhs); - case BINOP_OR: return CORD_asprintf("(%r || %r)", lhs, rhs); + case BINOP_AND: return CORD_asprintf("and(%r, %r)", lhs, rhs); + case BINOP_OR: return CORD_asprintf("or(%r, %r)", lhs, rhs); + case BINOP_XOR: return CORD_asprintf("xor(%r, %r)", lhs, rhs); default: break; } errx(1, "unimplemented binop"); @@ -77,21 +78,21 @@ CORD compile(ast_t *ast) CORD lhs = compile(update->lhs); CORD rhs = compile(update->rhs); switch (update->op) { - case BINOP_MULT: return CORD_asprintf("%r *= %r", lhs, rhs); - case BINOP_DIVIDE: return CORD_asprintf("%r /= %r", lhs, rhs); - case BINOP_MOD: return CORD_asprintf("%r = %r %% %r", lhs, lhs, rhs); - case BINOP_PLUS: return CORD_asprintf("%r += %r", lhs, rhs); - case BINOP_MINUS: return CORD_asprintf("%r -= %r", lhs, rhs); - case BINOP_LSHIFT: return CORD_asprintf("%r <<= %r", lhs, rhs); - case BINOP_RSHIFT: return CORD_asprintf("%r >>= %r", lhs, rhs); - case BINOP_EQ: return CORD_asprintf("%r = (%r == %r)", lhs, lhs, rhs); - case BINOP_NE: return CORD_asprintf("%r = (%r != %r)", lhs, lhs, rhs); - case BINOP_LT: return CORD_asprintf("%r = (%r < %r)", lhs, lhs, rhs); - case BINOP_LE: return CORD_asprintf("%r = (%r <= %r)", lhs, lhs, rhs); - case BINOP_GT: return CORD_asprintf("%r = (%r > %r)", lhs, lhs, rhs); - case BINOP_GE: return CORD_asprintf("%r = (%r >= %r)", lhs, lhs, rhs); - case BINOP_AND: return CORD_asprintf("%r = (%r && %r)", lhs, lhs, rhs); - case BINOP_OR: return CORD_asprintf("%r = (%r || %r)", lhs, lhs, rhs); + case BINOP_MULT: return CORD_asprintf("%r *= %r;", lhs, rhs); + case BINOP_DIVIDE: return CORD_asprintf("%r /= %r;", lhs, rhs); + case BINOP_MOD: return CORD_asprintf("%r = %r %% %r;", lhs, lhs, rhs); + case BINOP_PLUS: return CORD_asprintf("%r += %r;", lhs, rhs); + case BINOP_MINUS: return CORD_asprintf("%r -= %r;", lhs, rhs); + case BINOP_LSHIFT: return CORD_asprintf("%r <<= %r;", lhs, rhs); + case BINOP_RSHIFT: return CORD_asprintf("%r >>= %r;", lhs, rhs); + case BINOP_EQ: return CORD_asprintf("%r = (%r == %r);", lhs, lhs, rhs); + case BINOP_NE: return CORD_asprintf("%r = (%r != %r);", lhs, lhs, rhs); + case BINOP_LT: return CORD_asprintf("%r = (%r < %r);", lhs, lhs, rhs); + case BINOP_LE: return CORD_asprintf("%r = (%r <= %r);", lhs, lhs, rhs); + case BINOP_GT: return CORD_asprintf("%r = (%r > %r);", lhs, lhs, rhs); + case BINOP_GE: return CORD_asprintf("%r = (%r >= %r);", lhs, lhs, rhs); + case BINOP_AND: return CORD_asprintf("%r = (%r && %r);", lhs, lhs, rhs); + case BINOP_OR: return CORD_asprintf("%r = (%r || %r);", lhs, lhs, rhs); default: break; } errx(1, "unimplemented binop"); @@ -145,7 +146,7 @@ CORD compile(ast_t *ast) } case Declare: { auto decl = Match(ast, Declare); - return CORD_asprintf("__declare(%r, %r)", compile(decl->var), compile(decl->value)); + return CORD_asprintf("__declare(%r, %r);", compile(decl->var), compile(decl->value)); } case Assign: { auto assign = Match(ast, Assign); @@ -154,10 +155,22 @@ CORD compile(ast_t *ast) CORD_sprintf(&code, "%r = %r", compile(target->ast), compile(value->ast)); if (target->next) code = CORD_cat(code, ", "); } - return code; + return CORD_cat(code, ";"); } // Min, Max, // Array, Table, TableEntry, + case Array: { + auto array = Match(ast, Array); + if (!array->items) + return "(array_t){}"; + + CORD code = "__array("; + for (ast_list_t *item = array->items; item; item = item->next) { + code = CORD_cat(code, compile(item->ast)); + if (item->next) code = CORD_cat(code, ", "); + } + return CORD_cat_char(code, ')'); + } case FunctionDef: { auto fndef = Match(ast, FunctionDef); CORD code = CORD_asprintf("%r %r(", fndef->ret_type ? compile_type(fndef->ret_type) : "void", compile(fndef->name)); @@ -188,12 +201,60 @@ CORD compile(ast_t *ast) CORD_sprintf(&code, "%r\nelse %r", code, compile(if_->else_body)); return code; } - // For, While, If, + case While: { + auto while_ = Match(ast, While); + return CORD_asprintf("while (%r) %r", compile(while_->condition), compile(while_->body)); + } + case For: { + auto for_ = Match(ast, For); + CORD index = for_->index ? compile(for_->index) : "__i"; + return CORD_asprintf("{\n" + "__declare(__iter, %r);\n" + "for (int64_t %r = 1, __len = __length(__iter); %r <= __len; ++%r) {\n" + "__declare(%r, __safe_index(__iter, %s));\n" + "%r\n" + "}\n}", + compile(for_->iter), + index, index, index, + compile(for_->value), index, + compile(for_->body)); + } + // For, // Reduction, - // Skip, Stop, Pass, - // Return, + case Skip: { + if (Match(ast, Skip)->target) errx(1, "Named skips not yet implemented"); + return "continue"; + } + case Stop: { + if (Match(ast, Stop)->target) errx(1, "Named stops not yet implemented"); + return "break"; + } + case Pass: return ";"; + case Return: { + auto ret = Match(ast, Return)->value; + return ret ? CORD_asprintf("return %r;", compile(ret)) : "return;"; + } // Extern, - // TypeDef, + case TypeDef: { + auto def = Match(ast, TypeDef); + CORD code; + switch (def->type->tag) { + case TypeVar: { + CORD_sprintf(&code, "typedef %r %s_t;\n", compile_type(def->type), def->var.name); + break; + } + case TypeStruct: { + CORD_sprintf(&code, "typedef struct %s_s %s_t;\nstruct %s_s {\n", def->var.name, def->var.name, def->var.name); + for (arg_list_t *field = Match(def->type, TypeStruct)->fields; field; field = field->next) { + CORD_sprintf(&code, "%r%r %s;\n", code, compile_type(field->type), field->var.name); + } + code = CORD_cat(code, "};\n"); + break; + } + default: errx(1, "Typedef not implemented"); + } + return code; + } // Index, FieldAccess, // DocTest, // Use, |
