#include #include #include "shared.h" #include "intcode.h" #include "list.h" #include "quad.h" #include "mem.h" //compare two quadruples (actually, it works for any two pointers) int quadruple_cmp(const void *a, const void *b) { assert(a!= NULL && b != NULL); return (a==b); } list_head_t *list_makelist(quadruple_t *instr_ptr) { list_head_t *new_list = list_init(quadruple_cmp); list_insert(new_list,instr_ptr, NULL); return new_list; } //backpatches all the quadruples in the given list to point to the given instruction pointer. //used for gotos, both conditional and unconditional int backpatch(list_head_t *quad_list, quadruple_t *instr_ptr) { assert(quad_list != NULL); if(instr_ptr == NULL) { return 1; } list_entry_t *quad_entry = quad_list->list; quadruple_t *quad; while(quad_entry != NULL) { quad = (quadruple_t*)quad_entry->key; if(quad == NULL) { return 1; } quad_entry = quad_entry->next; quad->result = (intmdt_addr_t*)malloc(sizeof(intmdt_addr_t)); quad->result->type = code; quad->result->addr.instr_ptr = instr_ptr; } return 0; } //generates the code for the relational and equality operators //used for ==, !=, >, <, >=, <= intmdt_var_t *makeRel(void* arg1_v, char* op, void* arg2_v, intmdt_code_t *code, env_t *cur) { assert(arg1_v != NULL && arg2_v != NULL); intmdt_var_t *arg1_t = (intmdt_var_t*)arg1_v; intmdt_var_t *arg2_t = (intmdt_var_t*)arg2_v; intmdt_addr_t *arg1, *arg2; if(arg1_t->type == bool_expr || arg2->type == bool_expr) { fprintf(stderr, "cannot compare boolean expressions, line %d",yylineno); return NULL; } if(arg1_t->type == arith_expr) { arg1 = arg1_t->var.quad_ptr->result; } else { arg1 = arg1_t->var.addr_ptr; } if(arg2_t->type == arith_expr) { arg2 = arg2_t->var.quad_ptr->result; } else { arg2 = arg2_t->var.addr_ptr; } boolean_list_t *b = (boolean_list_t*)malloc(sizeof(boolean_list_t)); quadruple_t *next_instr = (quadruple_t*)(code_list->code + code_list->n); b->instr = next_instr; b->truelist = list_makelist(next_instr); b->falselist = list_makelist(++next_instr); gen2(code, op, arg1, arg2,NULL); gen2(code, NULL,NULL,NULL,NULL); intmdt_var_t *newVar = (intmdt_var_t*)malloc(sizeof(intmdt_var_t)); newVar->type = bool_expr; newVar->var.bool_list_ptr = b; return newVar; } //used for the bool->factor conversion, turnes a bool variable into an intmdt_var_t intmdt_var_t *makeBool(void *b,intmdt_code_t *code_list) { int* new_ref = (int*)malloc(sizeof(int)); *new_ref = ((int*)b == true_var); intmdt_var_t *var = (intmdt_var_t*)malloc(sizeof(intmdt_var_t)); var->type = bool_expr; boolean_list_t *blist =(boolean_list_t*)malloc(sizeof(boolean_list_t)); blist->instr = (quadruple_t*)(code_list->code + code_list->n); if((int*)b == true_var) { blist->truelist = list_makelist((quadruple_t*)(code_list->code + code_list->n )); blist->falselist = list_init(quadruple_cmp); } else { blist->falselist = list_makelist((quadruple_t*)(code_list->code + code_list->n )); blist->truelist = list_init(quadruple_cmp); } gen2(code_list,NULL,NULL,NULL,NULL); var->var.bool_list_ptr = blist; return var; } //generates the code needed to do a short circuit and intmdt_var_t *makeAnd(void *a_v, void *b_v, intmdt_code_t *code_list) { //TODO: need to also get a quadruple up through here, M.instr in the book's code intmdt_var_t *a = (intmdt_var_t*)a_v; intmdt_var_t *b = (intmdt_var_t*)b_v; if(!(a->type == bool_expr && b->type == bool_expr)){ fprintf(stderr,"ERROR: arguments to && must be boolean expressions, line %d\n",yylineno); return NULL; } boolean_list_t *a_b = a->var.bool_list_ptr; boolean_list_t *b_b = b->var.bool_list_ptr; backpatch(a_b->truelist, b_b->instr); intmdt_var_t *res = (intmdt_var_t*)malloc(sizeof(intmdt_var_t)); boolean_list_t *res_b = (boolean_list_t*)malloc(sizeof(boolean_list_t)); res_b->instr = a_b->instr; res_b->truelist = b_b->truelist; res_b->falselist = list_merge(a_b->falselist, b_b->falselist); res->type = bool_expr; res->var.bool_list_ptr = res_b; return res; } //generates the goto for the break //and puts it in the statement's nextlist intmdt_var_t *handleBreak(intmdt_code_t *code_list) { quadruple_t *quad = gen2(code_list, NULL, NULL, NULL, NULL); intmdt_var_t *var = malloc(sizeof(intmdt_var_t)); var->type = var_addr; assert(quad != NULL); var->var.quad_ptr = quad; var->nextlist = list_makelist(quad); return var; } //handles the nextlist attribute needed for breaks and continue (keep track of all breaks and continues //inside the loop void makeNextlist(void *a, void *b) { if(a == NULL) { return; } else { intmdt_var_t *a_i = (intmdt_var_t*)a; intmdt_var_t *b_i = (intmdt_var_t*)b; if(a_i->nextlist == NULL) { a_i->nextlist = b_i->nextlist; } else { a_i->nextlist = list_merge(a_i->nextlist, b_i->nextlist); } } } //generates the code needed for an if statement. intmdt_var_t *handleIf(void *cond_v, void*stmt_v, intmdt_code_t *code_list) { intmdt_var_t *cond = (intmdt_var_t*)cond_v; intmdt_var_t* stmt = (intmdt_var_t*)stmt_v; if(cond->type != bool_expr) { fprintf(stderr,"ERROR: condition in if statement must be boolean expression, line %d\n",yylineno); return NULL; } //TODO: need to handle break assert(stmt->type != bool_expr); //this should be an assert because statement handeling should get me here boolean_list_t *blist = cond->var.bool_list_ptr; backpatch(blist->truelist,stmt->var.quad_ptr); backpatch(blist->falselist, (quadruple_t*)(code_list->code + (code_list->n ))); //TODO: need to handle nextlist and that sort of thing //probably involves making another struct. //I'm going to guess intmdt_var_t *returned = malloc(sizeof(intmdt_var_t)); returned->type = var_addr; returned->var.quad_ptr = blist->instr; returned->nextlist = stmt->nextlist; return returned; } //handle the do-while loops. It's mostly the same as the if except for backpatching the nextlist intmdt_var_t *handleDoWhile(void *cond_v, void *stmt_v, intmdt_code_t *code_list) { handleIf(cond_v,stmt_v,code_list); intmdt_var_t* stmt = (intmdt_var_t*)stmt_v; intmdt_var_t *returned = malloc(sizeof(intmdt_var_t)); returned->type = var_addr; returned->var.quad_ptr = stmt->var.quad_ptr; if(stmt->nextlist != NULL) { backpatch(stmt->nextlist, code_list->code + code_list->n); } returned->nextlist = NULL; return returned; } //handles the code to generate short-circuit ors. intmdt_var_t *makeOr(void *a_v, void *b_v, intmdt_code_t *code_list) { intmdt_var_t *a = (intmdt_var_t*)a_v; intmdt_var_t *b = (intmdt_var_t*)b_v; if(!(a->type == bool_expr && b->type == bool_expr)){ fprintf(stderr,"ERROR: arguments to && must be boolean expressions, line %d\n",yylineno); return NULL; } boolean_list_t *a_b = a->var.bool_list_ptr; boolean_list_t *b_b = b->var.bool_list_ptr; backpatch(a_b->falselist, b_b->instr); intmdt_var_t *res = (intmdt_var_t*)malloc(sizeof(intmdt_var_t)); boolean_list_t *res_b = (boolean_list_t*)malloc(sizeof(boolean_list_t)); res_b->instr = a_b->instr; res_b->truelist = list_merge(a_b->truelist,b_b->truelist); res_b->falselist = b_b->falselist; res->type = bool_expr; res->var.bool_list_ptr = res_b; res->nextlist = NULL; return res; } //generate the code for a while loop and backpatch all of the breaks. intmdt_var_t *handleWhile(void *cond_v, void *stmt_v, intmdt_code_t *cd_list) { intmdt_var_t *stmt = (intmdt_var_t*)stmt_v; intmdt_var_t *cond = (intmdt_var_t*)cond_v; assert(stmt->type == var_addr); assert(cond->type == bool_expr); intmdt_addr_t *code_addr = malloc(sizeof(intmdt_addr_t)); code_addr->type = code; code_addr->addr.instr_ptr = cond->var.bool_list_ptr->instr; gen2(cd_list,NULL,NULL,NULL,code_addr); backpatch(cond->var.bool_list_ptr->truelist, stmt->var.quad_ptr); backpatch(cond->var.bool_list_ptr->falselist, cd_list->code + cd_list->n); if(stmt->nextlist != NULL) { backpatch(stmt->nextlist, cd_list->code + cd_list->n); } stmt->nextlist = NULL; return stmt; } //the code used to handle the if/else statements. It handles jumping in and out of the conditions intmdt_var_t *handleIfElse(void *cond_v, void *stmt1_v, void *stmt2_v, intmdt_code_t *cd_list) { intmdt_var_t *cond = (intmdt_var_t*)cond_v; intmdt_var_t*stmt2 = (intmdt_var_t*)stmt2_v; if(cond->type != bool_expr) { fprintf(stderr,"ERROR: if statmement must contain boolean expression, line %d\n",yylineno); } handleIf(cond_v,stmt1_v,cd_list); backpatch(cond->var.bool_list_ptr->falselist, stmt2->var.quad_ptr); list_head_t *gen_end = list_makelist(stmt2->var.quad_ptr - 1); backpatch(gen_end, cd_list->code + cd_list->n); intmdt_var_t *returned = malloc(sizeof(intmdt_var_t)); returned->type = var_addr; returned->var.quad_ptr = cond->var.bool_list_ptr->instr; return returned; }