From c72e7a2a284e88a39ec6ee6d486c765351cb9cc6 Mon Sep 17 00:00:00 2001 From: Scarlett Date: Wed, 16 Apr 2025 16:30:58 -0400 Subject: [PATCH] Type check errors --- src/grammar.y | 163 +++++++++++++-------- src/runner.c | 36 +++-- src/runner.h | 6 +- src/symbol_table.c | 1 - tests/sprint2/test/sp2_carls_mistake.alpha | 2 +- tests/sprint2/test/sp2_llnode.alpha | 9 +- 6 files changed, 128 insertions(+), 89 deletions(-) diff --git a/src/grammar.y b/src/grammar.y index c6044fd..a7d173e 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -19,9 +19,11 @@ %{ #include "../src/symbol_table.c" void yyerror(const char *err); + extern FILE *asc_flag; + extern bool tc_flag; int token_tracker; TableNode * tn; -// int counter; + void error_type(TableNode * left, TableNode * right, const char *format, ...); %} %union { @@ -169,10 +171,9 @@ definition: printdebug("see function def rule 1\n"); TableNode *node = table_lookup(getAncestor(cur), $1); if (node == undefined) { - - printdebug(" [TYPE CHECK] undefined nodedeclared at line %d, column %d", @1.first_line, @1.first_column); + error_type(undefined, undefined, "Undefined node declared."); }else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){ - printdebug("[TYPE CHECK] not a valid function declaration at line %d, column %d", @1.first_line, @1.first_column); + error_type(undefined, undefined, "Not a valid function declaration."); } else { printdebug("setting as keyword to true"); @@ -186,7 +187,7 @@ definition: //TableNode *parameter = getParameter(table_lookup(getAncestor(cur), getType(table_lookup(getAncestor(cur), $1)))); printdebug("type of parameter: %s", getName(parameter)); if (parameter == undefined) { - printdebug("[TYPE CHECK] function defined with as, but parameter is undefined at line %d, column %d", @1.first_line, @1.first_column); + error_type(undefined, undefined, "Undefined parameter in function definition."); }else if(getAdInfoType(parameter) != TYPE_RECORD_TYPE){ int type_of_param_type = getAdInfoType(parameter);//this is an enum value defined in symbol_table.h if( type_of_param_type == TYPE_UNDEFINED @@ -197,7 +198,7 @@ definition: || type_of_param_type == TYPE_SYSTEM_DEFINED || type_of_param_type == TYPE_RECORD || type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused - printdebug("[TYPE CHECK] type of parameter being passed in to function definition is %s which is invalid", getAdInfo(parameter)); + error_type(parameter, undefined, "Invalid type (%s) of parameter in function definition.", getAdInfo(parameter)); type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases } if(type_of_param_type == TYPE_UNDEFINED){ @@ -225,7 +226,7 @@ definition: || type_of_param_type == TYPE_SYSTEM_DEFINED || type_of_param_type == TYPE_RECORD_TYPE || type_of_param_type == TYPE_STRING){ // note that strings are actually arrays so this is unused - printdebug("[TYPE CHECK] type of parameter (if record) inside record being passed in to function definition is %s which is invalid", getType(entry)); + error_type(entry, undefined, "Invalid type (%s) of parameter in function definition.", getAdInfo(entry)); type_of_param_type = TYPE_UNDEFINED; // setting tag as undefined in these cases }else{ printdebug("type of parameter correctly being passed in to AS function definition is %s which is valid", getType(entry)); @@ -256,9 +257,9 @@ definition: } idlist R_PAREN ASSIGN sblock { TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1))); if ($8 == undefined) { - printdebug("sblock return type is undefined"); + error_type(undefined, undefined, "Expected %s as return type but got undefined (possibly NULL). Differing return types in function.", getName(expected)); } else if ($8 != expected) { - printdebug("expected %s as return type but got %s", getName(expected), getName($8)); + error_type(undefined, undefined, "Expected %s as return type but got %s. Differing return types in function.", getName(expected), getName($8)); } else { printdebug("CORRECT RETURN TYPE!!!"); } @@ -273,7 +274,7 @@ function_declaration: CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false)); } else{ - printdebug("[TYPE CHECK] function declaration of %s is not a valid function type at line %d, column %d", $2, @1.first_line, @1.first_column); + error_type(undefined, undefined, "Function declatation (%s) is not a valid function type", $2); CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false)); } @@ -285,7 +286,7 @@ function_declaration: CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false)); } else{ - printdebug("[TYPE CHECK] function declaration of %s is not a valid function type at line %d, column %d", $3, @1.first_line, @1.first_column); + error_type(undefined, undefined, "Function declatation (%s) is not a valid function type", $3); CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false)); } @@ -430,7 +431,7 @@ declaration: printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ; int d = getAdInfoType((TableNode*)$1); if(d == TYPE_UNDEFINED) { - printdebug("[TYPE CHECK] undefined type at line %d and column %d", @2.first_line, @2.first_column); + error_type(undefined, undefined, "Undefined type passed in declaration list"); CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); } else if(d == TYPE_FUNCTION_TYPE) { @@ -453,7 +454,7 @@ declaration: d = TYPE_PRIMITIVE; CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); }else { - printdebug("[TYPE CHECK] other invalid type passed at %d and column %d", @2.first_line, @2.first_column); + error_type(undefined, undefined, "Invalid type passed in declaration list."); CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); } } @@ -537,51 +538,39 @@ WHILE L_PAREN expression R_PAREN sblock { simple_statement: assignable ASSIGN expression - { - bool passCheck = false; - TableNode * left = (TableNode*)$1; - TableNode * right = (TableNode*)$3; - - printTableNode((TableNode*)$1); - printTableNode((TableNode*)$3); + { + 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)|| + (getAdInfoType((TableNode*)$1) == TYPE_ARRAY)|| + (getAdInfoType((TableNode*)$1) == TYPE_RECORD)|| + (getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE)){ - if (strcmp(getType(right), "primitive") == 0) { - if (strcmp((getType(left)),(getName(right))) == 0) { - printdebug("%s[☺] Passed primitive type check; %s = %s", COLOR_GREEN, getName(left), getName(right)); - passCheck = true; + node = getTypeEntry((TableNode*)$1); + } else{ + error_type(undefined, undefined, "Invalid type passed to assignable."); + node = undefined; } - } - if(strcmp(getName(left), getName(right)) == 0) { - printdebug("Passed standard type check; assignable = expression"); - passCheck = true; - } - - if((strcmp(getType(left), "array") == 0) && (strcmp(getName(right), "address") == 0)) { - printdebug("%s[☺] Passed array type check; %s = %s", COLOR_GREEN, getName(left), getName(right)); - passCheck = true; - } - - if((strcmp(getType(left), "record") == 0) && (strcmp(getName(right), "address") == 0)) { - printdebug("%s[☺] Passed address type check; %s = %s", COLOR_GREEN, getName(left), getName(right)); - passCheck = true; - } - - if((strcmp(getType(left), "function type primitive") == 0) && (strcmp(getName(right), "address") == 0)) { - printdebug("%s[☺] Passed function type primitive type check; %s = %s", COLOR_GREEN, getName(left), getName(right)); - passCheck = true; - } - - // Type check fails: - if (!passCheck) { - printdebug("%s[TYPE CHECK] %sMismatch at %sline %d and column %d%s", COLOR_ORANGE, COLOR_WHITE, COLOR_YELLOW, @2.first_line, @2.first_column, COLOR_WHITE); - printdebug(" - Invalid types %s$1: %s and $3: %s%s", COLOR_YELLOW, getType(left), getType(right), COLOR_WHITE); - printdebug(" - %sgetType for address: %s", COLOR_YELLOW, getType(left)); + 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)){ + printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getName(node), getName((TableNode*)$3)); + } else { + error_type(node, (TableNode*)$3, ""); } $$ = undefined; } + | RETURN expression {$$ = $2;} ; @@ -644,7 +633,7 @@ expression: $$=(TableNode*)$2; } else { $$=undefined; - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid type being negated is %s", @1.first_line,@1.first_column,getName((TableNode*)$2)); + error_type((TableNode*)$2, boo, ""); } } @@ -654,8 +643,8 @@ expression: if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) { $$=(TableNode*)$1; } else { - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3)); $$=undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -665,8 +654,8 @@ expression: if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) { $$=(TableNode*)$1; } else { - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3)); $$=undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -676,8 +665,8 @@ expression: if((TableNode*)$1 == (TableNode*)$3 && (TableNode*)$1 == integ) { $$=(TableNode*)$1; } else{ - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName($1),getName($3)); $$=undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -687,8 +676,8 @@ expression: if((strcmp(getName((TableNode*)$1),getName((TableNode*)$3))==0) && ((TableNode*)$1 == integ)) { $$=(TableNode*)$1; } else { - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3)); $$=undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -698,8 +687,8 @@ expression: if($1 == $3 && $1 == integ) { $$=$1; } else { - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3)); $$=undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -709,8 +698,8 @@ expression: if($1 == $3 && $1 == boo){ $$=$1; } else{ - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3)); $$=undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -720,8 +709,8 @@ expression: if((strcmp(getName((TableNode*)$1),getName((TableNode*)$3))==0) && $1 == boo) { $$=$1; } else { - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3)); $$=undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -731,8 +720,8 @@ expression: if($1 == $3 && $1==integ) { $$=boo; } else { - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s.", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3)); $$=undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -742,8 +731,8 @@ expression: if($1 == $3 && $1 != undefined) { $$=boo; } else { - printdebug("[TYPE CHECK] mismatch at line %d and column %d. Invalid types %s and %s", @2.first_line,@2.first_column,getName((TableNode*)$1),getName((TableNode*)$3)); $$ = undefined; + error_type((TableNode*)$1, (TableNode*)$3, ""); } } @@ -766,7 +755,7 @@ expression: $$= ((TableNode*)$1); } else { - printdebug("[TYPE CHECK] assignable passing up an invalid type to expression"); + error_type(undefined, undefined, "Invalid type passed to expression."); $$= ((TableNode*)$1); } @@ -782,10 +771,9 @@ expression: { int d = getAdInfoType((TableNode*)$2); if(d == TYPE_ARRAY_TYPE || d == TYPE_ARRAY || d == TYPE_RECORD_TYPE || d == TYPE_RECORD) { - //printdebug("[TYPE CHECK] valid memOp expression"); $$ = addr; } else { - printdebug("[TYPE CHECK] invalid memOp expression at line %d and column %d.", @2.first_line,@2.first_column,getName((TableNode*)$2)); + error_type(undefined, undefined, "Invalid memOp expression (%s).", getName((TableNode*)$2)); $$=undefined; } } @@ -989,6 +977,51 @@ types: -void yyerror(const char *err) { - fprintf(stderr, "ERROR: %s at token %s at line number %d,column number %d", err,yytext,yylloc.first_line,yylloc.first_column); +void error_type(TableNode * left, TableNode * right, const char *format, ...) { + int line = yylloc.first_line; + int column = yylloc.first_column; + + if (tc_flag) { + yyerror(""); + if (strcmp(format, "") == 0) { + if (asc_flag != NULL) { + fprintf(asc_flag, "(%d:%d) ** TYPE ERROR: %s != %s\n", line, column, getName(left), getName(right)); + } else { + fprintf(stderr, "%s(%d:%d) ** TYPE ERROR%s: %s%s %s!= %s%s\n", + COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, getName(left), COLOR_WHITE, COLOR_YELLOW, getName(right), COLOR_WHITE); + } + } else { + if (asc_flag != NULL) { + fprintf(asc_flag, "(%d:%d) ** TYPE ERROR: ", line, column); + va_list args; + va_start(args, format); + vfprintf(asc_flag, format, args); + va_end(args); + fprintf(asc_flag, "\n"); + } else { + fprintf(stderr, "%s(%d:%d) ** TYPE ERROR%s: %s", COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW); + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "%s\n", COLOR_WHITE); + } + } + } +} + +void yyerror(const char *err) { + int line = yylloc.first_line; + int column = yylloc.first_column; + + // Grammar Fallback Case + if (strcmp(err, "syntax error") == 0) { + if (asc_flag != NULL) { + fprintf(asc_flag, "(%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n", line, column, yytext); + } + else { + fprintf(stderr, "%s(%d:%d) ** SYNTAX ERROR%s: Incorrect syntax at token '%s%s%s'\n", + COLOR_RED, line, column, COLOR_WHITE, COLOR_YELLOW, yytext, COLOR_WHITE); + } + } } diff --git a/src/runner.c b/src/runner.c index 6915d29..3fa35ca 100644 --- a/src/runner.c +++ b/src/runner.c @@ -59,8 +59,9 @@ int check_flag(char *arg, char *alpha) { fprintf(stderr, "FLAGS REPEAT\n"); return -1; } else if (strcmp("-tc", arg) == 0) { - if (tc_flag == NULL) { - return new_file(arg, alpha); + if (tc_flag == false) { + tc_flag = true; + return 0; } fprintf(stderr, "FLAGS REPEAT\n"); return -1; @@ -124,13 +125,12 @@ int run(FILE *alpha) { } if (asc_flag != NULL) { - printf("Flag -asc is not implemented yet\n"); + printdebug("[-asc] Annotated Source Code is enabled."); fclose(asc_flag); } - if (tc_flag != NULL) { - printf("Flag -tc is not implemented yet\n"); - fclose(tc_flag); + if (tc_flag != false) { + printdebug("[-tc] Type checking is enabled."); } if (ir_flag != NULL) { @@ -180,8 +180,12 @@ int new_file(char *arg, char *alpha) { type_len = TOK_LEN; } else if (strcmp(arg, "-st") == 0) { type_len = ST_LEN; - } else if (strcmp(arg, "-tc") == 0) { - type_len = TC_LEN; + } else if (strcmp(arg, "-asc") == 0) { + type_len = ASC_LEN; + } else if (strcmp(arg, "-ir") == 0) { + type_len = IR_LEN; + } else if (strcmp(arg, "-cg") == 0) { + type_len = CG_LEN; } else { fprintf(stderr, INVALID); return -1; @@ -189,13 +193,17 @@ int new_file(char *arg, char *alpha) { // calculate lengths int basename_len = strlen(basename); - char *file_name = - calloc(basename_len - ALPHA_OFFSET + type_len + 2, sizeof(char)); + char *file_name = calloc(basename_len - ALPHA_OFFSET + type_len + 2, sizeof(char)); // coy filename and add extension - strncpy(file_name, basename, basename_len - ALPHA_OFFSET); - strcat(file_name, "."); - strcat(file_name, arg + 1); + if (strcmp(arg, "-cg") == 0) { + strncpy(file_name, basename, basename_len - ALPHA_OFFSET); + strcat(file_name, ".s"); + } else { + strncpy(file_name, basename, basename_len - ALPHA_OFFSET); + strcat(file_name, "."); + strcat(file_name, arg + 1); + } if (strcmp(arg, "-tok") == 0) { tok_flag = fopen(file_name, "w"); @@ -203,8 +211,6 @@ int new_file(char *arg, char *alpha) { st_flag = fopen(file_name, "w"); } else if (strcmp(arg, "-asc") == 0) { asc_flag = fopen(file_name, "w"); - } else if (strcmp(arg, "-tc") == 0) { - tc_flag = fopen(file_name, "w"); } else if (strcmp(arg, "-ir") == 0) { ir_flag = fopen(file_name, "w"); } else if (strcmp(arg, "-cg") == 0) { diff --git a/src/runner.h b/src/runner.h index 3e71a7a..7989473 100644 --- a/src/runner.h +++ b/src/runner.h @@ -4,7 +4,9 @@ #define ALPHA_OFFSET 6 #define TOK_LEN 3 #define ST_LEN 2 -#define TC_LEN 2 +#define ASC_LEN 3 +#define IR_LEN 2 +#define CG_LEN 1 #define HELP \ "HELP:\n" \ " How to run the alpha compiler:\n" \ @@ -44,10 +46,10 @@ SymbolTable *cur; FILE *alpha_file; FILE *tok_flag = NULL; FILE *st_flag = NULL; -FILE *tc_flag = NULL; FILE *ir_flag = NULL; FILE *cg_flag = NULL; FILE *asc_flag = NULL; +bool tc_flag = false; bool DEBUG = false; int no_flag = 0; int arg; diff --git a/src/symbol_table.c b/src/symbol_table.c index c1d3946..21669b5 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -185,7 +185,6 @@ TableNode *setRecOffsetInfo(SymbolTable *scope, TableNode *node) { counter++; } else if ((getAdInfoType(this) == TYPE_RECORD)) { offsets[counter] = 8; - printf("hitting record and adding to largest"); total_size = total_size + offsets[counter]; largest = offsets[counter]; counter++; diff --git a/tests/sprint2/test/sp2_carls_mistake.alpha b/tests/sprint2/test/sp2_carls_mistake.alpha index 26b8725..b7fa8ee 100644 --- a/tests/sprint2/test/sp2_carls_mistake.alpha +++ b/tests/sprint2/test/sp2_carls_mistake.alpha @@ -28,7 +28,7 @@ entry (arg) := { w := reserve w; (* see types.alpha – reserve returns a value of type address, which can be assigned to array and record variables*) w.x := 5; w.y := 7; - result := bar1(w); (* pass w (a rec type value) to bar1 *) + ressult := bar1(w); (* pass w (a rec type value) to bar1 *) result := bar2(5,7); (* implicitly build a rec type value, assign 5 and 7 to fields x and y, but call them r and s *) return 0; } diff --git a/tests/sprint2/test/sp2_llnode.alpha b/tests/sprint2/test/sp2_llnode.alpha index b102ba8..3ecfb11 100644 --- a/tests/sprint2/test/sp2_llnode.alpha +++ b/tests/sprint2/test/sp2_llnode.alpha @@ -14,20 +14,20 @@ function bar2 : T2 function make_list : list make_list (a) := { - [integer:orig_a; address: ret; address: curr; address: temp] + [integer:orig_a; llnode: ret; llnode: curr; llnode: temp] if (a < 0 | a = 0) then { return null; } else { - ret := reserve llnode; + ret := reserve ret; ret.prev := null; ret.next := null; ret.val := a; while (0 < a) { - temp := reserve llnode; + temp := reserve temp; temp.prev := null; temp.next := null; - temp.val := val; + temp.val := ret.val; if (a = orig_a) then { ret.next := temp; temp.prev := ret; @@ -68,7 +68,6 @@ bar2(r,s) := { entry (arg) := { [ integer: result ; rec: w; llnode: li] - li := make_list(6); result := foo(5); w := reserve w;