diff --git a/Codes_en_COREC/tests/test1.corec b/Codes_en_COREC/tests/test1.corec index d8c72207fa6db6a8587ab9d82ca32d297349de46..3e2bcc897e15da74defb9cd67bdb4b29dd13b60d 100644 --- a/Codes_en_COREC/tests/test1.corec +++ b/Codes_en_COREC/tests/test1.corec @@ -7,12 +7,12 @@ prog Test1 { a = 10; b = 2; - printstr("Affichage de variables, a: "); + printstr("Printing variable, a: "); print(a); - printstr("Affichage de variables, b: "); + printstr("Printing variable, b: "); print(b); - printstr("Affichage de variables, c: "); + printstr("Printing variable, c: "); print(c) } } diff --git a/Codes_en_COREC/tests/test2.corec b/Codes_en_COREC/tests/test2.corec index 1cbbcefab7b8f55633225918062c09ad436fbb07..a3a442a5d8f0aa383419f38dba6d0739ab99189f 100644 --- a/Codes_en_COREC/tests/test2.corec +++ b/Codes_en_COREC/tests/test2.corec @@ -7,44 +7,46 @@ prog Test2{ a = 10; b = 2; + printstr("a = 10, b = 2\n"); + c = a+b; - printstr("Addition, attendu 12: "); + printstr("a+b, expect 12 : "); print(c); c = a-b; - printstr("Substraction, attendu 8: "); + printstr("a-b, expect 8: "); print(c); c = a*b; - printstr("Multiplication, attendu 20: "); + printstr("a*b, expect 20: "); print(c); c = a/b; - printstr("Division, attendu 5: "); + printstr("a/b, expect 5: "); print(c); a += b; - printstr("Addition aff, attendu 12: "); + printstr("a += b aff, expect 12: "); print(a); a *= b; - printstr("Addition mult, attendu 24: "); + printstr("a *= b (a=12*2), expect 24: "); print(a); a /= b; - printstr("Addition mult, attendu 12: "); + printstr("a /= b (a=24/2), expect 12: "); print(a); a -= 4; - printstr("Addition mult, attendu 8: "); + printstr("a -= 4 (a=12-4), expect 8: "); print(a); c = a*a+2+b*b; - printstr("Addition mult, attendu 70: "); + printstr("a*a + 2 + b*b (8*8 + 2 + 2*2), expect 70: "); print(c); c= a*(a+b)-c/2; - printstr("Addition mult, attendu 45: "); + printstr(" a*(a+b)-c/2 (8*(8+2)-70/2), expect 45: "); print(c) } } diff --git a/Codes_en_COREC/tests/test3.corec b/Codes_en_COREC/tests/test3.corec index 93c55f2c0a8c1acfb037ffbb3f7892489f1b4505..21ad140b481f72e5e594fab374c7cbeb65c4c469 100644 --- a/Codes_en_COREC/tests/test3.corec +++ b/Codes_en_COREC/tests/test3.corec @@ -16,7 +16,7 @@ prog Test3 { f[0] = 1.0; // Implicit array of dim 1 length 1 -> f[0] array1[2] = f; - printstr("Expected result : 2.0 1.15 1.0 5.0 2.0 \nObtained Result : "); + printstr("Expected result : 2.00 1.15 1.00 5.00 2.00 \nObtained Result : "); print(array1) // contain all the values exchanges here if the code is correct } } diff --git a/Codes_en_COREC/tests/test4.corec b/Codes_en_COREC/tests/test4.corec index 1985bf0aed5aaee1c95504c5c9ff029a2095b8bd..e98a493406e29c5eada7bdd6d45c2c4c645563cb 100644 --- a/Codes_en_COREC/tests/test4.corec +++ b/Codes_en_COREC/tests/test4.corec @@ -13,21 +13,21 @@ prog Test4 { array[1] -= 2; array[2] /= 2; array[3] *= 2; - printstr("Expected : 4.0 0.0 1.0 4.0 0.0 0.0 \nObtained : "); + printstr("Expected : 4.00 0.00 1.00 4.00 0.00 0.00 \nObtained : "); print(array); array[1] = array[0] + float; array[2] = array[2] - float; array[3] = array[0] / float; array[4] = array[0] * float; - printstr("Expected : 4.0 7.0 -2.0 1.3333334 12.0 0.0 \nObtained : "); + printstr("Expected : 4.00 7.00 -2.00 1.33 12.00 0.00 \nObtained : "); print(array); array[2] = array[0] + array[1]; array[3] = array[0] - array[1]; array[4] = array[0] / array[1]; array[5] = array[0] * array[1]; - printstr("Expected : 4.0 7.0 11.0 -3.0 0.5714286 28.0 \nObtained : "); + printstr("Expected : 4.00 7.00 11.00 -3.00 0.57 28.00 \nObtained : "); print(array) } } diff --git a/Codes_en_COREC/tests/test5.corec b/Codes_en_COREC/tests/test5.corec index f2932258667e425dff75b8847d7f3158dd4a48dc..881dcd4206757ac05690ce33d0588a9f5ff2f49c 100644 --- a/Codes_en_COREC/tests/test5.corec +++ b/Codes_en_COREC/tests/test5.corec @@ -8,15 +8,15 @@ prog Test6 { f2 = 1.3; f1 += f2*2; - printstr("Expected : 1.2 + 1.3 * 2 = 3.8\nObtained : 1.2 + 1.3 * 2 = "); + printstr("Expected : 1.2 + 1.3 * 2 = 3.80\nObtained : 1.2 + 1.3 * 2 = "); print(f1); f2 = f2*2; - printstr("Expected : 1.3 * 2 = 2.6\nObtained : "); + printstr("Expected : 1.3 * 2 = 2.60\nObtained : "); print(f2); f1 /= f2+f2*4; - printstr("Expected : 3.8 / (2.6 + 2.6 * 4) = 0.29230767\nObtained : "); + printstr("Expected : 3.8 / (2.6 + 2.6 * 4) = 0.29\nObtained : "); print(f1) } } diff --git a/Codes_en_COREC/tests/test8.corec b/Codes_en_COREC/tests/test8.corec index 5fc568f43b4bd7b9c1c293b2faa0cd17caf4bba7..5d5baad19ceabe3d3a6d028198cc83d4442dc568 100644 --- a/Codes_en_COREC/tests/test8.corec +++ b/Codes_en_COREC/tests/test8.corec @@ -2,24 +2,105 @@ prog test8{ def Main { + Loc : a, b, c, (array,3) Rec : { a = 10; b = 2; + c = 17; + array = 0.12; printstr("a = 10 | b = 2"); - printstr("a<b ?"); + printstr("a>b ? "); a>b? { - printstr("oui") + printstr("YES\n") } - :printstr("non"); + :printstr("NO\n"); + + printstr("b equal 2 ? "); + b==2?printstr("YES\n"):printstr("NO\n"); + + printstr("advanced test, modify c if you want to test other branchings,\n"); + printstr("c=17 shouldn\'t work if one of the conditions isn't well implemented\n"); + c>10?{ + printstr("c > 10\n"); + c>=15?{ + printstr("c >= 15\n"); + c<19? { + printstr("c < 19\n"); + c<=16? { + printstr("c <= 16\n"); + c==15?printstr("c == 15"):printstr("c == 16") + } : { + printstr("c > 16\n"); + c==17?printstr("c == 17"):printstr("c == 18") + } + } : { + c==20?printstr("c == 20 "): { + printstr("c >= 19\n"); + c==19?printstr("c == 19 "):printstr("c must be <=20 (and >=0)") + } + } + } : { + printstr("c < 15\n"); + c>12? { + printstr("c > 12\n"); + c==13?printstr("c == 13"):printstr("c == 14") + } : { + printstr("c <= 12\n"); + c==12?printstr("c == 12"):printstr("c == 11") + } + } + } : { + printstr("c <= 10\n"); + c<1? { + printstr("c < 1\n"); + c==0?printstr("c == 0"):printstr("c must be >=0 (and <=20)") + } : { + printstr("c >= 1\n"); + c<=1?printstr("c == 1"): { + printstr("c > 1\n"); + c>=10?printstr("c == 10"): { + printstr("c < 10\n"); + c>2? { + printstr("c > 2\n"); + c<4?printstr("c == 3"): { + printstr("c >= 4\n"); + c==5?printstr("c == 5"):{ + printstr("c != 5\n"); + c>6?{ + printstr("c > 6\n"); + c==7?printstr("c == 7"): { + printstr("c != 7\n"); + c==8?printstr("c == 8"): { + printstr("c != 8\n"); + c<8?printstr("c == 6"):printstr("c == 9") + } + } + }:{ + printstr("c <= 6\n"); + c==6?printstr("c == 6"):printstr("c == 4") + } + } + } + }:printstr("c == 2") + } + } + } + }; + + printstr("\n\ntest conditions on float :\nIs 0.12 [array] greater than 0.1 : "); + array>0.1?printstr("YES\n"):printstr("NO\n"); + printstr("Is 0.12 [array] greater or equal to 0.12 : "); + array>=0.12?printstr("YES\n"):printstr("NO\n"); + printstr("Is 0.24 [array*2] equal to 0.24 : "); + array*2==0.24?printstr("YES\n"):printstr("NO\n"); + printstr("Is 0.11 [array-0.1] lesser than 0.12 [array] : "); + array-0.1<array?printstr("YES\n"):printstr("NO\n"); + printstr("Is 0.06 [array/2] lesser or equal to 0.06 [array-0.06] : "); + array/2<=array-0.06?printstr("YES\n"):printstr("NO\n") - printstr("b egal a 2 ?"); - b==2? - { - printstr("oui") - }: } } } diff --git a/Codes_en_COREC/tests/test9.corec b/Codes_en_COREC/tests/test9.corec index 562894dabe2f639881d02cc06dde1ed02c631e32..72bbfd1894599c1247e3e14c390060a86e6bcf0b 100644 --- a/Codes_en_COREC/tests/test9.corec +++ b/Codes_en_COREC/tests/test9.corec @@ -4,10 +4,10 @@ prog test9 { def Main { Loc: (f,1), saisie Rec : { - printstr("Saisie clavier :"); + printstr("Integer input asked:"); read(saisie); print(saisie); - printstr("Saisie float clavier:"); + printstr("Float input asked:"); read(f); print(f) } diff --git a/Makefile b/Makefile index 0d4f308f974a838effee9648301b7d7555518c94..d0ee398212bba144b457247079e1aaadcf5f78c1 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,9 @@ test_corec: all ./$(Compilateur_COREC) -tos < $(DIR_IN)/SystTriang.corec > $(DIR_OUT)/output7.asm test: all # Change to allDev if u want to display the lex tokens + ./$(Compilateur_COREC) -tos -o $(DIR_OUT)/output$(num).asm < $(DIR_IN)/tests/test$(num).corec + +testDev: allDev # Change to allDev if u want to display the lex tokens ./$(Compilateur_COREC) -tos -o $(DIR_OUT)/output$(num).asm < $(DIR_IN)/tests/test$(num).corec testTo: all diff --git a/README.md b/README.md index defef7834faaeb37ab00b29cf5f8ba58b49b8405..32880ef3d082d075bda597a00dfd618a89574586 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,9 @@ sudo apt install bison ### 6. branch test6 - Affectation multi dimensional array. ### 7. branch test7 -- Operations on multi dimensional array. **(TO DO :TRANSLATE IN MIPS)** +- Operations on multi dimensional array. +### 8. branch test8 +- conditional code execution ### 9.branch test9 - Read an int into an int variable - Read a float into a float variable diff --git a/corec.y b/corec.y index 24b6aadcca7d7310c56088b8279e1df44063a556..839648557e64cd6693f4b6d0e7a413049d03b028 100644 --- a/corec.y +++ b/corec.y @@ -11,6 +11,12 @@ struct symbol* symb_scope_function; // Boolean if we are in a print call uint8_t isPrintCall = 0; +// stack of the IF ELSE calls +struct labelStack * condition_stack; + +int indent; +char tabulation[INDENT_BUF]; + // Store the dimension or indexes when we call or declare an array struct symbol** tabArrayDim = NULL; // Store the length of the array @@ -35,6 +41,7 @@ void exit_safely(){ long int intval; float floatval; name_t strval; + wardLabels label; struct { struct symbol* ptr; @@ -60,7 +67,8 @@ void exit_safely(){ struct { uint8_t opnum; } opaff; -} + +}; %token prog %token def @@ -123,8 +131,9 @@ void exit_safely(){ %type <ptrNameDim> DLIST ARRAY ELIST %type <ptrValE> E T F CALL %type <ptrArray> ARRAYREF -%type <opaff> OPAFF -%type <opaff> OPREL +%type <opaff> OPAFF OPREL + + %% @@ -363,13 +372,13 @@ REC : } ; BLOCKINST : // Bloc of instructions - left_curly_bracket LISTEI right_curly_bracket + left_curly_bracket LISTEI right_curly_bracket | I ; LISTEI : LISTEI semicolon I // Last instruction hasn't a semilocon after | I - | %empty // Error detection -> Rec section empty + | %empty // Error detection -> Rec TODO section empty Rec isn't the only BLOCK using LISTEI { fprintf(stderr, "Error at line %u in function '%s': Unexpected end of rec section (shouldn't be empty).\n",lineNumber,symb_scope_function->u.name); exit_safely(); @@ -917,47 +926,21 @@ F : ; COND : - E OPREL E ternary_then B ternary_else B + CONDCHECK THEN B ELSE B { - struct symbol * boolean = newtemp(SYMTAB,INTEGER); - - switch($2.opnum){ - case 1: - gencode(CODE,OPREL_LT,boolean,$1.ptr,$3.ptr); - break; - - case 2: - gencode(CODE,OPREL_GT,boolean,$1.ptr,$3.ptr); - break; - - case 3: - gencode(CODE,OPREL_LE,boolean,$1.ptr,$3.ptr); - break; - - case 4: - gencode(CODE,OPREL_GE,boolean,$1.ptr,$3.ptr); - break; - - case 5: - gencode(CODE,OPREL_EQ,boolean,$1.ptr,$3.ptr); - break; - - default: - fprintf(stderr, "BUG\n"); - break; - } - name_t end_condition = snprintf(end_condition, sizeof(end_condition), "end_condition_%d", t->condition); - struct symbol * label = symtable_put_label(SYMTAB,end_condition); - name_t else_condition = snprintf(else_condition, sizeof(else_condition), "else_condition_%d", t->condition); - struct symbol * label = symtable_put_label(SYMTAB,else_condition); + // ENDIF label + gencode(CODE,RM_INDENT,NULL,NULL,NULL); + gencode(CODE,LABEL_W,condition_stack->elt.lbl2,NULL,NULL); - // TODO ahndle and gencode for if and else branches + pop_stack(&condition_stack); // we pop the current condition's labels since the condition is now over } ; B : BLOCKINST | %empty ; + + OPREL : inf { @@ -984,7 +967,70 @@ OPREL : ID : ID1 | ID2 + ; + +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); + switch($2.opnum){ + case 1: + gencode(CODE,OPREL_LT,tmp.lbl1,$1.ptr,$3.ptr); + break; + + case 2: + gencode(CODE,OPREL_GT,tmp.lbl1,$1.ptr,$3.ptr); + break; + + case 3: + gencode(CODE,OPREL_LE,tmp.lbl1,$1.ptr,$3.ptr); + break; + + case 4: + gencode(CODE,OPREL_GE,tmp.lbl1,$1.ptr,$3.ptr); + break; + + case 5: + gencode(CODE,OPREL_EQ,tmp.lbl1,$1.ptr,$3.ptr); + break; + + default: + fprintf(stderr, "BUG\n"); + break; + } + push_stack(&condition_stack,tmp); + (SYMTAB->condition) ++; + // go to else si la condition est fausse + + } + ; + +THEN : + ternary_then + { + + 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); + } + ; + +ELSE : + ternary_else + { + // goto endif juste après le code du IF + 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,ADD_INDENT,NULL,NULL,NULL); + } + ; %% void yyerror(const char * s) diff --git a/corecDev.l b/corecDev.l index 3e0143e135b57fff8adbeb85df52fdc557d404f7..25e59e242bcc87df56999c88a8d2d91df4348039 100644 --- a/corecDev.l +++ b/corecDev.l @@ -63,14 +63,20 @@ in {printf("in_dom"); return in_dom;} "/" {printf("divide"); return divide;} "%" {printf("mod"); return mod;} -([0-9]*[[:alpha:]]+|[[:alpha:]])[[:alnum:]]* { - printf("ID"); - if ( yyleng > 63 ) - fprintf(stderr,"Error at line %u: Identifier '%s' too long (> 31), truncated.\n",lineNumber,yytext); - strncpy(yylval.strval,yytext,63); - yylval.strval[64] = '\0'; - return ID; - } +[[:alpha:]][[:alnum:]]* { + if ( yyleng > 63 ) + fprintf(stderr,"Error at line %u: Identifier '%s' too long (> 63), truncated.\n",lineNumber,yytext); + strncpy(yylval.strval,yytext,63); + yylval.strval[64] = '\0'; + return ID1; + } +[0-9]*[[:alpha:]]+[[:alnum:]]* { + if ( yyleng > 63 ) + fprintf(stderr,"Error at line %u: Identifier '%s' too long (> 63), truncated.\n",lineNumber,yytext); + strncpy(yylval.strval,yytext,63); + yylval.strval[64] = '\0'; + return ID2; + } ["]([^"]|[\\]["])*["] { printf("chaine"); if ( yyleng > 1023 ) diff --git a/docs/tests.md b/docs/tests.md index bf98698d618e7757cacbd3ab11c69ea7f2c139cd..2bc6b3329034c2f931c65d788c469f7a82ad47ed 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -8,7 +8,7 @@ 5. Operation with float. 6. Declaration of local ND arrays and assignement of values. 7. Operation with ND arrays. -8. +8. if else and condition checks 9. Read an int or a float ## Error detection diff --git a/lib.c b/lib.c index 071790f6a9f5f3adcfe6f2e5ca4b8cdef8d5c694..bace0fd0c3445deb22038f18caf32e2b30794e02 100644 --- a/lib.c +++ b/lib.c @@ -1,9 +1,7 @@ #include "lib.h" -// TODO make it in a cleaner way -int indent = 0; -char tabulation[INDENT_BUF] = ""; + #define INDENT_MAKER struct symtable * symtable_new() @@ -20,7 +18,9 @@ struct symtable * symtable_new() exit(1); } t->temporary = 0; + t->condition = 0; t->size = 0; + init_indent(); return t; } @@ -97,7 +97,7 @@ struct symbol* symtable_get(struct symtable * t, const char * id, struct symbol* return &(t->symbols[i]); } return NULL; - } + } return &(t->symbols[i]); } @@ -193,13 +193,14 @@ struct symbol *newtemp(struct symtable * t, enum var_type ty) return s; } -struct symbol* symtable_put_label(struct symtable * t, const char * label_name, struct symbol* func_id) +struct symbol* symtable_put_label(struct symtable * t, const char* var_name, int cond_id, struct symbol* func_id) { if(t->size==t->capacity) symtable_grow(t); struct symbol *s = &(t->symbols[t->size]); s->kind = LABEL; - strcpy(s->u.name,label_name); + sprintf(s->u.name,"%s_%d",var_name,cond_id); + strcpy(s->scope_function,func_id->u.name); ++ (t->size); return s; } @@ -316,6 +317,7 @@ static void symbol_dump(struct symbol* s, FILE* fout) break; case LABEL: fprintf(fout,"%s",s->u.name); + break; default: fprintf(stderr,"BUG SYMBOL DUMP NOT RECOGNIZED\n"); break; @@ -416,6 +418,59 @@ static void quad_dump(struct quad * q, FILE* fout) symbol_dump(q->sym3,fout); fprintf(fout,"]"); break; + case OPREL_EQ: + symbol_dump(q->sym1,fout); + fprintf(fout," := "); + symbol_dump(q->sym2,fout); + fprintf(fout," == "); + symbol_dump(q->sym3,fout); + break; + case OPREL_GE: + symbol_dump(q->sym1,fout); + fprintf(fout," := "); + symbol_dump(q->sym2,fout); + fprintf(fout," >= "); + symbol_dump(q->sym3,fout); + break; + case OPREL_GT: + symbol_dump(q->sym1,fout); + fprintf(fout," := "); + symbol_dump(q->sym2,fout); + fprintf(fout," > "); + symbol_dump(q->sym3,fout); + break; + case OPREL_LE: + symbol_dump(q->sym1,fout); + fprintf(fout," := "); + symbol_dump(q->sym2,fout); + fprintf(fout," <= "); + symbol_dump(q->sym3,fout); + break; + case OPREL_LT: + symbol_dump(q->sym1,fout); + fprintf(fout," := "); + symbol_dump(q->sym2,fout); + fprintf(fout," < "); + symbol_dump(q->sym3,fout); + break; + case LABEL_W: + if(q->sym1!=NULL) + { + symbol_dump(q->sym1,fout); + fprintf(fout," :"); + } + break; + case GOTO_LABEL: + if(q->sym1!=NULL) + { + fprintf(fout,"goto "); + symbol_dump(q->sym1,fout); + } + break; + case ADD_INDENT: + break; + case RM_INDENT: + break; default: fprintf(stderr,"BUG quad_dump(...) : q->kind inconnu\n"); break; @@ -481,8 +536,8 @@ void code_mips_dump(struct symtable * t, struct code * c, FILE* fout){ // else if (t->symbols[i].kind == LABEL) { // fprintf(fout,"\t%s: .word 0\n",t->symbols[i].u.name); // } - else{ //NAME - fprintf(fout,"\ttemp%d: .word 0\n",i); + else{ // TODO check whether if in else shouldn't be printed or not ? + // fprintf(fout,"\ttemp%d: .word 0\n",i); } } @@ -527,7 +582,7 @@ void code_mips_dump(struct symtable * t, struct code * c, FILE* fout){ break; case DEF_MAIN: print_main_def(fout); - add_indent(1,c,t,fout); + add_indent(c,t,fout); break; case CALL_PRINT: print_print(t,c,fout,i); @@ -541,6 +596,33 @@ void code_mips_dump(struct symtable * t, struct code * c, FILE* fout){ case COPY: print_copy(t,c,fout,i); break; + case OPREL_EQ: + print_EQ_check(t,c,fout,i); + break; + case OPREL_GT: + print_GT_check(t,c,fout,i); + break; + case OPREL_GE: + print_GE_check(t,c,fout,i); + break; + case OPREL_LT: + print_LT_check(t,c,fout,i); + break; + case OPREL_LE: + print_LE_check(t,c,fout,i); + break; + case LABEL_W: + print_label_w(t,c,fout,i); + break; + case GOTO_LABEL: + print_goto(t,c,fout,i); + break; + case ADD_INDENT: + add_indent(c,t,fout); + break; + case RM_INDENT: + remove_indent(); + break; default: fprintf(stderr,"#BUG %d\n",c->quads[i].kind); break; @@ -711,7 +793,7 @@ void print_uop_minus(struct code * c, struct symtable* t, FILE* fout,int i) #endif if(ISFLOAT(c->quads[i].sym2)) { // float uop minus - if(!ISFLOAT(c->quads[i].sym2)) + if(!ISFLOAT(c->quads[i].sym2)) { // if sym2 is an integer convert it to a float and store it in $f0 convert_int_to_float("$f0","$t0",c->quads[i].sym2,t,fout); } else { // store it in $f0 @@ -736,6 +818,145 @@ void print_uop_minus(struct code * c, struct symtable* t, FILE* fout,int i) #endif } +// -------- COMPARISONS / OPREL RELATED -------- + +void print_EQ_check(struct symtable* t, struct code * c, FILE* fout,int i) +{ + #ifdef LIBDEBUG + fprintf(fout,"%s# equality check\n",tabulation); + #endif + if(c->quads[i].sym1->kind!=LABEL) + { + fprintf(stdout,"error gave a non label symbol, exiting\n"); + free_exit(1,c,t,fout); + } + if(ISFLOAT(c->quads[i].sym2)|| ISFLOAT(c->quads[i].sym3)) + { + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + fprintf(fout,"%sc.eq.s $f0, $f1\n",tabulation); + fprintf(fout,"%sbc1f %s\n",tabulation,c->quads[i].sym1->u.name); + } else { + // Check if we have variable names or just integers for sym2 and sym3 + print_nameOrInteger(c,fout,i,0b110); + // we wanna branch to the else when condition is false s owe do the opposite test == => != + fprintf(fout,"%sbne $t0, $t1, %s\n",tabulation,c->quads[i].sym1->u.name); + } +} + +void print_GT_check(struct symtable* t, struct code * c, FILE* fout,int i) +{ + #ifdef LIBDEBUG + fprintf(fout,"%s# Greater than check\n",tabulation); + #endif + if(c->quads[i].sym1->kind!=LABEL) + { + fprintf(stdout,"error gave a non label symbol, exiting\n"); + free_exit(1,c,t,fout); + } + if(ISFLOAT(c->quads[i].sym2)|| ISFLOAT(c->quads[i].sym3)) + { + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + // we go to else if lesser or equal is true since it's the oposite of greater than + fprintf(fout,"%sc.le.s $f0, $f1\n",tabulation); + fprintf(fout,"%sbc1t %s\n",tabulation,c->quads[i].sym1->u.name); + } else { + // Check if we have variable names or just integers for sym2 and sym3 + print_nameOrInteger(c,fout,i,0b110); + // we go to else if lesser or equal is true since it's the oposite of greater than + fprintf(fout,"%sble $t0, $t1, %s\n",tabulation,c->quads[i].sym1->u.name); + } +} +void print_GE_check(struct symtable* t, struct code * c, FILE* fout,int i) +{ + #ifdef LIBDEBUG + fprintf(fout,"%s# Greater or equal check\n",tabulation); + #endif + if(c->quads[i].sym1->kind!=LABEL) + { + fprintf(stdout,"error gave a non label symbol, exiting\n"); + free_exit(1,c,t,fout); + } + if(ISFLOAT(c->quads[i].sym2)|| ISFLOAT(c->quads[i].sym3)) + { + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + // we go to else if lesser than is true since it's the oposite of greater or equal + fprintf(fout,"%sc.lt.s $f0, $f1\n",tabulation); + fprintf(fout,"%sbc1t %s\n",tabulation,c->quads[i].sym1->u.name); + } else { + // Check if we have variable names or just integers for sym2 and sym3 + print_nameOrInteger(c,fout,i,0b110); + // we go to else if lesser than is true since it's the oposite of greater or equal + fprintf(fout,"%sblt $t0, $t1, %s\n",tabulation,c->quads[i].sym1->u.name); + } +} +void print_LT_check(struct symtable* t, struct code * c, FILE* fout,int i) +{ + #ifdef LIBDEBUG + fprintf(fout,"%s# Lesser than check\n",tabulation); + #endif + if(c->quads[i].sym1->kind!=LABEL) + { + fprintf(stdout,"error gave a non label symbol, exiting\n"); + free_exit(1,c,t,fout); + } + if(ISFLOAT(c->quads[i].sym2)|| ISFLOAT(c->quads[i].sym3)) + { + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + // we go to else if lesser than is false + fprintf(fout,"%sc.lt.s $f0, $f1\n",tabulation); + fprintf(fout,"%sbc1f %s\n",tabulation,c->quads[i].sym1->u.name); + } else { + // Check if we have variable names or just integers for sym2 and sym3 + print_nameOrInteger(c,fout,i,0b110); + // we go to else if greater or equal is true since it's the oposite of lesser than + fprintf(fout,"%sbge $t0, $t1, %s\n",tabulation,c->quads[i].sym1->u.name); + } +} +void print_LE_check(struct symtable* t, struct code * c, FILE* fout,int i) +{ + #ifdef LIBDEBUG + fprintf(fout,"%s# Lesser or equal check\n",tabulation); + #endif + if(c->quads[i].sym1->kind!=LABEL) + { + fprintf(stdout,"error gave a non label symbol, exiting\n"); + free_exit(1,c,t,fout); + } + if(ISFLOAT(c->quads[i].sym2)|| ISFLOAT(c->quads[i].sym3)) + { + load_float_bop_macro("$f0","$f1","$t0",c->quads[i].sym2,c->quads[i].sym3,t,fout); + // we go to else if lesser or equal is false + fprintf(fout,"%sc.le.s $f0, $f1\n",tabulation); + fprintf(fout,"%sbc1f %s\n",tabulation,c->quads[i].sym1->u.name); + } else { + // Check if we have variable names or just integers for sym2 and sym3 + print_nameOrInteger(c,fout,i,0b110); + // we go to else if greater than is true since it's the oposite of lesser or equal + fprintf(fout,"%sbgt $t0, $t1, %s\n",tabulation,c->quads[i].sym1->u.name); + } +} + +// -------- BRANCHING RELATED -------- + +void print_label_w(struct symtable* t, struct code * c, FILE* fout,int i) +{ + if(c->quads[i].sym1->kind!=LABEL) + { + fprintf(stdout,"error gave a non label symbol, exiting\n"); + free_exit(1,c,t,fout); + } + fprintf(fout,"%s%s:\n",tabulation,c->quads[i].sym1->u.name); +} + +void print_goto(struct symtable* t, struct code * c, FILE* fout,int i) +{ + if(c->quads[i].sym1->kind!=LABEL) + { + fprintf(stdout,"error gave a non label symbol, exiting\n"); + free_exit(1,c,t,fout); + } + fprintf(fout,"%sj %s\n",tabulation,c->quads[i].sym1->u.name); +} // -------- PRINT RELATED -------- void print_print(struct symtable * t,struct code * c, FILE* fout,int i) @@ -755,7 +976,7 @@ void print_print(struct symtable * t,struct code * c, FILE* fout,int i) // we avoid having 2 identical labels by putting the quad index at the end of it // /!\ start of the loop /!\ -- fprintf(fout,"%sprint_array_loop%d:\n",tabulation,i); - add_indent(1,c,t,fout); + add_indent(c,t,fout); // bge by security to avoid miss matching (which shouldn't be happening) fprintf(fout,"%sbge $t2, $t0, end_array_loop%d\n",tabulation,i); @@ -863,7 +1084,7 @@ void print_copy_array(struct symtable * t, struct code * c, FILE* fout,int i) #endif if(c->quads[i].sym2->kind != ARRAY){ fprintf(stdout,"Tried to do an Var = tab[index] operation but right part isn't an array should address this issue in the corec.y file\n"); - exit(1); + free_exit(1,c,t,fout); } // adress of the array element we want to copy load_tab_addr_macro("$t0", "$t1", "$t2", c->quads[i].sym2,c->quads[i].sym3,t,fout); @@ -886,7 +1107,7 @@ void print_allocate_array(struct symtable * t, struct code * c, FILE* fout,int i #endif if(c->quads[i].sym1->kind != ARRAY){ fprintf(stdout,"Tried to don an tab[index] = Var operation but left part isn't an array should address this issue in the corec.y file\n"); - exit(1); + free_exit(1,c,t,fout); } // number for the sbrk primitive call fprintf(fout,"%sli $v0, 9\n",tabulation); @@ -909,7 +1130,7 @@ void print_aff_array(struct symtable * t, struct code * c, FILE* fout,int i) #endif if(c->quads[i].sym1->kind != ARRAY){ fprintf(stdout,"Tried to do an tab[index] = Var operation but left part isn't an array should address this issue in the corec.y file\n"); - exit(1); + free_exit(1,c,t,fout); } // V alternative, effectue directement le*4 en calcul vu qu'on devrait passer par un load immediate dans tout les cas // fprintf(fout,"%sla $t0, %s\n",tabulation,c->quads[i].sym1->u.name); @@ -1078,7 +1299,6 @@ void print_SPACE_macro(FILE* fout){ fprintf(fout,".end_macro\n"); } - // ETC FEEL FREE TO ADD MORE SECTIONS // -------- DEBUG RELATED -------- @@ -1134,16 +1354,48 @@ 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; +} + +void pop_stack(labelStack ** stack) +{ + if((*stack) == NULL) + { + fprintf(stdout,"Trying to pop an empty stack \n"); + return; + } + labelStack * tmp = (*stack); + (*stack) = tmp->previous; + free(tmp); +} + +void raler(int err) +{ + if (err == 1) + perror (""); + exit(EXIT_FAILURE); + +} /************************* NAME TO DEFINE FUNCTIONS *************************/ -void add_indent(int code, struct code* c, struct symtable* t, FILE* fname){ +void add_indent(struct code* c, struct symtable* t, FILE* fname){ if(indent >= 1022) { printf("more than 1023 indentations ! write better code.\n"); - free_exit(code,c,t,fname); + free_exit(1,c,t,fname); } tabulation[indent] = '\t'; indent++; @@ -1159,4 +1411,10 @@ int remove_indent(){ indent--; tabulation[indent] = '\0'; return 0; +} + +void init_indent() +{ + indent=0; + tabulation[indent]='\0'; } \ No newline at end of file diff --git a/lib.h b/lib.h index 9744129475a5db58a7e1d0286ffd67ce1afe4672..fb93bd89c56bf6b2e443cedfc74a9744b6604bfa 100644 --- a/lib.h +++ b/lib.h @@ -11,6 +11,9 @@ extern struct symbol* symb_scope_function; #define LIBDEBUG #define ISFLOAT(X) ( X->kind == CONSTANT_FLOAT || X->kind == ARRAY || X->kind == NAME_FLOAT ) + + + /* TABLE DES SYMBOLES */ typedef char name_t[64]; @@ -39,6 +42,7 @@ enum kind{ LABEL // -> use the name attribut in the union u }; + // Struct symbol -> store a symbol struct symbol { enum kind kind; // attribut kind : the type of symbol; @@ -54,11 +58,13 @@ struct symbol { }; + + // Store the symbol table struct symtable { unsigned int capacity; unsigned int temporary; - unsigned int condition; // TODO find if necessary and how to name the different labels + unsigned int condition; unsigned int size; struct symbol* symbols; }; @@ -83,7 +89,7 @@ struct symbol* symtable_put_array(struct symtable * t, const char* var_name, uns // Add to the symtable a temporary function which is used to transform multiples addresses instruction to a group of 3 addresses instructions (uses NAME kind) struct symbol* newtemp(struct symtable * t,enum var_type ty); // Add to the symtable a label to branch different blocks of code -struct symbol* symtable_put_label(struct symtable * t, const char * label_name, struct symbol* func_id); +struct symbol* symtable_put_label(struct symtable * t, const char* var_name, int cond_id, struct symbol* func_id); // Get a pointer of a symbol with attribut name in the symtable (if 's' isn't in the table, return NULL) // (func_id is used for the scope of function on the local variable) @@ -107,7 +113,7 @@ void symtable_free(struct symtable * t); * COPY_ARRAY -> tmp=sym1 array=sym2 element=sym3 -> tmp= array[element] */ struct quad { - enum quad_kind { BOP_PLUS, BOP_MINUS, BOP_MULT, BOP_DIV, BOP_MOD, UOP_MINUS, COPY, COPY_ARRAY, ALLOCATE_ARRAY, AFF_ARRAY, DEF_MAIN, DEF_FUNCTION, CALL_PRINT, CALL_PRINTSTR, CALL_READ, CONDITION, OPREL_LT, OPREL_GT, OPREL_LE, OPREL_GE, OPREL_EQ} kind; + enum quad_kind { BOP_PLUS, BOP_MINUS, BOP_MULT, BOP_DIV, BOP_MOD, UOP_MINUS, COPY, COPY_ARRAY, ALLOCATE_ARRAY, AFF_ARRAY, DEF_MAIN, DEF_FUNCTION, CALL_PRINT, CALL_PRINTSTR, CALL_READ, CONDITION, OPREL_LT, OPREL_GT, OPREL_LE, OPREL_GE, OPREL_EQ, LABEL_W, GOTO_LABEL, ADD_INDENT, RM_INDENT} kind; struct symbol* sym1; struct symbol* sym2; struct symbol* sym3; @@ -168,6 +174,30 @@ void print_bop_mod(struct code * c, struct symtable* t, FILE* fout,int i); // add the UOP minus arithmetic operation TODO explain in more details void print_uop_minus(struct code * c, struct symtable* t, FILE* fout,int i); +// -------- COMPARISONS / OPREL RELATED -------- +/** @brief add the code to branch to symbol1 label if symbol2 and symbol3 aren't equal + */ +void print_EQ_check(struct symtable* t, struct code * c, FILE* fout,int i); +/** @brief add the code to branch to symbol1 label if symbol2 isn't > symbol3 + */ +void print_GT_check(struct symtable* t, struct code * c, FILE* fout,int i); +/** @brief add the code to branch to symbol1 label if symbol2 isn't >= symbol3 + */ +void print_GE_check(struct symtable* t, struct code * c, FILE* fout,int i); +/** @brief add the code to branch to symbol1 label if symbol2 isn't < symbol3 + */ +void print_LT_check(struct symtable* t, struct code * c, FILE* fout,int i); +/** @brief add the code to branch to symbol1 label if symbol2 isn't <= symbol3 + */ +void print_LE_check(struct symtable* t, struct code * c, FILE* fout,int i); + +// -------- BRANCHING RELATED -------- +/** @brief add the code to put the sym1 label into the mips code + */ +void print_label_w(struct symtable* t, struct code * c, FILE* fout,int i); +/** @brief add the code to go to sym1 label + */ +void print_goto(struct symtable* t, struct code * c, FILE* fout,int i); // -------- PRINT RELATED -------- // add the code to print the asked variable @@ -266,12 +296,48 @@ void debug_print_start(FILE * fout); void debug_print_end(FILE * fout); void debug_register_strings_declaration(FILE * fout); #endif + +// -------- STACK RELATED -------- +typedef struct { + int cond_number; + struct symbol * lbl1; + struct symbol * lbl2; +} wardLabels; + +typedef struct labelStack{ + wardLabels elt; + struct labelStack * previous; +} labelStack; + +extern labelStack * condition_stack; + +/** @brief add an element on top of the stack + */ +void push_stack(labelStack ** stack, wardLabels new_elt); + +/** @brief pop the top element of the stack + */ +void pop_stack(labelStack ** stack); + +// -------- ERROR CHECK -------- + +#define CHK(op,x) do { if ((op) == (x)) raler (1); } while (0) + +void raler(int err); + + // ETC FEEL FREE TO ADD MORE SECTIONS /************************* NAME TO DEFINE FUNCTIONS *************************/ +// TODO make it in a cleaner way +extern int indent; +extern char tabulation[INDENT_BUF]; + // add a tabulation to the indentation string -void add_indent(int code, struct code* c, struct symtable* t, FILE* fname); +void add_indent(struct code* c, struct symtable* t, FILE* fname); // remove a tabulation from the indentation string int remove_indent(); +// init the indentation tab +void init_indent();