diff --git a/check.sh b/check.sh old mode 100755 new mode 100644 diff --git a/src/grammar.y b/src/grammar.y index c7220c3..90ba7a4 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -38,6 +38,7 @@ %union { int integ; char* words; + char letter; void* tn; } @@ -547,30 +548,22 @@ WHILE L_PAREN expression R_PAREN sblock { simple_statement: assignable ASSIGN expression - { + { printdebug("simple statement"); TableNode* node; - if((getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE_TYPE|| - getAdInfoType((TableNode*)$1) == TYPE_ARRAY_TYPE|| - getAdInfoType((TableNode*)$1) == TYPE_RECORD_TYPE|| - getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_TYPE)){ - node = (TableNode*)$1; - }else if((getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION)|| + if((getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION)|| (getAdInfoType((TableNode*)$1) == TYPE_ARRAY)|| (getAdInfoType((TableNode*)$1) == TYPE_RECORD)|| (getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE)){ - - node = getTypeEntry((TableNode*)$1); + + node = ((TableNode*)$1); } else{ printdebug("Invalid type passed to assignable."); node = undefined; } - if((getAdInfoType(node) == TYPE_ARRAY_TYPE|| - getAdInfoType(node) == TYPE_RECORD_TYPE) && - (strcmp(getName((TableNode*)$3),"address") == 0)){ - printdebug("%s[☺] Passed array/record type check; %s = %s", COLOR_GREEN, getName(node), getName((TableNode*)$3)); - } - else if(getAdInfoType(node) == getAdInfoType((TableNode*)$3)){ + + if(getAdInfoType(node) == getAdInfoType((TableNode*)$3)){ + //EMIT ASSIGN INSTRUCTION HERE printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getName(node), getName((TableNode*)$3)); } else { throw_error(ERROR_TYPE, "%s != %s", getName(node), getName((TableNode*)$3)); @@ -580,7 +573,7 @@ simple_statement: } -| RETURN expression {$$ = $2;} +| RETURN expression {$$ = getTypeEntry((TableNode*)$2);} ; @@ -601,6 +594,7 @@ ablock: argument_list: + //NEED TO EMIT PARAMETERS HERE. MAYBE USE STACK STRUCTURE expression COMMA argument_list { CreateEntry(cur,getAdInfoType((TableNode*)$1), (TableNode*)$1, getName((TableNode*)$1), NULL); @@ -627,19 +621,29 @@ expression: | SUB_OR_NEG expression %prec UMINUS { printdebug("negative expression"); - if((TableNode*)$2 != integ) { - printdebug("cant negate something not an integer at line %d and column %d",@2.first_line,@2.first_column); - $$=undefined; + if(getTypeEntry((TableNode*)$2) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_unary_op(E_NEG,node,tn_or_const(NODE,$2)); + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + //result of unary operation + $$ = node; } else { - $$=(TableNode*)$2; + $$=undefined; + error_type(getTypeEntry((TableNode*)$2), integ, ""); } } | NOT expression { printdebug("not expression"); - if((TableNode*)$2 == boo) { - $$=(TableNode*)$2; + if(getTypeEntry((TableNode*)$2) == boo) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_unary_op(E_NOT,node,tn_or_const(NODE,$2)); + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + //result of unary operation + $$ = node; } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$2), getName(boo)); @@ -649,8 +653,11 @@ expression: | expression ADD expression { printdebug("add expression"); - if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) { - $$=(TableNode*)$1; + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_ADD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); @@ -660,8 +667,12 @@ expression: | expression SUB_OR_NEG expression { printdebug("sub or neg expression"); - if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) { - $$=(TableNode*)$1; + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_SUB,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + + $$ = node; } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); @@ -671,9 +682,12 @@ expression: | expression MUL expression { printdebug("multiply expression"); - if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) { - $$=(TableNode*)$1; - } else{ + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_MUL,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } @@ -682,8 +696,11 @@ expression: | expression DIV expression { printdebug("divide expression"); - if((strcmp(getName((TableNode*)$1),getName((TableNode*)$3))==0) && ((TableNode*)$1 == integ)) { - $$=(TableNode*)$1; + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_DIV,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); @@ -693,8 +710,11 @@ expression: | expression REM expression { printdebug("remainder expression"); - if($1 == $3 && $1 == integ) { - $$=$1; + if((getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_binary_op(E_MOD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); @@ -703,10 +723,13 @@ expression: | expression AND expression { - printdebug("AND expression"); - if($1 == $3 && $1 == boo){ - $$=$1; - } else{ + printdebug("AND"); + if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_binary_op(E_AND,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } @@ -715,8 +738,11 @@ expression: | expression OR expression { printdebug("OR"); - if((strcmp(getName((TableNode*)$1),getName((TableNode*)$3))==0) && $1 == boo) { - $$=$1; + if((getTypeEntry((TableNode*)$1)==getTypeEntry((TableNode*)$3)) && getTypeEntry((TableNode*)$1) == boo) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_binary_op(E_OR,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); @@ -726,8 +752,11 @@ expression: | expression LESS_THAN expression { printdebug("less than expression"); - if($1 == $3 && $1==integ) { - $$=boo; + if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1)==integ) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_binary_op(E_LESS_THAN,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; } else { $$=undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); @@ -737,8 +766,12 @@ expression: | expression EQUAL_TO expression { printdebug("equals check expression"); - if($1 == $3 && $1 != undefined) { - $$=boo; + if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1) != undefined) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + emit_binary_op(E_EQUAL_TO,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; + } else { $$ = undefined; throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); @@ -747,40 +780,23 @@ expression: | assignable { - printdebug("assignable expression. current type is %s",getName((TableNode*)$1)); - if(getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE|| - getAdInfoType((TableNode*)$1) == TYPE_ARRAY || - getAdInfoType((TableNode*)$1) == TYPE_RECORD){ - printdebug("assignable passing up to expression is primitive, array instance, or record instance. Passing up its type"); - $$= getTypeEntry((TableNode*)$1); - } - - else if(getAdInfoType((TableNode*)$1) == TYPE_ARRAY_TYPE|| - getAdInfoType((TableNode*)$1) == TYPE_RECORD_TYPE|| - getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_TYPE|| - getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE_TYPE || - getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION){ - printdebug("assignable passing up to expression is array type, record type, function type, or function declaration"); - $$= ((TableNode*)$1); - } - else { - printdebug("Invalid type passed to expression."); - $$= ((TableNode*)$1); - } - + $$ = $1; } | L_PAREN expression R_PAREN { - printdebug("paren expression. current type is %s",getName((TableNode*)$2)); + printdebug("paren expression. current type is %s",getType((TableNode*)$2)); $$=$2; } | memOp assignable { int d = getAdInfoType((TableNode*)$2); - if(d == TYPE_ARRAY_TYPE || d == TYPE_ARRAY || d == TYPE_RECORD_TYPE || d == TYPE_RECORD) { - $$ = addr; + if(d == TYPE_ARRAY ||d == TYPE_RECORD) { + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL); + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + $$ = node; } else { throw_error(ERROR_TYPE, "Invalid memOp expression (%s).", getName((TableNode*)$2)); $$=undefined; @@ -797,8 +813,9 @@ expression: assignable: ID { - $$ = getTypeEntry(look_up(cur,$1)); - printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getName((TableNode*)$$), $1); + TableNode* pass = look_up(cur,$1); + $$ = pass; + printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getType(pass), getName(pass)); } | assignable @@ -806,22 +823,24 @@ assignable: printdebug("%sBeginning rule 2 of assignable.", COLOR_CYAN); cur = CreateScope(cur, -1,-1); } + //we have to consider emmissions in ablocks ablock { - int type = getAdInfoType(look_up(getParent(cur), getName((TableNode*)$1))); + //int type = getAdInfoType(look_up(getParent(cur), getName((TableNode*)$1))); + int type = getAdInfoType(getTypeEntry((TableNode*)$1)); printdebug("%stype is %d", COLOR_PURPLE, type); printdebug("%s", getName((TableNode*)$1)); if (type == TYPE_FUNCTION_TYPE) { printdebug("%sEntering function call", COLOR_LIGHTGREEN); - if (look_up(getParent(cur), getName((TableNode*)$1))->additionalinfo->FunDecAdInfo->regularoras) { + if (look_up(getParent(cur), getType((TableNode*)$1))->additionalinfo->FunDecAdInfo->regularoras) { printdebug("as function"); //char *funtype = getType(look_up(cur, $1)); -// printdebug("%s", getType(look_up(cur, getName((TableNode*)$1)))); + //printdebug("%s", getType(look_up(cur, getName((TableNode*)$1)))); - TableNode * typeNode = $1; + TableNode * typeNode = getTypeEntry((TableNode*)$1); TableNode *param = getParameter(typeNode); printTableNode(param); @@ -862,7 +881,7 @@ assignable: } } } else { - char *expected = getName(getParameter(look_up(getParent(cur), getName((TableNode*)$1)))); + char *expected = getName(getParameter(look_up(getParent(cur), getType((TableNode*)$1)))); char *actual = getType(getFirstEntry(cur)); if (strcmp(expected, actual) != 0) { printdebug("expected %s expression in function call but got %s at line %d and column %d",expected, actual, @3.first_line, @3.first_column); @@ -871,29 +890,99 @@ assignable: printdebug("expected 1 argument but got %d", $3); } } - printTableNode(getReturn($1)); - $$ = getReturn($1); - printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName((TableNode*)$$), getName((TableNode*)$1)); + printTableNode(getReturn(getTypeEntry((TableNode*)$1))); + // + char* temp = temp_var_gen(); + TableNode* typeNode2 = getReturn(getTypeEntry($1)); + int t = -1; + if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){ + t = TYPE_PRIMITIVE; + } + else if(getAdInfoType(typeNode2) == TYPE_ARRAY_TYPE){ + t = TYPE_ARRAY; + } + else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){ + t = TYPE_RECORD; + } + else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){ + t = TYPE_FUNCTION_DECLARATION; + }else{ + t= TYPE_UNDEFINED; + printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper."); + } + TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL); + $$ = node; + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK for function call) + printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName(typeNode2), getName((TableNode*)$1)); } else if (type == TYPE_ARRAY_TYPE) { printdebug("%sEntering array call", COLOR_LIGHTGREEN); - if (getNumArrDim(look_up(getParent(cur), getName((TableNode*)$1))) != $2) { + if (getNumArrDim(look_up(getParent(cur), getType((TableNode*)$1))) != $2) { printdebug("expected %d arguments but had %d at line %d and column %d\n", getNumArrDim(look_up(cur, getName((TableNode*)$1))), $2, @2.first_line, @2.first_column); } - $$ = getArrType(look_up(cur, getName((TableNode*)$1))); - printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName((TableNode*)$$), getName((TableNode*)$1)); - printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName((TableNode*)$$), getName((TableNode*)$1)); + + char* temp = temp_var_gen(); + TableNode* typeNode2 = getArrType(look_up(getAncestor(cur), getType((TableNode*)$1))); + int t = -1; + if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){ + t = TYPE_PRIMITIVE; + } + else if(getAdInfoType(typeNode2) == TYPE_ARRAY_TYPE){ + t = TYPE_ARRAY; + } + else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){ + t = TYPE_RECORD; + } + else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){ + t = TYPE_FUNCTION_DECLARATION; + }else{ + t= TYPE_UNDEFINED; + printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper."); + } + TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL); + //emit assign here + //emit_array_access(char* node, char* array, ...) + $$ = node; + printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getType((TableNode*)$1), getName((TableNode*)$1)); } cur = getParent(cur); } | assignable rec_op ID - { - if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), getName((TableNode*)$1))), $3)) { + { + if(getAdInfoType((TableNode*)$1) != TYPE_RECORD_TYPE){ + printdebug("CHANGE ME [TYPE CHECK]Invalid type passed to record access"); + } + else if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3)) { - $$ = table_lookup(getRecList(table_lookup(getAncestor(cur), getName((TableNode*)$1))), $3); + TableNode* type = table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3); + char* temp = temp_var_gen(); + int t = -1; + if(getAdInfoType(type) == TYPE_PRIMITIVE_TYPE){ + t = TYPE_PRIMITIVE; + } + else if(getAdInfoType(type) == TYPE_ARRAY_TYPE){ + t = TYPE_ARRAY; + } + else if(getAdInfoType(type) == TYPE_RECORD_TYPE){ + t = TYPE_RECORD; + } + else if(getAdInfoType(type) == TYPE_FUNCTION_TYPE){ + t = TYPE_FUNCTION_DECLARATION; + }else{ + t= TYPE_UNDEFINED; + printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper."); + } + + TableNode* node = CreateEntry(cur,t, type, temp, NULL); + //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + //emit_field_access(char* node, char* record, $3) + $$=node; + }else{ + printdebug("CHANGE ME [TYPE CHECK] undefined type (Field Access Lookup failed)"); + $$=undefined; } - printdebug("[ASSIGNABLE - RULE 3] assignable = type: %s | ID = %s", getName((TableNode*)($$)), getName($1)); + printdebug("[ASSIGNABLE - RULE 3] record = name: %s | field = %s", getName((TableNode*)($1)), getName((TableNode*)$3)); } ; @@ -917,38 +1006,58 @@ memOp: constant: C_STRING { - $$ = $1; - printdebug("string of C_STRING in constant is %s",getName((TableNode*)$1)); + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, stri, temp, NULL); + emit_assignment(node, tn_or_const(STRING,$1)); + printdebug("string of C_STRING in constant is %s", $1); + $$ = node; } | C_INTEGER { - $$ = integ; - printdebug("string of C_INTEGER in constant is integer"); + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); + emit_assignment(node, tn_or_const(INTEGER,&$1)); + printdebug("number of C_INTEGER in constant is %d", $1); + $$ = node; } | C_NULL { - $$ = $1; - printdebug("string of C_NULL in constant is %s",getName((TableNode*)$1)); + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL); + emit_assignment(node, tn_or_const(ADDRESS,$1)); + printdebug("string of C_NULL in constant is NULL"); + $$ = node; } | C_CHARACTER { - $$ = $1; - printdebug("string of C_CHARACTER in constant is %s",getName((TableNode*)$1)); + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, chara, temp, NULL); + emit_assignment(node, tn_or_const(CHARACTER,&$1)); + printdebug("string of C_CHARACTER in constant is %s",$1); + $$ = node; } | C_TRUE { - $$ = $1; - printdebug("string of C_TRUE in constant is %s",getName((TableNode*)$1)); + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + uint_least8_t b = 1; + emit_assignment(node, tn_or_const(BOOLEAN,&b)); + printdebug("string of C_TRUE in constant is true"); + $$ = node; } | C_FALSE { - $$ = $1; - printdebug("string of C_FALSE in constant is %s",getName((TableNode*)$1)); + char* temp = temp_var_gen(); + TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); + uint_least8_t b = 0; + emit_assignment(node, tn_or_const(BOOLEAN,&b)); + printdebug("string of C_FALSE in constant is false"); + $$ = node; } ; diff --git a/src/lexicalStructure.lex b/src/lexicalStructure.lex index 8d92cdd..2aaf6d2 100644 --- a/src/lexicalStructure.lex +++ b/src/lexicalStructure.lex @@ -82,10 +82,10 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\] "," { if(tok_flag != NULL) {print_tok(COMMA);} incr(line_number,column_number,COMMA); return COMMA; } "->" { if(tok_flag != NULL) {print_tok(ARROW);} incr(line_number,column_number,ARROW); return ARROW; } -{DIGIT}+ { if(tok_flag != NULL) {print_tok(C_INTEGER);} incr(line_number,column_number,C_INTEGER); yylval.integ = atoi(yytext); return C_INTEGER; } -'{CHAR}' { if(tok_flag != NULL) {print_tok(C_CHARACTER);} incr(line_number,column_number,C_CHARACTER); yylval.tn = chara; return C_CHARACTER; } -\"{SCHAR}*\" { if(tok_flag != NULL) {print_tok(C_STRING);} incr(line_number,column_number,C_STRING); yylval.tn = stri; return C_STRING; } -{COMMENT} { if(tok_flag != NULL) {print_tok(COMMENT);} incr(line_number,column_number,COMMENT);} +{DIGIT}+ {if(tok_flag != NULL){print_tok(C_INTEGER);}incr(line_number,column_number,C_INTEGER);yylval.integ = atoi(yytext)/*words = strdup("integer")*/;return C_INTEGER;} +'{CHAR}' {if(tok_flag != NULL){print_tok(C_CHARACTER);}incr(line_number,column_number,C_CHARACTER);char* token = strdup(yytext)/*yylval.tn = chara*/;yylval.letter = token[1];return C_CHARACTER;} +\"{SCHAR}*\" {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);int k = strlen(yytext);yytext[k-1] = '\0';yylval.words = strdup(&yytext[1]);return C_STRING;} +{COMMENT} {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/} "(" { if(tok_flag != NULL) {print_tok(L_PAREN);} incr(line_number,column_number,L_PAREN); return L_PAREN; } ")" { if(tok_flag != NULL) {print_tok(R_PAREN);} incr(line_number,column_number,R_PAREN); return R_PAREN; } diff --git a/src/runner.c b/src/runner.c index 5833e3e..3f8a8c5 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2,7 +2,8 @@ /* The Translators - Spring 2025 */ #include "runner.h" - +FILE *ir_flag = NULL; +//Constant_Stack *head = NULL; int main(int argc, char *argv[]) { if (argc == 1) { fprintf(stderr, INVALID); @@ -35,6 +36,7 @@ int main(int argc, char *argv[]) { alpha_file = fopen(argv[argc - 1], "r"); } } + cg_flag = fopen("cg.s", "w"); return run(alpha_file); } @@ -140,7 +142,10 @@ int run(FILE *alpha) { if (st_flag != NULL) { print_symbol_table(top, st_flag); + emit_as_file(stdout, begin); fclose(st_flag); + generate(); + fclose(cg_flag); } if (asc_flag != NULL) { @@ -157,10 +162,10 @@ int run(FILE *alpha) { fclose(ir_flag); } - if (cg_flag != NULL) { - printf("Flag -cg is not implemented yet\n"); - fclose(cg_flag); - } + //if (cg_flag != NULL) { + // printf("Flag -cg is not implemented yet\n"); + //fclose(cg_flag); + //} if (yyin != NULL) { fclose(yyin); diff --git a/src/runner.h b/src/runner.h index 0573255..d20776b 100644 --- a/src/runner.h +++ b/src/runner.h @@ -37,7 +37,8 @@ #include "../tmp/grammar.tab.h" #include "symbol_table.h" -extern int line_number, column_number; +extern int line_number; +extern int column_number; extern char *yytext; extern FILE *yyin; extern bool DEBUG; @@ -48,9 +49,8 @@ SymbolTable *cur; FILE *alpha_file; FILE *tok_flag = NULL; FILE *st_flag = NULL; -FILE *ir_flag = NULL; -FILE *cg_flag = NULL; FILE *asc_flag = NULL; +FILE *cg_flag = NULL; bool tc_flag = false; bool DEBUG = false; int no_flag = 0; @@ -66,6 +66,7 @@ TableNode *boo; TableNode *recprime; TableNode *funtypeprime; TableNode *undefined; +extern Instruction* begin; int main(int argc, char *argv[]); int check_flag(char *arg, char *alpha); diff --git a/src/symbol_table.c b/src/symbol_table.c index a464b93..e1e8ea4 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -3,6 +3,17 @@ #include "symbol_table.h" +Constant_Stack * head = NULL; +int temp2_count = 0; +bool code_gen = true; +char* temp = NULL; +int label_count=0; +Instruction* begin = NULL; +Instruction* current = NULL; +int offset = 0; +int currentsp = 0; +CGNode *cgList = NULL; + void printdebug_impl(char *file, int line, const char *format, ...) { if (DEBUG) { printf("%s<%s> [%d]%s ", COLOR_DARKGRAY, file, line, @@ -15,6 +26,76 @@ void printdebug_impl(char *file, int line, const char *format, ...) { } } +char * temp_var_gen(){ + char * ret = calloc(9, sizeof(*ret)); + sprintf(ret, "$t%d", temp2_count); + temp2_count++; + return ret; +} + +Constant_Stack *Push(TableNode *type, void *value, bool isConst) { + if (type == NULL || type == undefined) { + printdebug( + "passed a NULL reference/undefined reference to " + "CreateConstantStack. Invalid."); + return NULL; + } + Constant_Stack *cs = (Constant_Stack *)malloc(sizeof(Constant_Stack)); + cs->theType = type; + cs->theValue = value; + cs->isConst = isConst; + if(head == NULL){ + head = cs; + cs->next = NULL; + }else{ + cs->next = head; + head = cs; + } + return cs; +} + +Constant_Stack *Pop() { + if (head == NULL) { + printf("cannot pop from an empty stack. Invalid.\n"); + return NULL; + } + Constant_Stack *cs = head; + head = head->next; + printf("Popped something of type %s\n", getName(cs->theType)); + return cs; +} + +Constant_Stack* Print_Stack(){ + if (head == NULL) { + printdebug("cannot print an empty stack. Invalid."); + return NULL; + } + Constant_Stack *cs = head; + while (cs != NULL) { + if(cs->theValue == NULL){ + printf("Type: %s, Value: NULL", getName(cs->theType)); + } + if(cs->theType == stri){ + printf("Type: %s, Value: %s\n", getName(cs->theType), *(char*)(cs->theValue)); + } + if(cs->theType == integ){ + printf("Type: %s, Value: %d\n", getName(cs->theType), (int *)(cs->theValue)); + } + if(cs->theType == chara){ + printf("Type: %s, Value: %c\n", getName(cs->theType), *(char *)cs->theValue); + } + if(cs->theType == boo){ + if(*(bool *)cs->theValue == true){ + printf("Type: %s, Value: true\n", getName(cs->theType));} + else{ + printf("Type: %s, Value: false\n", getName(cs->theType)); + } + } + cs = cs->next; + } + return cs; + } + // primitive additional info only stores the size of that type AdInfo *CreatePrimitiveInfo(int size) { AdInfo *info = (AdInfo *)malloc(sizeof(AdInfo)); @@ -1070,7 +1151,6 @@ TableNode *look_up(SymbolTable *table, char *x) { x, getLine(table), getColumn(table)); return look_up(table->Parent_Scope, x); } - int col_widths[5] = {30, 8, 8, 35, 35}; void printline(FILE *file_ptr, bool b) { if (b) { @@ -1481,3 +1561,997 @@ TableNode *printTableNode(TableNode *tn) { return tn; } +//________________________________________________________________________ + + +// TODO: this is here to bring your attention to the comment bellow. +// check if start is NULL if it is assign it to the start globle variable +// otherwise make it next of current and set cur to your instruction. +TNodeOrConst * getOperand1(Instruction * i){ + return i->operand1; +} + +TNodeOrConst * getOperand2(Instruction * i){ + return i->operand2; +} + +TableNode * getResult(Instruction * i){ + return i->result; +} + +Op getOp(Instruction * i){ + return i->opcode; +} + +int getLabel(Instruction * i){ + return i->label; +} + +int get_index(Instruction * i){ + return i->index; +} + +void set_label(Instruction * i, int label){ + i->label = label; +} + +bool isConst(TNodeOrConst * tnc) { + return tnc->d != NODE; +} + +TNodeOrConst * tn_or_const(Discriminant d, void * tnc) { + TNodeOrConst * count = calloc(1, sizeof(*count)); + count->d = d; + count->tnc_union = calloc(1, sizeof(*count->tnc_union)); + switch (d) { + case NODE: + count->tnc_union->node = tnc; + break; + case ADDRESS: + count->tnc_union->address = tnc; + break; + case STRING: + count->tnc_union->string = tnc; + break; + case INTEGER: + count->tnc_union->integer = *(int*)tnc; + break; + case CHARACTER: + count->tnc_union->character = *(char*)tnc; + break; + case BOOLEAN: + count->tnc_union->Boolean = *( uint_least8_t*)tnc; + break; + } + return count; +} + +static void emit_helper(void){ + Instruction * inst = calloc(1, sizeof(*inst)); + if(begin == NULL){ + begin = current = inst; + current->index = 1; + } else { + current->next = inst; + inst->prev = current; + inst->index = current->index+1; + current = inst; + } +} + +void emit_binary_op(Op op, TableNode * result, TNodeOrConst * arg1, TNodeOrConst * arg2){ + emit_helper(); + current->opcode = op; + // TODO: create temp and remove result from param list + current->result = result; + current->operand1 = arg1; + current->operand2 = arg2; + } + +void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg){ + emit_helper(); + current->opcode = op; + current->result = result; + current->operand1 = arg; + } + +void emit_assignment(TableNode * target, TNodeOrConst * source){ + emit_helper(); + current->opcode = E_ASSIGN; + current->result = target; + current->operand1 = source; + } + +char * get_string(TNodeOrConst * tc){ + + char * s; + switch (tc->d) { + case NODE: + return getName(tc->tnc_union->node); + case ADDRESS: + return strdup("null"); + case STRING: + return tc->tnc_union->string; + case INTEGER: + s = calloc(10, sizeof(char)); + sprintf(s, "%d", tc->tnc_union->integer); + return s; + case CHARACTER: + s = calloc(2, sizeof(char)); + sprintf(s, "%c", tc->tnc_union->character); + return s; + case BOOLEAN: + if(tc->tnc_union->Boolean){ + return strdup("true"); + } + return strdup("false"); + } +} + +void emit_as_file(FILE * out_file, Instruction * i){ + if(i == NULL){ + return; + } + switch(i->opcode){ + case E_LABEL: + break; + // this is a terrible one to start with + // fprintf(out_file, "%04.d: %d ", i->index, i->label); + case E_ADD: + fprintf(out_file, "%4.d: %s = %s + %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_SUB: + fprintf(out_file, "%4.d: %s = %s - %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_MUL: + fprintf(out_file, "%4.d: %s = %s * %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_DIV: + fprintf(out_file, "%4.d: %s = %s / %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_MOD: + fprintf(out_file, "%4.d: %s = %s %% %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_OR: + fprintf(out_file, "%4.d: %s = %s | %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_AND: + fprintf(out_file, "%4.d: %s = %s & %s\n", + i->index, getName(i->result), + get_string(i->operand1), + get_string(i->operand2)); + break; + case E_NEG: + fprintf(out_file, "%4.d: %s = -%s\n", + i->index, getName(i->result), + get_string(i->operand1)); + break; + case E_NOT: + fprintf(out_file, "%4.d: %s = !%s\n", + i->index, getName(i->result), + get_string(i->operand1)); + break; + case E_ASSIGN: + fprintf(out_file, "%4.d: %s = %s\n", + i->index, getName(i->result), + get_string(i->operand1)); + break; + case E_GOTO: + // are we ever going to use this? + // yes we do look at bounds checking + case E_IF_X_TRUE: + fprintf(out_file, "%4.d: if %s goto %d\n", + i->index, get_string(i->operand1), + i->label); + break; + case E_IF_X_FALSE: + fprintf(out_file, "%4.d: if %s false goto %d\n", + i->index, get_string(i->operand1), + i->label); + break; + case E_LESS_THAN: + fprintf(out_file, "%4.d: if %s < %s goto %d\n", + i->index, get_string(i->operand1), + get_string(i->operand2), i->label); + break; + case E_EQUAL_TO: + fprintf(out_file, "%4.d: if %s = %s goto %d\n", + i->index, get_string(i->operand1), + get_string(i->operand2), i->label); + break; + case E_CALL: + fprintf(out_file, "%4.d: call %s %s\n", + i->index, get_string(i->operand1), + get_string(i->operand2)); + break; + + case E_PARAM: + fprintf(out_file, "%4.d: param %s \n", + i->index, get_string(i->operand1)); + break; + case E_RETURN: + + case E_INDEX_COPY_RIGHT: + case E_INDEX_COPY_LEFT: + + case E_ADDRESS_OF: + + case E_DEREF_RIGHT: + case E_DEREF_LEFT: + } + + emit_as_file(out_file, i->next); +} + +void emit_label(int label){ + emit_helper(); + current->opcode = E_LABEL; + current->label = label; +} + +void emit_jump(int label){ + emit_helper(); + current->opcode = E_GOTO; + current->label = label; +} + +void emit_conditional_jump(Op condition, int label, ...){ + // when this instruction is a conditional jump then the imput looks like (Op, int, TNodeOrConst *). + // when the inst is a cond with a Relational operation then the input looks like (Op, int, TNodeOrConst *, TNodeOrConst *) + emit_helper(); + va_list argptr; + va_start(argptr, label); + current->opcode = condition; + current->label = label; + TNodeOrConst * n1; + TNodeOrConst * n2; + switch (condition) { + case E_IF_X_TRUE: case E_IF_X_FALSE: + n1 = va_arg(argptr, TNodeOrConst *); + current->operand1 = n1; + break; + case E_LESS_THAN: case E_EQUAL_TO: + n1 = va_arg(argptr, TNodeOrConst *); + n2 = va_arg(argptr, TNodeOrConst *); + current->operand1 = n1; + current->operand2 = n2; + break; + } + va_end(argptr); +} + +void emit_function_start(int name){ + emit_helper(); + current->opcode = E_LABEL; // I think this is right TODO: ask + current->label = name; + // this is probabaly a func decleration +} + +void emit_parameter(TNodeOrConst * param){ + emit_helper(); + current->opcode = E_PARAM; + current->operand1 = param; +} + +void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name){ + emit_helper(); + current->opcode = E_CALL; + current->operand1 = tn_or_const(INTEGER, ¶m_count); + current->operand2 = name; + current->result = result; +} + +void emit_return(TNodeOrConst * value){ + emit_helper(); + current->opcode = E_RETURN; + current->operand1 = value; +} + +void emit_reserve(TableNode * result, TNodeOrConst * size){ + emit_parameter(size); + emit_function_call(result, 1, tn_or_const(NODE, look_up(cur, "reserve"))); +} + +void emit_release(TableNode * pointer){ + emit_parameter(tn_or_const(NODE, pointer)); + emit_function_call(pointer, 1, tn_or_const(NODE, look_up(cur, "release"))); +} + +void emit_deref_right(){ + return; +} + +void emit_deref_left(){ + return; +} + +void emit_field_access(char* result, char* record, char* field){ + emit_helper(); +} + +void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index){ + emit_helper(); + current->opcode; + current->result = result; + current->operand1 = array; + current->operand2 = index; + // TODO: Still don't know what to do with the dimentions +} + +void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr){ + /* + {[string: 5] + . + . + s:= reserve s(5); + s(0) := 'H'; + s(1) := 'e'; + . + . + s._0 num of dims Known at compile time + s._1 size Known at run time + s._1 int | 1 byte + +-------+---+---+---+---+---+ + | 5 | H | e | l | l | o | + +-------+---+---+---+---+---+ + size + ^ + | + p + s._0 ok + s._1 ok + s._2 not ok + t_0 is index + t_1 = *(int *)p = s._1 + if t_0 < 0 GOTO ERROR + if t_0 < s._1 GOTO access array + GOTO ERROR + */ + //emit_conditional_jump(E_LESS_THAN, ); + //emit_conditional_jump(E_LESS_THAN, ); + //emit_jump(); + /* We need a label ERROR to jump to + */ +} + +/*// * Implement temp variable generator function that produces unique names (t1, t2, etc.) +char * temp_var_gen(){ + char * ret = calloc(9, sizeof(*ret)); + sprintf(ret, "$t%d", temp_count); + temp_count++; + return ret; +} +*/ +char * label_gen(){ + char * ret = calloc( 9, sizeof(*ret)); + sprintf(ret, "L_%d", label_count); + label_count++; + return ret; +} + +TableNode* getTN(TNodeOrConst * tnc){ + if(tnc->d == NODE){ + return tnc->tnc_union->node; + } + return NULL; +} +//we must fix this +int getConst(TNodeOrConst * tnc){ + if(tnc->d == INTEGER){ + return tnc->tnc_union->integer; + } + return -1; +} +//------------------------------------------------------------------------------------- +int generate(){ + offset = 0; + Instruction *i = begin; + while (i != NULL) { + switch(getOp(i)) { + case E_LABEL: + generateLabel(i); + break; + case E_ADD: + generateAdd(i); + break; + case E_SUB: + generateSub(i); + break; + case E_MUL: + generateMult(i); + break; + case E_DIV: + generateDiv(i); + break; + case E_MOD: + generateMod(i); + break; + case E_OR: + generateOr(i); + break; + case E_AND: + generateAnd(i); + break; + case E_NEG: + generateNeg(i); + break; + case E_NOT: + generateNot(i); + break; + case E_ASSIGN: + generateAssign(i); + break; + case E_GOTO: + generateGoto(i); + break; + case E_IF_X_TRUE: + generateIfTrue(i); + break; + case E_IF_X_FALSE: + generateIfFalse(i); + break; + case E_LESS_THAN: + generateLessThan(i); + break; + case E_EQUAL_TO: + generateEqualTo(i); + break; + case E_CALL: + generateCall(i); + break; + case E_PARAM: + generateParam(i); + break; + case E_RETURN: + generateReturn(i); + break; + case E_INDEX_COPY_RIGHT: + generateCopyRight(i); + break; + case E_INDEX_COPY_LEFT: + generateCopyLeft(i); + break; + case E_ADDRESS_OF: + generateAddressOf(i); + break; + default: + ; + } + i = i->next; + } + return -1; +} + +CGNode *getNextCG(CGNode *cg) { + if (cg == NULL) { + return NULL; + } + return cg->next; +} + +int getAddress(CGNode *cg) { + if (cg == NULL) { + return -1; + } + + return currentsp - cg->address; +} + +TableNode *getTNofCG(CGNode *cg) { + if (cg == NULL) { + return NULL; + } + return cg->tn; +} + +CGNode *findCG(TableNode *tn) { + CGNode *cg = cgList; + while (cg != NULL) { + if (getTNofCG(cg) == tn) { + return cg; + } + cg = getNextCG(cg); + } + return NULL; +} + +CGNode *addCG(TableNode *tn, int sp) { + CGNode *cg = calloc(1, sizeof(CGNode)); + cg->tn = tn; + cg->address = sp; + offset += getPrimSize(tn); //not sure if this is the correct amount to add to the offset + cg->next = cgList; + cgList = cg; + return cg; +} + + +int generateLabel(Instruction *inst) { + fprintf(cg_flag, ".L%d:\n", getLabel(inst)); + return 0; +} +int generateAdd(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateAdd failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op1)); + if (op1CG == NULL) { + printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op1))); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\taddl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); + return 0; +} + +int generateSub(Instruction *instruction) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(instruction); + TNodeOrConst *op2 = getOperand2(instruction); + CGNode *cg = findCG(getResult(instruction)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateSub failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(instruction), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateSub failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tsubl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); + return 0; +} + +int generateMult(Instruction *inst){ + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateMult failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateMult failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateMult failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tsubl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); + return 0; +} + +int generateDiv(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateDiv failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateDiv failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateDiv failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); //moves dividend into eax + fprintf(cg_flag, "\tcltd\n"); //sign extends the dividend in eax + fprintf(cg_flag, "\tidivl\t%d(%%rbp)\n", getAddress(op2CG));//divides edx by value accessed from stack + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); //stores result + return 0; +} + +int generateMod(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateMod failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateMod failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateMod failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); //moves dividend into eax + fprintf(cg_flag, "\tcltd\n"); //sign extends the dividend in eax + fprintf(cg_flag, "\tidivl\t%d(%%rbp)\n", getAddress(op2CG));//divides edx by value accessed from stack + fprintf(cg_flag, "\tmovl\t%%edx, %d(%%rbp)\n", getAddress(cg)); //stores result from edx (remainder) + return 0; +} + +int generateOr(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateOr failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateOr failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateOr failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\torll\t%d(%%rbp), %%eax\n", getAddress(op2CG));//divides edx by value accessed from stack + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); //stores result + return 0; +} + +int generateAnd(Instruction *inst) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("%sgenerateAnd failed, NULL operand", COLOR_RED); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateAnd failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateAnd failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tandl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); + return 0; +} +int generateNeg(Instruction *inst) { + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateNeg failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateNeg failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateNeg failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tnegl\t%d %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); + return 0; +} +int generateNot(Instruction *inst) { + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateNot failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateNot failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateNot failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tnotl\t%%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); + return 0; +} + +int generateAssign(Instruction *inst) { + TNodeOrConst *op1 = getOperand1(inst); + CGNode *cg = findCG(getResult(inst)); + + + if (op1 == NULL) { + printdebug("generateAssign failed, NULL operand"); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + + //add option for constant assignment (should be easy) + if (isConst(op1) == true) { + fprintf(cg_flag, "\tmovl\t$%d, %d(%%rbp)\n", getConst(op1), getAddress(cg)); + } + + + CGNode *op1CG = findCG(getTN(op1)); + if (op1CG == NULL) { + printdebug("generateAssign failed, op1 is not constant but not in CGlist"); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); + return 0; +} + +int generateGoto(Instruction *instruction){ + return -1; +} + +int generateCondGoto(Instruction *instruction) { + return -1; +} + +int generateIfTrue(Instruction *instruction){ + return -1; + // might just be a goto for where to go if something is true, or returning if something is true, or checking if true and writing goto if thats the case +} + +int generateIfFalse(Instruction *instruction){ + return -1; +} + +int generateLessThan(Instruction *inst){ + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("%sgenerateLessThan failed, NULL operand", COLOR_RED); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateLessThan failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateLessThan failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tcmpl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tsetl\t%%al\n"); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg)); + return 0; +} + +int generateEqualTo(Instruction *inst){ + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *cg = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("%sgenerateLessThan failed, NULL operand", COLOR_RED); + return -1; + } + + if (cg == NULL) { + cg = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); + if (op1CG == NULL) { + printdebug("generateLessThan failed, op1 is not constant but not in CGlist"); + return -1; + } + + if (op2CG == NULL) { + printdebug("generateLessThan failed, %s is not initialized/in CG", getName(getTN(op2))); + return -1; + } + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tcmpl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tsete\t%%al\n"); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg)); + return 0; +} +int generateCall(Instruction *instruction){ + return -1; + //will want to store parameters and then update the offset by adding 8? for stack pointer stuff, can then print call subroutine name, followed by movl of the result into the result's cg +} +int generateReturn(Instruction *instruction){ + return -1; + //will movl the result into the appropriate register and move the stack pointer/offset stuff back to correct value +} +int generateCopyRight(Instruction *instruction){ + return -1; +} +int generateCopyLeft(Instruction *instruction){ + return -1; +} +int generateAddressOf(Instruction *instruction){ + return -1; +} +int generateParam(Instruction *instruction){ + //need to check if op1 is null, then add it to the appropriate register/cg node. need a way to keep track of this, maybe just have global count of params generated + return -1; +} \ No newline at end of file diff --git a/src/symbol_table.h b/src/symbol_table.h index 1712676..0175541 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include #define SIZE_INT 4 #define SIZE_ADDR 8 @@ -12,6 +14,15 @@ #define SIZE_BOOL 4 //TODO: Ask Carl what this size should be struct TableNode; +typedef struct TFList TFList; +typedef struct CGNode CGNode; + +typedef struct Constant_Stack { + struct TableNode *theType; + void *theValue; + struct Constant_Stack *next; + bool isConst; +} Constant_Stack; typedef struct { int size; @@ -149,7 +160,7 @@ extern int line_number; extern int column_number; extern FILE *yyin; extern bool DEBUG; - +extern int temp2_count; extern TableNode *funprime; extern TableNode *arrayprim; extern TableNode *integ; @@ -160,6 +171,7 @@ extern TableNode *boo; extern TableNode *recprime; extern TableNode *funtypeprime; extern TableNode *undefined; +extern Constant_Stack *head; extern char *COLOR_RED; extern char *COLOR_GREEN; @@ -176,3 +188,188 @@ extern char *COLOR_LIGHTBLUE; extern char *COLOR_LIGHTPURPLE; extern char *COLOR_LIGHTCYAN; extern char *COLOR_WHITE; +//_____________________________________________________________ +// these are from page 364 +typedef enum { + E_LABEL = 10000, // this is not in the book + E_ADD, // 1 from the list + E_SUB, // 1 + E_MUL, // 1 + E_DIV, // 1 + E_MOD, // 1 + E_OR, // 1 + E_AND, // 1 + E_NEG, // 2 + E_NOT, // 2 + E_ASSIGN, // 3 + E_GOTO, // 4 + E_COND_GOTO, // 5 I don't thik I need this because we could just follow the < or the = and just assume that it's a cond got + E_IF_X_TRUE, // 5 + E_IF_X_FALSE, // 5 + E_LESS_THAN, // 6 rule 1 + 5 + E_EQUAL_TO, // 6 rule 1 + 5 + E_CALL, // 7 + E_PARAM, // 7 + E_RETURN, // 7 + E_INDEX_COPY_RIGHT, // 8 this is x = y[i] + E_INDEX_COPY_LEFT, // 8 x[i] = y + E_ADDRESS_OF, // 9 x = &y + E_DEREF_RIGHT, // 9 x = *y + E_DEREF_LEFT // 9 x* = y +} Op; + +typedef enum { + NODE = 11000, // TableNode + INTEGER, // int + STRING, // char * + CHARACTER, // char + ADDRESS, // void * + BOOLEAN // bool +} Discriminant; + +typedef union { + TableNode * node; + int integer; + char * string; + char character; + void * address; + bool Boolean; +} TNConstUnion; + +typedef struct { + Discriminant d; + TNConstUnion * tnc_union; +} TNodeOrConst; + + +typedef struct Instruction Instruction; +typedef struct Instruction { + Op opcode; + TableNode * result; + TNodeOrConst * operand1; + TNodeOrConst * operand2; + int label; + int index; + + Instruction * prev; + Instruction * next; +} Instruction; + + +typedef struct TFList { + Instruction * i; + TFList * next; +} TFList; + +TFList * make_list(Instruction * i); +// - makelist(i) function to create instruction lists +void merge(TFList * l1, TFList * l2); +// - merge(p1,p2) function to concatenate lists +void backpatch(TFList * l, int label); +// - backpatch(p,i) function to fill in jump targets + + +//int temp_count; +//int label_count; +//bool code_gen; +//Instruction * begin; +//Instruction * current; +//char * temp; + + + +TNodeOrConst * tn_or_const(Discriminant d, void * tnc); +void emit_binary_op(Op op, TableNode * result, TNodeOrConst * arg1, TNodeOrConst * arg2); +void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg); +void emit_assignment(TableNode * target, TNodeOrConst * source); +void emit_as_file(FILE * out_file, Instruction * instr_arr); +void emit_label(int label); +void emit_jump(int label); + +void emit_conditional_jump(Op condition, int label, ...); + +void emit_function_start(int name); +void emit_parameter(TNodeOrConst * param); +void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name); +void emit_return(TNodeOrConst * value); +void emit_reserve(TableNode * result, TNodeOrConst * size); +void emit_release(TableNode * pointer); +void emit_field_access(char* result, char* record, char* field); +void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index); +void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr); + +// * Implement instruction array storage for backpatching +/* +Track 2: Control Flow & Boolean Expressions +* Implement backpatching infrastructure: +* Create truelist and falselist attributes for Boolean expressions +* Create control flow emission functions: +* Add Bison actions for control structures: +- if-then-else with backpatching +- while loops with backpatching +* Implement short-circuit Boolean operations (&&, ||, !) +* Add marker (M) nonterminal for recording instruction positions +*/ + + +/* +Track 3: Functions & Complex Types +* Implement function-related emission: +* Add Bison actions for the 'as' clause +* Create memory layout calculation functions: +- calculate_record_size(Record_Type* type) → returns bytes needed +- calculate_array_size(Array_Type* type, int dimensions[]) → returns total bytes +- calculate_field_offset(Record_Type* type, char* field_name) → returns offset +* Add Bison actions for arrays and records +*/ + +/* +Track 4: Memory Access & Integration +* Implement array and record access code: +- emit_field_access(char* result, char* record, char* field) +- emit_array_access(char* result, char* array, char* index, char* dimension) +* Add array dimension access (a._1, a._2, etc.) +* Implement bounds checking emission: +- emit_bounds_check(char* index, char* size, char* error_label) +* Create the code generation driver function +* Implement common error handling +* Document the complete intermediate instruction set +* Build integration test suite covering all language features +* Implement row-major/column-major array layout calculation +*/ +//------------------------------------------------------------- +extern FILE *cg_flag; +typedef struct CGNode { + TableNode *tn; + int address; + CGNode *next; +}CGNode; + +int generate(); +CGNode *getNextCG(CGNode *cg); +int getAddress(CGNode *cg); +TableNode *getTNofCG(CGNode *cg); +int generateLabel(Instruction *instruction); +int generateAdd(Instruction *instruction); +int generateSub(Instruction *instruction); +int generateMult(Instruction *instruction); +int generateDiv(Instruction *instruction); +int generateMod(Instruction *instruction); +int generateOr(Instruction *instruction); +int generateAnd(Instruction *instruction); +int generateNeg(Instruction *instruction); +int generateNot(Instruction *instruction); +int generateDiv(Instruction *instruction); +int generateAssign(Instruction *instruction); // is this for something like x = 1? +int generateGoto(Instruction *instruction); +int generateCondGoto(Instruction *instruction); +int generateIfTrue(Instruction *instruction); +int generateIfFalse(Instruction *instruction); +int generateLessThan(Instruction *instruction); +int generateEqualTo(Instruction *instruction); +int generateCall(Instruction *instruction); +int generateReturn(Instruction *instruction); +int generateCopyRight(Instruction *instruction); +int generateCopyLeft(Instruction *instruction); +int generateAddressOf(Instruction *instruction); +int generateParam(Instruction *instruction); \ No newline at end of file diff --git a/test.sh b/test.sh old mode 100755 new mode 100644 diff --git a/tests/sprint2/test/sp2_simple.alpha b/tests/sprint2/test/sp2_simple.alpha index 58934e6..4042a5a 100644 --- a/tests/sprint2/test/sp2_simple.alpha +++ b/tests/sprint2/test/sp2_simple.alpha @@ -3,5 +3,5 @@ function entry: main entry(arg) := { [integer : x] - return 0; + return 2; } \ No newline at end of file diff --git a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha index bc88a72..2adb394 100644 --- a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha +++ b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha @@ -7,7 +7,7 @@ entry (arg) := { [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1; character : a; rec : r] x := 3 + 2 * 8; - x := 3 - 2 / 8; + x := 3 - 2 / 8; x := a * 2 % 8; b2 := 3 * 2 % 8; x := 3 % 2 * 8;