diff --git a/Codes_en_COREC/tests/test10.corec b/Codes_en_COREC/tests/test10.corec index 0c8d007c1353a0a44cf90a9fb05f46b8204837ac..c576aa63f3efd6105588fac4f0f941af001e7bff 100644 --- a/Codes_en_COREC/tests/test10.corec +++ b/Codes_en_COREC/tests/test10.corec @@ -1 +1,24 @@ // For with Dom + + + +prog Test10 { + def Main{ + Loc: c, a=15331, NP=10 + Dom: i in [0..NP-1], j in [0..NP-1], k in [0..NP-1], l in [0..NP-1], m in [0..NP-1] + Rec: { + c = 10000*i + 1000*j + 100*k + 10*l + m +1; + + c%a==0?{ + print(c) + }: + c==100000?{ + print(c); + printstr("counting from 1 to 100000 (5 imbricated loop going from 0 to 9)\n"); + printstr("change a value in the test to print every time the count is"); + printstr(" a multiple of a or when reaching 100000\nonly print every : "); + print(a) + }: + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index 32880ef3d082d075bda597a00dfd618a89574586..d6f7dcc53d835684275f4a989da30a76218f5c45 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ sudo apt install bison ### 9.branch test9 - Read an int into an int variable - Read a float into a float variable +### 10.branch test10 +- implemented DOM for main and functions See in the [test report](./docs/tests.md) file the report on COREC tests features and error detection. diff --git a/corec.y b/corec.y index 3212409829d15e8fae7d43f1fe4c10e716706c7c..db288670d11266b49fec5deb44575ada513dfa01 100644 --- a/corec.y +++ b/corec.y @@ -13,6 +13,9 @@ uint8_t isPrintCall = 0; // stack of the IF ELSE calls struct labelStack * condition_stack; +// stacks of the DOM +struct domStack * dom_stack; + int indent; char tabulation[INDENT_BUF]; @@ -28,6 +31,8 @@ void exit_safely(){ free(tabArrayDim); } yylex_destroy(); + free_stack((void**)condition_stack,LBLSTACK); + free_stack((void**)dom_stack,DOMSTACK); free_exit(1,CODE,SYMTAB,fname); } @@ -362,10 +367,62 @@ DOMLIST : ; D : ID1 in_dom left_bracket E double_period E right_bracket + { + struct symbol * id = symtable_get(SYMTAB,$1,symb_scope_function); + struct symbol * loop_start, * loop_end; + + if(id == NULL || strcmp(id->scope_function,symb_scope_function->u.name) != 0 ) + { + id = symtable_put_loc(SYMTAB,$1,symb_scope_function); + } else { + fprintf(stderr, "Error at line %u in function '%s': DOM var shouldn't exist yet.\n",lineNumber,symb_scope_function->u.name); + exit_safely(); + } + + loop_start = symtable_put_label(SYMTAB,"loop_start",SYMTAB->dom,symb_scope_function); + loop_end = symtable_put_label(SYMTAB,"loop_end",SYMTAB->dom,symb_scope_function); + ++(SYMTAB->dom); + domQuad * to_push; + CHK(to_push = malloc(sizeof(domQuad)),NULL); + to_push->dom_var=id; + to_push->lbl1=loop_start; + to_push->lbl2=loop_end; + // copy the start val into the dom var + gencode(CODE,COPY,id,$4.ptr,NULL); + // put the start loop label + gencode(CODE,LABEL_W,loop_start,NULL,NULL); + // we add an indent level since we enter a new label + gencode(CODE, ADD_INDENT,NULL,NULL,NULL); + // branch to end of loop if dom var (i,j,k or anything it's named) is greater than the end value of the loop (if lesser or equal is false) + gencode(CODE,OPREL_LE,loop_end,id,$6.ptr); + // now the start of the loop is initialized we just put the infos needed for the end in the stack + push_stack((void*)(&dom_stack),to_push,DOMSTACK); + + } ; REC : rec BLOCKINST + { + // once the rec block is over we have to add the end of the different dom loops + while(dom_stack != NULL) + { + // we get the head of the stack which should be the first elt since DOMLIST access the doms from right to left if wrongjust reverse it + domQuad * tmp = head_stack((void**)(&dom_stack), DOMSTACK); + // we can now gen the END LOOP code + struct symbol * one = symtable_const_int(SYMTAB,1); + // add one to the loop index + gencode(CODE,BOP_PLUS,tmp->dom_var,tmp->dom_var,one); + // jump to start of loop + gencode(CODE,GOTO_LABEL,tmp->lbl1,NULL,NULL); + // end of this loop + gencode(CODE,RM_INDENT,NULL,NULL,NULL); + // put the end loop label + gencode(CODE,LABEL_W,tmp->lbl2,NULL,NULL); + // no longer of use we delete it with it's elt + pop_stack((void**)(&dom_stack), DOMSTACK, 1); + } + } | %empty // Error dectection -> Function without a rec section { fprintf(stderr, "Error at line %u in function '%s': Unexpected end of function (shouldn't be empty).\n",lineNumber,symb_scope_function->u.name); @@ -931,9 +988,9 @@ COND : { // ENDIF label gencode(CODE,RM_INDENT,NULL,NULL,NULL); - gencode(CODE,LABEL_W,condition_stack->elt.lbl2,NULL,NULL); + gencode(CODE,LABEL_W,condition_stack->elt->lbl2,NULL,NULL); - pop_stack(&condition_stack); // we pop the current condition's labels since the condition is now over + pop_stack((void**)(&condition_stack),LBLSTACK,1); // we pop the current condition's labels since the condition is now over } ; B : @@ -974,36 +1031,37 @@ CONDCHECK: E OPREL E { - wardLabels tmp; - tmp.cond_number = SYMTAB->condition; - tmp.lbl1 = symtable_put_label(SYMTAB, "else", tmp.cond_number, symb_scope_function); - tmp.lbl2 = symtable_put_label(SYMTAB, "endif", tmp.cond_number, symb_scope_function); + wardLabels * tmp; + CHK(tmp = malloc(sizeof(wardLabels)),NULL); + tmp->cond_number = SYMTAB->condition; + tmp->lbl1 = symtable_put_label(SYMTAB, "else", tmp->cond_number, symb_scope_function); + tmp->lbl2 = symtable_put_label(SYMTAB, "endif", tmp->cond_number, symb_scope_function); switch($2.opnum){ case 1: - gencode(CODE,OPREL_LT,tmp.lbl1,$1.ptr,$3.ptr); + gencode(CODE,OPREL_LT,tmp->lbl1,$1.ptr,$3.ptr); break; case 2: - gencode(CODE,OPREL_GT,tmp.lbl1,$1.ptr,$3.ptr); + gencode(CODE,OPREL_GT,tmp->lbl1,$1.ptr,$3.ptr); break; case 3: - gencode(CODE,OPREL_LE,tmp.lbl1,$1.ptr,$3.ptr); + gencode(CODE,OPREL_LE,tmp->lbl1,$1.ptr,$3.ptr); break; case 4: - gencode(CODE,OPREL_GE,tmp.lbl1,$1.ptr,$3.ptr); + gencode(CODE,OPREL_GE,tmp->lbl1,$1.ptr,$3.ptr); break; case 5: - gencode(CODE,OPREL_EQ,tmp.lbl1,$1.ptr,$3.ptr); + gencode(CODE,OPREL_EQ,tmp->lbl1,$1.ptr,$3.ptr); break; default: fprintf(stderr, "BUG\n"); break; } - push_stack(&condition_stack,tmp); + push_stack((void**)(&condition_stack),(void*)tmp,LBLSTACK); (SYMTAB->condition) ++; // go to else si la condition est fausse @@ -1014,7 +1072,7 @@ THEN : ternary_then { - struct symbol * if_label = symtable_put_label(SYMTAB, "if", condition_stack->elt.cond_number, symb_scope_function); + struct symbol * if_label = symtable_put_label(SYMTAB, "if", condition_stack->elt->cond_number, symb_scope_function); // lavel de la sectrion IF gencode(CODE, LABEL_W, if_label, NULL, NULL); gencode(CODE,ADD_INDENT,NULL,NULL,NULL); @@ -1025,10 +1083,10 @@ ELSE : ternary_else { // goto endif juste après le code du IF - gencode(CODE, GOTO_LABEL, condition_stack->elt.lbl2, NULL, NULL); + gencode(CODE, GOTO_LABEL, condition_stack->elt->lbl2, NULL, NULL); gencode(CODE,RM_INDENT,NULL,NULL,NULL); // label de la section ELSE - gencode(CODE, LABEL_W, condition_stack->elt.lbl1, NULL, NULL); + gencode(CODE, LABEL_W, condition_stack->elt->lbl1, NULL, NULL); gencode(CODE,ADD_INDENT,NULL,NULL,NULL); } ; diff --git a/lib.c b/lib.c index 960b2decdc9c8d8c2b8b5a6528d8c46c32af6720..369288f3c3884ebc33be1589ab17437c7631f224 100644 --- a/lib.c +++ b/lib.c @@ -17,8 +17,14 @@ struct symtable * symtable_new() fprintf(stderr,"Bug memory allocation failed\n"); exit(1); } + // make the stack point to null at start + condition_stack = NULL; + dom_stack = NULL; + + // init the different counters t->temporary = 0; t->condition = 0; + t->dom = 0; t->size = 0; init_indent(); return t; @@ -87,23 +93,32 @@ struct symbol* symtable_const_double(struct symtable * t, float v) } } +// for a given name return either a local symbol with the right scope or a non local symbol struct symbol* symtable_get(struct symtable * t, const char * id, struct symbol* func_id) { + //should unsigned int i; - for ( i=0 ; i<t->size && strcmp(t->symbols[i].u.name,id) != 0; i++ ); - if(i<t->size){ - if(t->symbols[i].kind == NAME_LOC || t->symbols[i].kind == ARRAY){ - if(strcmp(func_id->u.name,t->symbols[i].scope_function) == 0){ - return &(t->symbols[i]); + struct symbol * best_fit = NULL; + for ( i=0 ; i<t->size; i++ ) + { + if(strcmp(t->symbols[i].u.name,id) == 0) + { + if(t->symbols[i].kind == NAME_LOC || t->symbols[i].kind == ARRAY) + { // these names are only unique whithin a function_scope + // if the scope function is the same it's the right symbol + if(strcmp(func_id->u.name,t->symbols[i].scope_function) == 0) + return &(t->symbols[i]); + } + else if ((t->symbols[i].kind == NAME || t->symbols[i].kind == NAME_FLOAT || t->symbols[i].kind == LABEL) ) + { // these names are supposed to be unique so no overwrite of best_fit should be happening + best_fit = &(t->symbols[i]); } - return NULL; - } - return &(t->symbols[i]); + } } - - return NULL; + return best_fit; } + struct symbol* symtable_put_name(struct symtable * t, const char * id) { if(t->size==t->capacity) @@ -419,36 +434,41 @@ static void quad_dump(struct quad * q, FILE* fout) fprintf(fout,"]"); break; case OPREL_EQ: + fprintf(fout,"go to "); symbol_dump(q->sym1,fout); - fprintf(fout," := "); + fprintf(fout," if "); symbol_dump(q->sym2,fout); fprintf(fout," == "); symbol_dump(q->sym3,fout); break; case OPREL_GE: + fprintf(fout,"go to "); symbol_dump(q->sym1,fout); - fprintf(fout," := "); + fprintf(fout," if "); symbol_dump(q->sym2,fout); fprintf(fout," >= "); symbol_dump(q->sym3,fout); break; case OPREL_GT: + fprintf(fout,"go to "); symbol_dump(q->sym1,fout); - fprintf(fout," := "); + fprintf(fout," if "); symbol_dump(q->sym2,fout); fprintf(fout," > "); symbol_dump(q->sym3,fout); break; case OPREL_LE: + fprintf(fout,"go to "); symbol_dump(q->sym1,fout); - fprintf(fout," := "); + fprintf(fout," if "); symbol_dump(q->sym2,fout); fprintf(fout," <= "); symbol_dump(q->sym3,fout); break; case OPREL_LT: + fprintf(fout,"go to "); symbol_dump(q->sym1,fout); - fprintf(fout," := "); + fprintf(fout," if "); symbol_dump(q->sym2,fout); fprintf(fout," < "); symbol_dump(q->sym3,fout); @@ -1429,31 +1449,127 @@ void debug_register_strings_declaration(FILE * fout){ } #endif -// -------- ERROR CHECK -------- -void push_stack(labelStack ** stack, wardLabels new_elt) -{ - labelStack * new; - CHK( new = malloc(sizeof(labelStack)) , NULL ); - new->elt.cond_number = new_elt.cond_number; - new->elt.lbl1 = new_elt.lbl1; - new->elt.lbl2 = new_elt.lbl2; - new->previous = (*stack); - (*stack) = new; +// -------- STACK RELATED -------- + + + +void push_stack(void** stack, void* new_elt, enum stacktype type) { + switch (type) { + case LBLSTACK: { + labelStack* new_l; + CHK(new_l = malloc(sizeof(labelStack)), NULL); + labelStack** curr_stack_l = (labelStack**)stack; + // setup the new head of stack + new_l->previous = *curr_stack_l; + new_l->elt = (wardLabels*)new_elt; + // update the ptr to the head of the stack + *curr_stack_l = new_l; + break; + } + case DOMSTACK: { + domStack* new_d; + CHK(new_d = malloc(sizeof(domStack)), NULL); + domStack** curr_stack_d = (domStack**)stack; + // setup the new head of stack + new_d->previous = *curr_stack_d; + new_d->elt = (domQuad*)new_elt; + // update the ptr to the head of the stack + *curr_stack_d = new_d; + break; + } + default: + fprintf(stderr, "Error during push stack, this stack type doesn't exist.\n"); + break; + } +} + + + +void pop_stack(void** stack, enum stacktype type, int del_elt) { + if (*stack == NULL) { + fprintf(stdout, "Trying to pop an empty stack\n"); + return; + } + + switch (type) { + case LBLSTACK: { + labelStack** curr_stack_l = (labelStack**)stack; + + // Free elt if we don't need it ( del_elt !=0 ) + if (del_elt && (*curr_stack_l)->elt != NULL) { + free((*curr_stack_l)->elt); + (*curr_stack_l)->elt = NULL; + } + labelStack* tmp_l = *curr_stack_l; + *curr_stack_l = (*curr_stack_l)->previous; + free(tmp_l); + tmp_l = NULL; + break; + } + + case DOMSTACK: { + domStack** curr_stack_d = (domStack**)stack; + // Free elt if we don't need it ( del_elt !=0 ) + if (del_elt && (*curr_stack_d)->elt != NULL) { + free((*curr_stack_d)->elt); + (*curr_stack_d)->elt = NULL; + } + domStack* tmp_d = *curr_stack_d; + *curr_stack_d = (*curr_stack_d)->previous; + free(tmp_d); + tmp_d = NULL; + break; + } + + default: + fprintf(stderr, "Error during pop stack, this stack type doesn't exist.\n"); + break; + } } -void pop_stack(labelStack ** stack) +void * head_stack(void ** stack, enum stacktype type) { if((*stack) == NULL) { - fprintf(stdout,"Trying to pop an empty stack \n"); - return; + fprintf(stdout,"Trying to get the head of an empty stack, shouldn't happen\n"); + return NULL; + } + switch(type) + { + case LBLSTACK: + return (void*) ((*(labelStack **)stack)->elt); + case DOMSTACK: + return (void*) ((*(domStack **)stack)->elt); + default: + fprintf(stderr, "Error during head return stack, this stack type doesn't exist.\n"); + return NULL; } - labelStack * tmp = (*stack); - (*stack) = tmp->previous; - free(tmp); } +void free_stack(void ** stack, enum stacktype type) +{ + switch(type) + { + case LBLSTACK: + labelStack ** curr_stack_l = (labelStack **) stack; + while(*curr_stack_l != NULL) + pop_stack((void**)curr_stack_l,LBLSTACK,1); + break; + case DOMSTACK: + domStack ** curr_stack_d = (domStack **) stack; + while(*curr_stack_d != NULL) + pop_stack((void**)curr_stack_d,DOMSTACK,1); + break; + default: + fprintf(stderr, "Error during free stack, this stack type doesn't exist.\n"); + break; + } +} + + +// -------- ERROR CHECK -------- + void raler(int err) { if (err == 1) diff --git a/lib.h b/lib.h index c0b24fd69963d59da11dfc45f9904d0c64bfb23f..b92cf2d02178197995671a9a8cde7b3451c4132f 100644 --- a/lib.h +++ b/lib.h @@ -65,6 +65,7 @@ struct symtable { unsigned int capacity; unsigned int temporary; unsigned int condition; + unsigned int dom; // TODO could make a name based on the local var and the functon, for the moment don't wan't to handle names being too loong unsigned int size; struct symbol* symbols; }; @@ -306,6 +307,12 @@ void debug_register_strings_declaration(FILE * fout); #endif // -------- STACK RELATED -------- + +enum stacktype { + LBLSTACK, + DOMSTACK, +}; + typedef struct { int cond_number; struct symbol * lbl1; @@ -313,19 +320,41 @@ typedef struct { } wardLabels; typedef struct labelStack{ - wardLabels elt; + wardLabels * elt; struct labelStack * previous; } labelStack; +typedef struct { + struct symbol * dom_var; + struct symbol * lbl1; + struct symbol * lbl2; +} domQuad; + +typedef struct domStack{ + domQuad * elt; + struct domStack * previous; +} domStack; + extern labelStack * condition_stack; +extern domStack * dom_stack; + + /** @brief add an element on top of the stack */ -void push_stack(labelStack ** stack, wardLabels new_elt); +void push_stack(void ** stack, void * new_elt, enum stacktype types); /** @brief pop the top element of the stack + * if del_elt != 0, free the elt inside of the stack struct */ -void pop_stack(labelStack ** stack); +void pop_stack(void ** stack, enum stacktype type, int del_elt); + +void * head_stack(void ** stack, enum stacktype type); + +/** @brief free a whole stack + */ +void free_stack(void ** stack, enum stacktype type); + // -------- ERROR CHECK --------