From ecafbf713a07a6eb9a79dbf036b0cf734ff3578e Mon Sep 17 00:00:00 2001 From: Scarlett Date: Wed, 23 Apr 2025 15:55:08 -0400 Subject: [PATCH 01/18] init branch --- src/grammar.h | 10 ++++++++++ src/lexicalStructure.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/grammar.h create mode 100644 src/lexicalStructure.h diff --git a/src/grammar.h b/src/grammar.h new file mode 100644 index 0000000..58cedbd --- /dev/null +++ b/src/grammar.h @@ -0,0 +1,10 @@ +#ifndef GRAMMAR_H +#define GRAMMAR_H + +#include "../src/runner.h" + +void yyerror(const char *err); +int token_tracker; +TableNode * tn; + +#endif \ No newline at end of file diff --git a/src/lexicalStructure.h b/src/lexicalStructure.h new file mode 100644 index 0000000..c7baafe --- /dev/null +++ b/src/lexicalStructure.h @@ -0,0 +1,33 @@ +#ifndef LEXICALSTRUCTURE_H +#define LEXICALSTRUCTURE_H + +#include "../tmp/grammar.tab.h" +#include "../src/symbol_table.h" + +extern SymbolTable * cur; +extern FILE* tok_flag; +extern TableNode *funprime; +extern TableNode *funtypeprime; +extern TableNode *arrayprim; +extern TableNode *recprime; +extern TableNode *integ; +extern TableNode *addr; +extern TableNode *chara; +extern TableNode *stri; +extern TableNode *boo; +extern TableNode *undefined; +extern void incr(int lnum,int cnum, int tok); +extern void print_tok(int tok); + +extern int line_number; +extern int column_number; +extern int yycolumn; +#define YY_USER_ACTION { \ + yylloc.first_line = yylineno; \ + yylloc.last_line = yylineno; \ + yylloc.first_column = yycolumn; \ + yylloc.last_column = yycolumn + yyleng - 1; \ + yycolumn += yyleng; \ +} + +#endif \ No newline at end of file From 945dda59d045133fc7dbfdda596298578f80c6dc Mon Sep 17 00:00:00 2001 From: Scarlett Date: Wed, 23 Apr 2025 17:11:43 -0400 Subject: [PATCH 02/18] throw_error() function implemented --- src/grammar.y | 117 +++++++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 49 deletions(-) diff --git a/src/grammar.y b/src/grammar.y index a7d173e..e98f9d0 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -23,7 +23,13 @@ extern bool tc_flag; int token_tracker; TableNode * tn; - void error_type(TableNode * left, TableNode * right, const char *format, ...); + typedef enum { + ERROR_RUNTIME = 1, + ERROR_SYNTAX = 2, + ERROR_TYPE = 3, + ERROR_UNDEFINED = 4 + } ErrorType; + void throw_error(ErrorType error_type, const char *format, ...); %} %union { @@ -171,9 +177,9 @@ definition: printdebug("see function def rule 1\n"); TableNode *node = table_lookup(getAncestor(cur), $1); if (node == undefined) { - error_type(undefined, undefined, "Undefined node declared."); + printdebug("Undefined node declared."); }else if(getAdInfoType(node) != TYPE_FUNCTION_DECLARATION){ - error_type(undefined, undefined, "Not a valid function declaration."); + throw_error(ERROR_SYNTAX, "Not a valid function declaration."); } else { printdebug("setting as keyword to true"); @@ -187,7 +193,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) { - error_type(undefined, undefined, "Undefined parameter in function definition."); + throw_error(ERROR_TYPE, "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 @@ -198,7 +204,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 - error_type(parameter, undefined, "Invalid type (%s) of parameter in function definition.", getAdInfo(parameter)); + throw_error(ERROR_TYPE, "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){ @@ -226,7 +232,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 - error_type(entry, undefined, "Invalid type (%s) of parameter in function definition.", getAdInfo(entry)); + throw_error(ERROR_TYPE, "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)); @@ -257,9 +263,9 @@ definition: } idlist R_PAREN ASSIGN sblock { TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1))); if ($8 == undefined) { - error_type(undefined, undefined, "Expected %s as return type but got undefined (possibly NULL). Differing return types in function.", getName(expected)); + throw_error(ERROR_TYPE, "Expected %s as return type but got undefined (possibly NULL). Differing return types in function.", getName(expected)); } else if ($8 != expected) { - error_type(undefined, undefined, "Expected %s as return type but got %s. Differing return types in function.", getName(expected), getName($8)); + throw_error(ERROR_TYPE, "Expected %s as return type but got %s. Differing return types in function.", getName(expected), getName($8)); } else { printdebug("CORRECT RETURN TYPE!!!"); } @@ -274,7 +280,7 @@ function_declaration: CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false)); } else{ - error_type(undefined, undefined, "Function declatation (%s) is not a valid function type", $2); + throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $2); CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false)); } @@ -286,7 +292,7 @@ function_declaration: CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false)); } else{ - error_type(undefined, undefined, "Function declatation (%s) is not a valid function type", $3); + throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $3); CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $5), $3, CreateFunctionDeclarationInfo(-1, false)); } @@ -431,7 +437,7 @@ declaration: printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ; int d = getAdInfoType((TableNode*)$1); if(d == TYPE_UNDEFINED) { - error_type(undefined, undefined, "Undefined type passed in declaration list"); + printdebug("Undefined type passed in declaration list"); CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); } else if(d == TYPE_FUNCTION_TYPE) { @@ -454,7 +460,7 @@ declaration: d = TYPE_PRIMITIVE; CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); }else { - error_type(undefined, undefined, "Invalid type passed in declaration list."); + printdebug("Invalid type passed in declaration list."); CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); } } @@ -552,7 +558,7 @@ simple_statement: node = getTypeEntry((TableNode*)$1); } else{ - error_type(undefined, undefined, "Invalid type passed to assignable."); + printdebug("Invalid type passed to assignable."); node = undefined; } @@ -564,7 +570,7 @@ simple_statement: 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, ""); + throw_error(ERROR_TYPE, "%s != %s", getName(node), getName((TableNode*)$3)); } $$ = undefined; @@ -633,7 +639,7 @@ expression: $$=(TableNode*)$2; } else { $$=undefined; - error_type((TableNode*)$2, boo, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$2), getName(boo)); } } @@ -644,7 +650,7 @@ expression: $$=(TableNode*)$1; } else { $$=undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -655,7 +661,7 @@ expression: $$=(TableNode*)$1; } else { $$=undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -666,7 +672,7 @@ expression: $$=(TableNode*)$1; } else{ $$=undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -677,7 +683,7 @@ expression: $$=(TableNode*)$1; } else { $$=undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -688,7 +694,7 @@ expression: $$=$1; } else { $$=undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -699,7 +705,7 @@ expression: $$=$1; } else{ $$=undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -710,7 +716,7 @@ expression: $$=$1; } else { $$=undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -721,7 +727,7 @@ expression: $$=boo; } else { $$=undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -732,7 +738,7 @@ expression: $$=boo; } else { $$ = undefined; - error_type((TableNode*)$1, (TableNode*)$3, ""); + throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3)); } } @@ -755,7 +761,7 @@ expression: $$= ((TableNode*)$1); } else { - error_type(undefined, undefined, "Invalid type passed to expression."); + printdebug("Invalid type passed to expression."); $$= ((TableNode*)$1); } @@ -773,7 +779,7 @@ expression: if(d == TYPE_ARRAY_TYPE || d == TYPE_ARRAY || d == TYPE_RECORD_TYPE || d == TYPE_RECORD) { $$ = addr; } else { - error_type(undefined, undefined, "Invalid memOp expression (%s).", getName((TableNode*)$2)); + throw_error(ERROR_TYPE, "Invalid memOp expression (%s).", getName((TableNode*)$2)); $$=undefined; } } @@ -977,35 +983,48 @@ types: -void error_type(TableNode * left, TableNode * right, const char *format, ...) { +void throw_error(ErrorType error_type, const char *format, ...) { int line = yylloc.first_line; int column = yylloc.first_column; + char * error_name = ""; + + switch (error_type) { + case ERROR_RUNTIME: + error_name = malloc(strlen("RUNTIME") + 1); + strcpy(error_name, "RUNTIME"); + break; + case ERROR_SYNTAX: + error_name = malloc(strlen("SYNTAX") + 1); + strcpy(error_name, "SYNTAX"); + break; + case ERROR_TYPE: + error_name = malloc(strlen("TYPE") + 1); + strcpy(error_name, "TYPE"); + break; + case ERROR_UNDEFINED: + error_name = malloc(strlen("UNDEFINED") + 1); + strcpy(error_name, "UNDEFINED"); + break; + } + + 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); - } + if (asc_flag != NULL) { + fprintf(asc_flag, "(%d:%d) ** %s ERROR: ", line, column, error_name); + va_list args; + va_start(args, format); + vfprintf(asc_flag, format, args); + va_end(args); + fprintf(asc_flag, "\n"); } 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); - } + fprintf(stderr, "%s(%d:%d) ** %s ERROR%s: %s", COLOR_RED, line, column, error_name, COLOR_WHITE, COLOR_YELLOW); + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "%s\n", COLOR_WHITE); } } } From 2c712ed2217f2f05b68abb43695128a55ea3c02f Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 12:46:07 -0400 Subject: [PATCH 03/18] Makefile rewrite --- Makefile | 81 +++++++----- src/grammar.h | 10 -- src/grammar.y | 11 +- src/intermediate_code.c | 268 ++++++++++++++++++++++++++++++++++------ src/intermediate_code.h | 99 +++++++++++---- src/lexicalStructure.h | 33 ----- src/runner.h | 2 + src/symbol_table.c | 2 - src/symbol_table.h | 22 ++-- test.alpha | 29 ----- 10 files changed, 380 insertions(+), 177 deletions(-) delete mode 100644 src/grammar.h delete mode 100644 src/lexicalStructure.h delete mode 100644 test.alpha diff --git a/Makefile b/Makefile index c9797be..bb5c7bb 100644 --- a/Makefile +++ b/Makefile @@ -1,39 +1,73 @@ +# ----- Definitions ----- CC := gcc FLEX := flex +BISON = bison + +CFLAGS := -ggdb +BISONFLAGS := -d + LEX := src/lexicalStructure.lex +YACC := src/grammar.y EXE := alpha -CFLAGS := -YACC := bison + +OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o tmp/intermediate_code.o +# tmp/intermediate_code.o codegen.o TESTS-S1 := $(wildcard tests/sprint1/test/*.alpha) TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha) TESTS-S3 := $(wildcard tests/sprint3/test/*.alpha) TESTS-S4 := $(wildcard tests/sprint4/test/*.alpha) +# ---------- -compiler: clean runner -tmp/grammar.tab.c: src/grammar.y + +# ----- Targets ----- +all: compiler + +compiler: clean tmp $(OBJS) + $(CC) $(CFLAGS) -o $(EXE) $(OBJS) + +clean: + rm -f $(EXE) + rm -rf out + rm -rf tmp + +tmp: mkdir -p tmp - $(YACC) -d src/grammar.y - mv grammar.tab.c tmp/ - mv grammar.tab.h tmp/ -tmp/lex.yy.c: src/lexicalStructure.lex tmp/grammar.tab.c +tmp/grammar.tab.c tmp/grammar.tab.h: $(YACC) + $(BISON) $(BISONFLAGS) -o tmp/grammar.tab.c $(YACC) + +tmp/lex.yy.c tmp/flex.h: $(LEX) tmp/grammar.tab.h $(FLEX) -o tmp/lex.yy.c $(LEX) - mv flex.h tmp/ + mv flex.h tmp/flex.h +# ----------- -tmp/runner.o: src/runner.c src/runner.h tmp/flex.h - $(CC) $(CFLAGS) -o tmp/runner.o -c src/runner.c + + +# ----- Create Objs ----- +tmp/grammar.tab.o: tmp/grammar.tab.c + $(CC) $(CFLAGS) -c tmp/grammar.tab.c -o tmp/grammar.tab.o + +tmp/lex.yy.o: tmp/lex.yy.c + $(CC) $(CFLAGS) -c tmp/lex.yy.c -o tmp/lex.yy.o tmp/symbol_table.o: src/symbol_table.c src/symbol_table.h - $(CC) $(CFLAGS) -o tmp/symbol_table.o -c src/symbol_table.c + $(CC) $(CFLAGS) -c src/symbol_table.c -o tmp/symbol_table.o -runner: tmp/lex.yy.c tmp/runner.o tmp/symbol_table.o - $(CC) $(CFLAGS) -o $(EXE) -g -ggdb tmp/runner.o tmp/grammar.tab.c tmp/lex.yy.c +tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h + $(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o -debug: CFLAGS += -DDEBUG=1 -debug: clean compiler +# tmp/codegen.o: src/codegen.c src/codegen.h +# $(CC) $(CFLAGS) -c src/codegen.c -o tmp/codegen.o +tmp/runner.o: src/runner.c src/runner.h tmp/flex.h tmp/grammar.tab.h + $(CC) $(CFLAGS) -c src/runner.c -o tmp/runner.o +# ----------- + + + +# ----- Tests ----- test: chmod +x ./check.sh chmod +x ./test.sh @@ -67,15 +101,6 @@ test-s4: ./test.sh sp4 ./check.sh sp4 -clean: - rm -f *.o - rm -f lex.yy.c - rm -f $(EXE) - rm -f flex.h - rm -f *.tok - rm -f grammar.tab.c - rm -f grammar.tab.h - rm -f *.st - rm -rf out - rm -rf tmp - rm -f parser +# Temprorary test ~ Scarlett +test-make: clean tmp tmp/grammar.tab.c tmp/grammar.tab.h tmp/lex.yy.c tmp/flex.h tmp/grammar.tab.o tmp/lex.yy.o tmp/symbol_table.o tmp/runner.o +# ----------- \ No newline at end of file diff --git a/src/grammar.h b/src/grammar.h deleted file mode 100644 index 58cedbd..0000000 --- a/src/grammar.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef GRAMMAR_H -#define GRAMMAR_H - -#include "../src/runner.h" - -void yyerror(const char *err); -int token_tracker; -TableNode * tn; - -#endif \ No newline at end of file diff --git a/src/grammar.y b/src/grammar.y index e98f9d0..c7220c3 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -17,18 +17,21 @@ // Please ask Scarlett if you are unsure of how to format something. Thanks! 😀 %{ - #include "../src/symbol_table.c" - void yyerror(const char *err); + #include "../src/symbol_table.h" extern FILE *asc_flag; extern bool tc_flag; - int token_tracker; - TableNode * tn; + typedef enum { ERROR_RUNTIME = 1, ERROR_SYNTAX = 2, ERROR_TYPE = 3, ERROR_UNDEFINED = 4 } ErrorType; + + int token_tracker; + TableNode * tn; + + void yyerror(const char *err); void throw_error(ErrorType error_type, const char *format, ...); %} diff --git a/src/intermediate_code.c b/src/intermediate_code.c index 6ac5429..6b1b32f 100644 --- a/src/intermediate_code.c +++ b/src/intermediate_code.c @@ -1,4 +1,3 @@ -#include #include "intermediate_code.h" Instruction * begin; @@ -9,11 +8,42 @@ char * temp = NULL; // 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 * tn_or_const(Op op, void * tnc) { +TNodeOrConst * getOperand2(Instruction * i){ + return i->operand2; +} + +TableNode * get_result(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 = op; - switch (op) { + count->d = d; + switch (d) { case NODE: count->tnc_union->node = tnc; break; @@ -52,10 +82,10 @@ static void emit_helper(void){ 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; - return; } void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg){ @@ -63,38 +93,162 @@ void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg){ current->opcode = op; current->result = result; current->operand1 = arg; - return; } void emit_assignment(TableNode * target, TNodeOrConst * source){ emit_helper(); - current->opcode = E_ASSIGN; // TODO: replace with move + current->opcode = E_ASSIGN; current->result = target; current->operand1 = source; - return; } -void emit_as_file(FILE * out_file, Instruction * instr_arr){ - if(instr_arr == NULL){ - return; +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"); } - - //fprintf(out_file, - return; } +void emit_as_file(FILE * out_file, Instruction * i){ + if(!i){ + return; + } + switch(i->opcode){ + case E_LABEL: + // 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->operand2)); + 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; - return; } + void emit_jump(int label){ emit_helper(); current->opcode = E_GOTO; current->label = label; - return; } void emit_conditional_jump(Op condition, int label, ...){ @@ -112,7 +266,7 @@ void emit_conditional_jump(Op condition, int label, ...){ n1 = va_arg(argptr, TNodeOrConst *); current->operand1 = n1; break; - case E_LESSTHEN: case E_EQUALTO: + case E_LESS_THAN: case E_EQUAL_TO: n1 = va_arg(argptr, TNodeOrConst *); n2 = va_arg(argptr, TNodeOrConst *); current->operand1 = n1; @@ -120,7 +274,6 @@ void emit_conditional_jump(Op condition, int label, ...){ break; } va_end(argptr); - return; } void emit_function_start(int name){ @@ -128,14 +281,12 @@ void emit_function_start(int name){ current->opcode = E_LABEL; // I think this is right TODO: ask current->label = name; // this is probabaly a func decleration - return; } void emit_parameter(TNodeOrConst * param){ emit_helper(); current->opcode = E_PARAM; current->operand1 = param; - return; } void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name){ @@ -144,37 +295,80 @@ void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name current->operand1 = tn_or_const(INTEGER, ¶m_count); current->operand2 = name; current->result = result; - return; } + void emit_return(TNodeOrConst * value){ emit_helper(); current->opcode = E_RETURN; current->operand1 = value; - return; } -void emit_reserve(char* result, char* type_name, int size){ - emit_helper(); - return; + +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(char* pointer){ - emit_helper(); + +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(); - return; -} -void emit_array_access(char* result, char* array, char* index, char* dimension){ - emit_helper(); - return; -} -void emit_bounds_check(char* index, char* size, char* error_label){ - emit_helper(); - return; } +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(){ @@ -189,4 +383,4 @@ char * label_gen(){ sprintf(ret, "L_%d", label_count); label_count++; return ret; -} +} \ No newline at end of file diff --git a/src/intermediate_code.h b/src/intermediate_code.h index fc3cdc4..b6e6fd4 100644 --- a/src/intermediate_code.h +++ b/src/intermediate_code.h @@ -2,12 +2,15 @@ // * Add Bison actions for arithmetic expressions: // - Addition: $$ = new_temp(); emit_binary_op($$, "ADD", $1, $3); // - Subtraction, multiplication, division, modulo -#include "runner.h" +#pragma once + +#include "symbol_table.h" +#include #include // these are from page 364 typedef enum { - E_LABEL = 10000, // this is not in the book + E_LABEL = 10000, // this is not in the book E_ADD, // 1 from the list E_SUB, // 1 E_MUL, // 1 @@ -22,16 +25,16 @@ typedef enum { 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_LESSTHEN, // 6 rule 1 + 5 - E_EQUALTO, // 6 rule 1 + 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 - E_INDEX_COPY_LEFT, // 8 - E_ADDRESS_OF // 9 - /* for x = *y and *y = x we can just use index copy right and left with - index 0*/ + 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 { @@ -70,6 +73,20 @@ typedef struct Instruction { 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 + + extern Instruction * begin; extern Instruction * current; int temp_count = 0; @@ -77,34 +94,62 @@ int label_count = 0; bool code_gen = true; - -TNodeOrConst * tn_or_const(Op op, void * tnc); - +TNodeOrConst * tn_or_const(Discriminant , void * ); 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); -// TODO: Find out what these are suposed to do. Guess is create an entry in -// the list of instructions. Guess is that its suposed to ret a struct ptr - -// * Implement integer/boolean/character specific operation handling -// TODO: Find out what this means. - -// * Create output function to write instructions to file with line formatting void emit_as_file(FILE * out_file, Instruction * instr_arr); - -// * Implement instruction array storage for backpatching - 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(char* result, char* type_name, int size); -void emit_release(char* pointer); - +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(char* result, char* array, char* index, char* dimension); -void emit_bounds_check(char* index, char* size, char* error_label); +void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index); +void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr, int error_label); + +// * 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 + */ \ No newline at end of file diff --git a/src/lexicalStructure.h b/src/lexicalStructure.h deleted file mode 100644 index c7baafe..0000000 --- a/src/lexicalStructure.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef LEXICALSTRUCTURE_H -#define LEXICALSTRUCTURE_H - -#include "../tmp/grammar.tab.h" -#include "../src/symbol_table.h" - -extern SymbolTable * cur; -extern FILE* tok_flag; -extern TableNode *funprime; -extern TableNode *funtypeprime; -extern TableNode *arrayprim; -extern TableNode *recprime; -extern TableNode *integ; -extern TableNode *addr; -extern TableNode *chara; -extern TableNode *stri; -extern TableNode *boo; -extern TableNode *undefined; -extern void incr(int lnum,int cnum, int tok); -extern void print_tok(int tok); - -extern int line_number; -extern int column_number; -extern int yycolumn; -#define YY_USER_ACTION { \ - yylloc.first_line = yylineno; \ - yylloc.last_line = yylineno; \ - yylloc.first_column = yycolumn; \ - yylloc.last_column = yycolumn + yyleng - 1; \ - yycolumn += yyleng; \ -} - -#endif \ No newline at end of file diff --git a/src/runner.h b/src/runner.h index 7989473..16b505b 100644 --- a/src/runner.h +++ b/src/runner.h @@ -1,6 +1,8 @@ /* Runner File - Compiles alpha Compiler */ /* The Translators - Spring 2025 */ +#pragma once + #define ALPHA_OFFSET 6 #define TOK_LEN 3 #define ST_LEN 2 diff --git a/src/symbol_table.c b/src/symbol_table.c index 21669b5..a464b93 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -1072,7 +1072,6 @@ TableNode *look_up(SymbolTable *table, char *x) { } int col_widths[5] = {30, 8, 8, 35, 35}; -void printline(FILE *file_ptr, bool b); void printline(FILE *file_ptr, bool b) { if (b) { fprintf(file_ptr, "oop\n"); @@ -1087,7 +1086,6 @@ void printline(FILE *file_ptr, bool b) { fprintf(file_ptr, "\n"); } -void st_fprint(FILE *file_ptr, char *label1, int label2, int label3, char *label4, char *label5); void st_fprint(FILE *file_ptr, char *label1, int label2, int label3, char *label4, char *label5) { if (label3 == -100) { fprintf(file_ptr, "%-*s: %0*d : %*s :%-*s:%-*s\n", diff --git a/src/symbol_table.h b/src/symbol_table.h index 01d4458..1712676 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -82,12 +84,20 @@ typedef enum { TYPE_PRIMITIVE_TYPE = 12 } types; +void printdebug_impl(char *file, int line, const char *format, ...); +#define printdebug(format, ...) \ + printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__) + +void printdebug_impl(char *file, int line, const char *format, ...); AdInfo *CreatePrimitiveInfo(int size); int getPrimSize(TableNode *definition); AdInfo *CreateArrayInfo(int dim, TableNode *type); int getNumArrDim(TableNode *definition); TableNode *getArrType(TableNode *definition); AdInfo *CreateRecordInfo(int length, SymbolTable *recordScope); +int getRecTotal(TableNode *node); +TableNode *setRecOffsetInfo(SymbolTable *scope, TableNode *node); +int *getRecOffsets(TableNode *node); int getRecLength(TableNode *definition); SymbolTable *getRecList(TableNode *definition); TableNode *setRecSize(TableNode *tn, int n); @@ -103,19 +113,21 @@ TableNode *getReturn(TableNode *definition); SymbolTable *CreateScope(SymbolTable *ParentScope, int Line, int Column); SymbolTable *init(SymbolTable *start); TableNode *populateTypeAndInfo(TableNode *tn, TableNode *type, AdInfo *info); +AdInfo *getAdInfo(TableNode *tn); int getAdInfoType(TableNode *tn); -TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id, - AdInfo *ad); +TableNode *CreateEntry(SymbolTable *table, int tag, TableNode *typeOf, char *id, AdInfo *ad); +TableNode *getTypeEntry(TableNode *tn); char *getType(TableNode *tn); char *getName(TableNode *tn); int getLine(SymbolTable *st); int getColumn(SymbolTable *st); -TableNode *getTypeEntry(TableNode *tn); TableNode *addName(TableNode *tn, char *str); SymbolTable *setLineNumber(SymbolTable *st, int line); SymbolTable *setColumnNumber(SymbolTable *st, int column); TableNode *table_lookup(SymbolTable *table, char *x); TableNode *look_up(SymbolTable *table, char *x); +void printline(FILE *file_ptr, bool b); +void st_fprint(FILE *file_ptr, char *label1, int label2, int label3, char *label4, char *label5); void print_symbol_table(SymbolTable *table, FILE *file_ptr); SymbolTable *getAncestor(SymbolTable *table); SymbolTable *removeEntry(SymbolTable *scope, char *search); @@ -126,11 +138,7 @@ SymbolTable *getFirstChild(ListOfTable *lt); ListOfTable *getRestOfChildren(ListOfTable *lt); TableNode *getFirstEntry(SymbolTable *st); TableNode *getNextEntry(TableNode *tn); - TableNode *printTableNode(TableNode *tn); -void printdebug_impl(char *file, int line, const char *format, ...); -#define printdebug(format, ...) \ - printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__) extern int yylex(void); extern char *yytext; diff --git a/test.alpha b/test.alpha deleted file mode 100644 index 7b06a5e..0000000 --- a/test.alpha +++ /dev/null @@ -1,29 +0,0 @@ - - - -type a : 1 -> integers -type t : integer -> a -type r : integer -> integer - - - -function foo : t -function bar : r -function entry : - -bar(a) := { - 5 + bar(a - 1); - return a * bar(a-1); -} - -foo(c) := { - [a: arg] - arg := reserve arg(c); - return arg; -} - -entry(args) := { - [a: b] - b := foo(8); -} - From f0d81ff5fdedb6ec54b639057755cbf42b1a98cb Mon Sep 17 00:00:00 2001 From: Partho Date: Fri, 25 Apr 2025 13:01:31 -0400 Subject: [PATCH 04/18] combined symbol table with IR in this branch --- src/grammar.y | 14 +- src/intermediate_code.c | 5 - src/intermediate_code.h | 3 +- src/runner.c | 3 +- src/runner.h | 1 + src/symbol_table.c | 390 +++++++++++++++++++++++++++++++++++++++- src/symbol_table.h | 152 ++++++++++++++++ 7 files changed, 552 insertions(+), 16 deletions(-) diff --git a/src/grammar.y b/src/grammar.y index 110ffb4..74d7e92 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -1005,7 +1005,7 @@ constant: { char* temp = temp_var_gen(); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, stri, temp, NULL); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + emit_assignment(node, tn_or_const(STRING,$1)); printdebug("string of C_STRING in constant is %s", $1); $$ = node; } @@ -1014,7 +1014,7 @@ constant: { char* temp = temp_var_gen(); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, integ, temp, NULL); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + emit_assignment(node, tn_or_const(INTEGER,&$1)); printdebug("number of C_INTEGER in constant is %d", $1); $$ = node; } @@ -1023,7 +1023,7 @@ constant: { 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) + emit_assignment(node, tn_or_const(ADDRESS,$1)); printdebug("string of C_NULL in constant is NULL"); $$ = node; } @@ -1032,7 +1032,7 @@ constant: { char* temp = temp_var_gen(); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, chara, temp, NULL); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + emit_assignment(node, tn_or_const(CHARACTER,&$1)); printdebug("string of C_CHARACTER in constant is %s",$1); $$ = node; } @@ -1041,7 +1041,8 @@ constant: { char* temp = temp_var_gen(); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + uint_least8_t b = 1; + emit_assignment(node, tn_or_const(BOOLEAN,&b)); printdebug("string of C_TRUE in constant is true"); $$ = node; } @@ -1050,7 +1051,8 @@ constant: { char* temp = temp_var_gen(); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) + 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/intermediate_code.c b/src/intermediate_code.c index 6ac5429..3ccec2c 100644 --- a/src/intermediate_code.c +++ b/src/intermediate_code.c @@ -1,9 +1,4 @@ -#include -#include "intermediate_code.h" -Instruction * begin; -Instruction * current; -char * temp = NULL; // TODO: this is here to bring your attention to the comment bellow. diff --git a/src/intermediate_code.h b/src/intermediate_code.h index fc3cdc4..2bb423a 100644 --- a/src/intermediate_code.h +++ b/src/intermediate_code.h @@ -2,8 +2,7 @@ // * Add Bison actions for arithmetic expressions: // - Addition: $$ = new_temp(); emit_binary_op($$, "ADD", $1, $3); // - Subtraction, multiplication, division, modulo -#include "runner.h" -#include + // these are from page 364 typedef enum { diff --git a/src/runner.c b/src/runner.c index 3fa35ca..9ca6cfa 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2,7 +2,7 @@ /* The Translators - Spring 2025 */ #include "runner.h" - +//Constant_Stack *head = NULL; int main(int argc, char *argv[]) { if (argc == 1) { fprintf(stderr, INVALID); @@ -121,6 +121,7 @@ int run(FILE *alpha) { if (st_flag != NULL) { print_symbol_table(top, st_flag); + //emit_as_file(stdout, begin); fclose(st_flag); } diff --git a/src/runner.h b/src/runner.h index 7989473..74a7ecf 100644 --- a/src/runner.h +++ b/src/runner.h @@ -64,6 +64,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 de7d3f6..5fe39c3 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -3,8 +3,13 @@ #include "symbol_table.h" -Constant_Stack* head = NULL; +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; void printdebug_impl(char *file, int line, const char *format, ...) { if (DEBUG) { @@ -1143,7 +1148,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); void printline(FILE *file_ptr, bool b) { @@ -1556,3 +1560,385 @@ 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 * get_result(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; + 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++; + 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){ + return; + } + switch(i->opcode){ + case E_LABEL: + // 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->operand2)); + 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; +} \ No newline at end of file diff --git a/src/symbol_table.h b/src/symbol_table.h index 6a41551..4a9d88b 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include #define SIZE_INT 4 #define SIZE_ADDR 8 @@ -10,6 +12,7 @@ #define SIZE_BOOL 4 //TODO: Ask Carl what this size should be struct TableNode; +typedef struct TFList TFList; typedef struct Constant_Stack { struct TableNode *theType; @@ -176,3 +179,152 @@ 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 +*/ \ No newline at end of file From 95c37db9ff79e3de1a98c123eda4cc2115b6ff84 Mon Sep 17 00:00:00 2001 From: Partho Date: Fri, 25 Apr 2025 13:37:32 -0400 Subject: [PATCH 05/18] fixing still --- src/grammar.y | 2 ++ src/runner.c | 2 +- src/symbol_table.c | 6 +++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/grammar.y b/src/grammar.y index 74d7e92..72aa3b3 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -615,6 +615,7 @@ expression: 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; @@ -630,6 +631,7 @@ expression: 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; diff --git a/src/runner.c b/src/runner.c index 9ca6cfa..c10cd6a 100644 --- a/src/runner.c +++ b/src/runner.c @@ -121,7 +121,7 @@ int run(FILE *alpha) { if (st_flag != NULL) { print_symbol_table(top, st_flag); - //emit_as_file(stdout, begin); + emit_as_file(stdout, begin); fclose(st_flag); } diff --git a/src/symbol_table.c b/src/symbol_table.c index 5fe39c3..db7523e 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -1601,6 +1601,7 @@ bool isConst(TNodeOrConst * tnc) { 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; @@ -1632,7 +1633,7 @@ static void emit_helper(void){ } else { current->next = inst; inst->prev = current; - inst->index = current->index++; + inst->index = current->index+1; current = inst; } } @@ -1661,6 +1662,7 @@ void emit_assignment(TableNode * target, TNodeOrConst * source){ } char * get_string(TNodeOrConst * tc){ + char * s; switch (tc->d) { case NODE: @@ -1670,10 +1672,12 @@ char * get_string(TNodeOrConst * tc){ case STRING: return tc->tnc_union->string; case INTEGER: + return getName(integ); s = calloc(10, sizeof(char)); sprintf(s, "%d", tc->tnc_union->integer); return s; case CHARACTER: + return getName(chara); s = calloc(2, sizeof(char)); sprintf(s, "%c", tc->tnc_union->character); return s; From 49a0330d08f79f94235be95403f74e6328db1690 Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 15:04:20 -0400 Subject: [PATCH 06/18] Lexxer cleanup --- Makefile | 10 ++-- src/lexicalStructure.lex | 118 +++++++++++++++++++-------------------- src/runner.c | 3 +- 3 files changed, 66 insertions(+), 65 deletions(-) diff --git a/Makefile b/Makefile index bb5c7bb..8798f2e 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,8 @@ LEX := src/lexicalStructure.lex YACC := src/grammar.y EXE := alpha -OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o tmp/intermediate_code.o -# tmp/intermediate_code.o codegen.o +OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o +# tmp/intermediate_code.o codegen.o <--- Add to line above TESTS-S1 := $(wildcard tests/sprint1/test/*.alpha) TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha) @@ -55,8 +55,10 @@ tmp/lex.yy.o: tmp/lex.yy.c tmp/symbol_table.o: src/symbol_table.c src/symbol_table.h $(CC) $(CFLAGS) -c src/symbol_table.c -o tmp/symbol_table.o -tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h - $(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o +# Uncomment rules when ready + +# tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h +# $(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o # tmp/codegen.o: src/codegen.c src/codegen.h # $(CC) $(CFLAGS) -c src/codegen.c -o tmp/codegen.o diff --git a/src/lexicalStructure.lex b/src/lexicalStructure.lex index e11ef39..8d92cdd 100644 --- a/src/lexicalStructure.lex +++ b/src/lexicalStructure.lex @@ -8,9 +8,6 @@ %{ #include "../tmp/grammar.tab.h" #include "../src/symbol_table.h" - #ifndef DEBUG - #define DEBUG 0 - #endif extern SymbolTable * cur; extern FILE* tok_flag; extern TableNode *funprime; @@ -26,14 +23,17 @@ extern void incr(int lnum,int cnum, int tok); extern void print_tok(int tok); - int line_number = 1, column_number = 1; + int line_number = 1; + int column_number = 1; int yycolumn = 1; - #define YY_USER_ACTION { \ - yylloc.first_line = yylineno; \ - yylloc.last_line = yylineno; \ - yylloc.first_column = yycolumn; \ - yylloc.last_column = yycolumn + yyleng - 1; \ - yycolumn += yyleng; } + + #define YY_USER_ACTION { \ + yylloc.first_line = yylineno; \ + yylloc.last_line = yylineno; \ + yylloc.first_column = yycolumn; \ + yylloc.last_column = yycolumn + yyleng - 1; \ + yycolumn += yyleng; \ + } %} STARCOM [^\*]|\*+[^\)\*]+ @@ -46,63 +46,63 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\] %% -"integer" {if(DEBUG) {printf( "T_INTEGER: %s (%d)\n", yytext, T_INTEGER);} else {if(tok_flag != NULL){print_tok(T_INTEGER);}incr(line_number,column_number,T_INTEGER);yylval.tn = integ;return T_INTEGER;}} -"address" {if(DEBUG) {printf( "T_ADDRESS: %s (%d)\n", yytext, T_ADDRESS);} else {if(tok_flag != NULL){print_tok(T_ADDRESS);}incr(line_number,column_number,T_ADDRESS);yylval.tn = addr;return T_ADDRESS;}} -"Boolean" {if(DEBUG) {printf( "T_BOOLEAN: %s (%d)\n", yytext, T_BOOLEAN);} else {if(tok_flag != NULL){print_tok(T_INTEGER);}incr(line_number,column_number,T_INTEGER);yylval.tn = boo;return T_BOOLEAN;}} -"character" {if(DEBUG) {printf( "T_CHARACTER: %s (%d)\n", yytext, T_CHARACTER);} else {if(tok_flag != NULL){print_tok(T_CHARACTER);}incr(line_number,column_number,T_CHARACTER);yylval.tn = chara;return T_CHARACTER;}} +"integer" { if(tok_flag != NULL) {print_tok(T_INTEGER);} incr(line_number,column_number,T_INTEGER); yylval.tn = integ; return T_INTEGER; } +"address" { if(tok_flag != NULL) {print_tok(T_ADDRESS);} incr(line_number,column_number,T_ADDRESS); yylval.tn = addr; return T_ADDRESS; } +"Boolean" { if(tok_flag != NULL) {print_tok(T_INTEGER);} incr(line_number,column_number,T_INTEGER); yylval.tn = boo; return T_BOOLEAN; } +"character" { if(tok_flag != NULL) {print_tok(T_CHARACTER);} incr(line_number,column_number,T_CHARACTER); yylval.tn = chara; return T_CHARACTER; } -"while" {if(DEBUG) {printf( "WHILE: %s (%d)\n", yytext, WHILE);} else {if(tok_flag != NULL){print_tok(WHILE);}incr(line_number,column_number,WHILE);return WHILE;}} -"if" {if(DEBUG) {printf( "IF: %s (%d)\n", yytext, IF);} else {if(tok_flag != NULL){print_tok(IF);}incr(line_number,column_number,IF);return IF;}} -"then" {if(DEBUG) {printf( "THEN: %s (%d)\n", yytext, THEN);} else {if(tok_flag != NULL){print_tok(THEN);}incr(line_number,column_number,THEN);return THEN;}} -"else" {if(DEBUG) {printf( "ELSE: %s (%d)\n", yytext, ELSE);} else {if(tok_flag != NULL){print_tok(ELSE);}incr(line_number,column_number,ELSE);return ELSE;}} -"type" {if(DEBUG) {printf( "TYPE: %s (%d)\n", yytext, TYPE);} else {if(tok_flag != NULL){print_tok(TYPE);}incr(line_number,column_number,TYPE);return TYPE;}} -"function" {if(DEBUG) {printf( "FUNCTION: %s (%d)\n", yytext, FUNCTION);} else {if(tok_flag != NULL){print_tok(FUNCTION);}incr(line_number,column_number,FUNCTION);return FUNCTION;}} -"return" {if(DEBUG) {printf( "RETURN: %s (%d)\n", yytext, RETURN);} else {if(tok_flag != NULL){print_tok(RETURN);}incr(line_number,column_number,RETURN);return RETURN;}} -"external" {if(DEBUG) {printf( "EXTERNAL: %s (%d)\n", yytext, EXTERNAL);} else {if(tok_flag != NULL){print_tok(EXTERNAL);}incr(line_number,column_number,EXTERNAL);return EXTERNAL;}} -"as" {if(DEBUG) {printf( "AS: %s (%d)\n", yytext, AS);} else {if(tok_flag != NULL){print_tok(AS);}incr(line_number,column_number,AS);return AS;}} +"while" { if(tok_flag != NULL) {print_tok(WHILE);} incr(line_number,column_number,WHILE); return WHILE; } +"if" { if(tok_flag != NULL) {print_tok(IF);} incr(line_number,column_number,IF); return IF; } +"then" { if(tok_flag != NULL) {print_tok(THEN);} incr(line_number,column_number,THEN); return THEN; } +"else" { if(tok_flag != NULL) {print_tok(ELSE);} incr(line_number,column_number,ELSE); return ELSE; } +"type" { if(tok_flag != NULL) {print_tok(TYPE);} incr(line_number,column_number,TYPE); return TYPE; } +"function" { if(tok_flag != NULL) {print_tok(FUNCTION);} incr(line_number,column_number,FUNCTION); return FUNCTION; } +"return" { if(tok_flag != NULL) {print_tok(RETURN);} incr(line_number,column_number,RETURN); return RETURN; } +"external" { if(tok_flag != NULL) {print_tok(EXTERNAL);} incr(line_number,column_number,EXTERNAL); return EXTERNAL; } +"as" { if(tok_flag != NULL) {print_tok(AS);} incr(line_number,column_number,AS); return AS; } -"release" {if(DEBUG) {printf( "RELEASE: %s (%d)\n", yytext, RELEASE);} else {if(tok_flag != NULL){print_tok(RELEASE);}incr(line_number,column_number,RELEASE);return RELEASE;}} -"reserve" {if(DEBUG) {printf( "RESERVE: %s (%d)\n", yytext, RESERVE);} else {if(tok_flag != NULL){print_tok(RESERVE);}incr(line_number,column_number,RESERVE);return RESERVE;}} +"release" { if(tok_flag != NULL) {print_tok(RELEASE);} incr(line_number,column_number,RELEASE); return RELEASE; } +"reserve" { if(tok_flag != NULL) {print_tok(RESERVE);} incr(line_number,column_number,RESERVE); return RESERVE; } -"+" {if(DEBUG) {printf( "ADD: %s (%d)\n", yytext, ADD);} else {if(tok_flag != NULL){print_tok(ADD);}incr(line_number,column_number,ADD);return ADD;}} -"-" {if(DEBUG) {printf( "SUB_OR_NEG: %s (%d)\n", yytext, SUB_OR_NEG);} else {if(tok_flag != NULL){print_tok(SUB_OR_NEG);}incr(line_number,column_number,SUB_OR_NEG);return SUB_OR_NEG;}} -"*" {if(DEBUG) {printf( "MUL: %s (%d)\n", yytext, MUL);} else {if(tok_flag != NULL){print_tok(MUL);}incr(line_number,column_number,MUL);return MUL;}} -"/" {if(DEBUG) {printf( "DIV: %s (%d)\n", yytext, DIV);} else {if(tok_flag != NULL){print_tok(DIV);}incr(line_number,column_number,DIV);return DIV;}} -"%" {if(DEBUG) {printf( "REM: %s (%d)\n", yytext, REM);} else {if(tok_flag != NULL){print_tok(REM);}incr(line_number,column_number,REM);return REM;}} -"<" {if(DEBUG) {printf( "LESS_THAN: %s (%d)\n", yytext, LESS_THAN);} else {if(tok_flag != NULL){print_tok(LESS_THAN);}incr(line_number,column_number,LESS_THAN);return LESS_THAN;}} -"=" {if(DEBUG) {printf( "EQUAL_TO: %s (%d)\n", yytext, EQUAL_TO);} else {if(tok_flag != NULL){print_tok(EQUAL_TO);}incr(line_number,column_number,EQUAL_TO);return EQUAL_TO;}} -":=" {if(DEBUG) {printf( "ASSIGN: %s (%d)\n", yytext, ASSIGN);} else {if(tok_flag != NULL){print_tok(ASSIGN);}incr(line_number,column_number,ASSIGN);return ASSIGN;}} -"!" {if(DEBUG) {printf( "NOT: %s (%d)\n", yytext, NOT);} else {if(tok_flag != NULL){print_tok(NOT);}incr(line_number,column_number,NOT);return NOT;}} -"&" {if(DEBUG) {printf( "AND: %s (%d)\n", yytext, AND);} else {if(tok_flag != NULL){print_tok(AND);}incr(line_number,column_number,AND);return AND;}} -"|" {if(DEBUG) {printf( "OR: %s (%d)\n", yytext, OR);} else {if(tok_flag != NULL){print_tok(OR);}incr(line_number,column_number,OR);return OR;}} -"." {if(DEBUG) {printf( "DOT: %s (%d)\n", yytext, DOT);} else {if(tok_flag != NULL){print_tok(DOT);}incr(line_number,column_number,DOT);return DOT;}} +"+" { if(tok_flag != NULL) {print_tok(ADD);} incr(line_number,column_number,ADD); return ADD; } +"-" { if(tok_flag != NULL) {print_tok(SUB_OR_NEG);} incr(line_number,column_number,SUB_OR_NEG); return SUB_OR_NEG; } +"*" { if(tok_flag != NULL) {print_tok(MUL);} incr(line_number,column_number,MUL); return MUL; } +"/" { if(tok_flag != NULL) {print_tok(DIV);} incr(line_number,column_number,DIV); return DIV; } +"%" { if(tok_flag != NULL) {print_tok(REM);} incr(line_number,column_number,REM); return REM; } +"<" { if(tok_flag != NULL) {print_tok(LESS_THAN);} incr(line_number,column_number,LESS_THAN); return LESS_THAN; } +"=" { if(tok_flag != NULL) {print_tok(EQUAL_TO);} incr(line_number,column_number,EQUAL_TO); return EQUAL_TO; } +":=" { if(tok_flag != NULL) {print_tok(ASSIGN);} incr(line_number,column_number,ASSIGN); return ASSIGN; } +"!" { if(tok_flag != NULL) {print_tok(NOT);} incr(line_number,column_number,NOT); return NOT; } +"&" { if(tok_flag != NULL) {print_tok(AND);} incr(line_number,column_number,AND); return AND; } +"|" { if(tok_flag != NULL) {print_tok(OR);} incr(line_number,column_number,OR); return OR; } +"." { if(tok_flag != NULL) {print_tok(DOT);} incr(line_number,column_number,DOT); return DOT; } -";" {if(DEBUG) {printf( "SEMI_COLON: %s (%d)\n", yytext, SEMI_COLON);} else {if(tok_flag != NULL){print_tok(SEMI_COLON);}incr(line_number,column_number,SEMI_COLON);return SEMI_COLON;}} -":" {if(DEBUG) {printf( "COLON: %s (%d)\n", yytext, COLON);} else {if(tok_flag != NULL){print_tok(COLON);}incr(line_number,column_number,COLON);return COLON;}} -"," {if(DEBUG) {printf( "COMMA: %s (%d)\n", yytext, COMMA);} else {if(tok_flag != NULL){print_tok(COMMA);}incr(line_number,column_number,COMMA);return COMMA;}} -"->" {if(DEBUG) {printf( "ARROW: %s (%d)\n", yytext, ARROW);} else {if(tok_flag != NULL){print_tok(ARROW);}incr(line_number,column_number,ARROW);return ARROW;}} +";" { if(tok_flag != NULL) {print_tok(SEMI_COLON);} incr(line_number,column_number,SEMI_COLON); return SEMI_COLON; } +":" { if(tok_flag != NULL) {print_tok(COLON);} incr(line_number,column_number,COLON); return COLON; } +"," { 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(DEBUG) {printf( "C_INTEGER: %s (%d)\n", yytext, C_INTEGER);} else {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(DEBUG) {printf( "C_CHARACTER: %s (%d)\n", yytext, C_CHARACTER);} else {if(tok_flag != NULL){print_tok(C_CHARACTER);}incr(line_number,column_number,C_CHARACTER);yylval.tn = chara;return C_CHARACTER;}} -\"{SCHAR}*\" {if(DEBUG) {printf( "C_STRING: %s (%d)\n", yytext, C_STRING);} else {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);yylval.tn = stri;return C_STRING;}} -{COMMENT} {if(DEBUG) {printf( "COMMENT: %s (%d)\n", yytext, COMMENT);} else {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/}} +{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);} -"(" {if(DEBUG) {printf( "L_PAREN: %s (%d)\n", yytext, L_PAREN);} else {if(tok_flag != NULL){print_tok(L_PAREN);}incr(line_number,column_number,L_PAREN);return L_PAREN;}} -")" {if(DEBUG) {printf( "R_PAREN: %s (%d)\n", yytext, R_PAREN);} else {if(tok_flag != NULL){print_tok(R_PAREN);}incr(line_number,column_number,R_PAREN);return R_PAREN;}} -"[" {if(DEBUG) {printf( "L_BRACKET: %s (%d)\n", yytext, L_BRACKET);} else {if(tok_flag != NULL){print_tok(L_BRACKET);}incr(line_number,column_number,L_BRACKET);return L_BRACKET;}} -"]" {if(DEBUG) {printf( "R_BRACKET: %s (%d)\n", yytext, R_BRACKET);} else {if(tok_flag != NULL){print_tok(R_BRACKET);}incr(line_number,column_number,R_BRACKET);return R_BRACKET;}} -"{" {if(DEBUG) {printf( "L_BRACE: %s (%d)\n", yytext, L_BRACE);} else {if(tok_flag != NULL){print_tok(L_BRACE);}incr(line_number,column_number,L_BRACE);return L_BRACE;}} -"}" {if(DEBUG) {printf( "R_BRACE: %s (%d)\n", yytext, R_BRACE);} else {if(tok_flag != NULL){print_tok(R_BRACE);}incr(line_number,column_number,R_BRACE);return R_BRACE;}} +"(" { 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; } +"[" { if(tok_flag != NULL) {print_tok(L_BRACKET);} incr(line_number,column_number,L_BRACKET); return L_BRACKET; } +"]" { if(tok_flag != NULL) {print_tok(R_BRACKET);} incr(line_number,column_number,R_BRACKET); return R_BRACKET; } +"{" { if(tok_flag != NULL) {print_tok(L_BRACE);} incr(line_number,column_number,L_BRACE); return L_BRACE; } +"}" { if(tok_flag != NULL) {print_tok(R_BRACE);} incr(line_number,column_number,R_BRACE); return R_BRACE; } -"true" {if(DEBUG) {printf( "C_TRUE: %s (%d)\n", yytext, C_TRUE);} else {if(tok_flag != NULL){print_tok(C_TRUE);}incr(line_number,column_number,C_TRUE);yylval.tn = boo;return C_TRUE;}} -"false" {if(DEBUG) {printf( "C_FALSE: %s (%d)\n", yytext, C_FALSE);} else {if(tok_flag != NULL){print_tok(C_FALSE);}incr(line_number,column_number,C_FALSE);yylval.tn = boo;return C_FALSE;}} -"null" {if(DEBUG) {printf( "C_NULL: %s (%d)\n", yytext, C_NULL);} else {if(tok_flag != NULL){print_tok(C_NULL);}incr(line_number,column_number,C_NULL);yylval.tn = addr;return C_NULL;}} +"true" { if(tok_flag != NULL) {print_tok(C_TRUE);} incr(line_number,column_number,C_TRUE); yylval.tn = boo; return C_TRUE; } +"false" { if(tok_flag != NULL) {print_tok(C_FALSE);} incr(line_number,column_number,C_FALSE); yylval.tn = boo; return C_FALSE; } +"null" { if(tok_flag != NULL) {print_tok(C_NULL);} incr(line_number,column_number,C_NULL); yylval.tn = addr; return C_NULL; } -{ID} {if(DEBUG) {printf( "ID: %s (%d)\n", yytext, ID);} else {if(tok_flag != NULL){print_tok(ID);}incr(line_number,column_number,ID);yylval.words = strdup(yytext); return ID;}} +{ID} { if(tok_flag != NULL) {print_tok(ID);} incr(line_number,column_number,ID); yylval.words = strdup(yytext); return ID; } -\n {yycolumn=1;incr(line_number,column_number,0);} -\t {incr(line_number,column_number,0);} -" " {incr(line_number,column_number,0);} -. {incr(line_number,column_number,0);} +\n { yycolumn = 1; incr(line_number,column_number,0); } +\t { incr(line_number,column_number,0); } +" " { incr(line_number,column_number,0); } +. { incr(line_number,column_number,0); } %% diff --git a/src/runner.c b/src/runner.c index 3fa35ca..0ccb74f 100644 --- a/src/runner.c +++ b/src/runner.c @@ -22,8 +22,7 @@ int main(int argc, char *argv[]) { } else { - if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != - 0) { + if (is_alpha_file(argv[argc - 1], strlen(argv[argc - 1])) != 0) { fprintf(stderr, INVALID); return -1; } else { From 46d8a852a64b2cfdf1c59f958379c02f6502f844 Mon Sep 17 00:00:00 2001 From: Partho Date: Fri, 25 Apr 2025 15:36:31 -0400 Subject: [PATCH 07/18] trying to get annie's to work --- src/grammar.y | 28 +- src/intermediate_code.c | 1 + src/runner.c | 2 + src/runner.h | 5 +- src/symbol_table.c | 532 +++++++++++++++++- src/symbol_table.h | 39 +- .../sp3_integer_binary_op_typecheck.alpha | 2 +- 7 files changed, 581 insertions(+), 28 deletions(-) diff --git a/src/grammar.y b/src/grammar.y index 72aa3b3..00a294f 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -647,8 +647,7 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of binary operation + emit_binary_op(E_ADD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); $$ = node; } else { $$=undefined; @@ -662,8 +661,8 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of binary operation + emit_binary_op(E_SUB,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); + $$ = node; } else { $$=undefined; @@ -677,8 +676,7 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of binary operation + emit_binary_op(E_MUL,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); $$ = node; } else { $$=undefined; @@ -692,8 +690,7 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of binary operation + emit_binary_op(E_DIV,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); $$ = node; } else { $$=undefined; @@ -707,8 +704,7 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of binary operation + emit_binary_op(E_MOD,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); $$ = node; } else { $$=undefined; @@ -722,8 +718,7 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of comparison + emit_binary_op(E_AND,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); $$ = node; } else { $$=undefined; @@ -737,8 +732,7 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of comparison + emit_binary_op(E_OR,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); $$ = node; } else { $$=undefined; @@ -752,8 +746,7 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of comparison + emit_binary_op(E_LESS_THAN,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); $$ = node; } else { $$=undefined; @@ -767,8 +760,7 @@ expression: 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); - //NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK) - //result of compariosn + emit_binary_op(E_EQUAL_TO,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3)); $$ = node; } else { diff --git a/src/intermediate_code.c b/src/intermediate_code.c index 3ccec2c..6349054 100644 --- a/src/intermediate_code.c +++ b/src/intermediate_code.c @@ -5,6 +5,7 @@ // 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 * tn_or_const(Op op, void * tnc) { TNodeOrConst * count = calloc(1, sizeof(*count)); count->d = op; diff --git a/src/runner.c b/src/runner.c index c10cd6a..736be1c 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2,6 +2,8 @@ /* The Translators - Spring 2025 */ #include "runner.h" +FILE *ir_flag = NULL; +FILE *cg_flag = NULL; //Constant_Stack *head = NULL; int main(int argc, char *argv[]) { if (argc == 1) { diff --git a/src/runner.h b/src/runner.h index 74a7ecf..7e134f2 100644 --- a/src/runner.h +++ b/src/runner.h @@ -35,7 +35,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; @@ -46,8 +47,6 @@ 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; bool tc_flag = false; bool DEBUG = false; diff --git a/src/symbol_table.c b/src/symbol_table.c index db7523e..4ec3e70 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -10,6 +10,9 @@ 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) { @@ -1574,7 +1577,7 @@ TNodeOrConst * getOperand2(Instruction * i){ return i->operand2; } -TableNode * get_result(Instruction * i){ +TableNode * getResult(Instruction * i){ return i->result; } @@ -1672,12 +1675,10 @@ char * get_string(TNodeOrConst * tc){ case STRING: return tc->tnc_union->string; case INTEGER: - return getName(integ); s = calloc(10, sizeof(char)); sprintf(s, "%d", tc->tnc_union->integer); return s; case CHARACTER: - return getName(chara); s = calloc(2, sizeof(char)); sprintf(s, "%c", tc->tnc_union->character); return s; @@ -1690,11 +1691,12 @@ char * get_string(TNodeOrConst * tc){ } void emit_as_file(FILE * out_file, Instruction * i){ - if(!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: @@ -1752,7 +1754,7 @@ void emit_as_file(FILE * out_file, Instruction * i){ case E_ASSIGN: fprintf(out_file, "%4.d: %s = %s\n", i->index, getName(i->result), - get_string(i->operand2)); + get_string(i->operand1)); break; case E_GOTO: // are we ever going to use this? @@ -1945,4 +1947,524 @@ char * label_gen(){ sprintf(ret, "L_%d", label_count); label_count++; return ret; +} +//------------------------------------------------------------------------------------- +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: + ; + } + } + 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; +} +/* +movl $1, -4(%rbp) +add -4(%rbp), $2 +*/ +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 *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateAdd failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + + + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(op2); + 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(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateSub failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(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 *instruction){ + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateMult failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(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 *instruction) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateDiv failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(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 *instruction) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateMod failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(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 *instruction) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateOr failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(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 *instruction) { + /* + Both immediate: + One immediate: + Neither immediate: + */ + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("%sgenerateAnd failed, NULL operand", COLOR_RED); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(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, "\tandl\t%d(\%rbp), %eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t\%eax, %d(\%rbp)\n", getAddress(cg)); + return 0; +} +int generateNeg(Instruction *instruction) { + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateNeg failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(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 *instruction) { + TNodeOrConst *op1 = getOperand1(inst); + TNodeOrConst *op2 = getOperand2(inst); + CGNode *result = findCG(getResult(inst)); + + if (op1 == NULL || op2 == NULL) { + printdebug("generateNot failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + + CGNode *op1CG = findCG(op1); + CGNode *op2CG = findCG(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 *instruction) { + TNodeOrConst *op1 = getOperand1(inst); + CGNode *result = findCG(getResult(inst)); + + + if (op1 == NULL) { + printdebug("generateAssign failed, NULL operand"); + return -1; + } + + if (result == NULL) { + result = addCG(getResult(inst), offset); + } + + + //add option for constant assignment (should be easy) + + + CGNode *op1CG = findCG(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(Instruciton *instruction) { + return -1; +} + +int generateIfTrue(Instruction *instruction){ + return -1; +} + +int generateIfFalse(Instruction *instruction){ + return -1; +} + +int generateLessThan(Instruction *instruction){ + return -1; +} +int generateEqualTo(Instruction *instruction){ + return -1; +} +int generateCall(Instruction *instruction){ + return -1; +} +int generateReturn(Instruction *instruction){ + return -1; +} +int generateCopyRight(Instruction *instruction){ + return -1; +} +int generateCopyLeft(Instruction *instruction){ + return -1; +} +int generateAddressOf(Instruction *instruction){ + return -1; +} +int generateParam(Instruction *instruction){ + return -1; } \ No newline at end of file diff --git a/src/symbol_table.h b/src/symbol_table.h index 4a9d88b..41138b8 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -13,6 +13,7 @@ struct TableNode; typedef struct TFList TFList; +typedef struct CGNode CGNode; typedef struct Constant_Stack { struct TableNode *theType; @@ -327,4 +328,40 @@ Track 4: Memory Access & Integration * Document the complete intermediate instruction set * Build integration test suite covering all language features * Implement row-major/column-major array layout calculation -*/ \ No newline at end of file +*/ +//------------------------------------------------------------- +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/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; From 1999230265bac512c9aa8d190af15d77f5e57e8d Mon Sep 17 00:00:00 2001 From: Partho Date: Fri, 25 Apr 2025 16:55:27 -0400 Subject: [PATCH 08/18] got compilation to work --- cg.s | 44 +++++++ src/runner.c | 12 +- src/runner.h | 1 + src/symbol_table.c | 289 +++++++++++++++++++++++++++++---------------- 4 files changed, 241 insertions(+), 105 deletions(-) create mode 100644 cg.s diff --git a/cg.s b/cg.s new file mode 100644 index 0000000..47bbe30 --- /dev/null +++ b/cg.s @@ -0,0 +1,44 @@ + movl $3, 0(%rbp) + movl $2, 1(%rbp) + movl $8, 2(%rbp) + movl 1(%rbp), %eax + subl 2(%rbp), %eax + movl %eax, 3(%rbp) + movl 0(%rbp), %eax + addl 0(%rbp), %eax + movl %eax, 4(%rbp) + movl $3, 5(%rbp) + movl $2, 6(%rbp) + movl $8, 7(%rbp) + movl 6(%rbp), %eax + cltd + idivl 7(%rbp) + movl %eax, 8(%rbp) + movl 5(%rbp), %eax + subl 8(%rbp), %eax + movl %eax, 9(%rbp) + movl $2, 10(%rbp) + movl $8, 11(%rbp) + movl $3, 12(%rbp) + movl $2, 13(%rbp) + movl 12(%rbp), %eax + subl 13(%rbp), %eax + movl %eax, 14(%rbp) + movl $8, 15(%rbp) + movl 14(%rbp), %eax + cltd + idivl 15(%rbp) + movl %edx, 16(%rbp) + movl $3, 17(%rbp) + movl $2, 18(%rbp) + movl 17(%rbp), %eax + cltd + idivl 18(%rbp) + movl %edx, 19(%rbp) + movl $8, 20(%rbp) + movl 19(%rbp), %eax + subl 20(%rbp), %eax + movl %eax, 21(%rbp) + movl $3, 22(%rbp) + movl $8, 23(%rbp) + movl $0, 24(%rbp) diff --git a/src/runner.c b/src/runner.c index 736be1c..2253b73 100644 --- a/src/runner.c +++ b/src/runner.c @@ -3,7 +3,6 @@ #include "runner.h" FILE *ir_flag = NULL; -FILE *cg_flag = NULL; //Constant_Stack *head = NULL; int main(int argc, char *argv[]) { if (argc == 1) { @@ -38,6 +37,7 @@ int main(int argc, char *argv[]) { alpha_file = fopen(argv[argc - 1], "r"); } } + cg_flag = fopen("cg.s", "w"); return run(alpha_file); } @@ -125,6 +125,8 @@ int run(FILE *alpha) { print_symbol_table(top, st_flag); emit_as_file(stdout, begin); fclose(st_flag); + generate(); + fclose(cg_flag); } if (asc_flag != NULL) { @@ -141,10 +143,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 7e134f2..503b319 100644 --- a/src/runner.h +++ b/src/runner.h @@ -48,6 +48,7 @@ FILE *alpha_file; FILE *tok_flag = NULL; FILE *st_flag = NULL; FILE *asc_flag = NULL; +FILE *cg_flag = NULL; bool tc_flag = false; bool DEBUG = false; int no_flag = 0; diff --git a/src/symbol_table.c b/src/symbol_table.c index 4ec3e70..441eb5c 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -1948,10 +1948,24 @@ char * label_gen(){ 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; + Instruction *i = begin; while (i != NULL) { switch(getOp(i)) { case E_LABEL: @@ -2023,6 +2037,7 @@ int generate(){ default: ; } + i = i->next; } return -1; } @@ -2038,6 +2053,7 @@ int getAddress(CGNode *cg) { if (cg == NULL) { return -1; } + return currentsp - cg->address; } @@ -2047,10 +2063,7 @@ TableNode *getTNofCG(CGNode *cg) { } return cg->tn; } -/* -movl $1, -4(%rbp) -add -4(%rbp), $2 -*/ + CGNode *findCG(TableNode *tn) { CGNode *cg = cgList; while (cg != NULL) { @@ -2085,20 +2098,20 @@ int generateAdd(Instruction *inst) { */ TNodeOrConst *op1 = getOperand1(inst); TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL || op2 == NULL) { printdebug("generateAdd failed, NULL operand"); return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(inst), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + 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; @@ -2109,9 +2122,9 @@ int generateAdd(Instruction *inst) { 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)); + 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; } @@ -2121,21 +2134,21 @@ int generateSub(Instruction *instruction) { One immediate: Neither immediate: */ - TNodeOrConst *op1 = getOperand1(inst); - TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + 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 (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(instruction), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + 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; @@ -2146,13 +2159,13 @@ int generateSub(Instruction *instruction) { 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)); + 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 *instruction){ +int generateMult(Instruction *inst){ /* Both immediate: One immediate: @@ -2160,18 +2173,18 @@ int generateMult(Instruction *instruction){ */ TNodeOrConst *op1 = getOperand1(inst); TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL || op2 == NULL) { printdebug("generateMult failed, NULL operand"); return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(inst), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + 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; @@ -2182,13 +2195,13 @@ int generateMult(Instruction *instruction){ 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)); + 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 *instruction) { +int generateDiv(Instruction *inst) { /* Both immediate: One immediate: @@ -2196,19 +2209,19 @@ int generateDiv(Instruction *instruction) { */ TNodeOrConst *op1 = getOperand1(inst); TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL || op2 == NULL) { printdebug("generateDiv failed, NULL operand"); return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(inst), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + 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; @@ -2219,14 +2232,14 @@ int generateDiv(Instruction *instruction) { return -1; } - fprintf(cg_flag, "\tmovl\t%d(\%rbp), \%eax\n", getAddress(op1CG)); //moves dividend into eax + 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 + 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 *instruction) { +int generateMod(Instruction *inst) { /* Both immediate: One immediate: @@ -2234,18 +2247,18 @@ int generateMod(Instruction *instruction) { */ TNodeOrConst *op1 = getOperand1(inst); TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL || op2 == NULL) { printdebug("generateMod failed, NULL operand"); return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(inst), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + 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; @@ -2256,14 +2269,14 @@ int generateMod(Instruction *instruction) { return -1; } - fprintf(cg_flag, "\tmovl\t%d(\%rbp), \%eax\n", getAddress(op1CG)); //moves dividend into eax + 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) + 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 *instruction) { +int generateOr(Instruction *inst) { /* Both immediate: One immediate: @@ -2271,19 +2284,19 @@ int generateOr(Instruction *instruction) { */ TNodeOrConst *op1 = getOperand1(inst); TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL || op2 == NULL) { printdebug("generateOr failed, NULL operand"); return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(inst), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + 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; @@ -2294,13 +2307,13 @@ int generateOr(Instruction *instruction) { 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 + 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 *instruction) { +int generateAnd(Instruction *inst) { /* Both immediate: One immediate: @@ -2308,50 +2321,50 @@ int generateAnd(Instruction *instruction) { */ TNodeOrConst *op1 = getOperand1(inst); TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL || op2 == NULL) { printdebug("%sgenerateAnd failed, NULL operand", COLOR_RED); return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(inst), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + CGNode *op1CG = findCG(getTN(op1)); + CGNode *op2CG = findCG(getTN(op2)); if (op1CG == NULL) { - printdebug("generateNeg failed, op1 is not constant but not in CGlist"); + printdebug("generateAnd 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))); + 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)); + 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 *instruction) { +int generateNeg(Instruction *inst) { TNodeOrConst *op1 = getOperand1(inst); TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL || op2 == NULL) { printdebug("generateNeg failed, NULL operand"); return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(inst), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + 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; @@ -2362,27 +2375,27 @@ int generateNeg(Instruction *instruction) { 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)); + 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 *instruction) { +int generateNot(Instruction *inst) { TNodeOrConst *op1 = getOperand1(inst); TNodeOrConst *op2 = getOperand2(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL || op2 == NULL) { printdebug("generateNot failed, NULL operand"); return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + if (cg == NULL) { + cg = addCG(getResult(inst), offset); } - CGNode *op1CG = findCG(op1); - CGNode *op2CG = findCG(op2); + 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; @@ -2393,15 +2406,15 @@ int generateNot(Instruction *instruction) { 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)); + 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 *instruction) { +int generateAssign(Instruction *inst) { TNodeOrConst *op1 = getOperand1(inst); - CGNode *result = findCG(getResult(inst)); + CGNode *cg = findCG(getResult(inst)); if (op1 == NULL) { @@ -2409,22 +2422,25 @@ int generateAssign(Instruction *instruction) { return -1; } - if (result == NULL) { - result = addCG(getResult(inst), offset); + 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(op1); + 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)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); return 0; } @@ -2432,29 +2448,101 @@ int generateGoto(Instruction *instruction){ return -1; } -int generateCondGoto(Instruciton *instruction) { +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 *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 *instruction){ - return -1; + +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; @@ -2466,5 +2554,6 @@ 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 From f256a90e3e4d34d7559ca2984e80ba53d1b6a8a7 Mon Sep 17 00:00:00 2001 From: Moroseui <157774170+Moroseui@users.noreply.github.com> Date: Fri, 25 Apr 2025 17:21:49 -0400 Subject: [PATCH 09/18] deleted extra files --- cg.s | 44 ---------- check.sh | 0 src/intermediate_code.c | 188 ---------------------------------------- src/intermediate_code.h | 109 ----------------------- test.alpha | 29 ------- test.sh | 0 6 files changed, 370 deletions(-) delete mode 100644 cg.s mode change 100755 => 100644 check.sh delete mode 100644 src/intermediate_code.c delete mode 100644 src/intermediate_code.h delete mode 100644 test.alpha mode change 100755 => 100644 test.sh diff --git a/cg.s b/cg.s deleted file mode 100644 index 47bbe30..0000000 --- a/cg.s +++ /dev/null @@ -1,44 +0,0 @@ - movl $3, 0(%rbp) - movl $2, 1(%rbp) - movl $8, 2(%rbp) - movl 1(%rbp), %eax - subl 2(%rbp), %eax - movl %eax, 3(%rbp) - movl 0(%rbp), %eax - addl 0(%rbp), %eax - movl %eax, 4(%rbp) - movl $3, 5(%rbp) - movl $2, 6(%rbp) - movl $8, 7(%rbp) - movl 6(%rbp), %eax - cltd - idivl 7(%rbp) - movl %eax, 8(%rbp) - movl 5(%rbp), %eax - subl 8(%rbp), %eax - movl %eax, 9(%rbp) - movl $2, 10(%rbp) - movl $8, 11(%rbp) - movl $3, 12(%rbp) - movl $2, 13(%rbp) - movl 12(%rbp), %eax - subl 13(%rbp), %eax - movl %eax, 14(%rbp) - movl $8, 15(%rbp) - movl 14(%rbp), %eax - cltd - idivl 15(%rbp) - movl %edx, 16(%rbp) - movl $3, 17(%rbp) - movl $2, 18(%rbp) - movl 17(%rbp), %eax - cltd - idivl 18(%rbp) - movl %edx, 19(%rbp) - movl $8, 20(%rbp) - movl 19(%rbp), %eax - subl 20(%rbp), %eax - movl %eax, 21(%rbp) - movl $3, 22(%rbp) - movl $8, 23(%rbp) - movl $0, 24(%rbp) diff --git a/check.sh b/check.sh old mode 100755 new mode 100644 diff --git a/src/intermediate_code.c b/src/intermediate_code.c deleted file mode 100644 index 6349054..0000000 --- a/src/intermediate_code.c +++ /dev/null @@ -1,188 +0,0 @@ - - - -// 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 * tn_or_const(Op op, void * tnc) { - TNodeOrConst * count = calloc(1, sizeof(*count)); - count->d = op; - switch (op) { - 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 = *(bool*)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++; - current = inst; - } -} - -void emit_binary_op(Op op, TableNode * result, TNodeOrConst * arg1, TNodeOrConst * arg2){ - emit_helper(); - current->opcode = op; - current->result = result; - current->operand1 = arg1; - current->operand2 = arg2; - return; - } - -void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg){ - emit_helper(); - current->opcode = op; - current->result = result; - current->operand1 = arg; - return; - } - -void emit_assignment(TableNode * target, TNodeOrConst * source){ - emit_helper(); - current->opcode = E_ASSIGN; // TODO: replace with move - current->result = target; - current->operand1 = source; - return; - } - -void emit_as_file(FILE * out_file, Instruction * instr_arr){ - if(instr_arr == NULL){ - return; - } - - //fprintf(out_file, - return; -} - - -void emit_label(int label){ - emit_helper(); - current->opcode = E_LABEL; - current->label = label; - return; -} -void emit_jump(int label){ - emit_helper(); - current->opcode = E_GOTO; - current->label = label; - return; -} - -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_LESSTHEN: case E_EQUALTO: - n1 = va_arg(argptr, TNodeOrConst *); - n2 = va_arg(argptr, TNodeOrConst *); - current->operand1 = n1; - current->operand2 = n2; - break; - } - va_end(argptr); - return; -} - -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 - return; -} - -void emit_parameter(TNodeOrConst * param){ - emit_helper(); - current->opcode = E_PARAM; - current->operand1 = param; - return; -} - -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; - return; -} -void emit_return(TNodeOrConst * value){ - emit_helper(); - current->opcode = E_RETURN; - current->operand1 = value; - return; -} -void emit_reserve(char* result, char* type_name, int size){ - emit_helper(); - return; -} -void emit_release(char* pointer){ - emit_helper(); - return; -} - - -void emit_field_access(char* result, char* record, char* field){ - emit_helper(); - return; -} -void emit_array_access(char* result, char* array, char* index, char* dimension){ - emit_helper(); - return; -} -void emit_bounds_check(char* index, char* size, char* error_label){ - emit_helper(); - return; -} - - -// * 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; -} diff --git a/src/intermediate_code.h b/src/intermediate_code.h deleted file mode 100644 index 2bb423a..0000000 --- a/src/intermediate_code.h +++ /dev/null @@ -1,109 +0,0 @@ -// Track 1: Core Infrastructure & Basic Expressions -// * Add Bison actions for arithmetic expressions: -// - Addition: $$ = new_temp(); emit_binary_op($$, "ADD", $1, $3); -// - Subtraction, multiplication, division, modulo - - -// 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_LESSTHEN, // 6 rule 1 + 5 - E_EQUALTO, // 6 rule 1 + 5 - E_CALL, // 7 - E_PARAM, // 7 - E_RETURN, // 7 - E_INDEX_COPY_RIGHT, // 8 - E_INDEX_COPY_LEFT, // 8 - E_ADDRESS_OF // 9 - /* for x = *y and *y = x we can just use index copy right and left with - index 0*/ -} 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; - -extern Instruction * begin; -extern Instruction * current; -int temp_count = 0; -int label_count = 0; -bool code_gen = true; - - - -TNodeOrConst * tn_or_const(Op op, 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); -// TODO: Find out what these are suposed to do. Guess is create an entry in -// the list of instructions. Guess is that its suposed to ret a struct ptr - -// * Implement integer/boolean/character specific operation handling -// TODO: Find out what this means. - -// * Create output function to write instructions to file with line formatting -void emit_as_file(FILE * out_file, Instruction * instr_arr); - -// * Implement instruction array storage for backpatching - -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(char* result, char* type_name, int size); -void emit_release(char* pointer); - -void emit_field_access(char* result, char* record, char* field); -void emit_array_access(char* result, char* array, char* index, char* dimension); -void emit_bounds_check(char* index, char* size, char* error_label); diff --git a/test.alpha b/test.alpha deleted file mode 100644 index 7b06a5e..0000000 --- a/test.alpha +++ /dev/null @@ -1,29 +0,0 @@ - - - -type a : 1 -> integers -type t : integer -> a -type r : integer -> integer - - - -function foo : t -function bar : r -function entry : - -bar(a) := { - 5 + bar(a - 1); - return a * bar(a-1); -} - -foo(c) := { - [a: arg] - arg := reserve arg(c); - return arg; -} - -entry(args) := { - [a: b] - b := foo(8); -} - diff --git a/test.sh b/test.sh old mode 100755 new mode 100644 From 666f68823883c71bd705e9d0a5c17b0ab3360e87 Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 17:25:38 -0400 Subject: [PATCH 10/18] Ready to rebase --- a.out | 0 src/codegen.c | 0 src/codegen.h | 0 src/runner.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/runner.h | 14 +++++++++ 5 files changed, 92 insertions(+) create mode 100644 a.out create mode 100644 src/codegen.c create mode 100644 src/codegen.h diff --git a/a.out b/a.out new file mode 100644 index 0000000..e69de29 diff --git a/src/codegen.c b/src/codegen.c new file mode 100644 index 0000000..e69de29 diff --git a/src/codegen.h b/src/codegen.h new file mode 100644 index 0000000..e69de29 diff --git a/src/runner.c b/src/runner.c index 0ccb74f..5833e3e 100644 --- a/src/runner.c +++ b/src/runner.c @@ -108,6 +108,26 @@ int run(FILE *alpha) { fprintf(stderr, "INPUT FILE NOT FOUND\n"); return -1; } + + char *line; + int i = 1; + while ((line = file_read_line(alpha)) != NULL) { + CodeLine *code_line = malloc(sizeof(CodeLine)); + code_line->line_number = i; + code_line->line = malloc(strlen(line) + 1); + strcpy(code_line->line, line); + code_line->next = NULL; + code_line->is_error = false; + append_code_line(code_line); + free(line); + i++; + } + + fseek(alpha, 0, SEEK_SET); + + + // print_code_lines(); + yyin = alpha; yyparse(); @@ -225,3 +245,61 @@ int is_alpha_file(char *alpha, int file_len) { } return 0; // is alpha file } + +void insert_code_line(char *line, int line_number) { +} + +void append_code_line(CodeLine *code_line) { + if (code_line == NULL) return; + + if (code_head == NULL) { + code_head = code_line; + } else { + CodeLine *current = code_head; + while (current->next != NULL) { + current = current->next; + } + current->next = code_line; + } +} + +void print_code_lines() { + CodeLine *current = code_head; + while (current != NULL) { + printf("%d %03d: %s",current->line_number, current->line); + current = current->next; + } +} + +char *file_read_line(FILE *fp) { + if (fp == NULL) return NULL; + + size_t size = 128; + size_t len = 0; + char *str = malloc(size); + if (!str) return NULL; + + int c; + while ((c = fgetc(fp)) != EOF) { + if (len + 1 >= size) { + size *= 2; + char *new_buffer = realloc(str, size); + if (!new_buffer) { + free(str); + return NULL; + } + str = new_buffer; + } + + str[len++] = (char)c; + if (c == '\n') break; + } + + if (len == 0 && c == EOF) { + free(str); + return NULL; + } + + str[len] = '\0'; + return str; +} \ No newline at end of file diff --git a/src/runner.h b/src/runner.h index 16b505b..0573255 100644 --- a/src/runner.h +++ b/src/runner.h @@ -91,3 +91,17 @@ char *COLOR_LIGHTBLUE = "\033[1;34m"; char *COLOR_LIGHTPURPLE = "\033[1;35m"; char *COLOR_LIGHTCYAN = "\033[1;36m"; char *COLOR_WHITE = "\033[1;37m"; + +typedef struct CodeLine { + char *line; + int line_number; + bool is_error; + struct CodeLine *next; +} CodeLine; + +CodeLine *code_head; + +char *file_read_line(FILE *fp); +void insert_code_line(char *line, int line_number); +void append_code_line(CodeLine *code_line); +void print_code_lines(); \ No newline at end of file From ab406471cc41e30acec36aa7a79395947fe83b2e Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 17:39:49 -0400 Subject: [PATCH 11/18] Now ready for rebase --- a.out | 0 src/intermediate_code.c | 386 ---------------------------------------- src/intermediate_code.h | 155 ---------------- 3 files changed, 541 deletions(-) delete mode 100644 a.out diff --git a/a.out b/a.out deleted file mode 100644 index e69de29..0000000 diff --git a/src/intermediate_code.c b/src/intermediate_code.c index 6b1b32f..e69de29 100644 --- a/src/intermediate_code.c +++ b/src/intermediate_code.c @@ -1,386 +0,0 @@ -#include "intermediate_code.h" - -Instruction * begin; -Instruction * current; -char * temp = NULL; - - -// 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 * get_result(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; - 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 = *(bool*)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++; - 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){ - return; - } - switch(i->opcode){ - case E_LABEL: - // 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->operand2)); - 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; -} \ No newline at end of file diff --git a/src/intermediate_code.h b/src/intermediate_code.h index b6e6fd4..e69de29 100644 --- a/src/intermediate_code.h +++ b/src/intermediate_code.h @@ -1,155 +0,0 @@ -// Track 1: Core Infrastructure & Basic Expressions -// * Add Bison actions for arithmetic expressions: -// - Addition: $$ = new_temp(); emit_binary_op($$, "ADD", $1, $3); -// - Subtraction, multiplication, division, modulo -#pragma once - -#include "symbol_table.h" -#include -#include - -// 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 - - -extern Instruction * begin; -extern Instruction * current; -int temp_count = 0; -int label_count = 0; -bool code_gen = true; - - -TNodeOrConst * tn_or_const(Discriminant , void * ); -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, int error_label); - -// * 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 - */ \ No newline at end of file From 086c8ba1703994e0b438b0c52f24c34cb109d1b2 Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 19:29:05 -0400 Subject: [PATCH 12/18] Project restucture with IR and CG --- Makefile | 17 +- check.sh | 0 src/codegen.c | 590 ++++++++++++++++++++++ src/codegen.h | 57 +++ src/grammar.h | 28 ++ src/grammar.y | 19 +- src/intermediate_code.c | 399 +++++++++++++++ src/intermediate_code.h | 121 +++++ src/lexicalStructure.h | 29 ++ src/lexicalStructure.lex | 29 +- src/runner.c | 7 +- src/runner.h | 4 +- src/symbol_table.c | 1034 +------------------------------------- src/symbol_table.h | 198 +------- test.sh | 0 15 files changed, 1262 insertions(+), 1270 deletions(-) mode change 100644 => 100755 check.sh create mode 100644 src/grammar.h create mode 100644 src/lexicalStructure.h mode change 100644 => 100755 test.sh diff --git a/Makefile b/Makefile index 8798f2e..e91f705 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,7 @@ LEX := src/lexicalStructure.lex YACC := src/grammar.y EXE := alpha -OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o -# tmp/intermediate_code.o codegen.o <--- Add to line above +OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o tmp/intermediate_code.o tmp/codegen.o TESTS-S1 := $(wildcard tests/sprint1/test/*.alpha) TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha) @@ -31,6 +30,7 @@ clean: rm -f $(EXE) rm -rf out rm -rf tmp + rm -f *.s tmp: mkdir -p tmp @@ -55,13 +55,11 @@ tmp/lex.yy.o: tmp/lex.yy.c tmp/symbol_table.o: src/symbol_table.c src/symbol_table.h $(CC) $(CFLAGS) -c src/symbol_table.c -o tmp/symbol_table.o -# Uncomment rules when ready +tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h + $(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o -# tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h -# $(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o - -# tmp/codegen.o: src/codegen.c src/codegen.h -# $(CC) $(CFLAGS) -c src/codegen.c -o tmp/codegen.o +tmp/codegen.o: src/codegen.c src/codegen.h + $(CC) $(CFLAGS) -c src/codegen.c -o tmp/codegen.o tmp/runner.o: src/runner.c src/runner.h tmp/flex.h tmp/grammar.tab.h $(CC) $(CFLAGS) -c src/runner.c -o tmp/runner.o @@ -102,7 +100,4 @@ test-s4: chmod +x ./test.sh ./test.sh sp4 ./check.sh sp4 - -# Temprorary test ~ Scarlett -test-make: clean tmp tmp/grammar.tab.c tmp/grammar.tab.h tmp/lex.yy.c tmp/flex.h tmp/grammar.tab.o tmp/lex.yy.o tmp/symbol_table.o tmp/runner.o # ----------- \ No newline at end of file diff --git a/check.sh b/check.sh old mode 100644 new mode 100755 diff --git a/src/codegen.c b/src/codegen.c index e69de29..358f3bd 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -0,0 +1,590 @@ +#include "codegen.h" + +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/codegen.h b/src/codegen.h index e69de29..a228b94 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "intermediate_code.h" +#include "symbol_table.h" + +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); +CGNode *findCG(TableNode *tn); +CGNode *addCG(TableNode *tn, int sp); +int generateLabel(Instruction *inst); +int generateAdd(Instruction *inst); +int generateSub(Instruction *instruction); +int generateMult(Instruction *inst); +int generateDiv(Instruction *inst); +int generateMod(Instruction *inst); +int generateOr(Instruction *inst); +int generateAnd(Instruction *inst); +int generateNeg(Instruction *inst); +int generateNot(Instruction *inst); +int generateAssign(Instruction *inst); +int generateGoto(Instruction *instruction); +int generateCondGoto(Instruction *instruction); +int generateIfTrue(Instruction *instruction); +int generateIfFalse(Instruction *instruction); +int generateLessThan(Instruction *inst); +int generateEqualTo(Instruction *inst); +int generateCall(Instruction *instruction); +int generateReturn(Instruction *instruction); +int generateCopyRight(Instruction *instruction); +int generateCopyLeft(Instruction *instruction); +int generateAddressOf(Instruction *instruction); +int generateParam(Instruction *instruction); + +extern int label_count; +extern Instruction *begin; +extern Instruction *current; + +extern int offset; +extern int currentsp; +extern CGNode *cgList; \ No newline at end of file diff --git a/src/grammar.h b/src/grammar.h new file mode 100644 index 0000000..018974e --- /dev/null +++ b/src/grammar.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../src/codegen.h" +#include "../src/intermediate_code.h" +#include "../src/symbol_table.h" +extern FILE *asc_flag; +extern bool tc_flag; + +typedef enum { + ERROR_RUNTIME = 1, + ERROR_SYNTAX = 2, + ERROR_TYPE = 3, + ERROR_UNDEFINED = 4 +} ErrorType; + +int token_tracker; +TableNode *tn; + +void yyerror(const char *err); +void throw_error(ErrorType error_type, const char *format, ...); + +int label_count; +Instruction *begin; +Instruction *current; + +int offset; +int currentsp; +CGNode *cgList; \ No newline at end of file diff --git a/src/grammar.y b/src/grammar.y index 90ba7a4..75e70ec 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -17,22 +17,7 @@ // Please ask Scarlett if you are unsure of how to format something. Thanks! 😀 %{ - #include "../src/symbol_table.h" - extern FILE *asc_flag; - extern bool tc_flag; - - typedef enum { - ERROR_RUNTIME = 1, - ERROR_SYNTAX = 2, - ERROR_TYPE = 3, - ERROR_UNDEFINED = 4 - } ErrorType; - - int token_tracker; - TableNode * tn; - - void yyerror(const char *err); - void throw_error(ErrorType error_type, const char *format, ...); + #include "../src/grammar.h" %} %union { @@ -630,7 +615,7 @@ expression: $$ = node; } else { $$=undefined; - error_type(getTypeEntry((TableNode*)$2), integ, ""); + throw_error(ERROR_TYPE, "%s != %s", getName(getTypeEntry((TableNode*)$2)), getName(integ)); } } diff --git a/src/intermediate_code.c b/src/intermediate_code.c index e69de29..65458cf 100644 --- a/src/intermediate_code.c +++ b/src/intermediate_code.c @@ -0,0 +1,399 @@ +#include "intermediate_code.h" + +// 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; +} \ No newline at end of file diff --git a/src/intermediate_code.h b/src/intermediate_code.h index e69de29..fd654e0 100644 --- a/src/intermediate_code.h +++ b/src/intermediate_code.h @@ -0,0 +1,121 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "symbol_table.h" + +// 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; + +TNodeOrConst* getOperand1(Instruction* i); +TNodeOrConst* getOperand2(Instruction* i); +TableNode* getResult(Instruction* i); +Op getOp(Instruction* i); +int getLabel(Instruction* i); +int get_index(Instruction* i); +void set_label(Instruction* i, int label); +bool isConst(TNodeOrConst* tnc); +TNodeOrConst* tn_or_const(Discriminant d, void* tnc); +static void emit_helper(void); +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); +char* get_string(TNodeOrConst* tc); +void emit_as_file(FILE* out_file, Instruction* i); +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_deref_right(); +void emit_deref_left(); +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); +char* label_gen(); +TableNode* getTN(TNodeOrConst* tnc); +int getConst(TNodeOrConst* tnc); + +extern int label_count; +extern Instruction* begin; +extern Instruction* current; + +extern int offset; +extern int currentsp; +extern CGNode* cgList; \ No newline at end of file diff --git a/src/lexicalStructure.h b/src/lexicalStructure.h new file mode 100644 index 0000000..1b77a94 --- /dev/null +++ b/src/lexicalStructure.h @@ -0,0 +1,29 @@ +#include "../src/symbol_table.h" +#include "../tmp/grammar.tab.h" + +extern SymbolTable *cur; +extern FILE *tok_flag; +extern TableNode *funprime; +extern TableNode *funtypeprime; +extern TableNode *arrayprim; +extern TableNode *recprime; +extern TableNode *integ; +extern TableNode *addr; +extern TableNode *chara; +extern TableNode *stri; +extern TableNode *boo; +extern TableNode *undefined; +extern void incr(int lnum, int cnum, int tok); +extern void print_tok(int tok); + +int line_number = 1; +int column_number = 1; +int yycolumn = 1; + +#define YY_USER_ACTION { \ + yylloc.first_line = yylineno; \ + yylloc.last_line = yylineno; \ + yylloc.first_column = yycolumn; \ + yylloc.last_column = yycolumn + yyleng - 1; \ + yycolumn += yyleng; \ +} diff --git a/src/lexicalStructure.lex b/src/lexicalStructure.lex index 2aaf6d2..cd1b56e 100644 --- a/src/lexicalStructure.lex +++ b/src/lexicalStructure.lex @@ -6,34 +6,7 @@ %option yylineno %{ - #include "../tmp/grammar.tab.h" - #include "../src/symbol_table.h" - extern SymbolTable * cur; - extern FILE* tok_flag; - extern TableNode *funprime; - extern TableNode *funtypeprime; - extern TableNode *arrayprim; - extern TableNode *recprime; - extern TableNode *integ; - extern TableNode *addr; - extern TableNode *chara; - extern TableNode *stri; - extern TableNode *boo; - extern TableNode *undefined; - extern void incr(int lnum,int cnum, int tok); - extern void print_tok(int tok); - - int line_number = 1; - int column_number = 1; - int yycolumn = 1; - - #define YY_USER_ACTION { \ - yylloc.first_line = yylineno; \ - yylloc.last_line = yylineno; \ - yylloc.first_column = yycolumn; \ - yylloc.last_column = yycolumn + yyleng - 1; \ - yycolumn += yyleng; \ - } + #include "../src/lexicalStructure.h" %} STARCOM [^\*]|\*+[^\)\*]+ diff --git a/src/runner.c b/src/runner.c index 3f8a8c5..afeeb73 100644 --- a/src/runner.c +++ b/src/runner.c @@ -127,7 +127,6 @@ int run(FILE *alpha) { fseek(alpha, 0, SEEK_SET); - // print_code_lines(); yyin = alpha; @@ -163,8 +162,8 @@ int run(FILE *alpha) { } //if (cg_flag != NULL) { - // printf("Flag -cg is not implemented yet\n"); - //fclose(cg_flag); + // printf("Flag -cg is not implemented yet\n"); + //fclose(cg_flag); //} if (yyin != NULL) { @@ -271,7 +270,7 @@ void append_code_line(CodeLine *code_line) { void print_code_lines() { CodeLine *current = code_head; while (current != NULL) { - printf("%d %03d: %s",current->line_number, current->line); + printf("%d %03d: %s", current->line_number, current->line); current = current->next; } } diff --git a/src/runner.h b/src/runner.h index d20776b..d5531bd 100644 --- a/src/runner.h +++ b/src/runner.h @@ -35,6 +35,8 @@ #include "../tmp/flex.h" #include "../tmp/grammar.tab.h" +#include "codegen.h" +#include "intermediate_code.h" #include "symbol_table.h" extern int line_number; @@ -66,7 +68,7 @@ TableNode *boo; TableNode *recprime; TableNode *funtypeprime; TableNode *undefined; -extern Instruction* begin; +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 e1e8ea4..2fc926c 100644 --- a/src/symbol_table.c +++ b/src/symbol_table.c @@ -3,16 +3,8 @@ #include "symbol_table.h" -Constant_Stack * head = NULL; +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) { @@ -26,8 +18,8 @@ void printdebug_impl(char *file, int line, const char *format, ...) { } } -char * temp_var_gen(){ - char * ret = calloc(9, sizeof(*ret)); +char *temp_var_gen() { + char *ret = calloc(9, sizeof(*ret)); sprintf(ret, "$t%d", temp2_count); temp2_count++; return ret; @@ -44,10 +36,10 @@ Constant_Stack *Push(TableNode *type, void *value, bool isConst) { cs->theType = type; cs->theValue = value; cs->isConst = isConst; - if(head == NULL){ + if (head == NULL) { head = cs; cs->next = NULL; - }else{ + } else { cs->next = head; head = cs; } @@ -65,36 +57,36 @@ Constant_Stack *Pop() { return cs; } -Constant_Stack* Print_Stack(){ +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){ + 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 == stri) { + printf("Type: %s, Value: %s\n", getName(cs->theType), *(char *)(cs->theValue)); } - if(cs->theType == integ){ + if (cs->theType == integ) { printf("Type: %s, Value: %d\n", getName(cs->theType), (int *)(cs->theValue)); } - if(cs->theType == chara){ + 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{ + 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) { @@ -1561,997 +1553,3 @@ 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 0175541..aa9bb64 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -2,16 +2,15 @@ #include #include +#include #include #include #include -#include -#include #define SIZE_INT 4 #define SIZE_ADDR 8 #define SIZE_CHAR 1 -#define SIZE_BOOL 4 //TODO: Ask Carl what this size should be +#define SIZE_BOOL 1 struct TableNode; typedef struct TFList TFList; @@ -63,7 +62,6 @@ typedef struct ListOfTable { struct ListOfTable *next; } ListOfTable; -//Table node to store typedef struct TableNode { struct TableNode *theType; int tag; @@ -99,7 +97,10 @@ void printdebug_impl(char *file, int line, const char *format, ...); #define printdebug(format, ...) \ printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__) -void printdebug_impl(char *file, int line, const char *format, ...); +char *temp_var_gen(); +Constant_Stack *Push(TableNode *type, void *value, bool isConst); +Constant_Stack *Pop(); +Constant_Stack *Print_Stack(); AdInfo *CreatePrimitiveInfo(int size); int getPrimSize(TableNode *definition); AdInfo *CreateArrayInfo(int dim, TableNode *type); @@ -187,189 +188,4 @@ extern char *COLOR_YELLOW; 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 +extern char *COLOR_WHITE; \ No newline at end of file diff --git a/test.sh b/test.sh old mode 100644 new mode 100755 From 55116599f8d4cf01535cbde4ccb4290cec1b38d7 Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 19:39:52 -0400 Subject: [PATCH 13/18] pragma + watermarks --- src/codegen.c | 3 +++ src/codegen.h | 3 +++ src/grammar.h | 3 +++ src/grammar.y | 1 - src/intermediate_code.c | 3 +++ src/intermediate_code.h | 3 +++ src/lexicalStructure.h | 5 +++++ src/symbol_table.h | 3 +++ src/typedefs.h | 3 +++ 9 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/codegen.c b/src/codegen.c index 358f3bd..dfce1ff 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1,3 +1,6 @@ +/* Code Generator */ +/* The Translators - Spring 2025 */ + #include "codegen.h" int generate() { diff --git a/src/codegen.h b/src/codegen.h index a228b94..3203a52 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -1,3 +1,6 @@ +/* Code Generator */ +/* The Translators - Spring 2025 */ + #pragma once #include diff --git a/src/grammar.h b/src/grammar.h index 018974e..94f43b1 100644 --- a/src/grammar.h +++ b/src/grammar.h @@ -1,3 +1,6 @@ +/* Syntax Analyzer with Bison (3.8.2) */ +/* The Translators - Spring 2025 */ + #pragma once #include "../src/codegen.h" diff --git a/src/grammar.y b/src/grammar.y index 75e70ec..3dda42f 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -1,4 +1,3 @@ - /* Syntax Analyzer with Bison (3.8.2) */ /* The Translators - Spring 2025 */ diff --git a/src/intermediate_code.c b/src/intermediate_code.c index 65458cf..103df2b 100644 --- a/src/intermediate_code.c +++ b/src/intermediate_code.c @@ -1,3 +1,6 @@ +/* Intermediate Code */ +/* The Translators - Spring 2025 */ + #include "intermediate_code.h" // TODO: this is here to bring your attention to the comment bellow. diff --git a/src/intermediate_code.h b/src/intermediate_code.h index fd654e0..d2b5088 100644 --- a/src/intermediate_code.h +++ b/src/intermediate_code.h @@ -1,3 +1,6 @@ +/* Intermediate Code */ +/* The Translators - Spring 2025 */ + #pragma once #include diff --git a/src/lexicalStructure.h b/src/lexicalStructure.h index 1b77a94..bdd0db7 100644 --- a/src/lexicalStructure.h +++ b/src/lexicalStructure.h @@ -1,3 +1,8 @@ +/* Lexical Analyzer with Flex (1.6.0) */ +/* The Translators - Spring 2025 */ + +#pragma once + #include "../src/symbol_table.h" #include "../tmp/grammar.tab.h" diff --git a/src/symbol_table.h b/src/symbol_table.h index aa9bb64..391f05a 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -1,3 +1,6 @@ +/* Symbol Table */ +/* The Translators - Spring 2025 */ + #pragma once #include diff --git a/src/typedefs.h b/src/typedefs.h index 5405f66..5c476bf 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -1,3 +1,6 @@ +/* Type Definitions */ +/* The Translators - Spring 2025 */ + // identifier #define ID 101 // type names From 3ea41f40fa46f532d65c12a42b52027be31a2c0c Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 22:14:31 -0400 Subject: [PATCH 14/18] TC & ASC Implemented. yyerrors updated. --- Makefile | 1 + src/grammar.h | 1 + src/grammar.y | 126 ++++++++++++++---- src/runner.c | 55 +++++--- src/runner.h | 3 +- tests/sprint2/test/sp2_llnode.alpha | 2 +- .../sp3_integer_binary_op_typecheck.alpha | 6 +- 7 files changed, 148 insertions(+), 46 deletions(-) diff --git a/Makefile b/Makefile index e91f705..6fefed1 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ clean: rm -rf out rm -rf tmp rm -f *.s + rm -f *.out tmp: mkdir -p tmp diff --git a/src/grammar.h b/src/grammar.h index 94f43b1..2b7b03c 100644 --- a/src/grammar.h +++ b/src/grammar.h @@ -8,6 +8,7 @@ #include "../src/symbol_table.h" extern FILE *asc_flag; extern bool tc_flag; +extern void insert_code_line(char * error_message, int line_number); typedef enum { ERROR_RUNTIME = 1, diff --git a/src/grammar.y b/src/grammar.y index 3dda42f..2751080 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -106,6 +106,7 @@ program: prototype_or_definition_list + | error { yyerrok; } ; @@ -115,12 +116,17 @@ prototype_or_definition_list: | definition prototype_or_definition_list | prototype | definition + | error { yyerrok; } ; prototype: - L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID; + L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID + + | error { yyerrok; } + + ; @@ -259,7 +265,7 @@ definition: } } - ; + ; function_declaration: FUNCTION ID COLON ID @@ -285,6 +291,7 @@ function_declaration: } } + ; @@ -344,6 +351,9 @@ idlist: printdebug("Type of entry is %s", getType(entry)); printdebug("tag is %d", getAdInfoType(entry)); } + + | error { yyerrok; } + ; @@ -391,6 +401,9 @@ sblock: } R_BRACE {$$ = $5;} + + | error { yyerrok; } + ; @@ -408,13 +421,20 @@ dblock: printdebug("Created a new scope when seeing a dblock"); } } - declaration_list R_BRACKET; + declaration_list R_BRACKET + + | error { yyerrok; } + + ; declaration_list: declaration SEMI_COLON declaration_list | declaration + + | error { yyerrok; } + ; @@ -452,6 +472,9 @@ declaration: CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); } } + + | error { yyerrok; } + ; @@ -468,6 +491,9 @@ id_or_types: printdebug("string of type is %s in types pattern of id_or_type rule.",getName((TableNode*)$1)); $$ = (TableNode*)$1; } + + | error { yyerrok; } + ; @@ -503,6 +529,7 @@ compound_statement statement_list { | simple_statement SEMI_COLON { $$ = $1; } + ; @@ -523,9 +550,11 @@ WHILE L_PAREN expression R_PAREN sblock { $$ = undefined; } } - | sblock { + + | sblock { $$ = $1; } + ; @@ -557,7 +586,10 @@ simple_statement: } -| RETURN expression {$$ = getTypeEntry((TableNode*)$2);} + | RETURN expression {$$ = getTypeEntry((TableNode*)$2);} + + | error { yyerrok; } + ; @@ -565,6 +597,9 @@ simple_statement: rec_op: DOT + | error { yyerrok; } + + ; ablock: @@ -573,6 +608,9 @@ ablock: $$ = $2; printdebug("ablock is %d", $$); } + + | error { yyerrok; } + ; @@ -591,6 +629,9 @@ argument_list: CreateEntry(cur,getAdInfoType((TableNode*)$1),(TableNode*)$1, getName((TableNode*)$1), NULL); $$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$); } + + | error { yyerrok; } + ; @@ -786,6 +827,8 @@ expression: $$=undefined; } } + + | error { yyerrok; } ; @@ -969,6 +1012,8 @@ assignable: printdebug("[ASSIGNABLE - RULE 3] record = name: %s | field = %s", getName((TableNode*)($1)), getName((TableNode*)$3)); } + | error { yyerrok; } + ; @@ -984,6 +1029,8 @@ memOp: printdebug("release expression"); } + | error { yyerrok; } + ; @@ -1043,7 +1090,7 @@ constant: printdebug("string of C_FALSE in constant is false"); $$ = node; } - + ; @@ -1071,8 +1118,7 @@ types: { $$ = $1; printdebug("string of T_BOOLEAN in types is %s",getName((TableNode*)$1)); - } - + } ; %% @@ -1104,24 +1150,50 @@ void throw_error(ErrorType error_type, const char *format, ...) { break; } + if (asc_flag) { + /* yyerror(""); */ + int needed = snprintf(NULL, 0, " LINE (%d:%d) ** %s ERROR: ", line, column, error_name); + char *error_message = malloc(needed + 1); + snprintf(error_message, needed + 1, " LINE (%d:%d) ** %s ERROR: ", line, column, error_name); - if (tc_flag) { - yyerror(""); - if (asc_flag != NULL) { - fprintf(asc_flag, "(%d:%d) ** %s ERROR: ", line, column, error_name); - va_list args; - va_start(args, format); - vfprintf(asc_flag, format, args); + va_list args; + va_start(args, format); + va_list args_copy; + va_copy(args_copy, args); + int needed2 = vsnprintf(NULL, 0, format, args_copy) + 1; + va_end(args_copy); + + char *error_message2 = malloc(needed2); + if (error_message2 == NULL) { + fprintf(stderr, "Memory allocation failed\n"); va_end(args); - fprintf(asc_flag, "\n"); - } else { - fprintf(stderr, "%s(%d:%d) ** %s ERROR%s: %s", COLOR_RED, line, column, error_name, COLOR_WHITE, COLOR_YELLOW); - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - fprintf(stderr, "%s\n", COLOR_WHITE); + return; } + + vsnprintf(error_message2, needed2, format, args); + va_end(args); + + int total_needed = needed + needed2 + 2; + char *total_error_message = malloc(total_needed); + if (total_error_message == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + free(error_message); + free(error_message2); + return; + } + + snprintf(total_error_message, total_needed, "%s%s\n\n", error_message, error_message2); + if (tc_flag) { + insert_code_line(total_error_message, line); + } else { + if (error_type != ERROR_TYPE) { + insert_code_line(total_error_message, line); + } + } + + free(error_message); + free(error_message2); + free(total_error_message); } } @@ -1132,11 +1204,13 @@ void yyerror(const char *err) { // 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); + int needed = snprintf(NULL, 0, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n\n", line, column, yytext); + char *error_message = malloc(needed + 1); + snprintf(error_message, needed + 1, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n\n", line, column, yytext); + insert_code_line(error_message, line); } 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); + fprintf(stderr, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token %s\n\n", line, column, yytext); } } } diff --git a/src/runner.c b/src/runner.c index afeeb73..a74c424 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2,8 +2,7 @@ /* 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); @@ -36,7 +35,6 @@ int main(int argc, char *argv[]) { alpha_file = fopen(argv[argc - 1], "r"); } } - cg_flag = fopen("cg.s", "w"); return run(alpha_file); } @@ -127,8 +125,6 @@ int run(FILE *alpha) { fseek(alpha, 0, SEEK_SET); - // print_code_lines(); - yyin = alpha; yyparse(); @@ -140,15 +136,14 @@ int run(FILE *alpha) { } if (st_flag != NULL) { + printdebug("[-st] Symbol Table is enabled."); print_symbol_table(top, st_flag); - emit_as_file(stdout, begin); fclose(st_flag); - generate(); - fclose(cg_flag); } if (asc_flag != NULL) { printdebug("[-asc] Annotated Source Code is enabled."); + print_code_lines(); fclose(asc_flag); } @@ -157,14 +152,16 @@ int run(FILE *alpha) { } if (ir_flag != NULL) { - printf("Flag -ir is not implemented yet\n"); + printdebug("[-ir] Intermediate code is enabled."); + emit_as_file(ir_flag, begin); fclose(ir_flag); } - //if (cg_flag != NULL) { - // printf("Flag -cg is not implemented yet\n"); - //fclose(cg_flag); - //} + if (cg_flag != NULL) { + printdebug("[-cg] Code generation is enabled."); + generate(); + fclose(cg_flag); + } if (yyin != NULL) { fclose(yyin); @@ -250,7 +247,26 @@ int is_alpha_file(char *alpha, int file_len) { return 0; // is alpha file } -void insert_code_line(char *line, int line_number) { +void insert_code_line(char * error_message, int line_number) { + CodeLine *error_line = malloc(sizeof(CodeLine)); + error_line->line_number = line_number; + error_line->line = malloc(strlen(error_message) + 1); + strcpy(error_line->line, error_message); + error_line->next = NULL; + error_line->is_error = true; + + if (error_line == NULL || code_head == NULL) return; + + int line = error_line->line_number; + CodeLine *current = code_head; + while (current != NULL) { + if (current->line_number == line) { + CodeLine *next_code_line = current->next; + current->next = error_line; + error_line->next = next_code_line; + } + current = current->next; + } } void append_code_line(CodeLine *code_line) { @@ -268,9 +284,18 @@ void append_code_line(CodeLine *code_line) { } void print_code_lines() { + if (code_head == NULL) { + printf("No code lines to print.\n"); + return; + } + CodeLine *current = code_head; while (current != NULL) { - printf("%d %03d: %s", current->line_number, current->line); + if (current->is_error) { + fprintf(asc_flag, "%s", current->line); + } else { + fprintf(asc_flag, "%03d: %s", current->line_number, current->line); + } current = current->next; } } diff --git a/src/runner.h b/src/runner.h index d5531bd..9971eed 100644 --- a/src/runner.h +++ b/src/runner.h @@ -52,6 +52,7 @@ FILE *alpha_file; FILE *tok_flag = NULL; FILE *st_flag = NULL; FILE *asc_flag = NULL; +FILE *ir_flag = NULL; FILE *cg_flag = NULL; bool tc_flag = false; bool DEBUG = false; @@ -105,6 +106,6 @@ typedef struct CodeLine { CodeLine *code_head; char *file_read_line(FILE *fp); -void insert_code_line(char *line, int line_number); +void insert_code_line(char * error_message, int line_number); void append_code_line(CodeLine *code_line); void print_code_lines(); \ No newline at end of file diff --git a/tests/sprint2/test/sp2_llnode.alpha b/tests/sprint2/test/sp2_llnode.alpha index 3ecfb11..c611b3c 100644 --- a/tests/sprint2/test/sp2_llnode.alpha +++ b/tests/sprint2/test/sp2_llnode.alpha @@ -21,7 +21,7 @@ make_list (a) := { } else { ret := reserve ret; ret.prev := null; - ret.next := null; + ret.next :s= null;g ret.val := a; while (0 < a) { temp := reserve temp; diff --git a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha index 2adb394..a804c23 100644 --- a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha +++ b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha @@ -8,12 +8,12 @@ entry (arg) := { x := 3 + 2 * 8; x := 3 - 2 / 8; - x := a * 2 % 8; + x := a * 2 % 8;s b2 := 3 * 2 % 8; x := 3 % 2 * 8; x := 3 + arr - 8; - x := r.x; - x := a.x; + x := r.x; + x := a.x; return 0; } From 74dc4f568fdae02f2493a5325f061bb8b8e3daa1 Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 22:41:58 -0400 Subject: [PATCH 15/18] Quick throw --- src/grammar.y | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/grammar.y b/src/grammar.y index 2751080..cfcc476 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -445,6 +445,7 @@ declaration: printdebug("ID/TYPE: %s, ID: %s", getName((TableNode*)$1), $3) ; int d = getAdInfoType((TableNode*)$1); if(d == TYPE_UNDEFINED) { + throw_error(ERROR_TYPE, "Undefined type passed in declaration list"); printdebug("Undefined type passed in declaration list"); CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); } @@ -468,7 +469,7 @@ declaration: d = TYPE_PRIMITIVE; CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); }else { - printdebug("Invalid type passed in declaration list."); + throw_error(ERROR_TYPE, "%s is being defined with an undefined type", $3); CreateEntry(cur,d,(TableNode*)$1,$3,getAdInfo((TableNode*)$1)); } } @@ -841,6 +842,9 @@ assignable: ID { TableNode* pass = look_up(cur,$1); + if(pass == undefined){ + throw_error(ERROR_TYPE, "Undefined variable %s", $1); + } $$ = pass; printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getType(pass), getName(pass)); } From 747a48b2117e8e7b96bd5f83bcf2c0fa6f0f1b5e Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 23:09:46 -0400 Subject: [PATCH 16/18] implemented annies and meyers stuff --- src/codegen.c | 355 +++++++++++++++++++++------------------- src/grammar.y | 2 +- src/intermediate_code.c | 14 +- src/intermediate_code.h | 4 +- 4 files changed, 199 insertions(+), 176 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index dfce1ff..825fd55 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -3,78 +3,79 @@ #include "codegen.h" -int generate() { +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:; + 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; } @@ -117,13 +118,14 @@ CGNode *findCG(TableNode *tn) { 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 + offset += getPrimSize(getTypeEntry(tn)); + cg->address = offset; cg->next = cgList; cgList = cg; return cg; } + int generateLabel(Instruction *inst) { fprintf(cg_flag, ".L%d:\n", getLabel(inst)); return 0; @@ -137,7 +139,7 @@ int generateAdd(Instruction *inst) { 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; @@ -146,7 +148,8 @@ int generateAdd(Instruction *inst) { if (cg == NULL) { cg = addCG(getResult(inst), offset); } - + + CGNode *op1CG = findCG(getTN(op1)); CGNode *op2CG = findCG(getTN(op1)); if (op1CG == NULL) { @@ -158,15 +161,15 @@ int generateAdd(Instruction *inst) { 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)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#addition start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\taddl\t%%edx, %%eax\n"); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#addition end\n", getAddress(cg)); return 0; } int generateSub(Instruction *instruction) { - /* + /* Both immediate: One immediate: Neither immediate: @@ -174,7 +177,7 @@ int generateSub(Instruction *instruction) { 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; @@ -183,7 +186,7 @@ int generateSub(Instruction *instruction) { if (cg == NULL) { cg = addCG(getResult(instruction), offset); } - + CGNode *op1CG = findCG(getTN(op1)); CGNode *op2CG = findCG(getTN(op2)); if (op1CG == NULL) { @@ -196,14 +199,14 @@ int generateSub(Instruction *instruction) { return -1; } - fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#subtraction start\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)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#subtraction end\n", getAddress(cg)); return 0; } -int generateMult(Instruction *inst) { - /* +int generateMult(Instruction *inst){ + /* Both immediate: One immediate: Neither immediate: @@ -211,7 +214,7 @@ int generateMult(Instruction *inst) { 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; @@ -232,14 +235,14 @@ int generateMult(Instruction *inst) { 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)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#multiplication start\n", getAddress(op1CG)); + fprintf(cg_flag, "\timull\t%d(%%rbp), %%eax\n", getAddress(op2CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#multiplication end\n", getAddress(cg)); return 0; } int generateDiv(Instruction *inst) { - /* + /* Both immediate: One immediate: Neither immediate: @@ -247,7 +250,7 @@ int generateDiv(Instruction *inst) { 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; @@ -256,7 +259,7 @@ int generateDiv(Instruction *inst) { if (cg == NULL) { cg = addCG(getResult(inst), offset); } - + CGNode *op1CG = findCG(getTN(op1)); CGNode *op2CG = findCG(getTN(op2)); if (op1CG == NULL) { @@ -269,10 +272,10 @@ int generateDiv(Instruction *inst) { 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 + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#division start\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)\t#division end\n", getAddress(cg)); //stores result return 0; } @@ -285,7 +288,7 @@ int generateMod(Instruction *inst) { 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; @@ -300,21 +303,21 @@ int generateMod(Instruction *inst) { 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) + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#mod start\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)\t#mod end\n", getAddress(cg)); //stores result from edx (remainder) return 0; } int generateOr(Instruction *inst) { - /* + /* Both immediate: One immediate: Neither immediate: @@ -322,7 +325,7 @@ int generateOr(Instruction *inst) { 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; @@ -331,7 +334,7 @@ int generateOr(Instruction *inst) { if (cg == NULL) { cg = addCG(getResult(inst), offset); } - + CGNode *op1CG = findCG(getTN(op1)); CGNode *op2CG = findCG(getTN(op2)); if (op1CG == NULL) { @@ -344,9 +347,24 @@ int generateOr(Instruction *inst) { 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 + int label = label_gen(); + + fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\t#start or\n", getAddress(op1CG)); + fprintf(cg_flag, "\tjne\t.L%dor2\n", label); + + fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\n", getAddress(op2CG)); + fprintf(cg_flag, "\tje\t.L%dor3\n", label); + + fprintf(cg_flag, ".L%dor2:\n", label); + fprintf(cg_flag, "\tmovl\t$1, %%eax\n"); + fprintf(cg_flag, "\tjmp\t.L%dor4\n", label); + + fprintf(cg_flag, ".L%dor3:\n", label); + fprintf(cg_flag, "\tmovl\t$0, %%eax\n"); + + fprintf(cg_flag, ".L%dor4:\n", label); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg)); + fprintf(cg_flag, "\tandb\t$1, %d(%%rbp)\t#or end\n", getAddress(cg)); //stores result return 0; } @@ -359,7 +377,7 @@ int generateAnd(Instruction *inst) { 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; @@ -368,7 +386,7 @@ int generateAnd(Instruction *inst) { if (cg == NULL) { cg = addCG(getResult(inst), offset); } - + CGNode *op1CG = findCG(getTN(op1)); CGNode *op2CG = findCG(getTN(op2)); if (op1CG == NULL) { @@ -380,18 +398,30 @@ int generateAnd(Instruction *inst) { printdebug("generateAnd failed, %s is not initialized/in CG", getName(getTN(op2))); return -1; } + int label = label_gen(); - 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)); + fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\t#start and\n", getAddress(op1CG)); + fprintf(cg_flag, "\tje\t.L%dor2\n", label); + + fprintf(cg_flag, "\tcmpl\t$0, %d(%%rbp)\n", getAddress(op2CG)); + fprintf(cg_flag, "\tje\t.L%dor2\n", label); + + fprintf(cg_flag, "\tmovl\t$1, %%eax\n"); + fprintf(cg_flag, "\tjmp\t.L%dor3\n", label); + + fprintf(cg_flag, ".L%dor2:\n", label); + fprintf(cg_flag, "\tmovl\t$0, %%eax\n"); + + fprintf(cg_flag, ".L%dor3:\n", label); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg)); + fprintf(cg_flag, "\tandb\t$1, %d(%%rbp)\t#and end\n", getAddress(cg)); //stores result return 0; } int generateNeg(Instruction *inst) { TNodeOrConst *op1 = getOperand1(inst); - TNodeOrConst *op2 = getOperand2(inst); CGNode *cg = findCG(getResult(inst)); - - if (op1 == NULL || op2 == NULL) { + + if (op1 == NULL) { printdebug("generateNeg failed, NULL operand"); return -1; } @@ -399,30 +429,23 @@ int generateNeg(Instruction *inst) { 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)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#negation start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tnegl\t%%eax\n"); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#negation end\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) { + + if (op1 == NULL) { printdebug("generateNot failed, NULL operand"); return -1; } @@ -430,22 +453,20 @@ int generateNot(Instruction *inst) { 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)); + fprintf(cg_flag, "\tmovzbl\t%d(%%rbp), %%eax\t#not start\n", getAddress(op1CG)); + fprintf(cg_flag, "\ttestl\t%%eax, %%eax\n"); + fprintf(cg_flag, "\tsetne\t%%al\n"); + fprintf(cg_flag, "\txorl\t$1, %%eax\n"); + fprintf(cg_flag, "\tmovzbl\t%%al, %%eax\n"); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg)); + fprintf(cg_flag, "\tandb\t$1, %d(%%rbp)\t#not end\n", getAddress(cg)); return 0; } @@ -453,6 +474,7 @@ int generateAssign(Instruction *inst) { TNodeOrConst *op1 = getOperand1(inst); CGNode *cg = findCG(getResult(inst)); + if (op1 == NULL) { printdebug("generateAssign failed, NULL operand"); return -1; @@ -462,23 +484,26 @@ int generateAssign(Instruction *inst) { 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)); + fprintf(cg_flag, "\tmovl\t$%d, %d(%%rbp)\t#constant assign\n", getConst(op1), getAddress(cg)); + return 0; } - + CGNode *op1CG = findCG(getTN(op1)); if (op1CG == NULL) { + printf("failed here\n"); 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)); + + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#assign start\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\t#assign end\n", getAddress(cg)); return 0; } -int generateGoto(Instruction *instruction) { +int generateGoto(Instruction *instruction){ return -1; } @@ -486,17 +511,17 @@ int generateCondGoto(Instruction *instruction) { return -1; } -int generateIfTrue(Instruction *instruction) { +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) { +int generateIfFalse(Instruction *instruction){ return -1; } -int generateLessThan(Instruction *inst) { - /* +int generateLessThan(Instruction *inst){ + /* Both immediate: One immediate: Neither immediate: @@ -504,7 +529,7 @@ int generateLessThan(Instruction *inst) { 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; @@ -513,7 +538,7 @@ int generateLessThan(Instruction *inst) { if (cg == NULL) { cg = addCG(getResult(inst), offset); } - + CGNode *op1CG = findCG(getTN(op1)); CGNode *op2CG = findCG(getTN(op2)); if (op1CG == NULL) { @@ -526,15 +551,15 @@ int generateLessThan(Instruction *inst) { return -1; } - fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#less than start\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)); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\t#less than end\n", getAddress(cg)); return 0; } -int generateEqualTo(Instruction *inst) { - /* +int generateEqualTo(Instruction *inst){ + /* Both immediate: One immediate: Neither immediate: @@ -542,7 +567,7 @@ int generateEqualTo(Instruction *inst) { 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; @@ -551,7 +576,7 @@ int generateEqualTo(Instruction *inst) { if (cg == NULL) { cg = addCG(getResult(inst), offset); } - + CGNode *op1CG = findCG(getTN(op1)); CGNode *op2CG = findCG(getTN(op2)); if (op1CG == NULL) { @@ -564,30 +589,30 @@ int generateEqualTo(Instruction *inst) { return -1; } - fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); + fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\t#equal to start\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)); + fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\t#equal to end\n", getAddress(cg)); return 0; } -int generateCall(Instruction *instruction) { +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) { +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) { +int generateCopyRight(Instruction *instruction){ return -1; } -int generateCopyLeft(Instruction *instruction) { +int generateCopyLeft(Instruction *instruction){ return -1; } -int generateAddressOf(Instruction *instruction) { +int generateAddressOf(Instruction *instruction){ return -1; } -int generateParam(Instruction *instruction) { +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/grammar.y b/src/grammar.y index cfcc476..9f96a6c 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -577,7 +577,7 @@ simple_statement: if(getAdInfoType(node) == getAdInfoType((TableNode*)$3)){ - //EMIT ASSIGN INSTRUCTION HERE + emit_assignment($1, tn_or_const(NODE, $3)); 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)); diff --git a/src/intermediate_code.c b/src/intermediate_code.c index 103df2b..9948115 100644 --- a/src/intermediate_code.c +++ b/src/intermediate_code.c @@ -278,11 +278,11 @@ void emit_conditional_jump(Op condition, int label, ...) { va_end(argptr); } -void emit_function_start(int name) { +void emit_function_start(TNodeOrConst * name) { emit_helper(); current->opcode = E_LABEL; // I think this is right TODO: ask - current->label = name; - // this is probabaly a func decleration + current->operand1 = name; + // this is probabaly a func declaration } void emit_parameter(TNodeOrConst* param) { @@ -380,11 +380,9 @@ char * temp_var_gen(){ return ret; } */ -char* label_gen() { - char* ret = calloc(9, sizeof(*ret)); - sprintf(ret, "L_%d", label_count); +int label_gen(){ label_count++; - return ret; + return label_count; } TableNode* getTN(TNodeOrConst* tnc) { @@ -393,7 +391,7 @@ TableNode* getTN(TNodeOrConst* tnc) { } return NULL; } -//we must fix this + int getConst(TNodeOrConst* tnc) { if (tnc->d == INTEGER) { return tnc->tnc_union->integer; diff --git a/src/intermediate_code.h b/src/intermediate_code.h index d2b5088..c1efb76 100644 --- a/src/intermediate_code.h +++ b/src/intermediate_code.h @@ -100,7 +100,7 @@ void emit_as_file(FILE* out_file, Instruction* i); 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_function_start(TNodeOrConst * name); void emit_parameter(TNodeOrConst* param); void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name); void emit_return(TNodeOrConst* value); @@ -111,7 +111,7 @@ void emit_deref_left(); 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); -char* label_gen(); +int label_gen(); TableNode* getTN(TNodeOrConst* tnc); int getConst(TNodeOrConst* tnc); From 6e4841f0c1ff8a3b17f7fc01d69755fe604c296a Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 23:26:50 -0400 Subject: [PATCH 17/18] Big testing update --- src/codegen.c | 2 +- src/grammar.y | 2 +- test.sh | 4 ++-- tests/sprint2/test/sp2_llnode.alpha | 2 +- .../sp3_integer_binary_op_typecheck.alpha | 6 +++--- tests/sprint4/expected/sp4_cg_add.expected | 12 +++++++++++ tests/sprint4/expected/sp4_cg_and.expected | 20 ++++++++++++++++++ tests/sprint4/expected/sp4_cg_div.expected | 12 +++++++++++ .../sprint4/expected/sp4_cg_equal_to.expected | 13 ++++++++++++ .../expected/sp4_cg_less_than.expected | 13 ++++++++++++ tests/sprint4/expected/sp4_cg_mod.expected | 12 +++++++++++ tests/sprint4/expected/sp4_cg_mult.expected | 11 ++++++++++ tests/sprint4/expected/sp4_cg_neg.expected | 8 +++++++ tests/sprint4/expected/sp4_cg_not.expected | 13 ++++++++++++ tests/sprint4/expected/sp4_cg_or.expected | 21 +++++++++++++++++++ tests/sprint4/expected/sp4_cg_sub.expected | 11 ++++++++++ tests/sprint4/test/sp4_cg_add.alpha | 10 +++++++++ tests/sprint4/test/sp4_cg_and.alpha | 10 +++++++++ tests/sprint4/test/sp4_cg_div.alpha | 10 +++++++++ tests/sprint4/test/sp4_cg_equal_to.alpha | 10 +++++++++ tests/sprint4/test/sp4_cg_less_than.alpha | 10 +++++++++ tests/sprint4/test/sp4_cg_mod.alpha | 10 +++++++++ tests/sprint4/test/sp4_cg_mult.alpha | 10 +++++++++ tests/sprint4/test/sp4_cg_neg.alpha | 9 ++++++++ tests/sprint4/test/sp4_cg_not.alpha | 9 ++++++++ tests/sprint4/test/sp4_cg_or.alpha | 10 +++++++++ tests/sprint4/test/sp4_cg_sub.alpha | 10 +++++++++ 27 files changed, 262 insertions(+), 8 deletions(-) create mode 100644 tests/sprint4/expected/sp4_cg_add.expected create mode 100644 tests/sprint4/expected/sp4_cg_and.expected create mode 100644 tests/sprint4/expected/sp4_cg_div.expected create mode 100644 tests/sprint4/expected/sp4_cg_equal_to.expected create mode 100644 tests/sprint4/expected/sp4_cg_less_than.expected create mode 100644 tests/sprint4/expected/sp4_cg_mod.expected create mode 100644 tests/sprint4/expected/sp4_cg_mult.expected create mode 100644 tests/sprint4/expected/sp4_cg_neg.expected create mode 100644 tests/sprint4/expected/sp4_cg_not.expected create mode 100644 tests/sprint4/expected/sp4_cg_or.expected create mode 100644 tests/sprint4/expected/sp4_cg_sub.expected create mode 100644 tests/sprint4/test/sp4_cg_add.alpha create mode 100644 tests/sprint4/test/sp4_cg_and.alpha create mode 100644 tests/sprint4/test/sp4_cg_div.alpha create mode 100644 tests/sprint4/test/sp4_cg_equal_to.alpha create mode 100644 tests/sprint4/test/sp4_cg_less_than.alpha create mode 100644 tests/sprint4/test/sp4_cg_mod.alpha create mode 100644 tests/sprint4/test/sp4_cg_mult.alpha create mode 100644 tests/sprint4/test/sp4_cg_neg.alpha create mode 100644 tests/sprint4/test/sp4_cg_not.alpha create mode 100644 tests/sprint4/test/sp4_cg_or.alpha create mode 100644 tests/sprint4/test/sp4_cg_sub.alpha diff --git a/src/codegen.c b/src/codegen.c index 825fd55..250d2a4 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -118,7 +118,7 @@ CGNode *findCG(TableNode *tn) { CGNode *addCG(TableNode *tn, int sp) { CGNode *cg = calloc(1, sizeof(CGNode)); cg->tn = tn; - offset += getPrimSize(getTypeEntry(tn)); + offset += 4; // <- quick fix getPrimSize(getTypeEntry(tn)) cg->address = offset; cg->next = cgList; cgList = cg; diff --git a/src/grammar.y b/src/grammar.y index 9f96a6c..7060c94 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -1214,7 +1214,7 @@ void yyerror(const char *err) { insert_code_line(error_message, line); } else { - fprintf(stderr, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token %s\n\n", line, column, yytext); + fprintf(stderr, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token %s\n", line, column, yytext); } } } diff --git a/test.sh b/test.sh index 8443215..3f6f5a9 100755 --- a/test.sh +++ b/test.sh @@ -84,7 +84,7 @@ if [ $# -eq 0 ]; then if [ -f "$file" ]; then filename=$(basename -- "$file") echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" - ./alpha -st -debug "$file" + ./alpha -cg "$file" echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n${WHITE}" switchfunc fi @@ -154,7 +154,7 @@ else if [[ "$file" == *"$1"* ]]; then filename=$(basename -- "$file") echo -e "- ${SWITCH}Running test: ${LIGHTBLUE}$filename ${SWITCH}-----${WHITE}" - ./alpha -st -debug "$file" + ./alpha -cg -debug "$file" echo -e "${SWITCH}----- End of test: ${LIGHTBLUE}$filename ${SWITCH}-${WHITE}\n" switchfunc fi diff --git a/tests/sprint2/test/sp2_llnode.alpha b/tests/sprint2/test/sp2_llnode.alpha index c611b3c..3ecfb11 100644 --- a/tests/sprint2/test/sp2_llnode.alpha +++ b/tests/sprint2/test/sp2_llnode.alpha @@ -21,7 +21,7 @@ make_list (a) := { } else { ret := reserve ret; ret.prev := null; - ret.next :s= null;g + ret.next := null; ret.val := a; while (0 < a) { temp := reserve temp; diff --git a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha index a804c23..2adb394 100644 --- a/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha +++ b/tests/sprint3/test/sp3_integer_binary_op_typecheck.alpha @@ -8,12 +8,12 @@ entry (arg) := { x := 3 + 2 * 8; x := 3 - 2 / 8; - x := a * 2 % 8;s + x := a * 2 % 8; b2 := 3 * 2 % 8; x := 3 % 2 * 8; x := 3 + arr - 8; - x := r.x; - x := a.x; + x := r.x; + x := a.x; return 0; } diff --git a/tests/sprint4/expected/sp4_cg_add.expected b/tests/sprint4/expected/sp4_cg_add.expected new file mode 100644 index 0000000..4764400 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_add.expected @@ -0,0 +1,12 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #addition start + movl -16(%rbp), %eax + addl %edx, %eax + movl %eax, -20(%rbp) #addition end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_and.expected b/tests/sprint4/expected/sp4_cg_and.expected new file mode 100644 index 0000000..be6a53e --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_and.expected @@ -0,0 +1,20 @@ + movl $-1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $-1, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + cmpl $0, -8(%rbp) #start and + je .L1or2 + cmpl $0, -16(%rbp) + je .L1or2 + movl $1, %eax + jmp .L1or3 +.L1or2: + movl $0, %eax +.L1or3: + movb %al, -20(%rbp) + andb $1, -20(%rbp) #and end + movl -20(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl $1, -24(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_div.expected b/tests/sprint4/expected/sp4_cg_div.expected new file mode 100644 index 0000000..1a71c6e --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_div.expected @@ -0,0 +1,12 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #division start + cltd + idivl -8(%rbp) + movl %eax, -20(%rbp) #division end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_equal_to.expected b/tests/sprint4/expected/sp4_cg_equal_to.expected new file mode 100644 index 0000000..e29c6c1 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_equal_to.expected @@ -0,0 +1,13 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $2, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -8(%rbp), %eax #equal to start + cmpl -16(%rbp), %eax + sete %al + movb %al, -20(%rbp) #equal to end + movl -20(%rbp), %eax #assign start + movl %eax, -24(%rbp) #assign end + movl $1, -28(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_less_than.expected b/tests/sprint4/expected/sp4_cg_less_than.expected new file mode 100644 index 0000000..b8d8904 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_less_than.expected @@ -0,0 +1,13 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $2, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -8(%rbp), %eax #less than start + cmpl -16(%rbp), %eax + setl %al + movb %al, -20(%rbp) #less than end + movl -20(%rbp), %eax #assign start + movl %eax, -24(%rbp) #assign end + movl $1, -28(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_mod.expected b/tests/sprint4/expected/sp4_cg_mod.expected new file mode 100644 index 0000000..97d4259 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_mod.expected @@ -0,0 +1,12 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #mod start + cltd + idivl -8(%rbp) + movl %edx, -20(%rbp) #mod end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_mult.expected b/tests/sprint4/expected/sp4_cg_mult.expected new file mode 100644 index 0000000..20b0a57 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_mult.expected @@ -0,0 +1,11 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #multiplication start + imull -16(%rbp), %eax + movl %eax, -20(%rbp) #multiplication end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_neg.expected b/tests/sprint4/expected/sp4_cg_neg.expected new file mode 100644 index 0000000..5f61770 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_neg.expected @@ -0,0 +1,8 @@ + movl $3, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl -8(%rbp), %eax #negation start + negl %eax + movl %eax, -12(%rbp) #negation end + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end diff --git a/tests/sprint4/expected/sp4_cg_not.expected b/tests/sprint4/expected/sp4_cg_not.expected new file mode 100644 index 0000000..b2e4bda --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_not.expected @@ -0,0 +1,13 @@ + movl $-1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movzbl -8(%rbp), %eax #not start + testl %eax, %eax + setne %al + xorl $1, %eax + movzbl %al, %eax + movb %al, -12(%rbp) + andb $1, -12(%rbp) #not end + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl $1, -20(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_or.expected b/tests/sprint4/expected/sp4_cg_or.expected new file mode 100644 index 0000000..120058f --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_or.expected @@ -0,0 +1,21 @@ + movl $-1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $-1, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + cmpl $0, -8(%rbp) #start or + jne .L1or2 + cmpl $0, -16(%rbp) + je .L1or3 +.L1or2: + movl $1, %eax + jmp .L1or4 +.L1or3: + movl $0, %eax +.L1or4: + movb %al, -20(%rbp) + andb $1, -20(%rbp) #or end + movl -20(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl $1, -24(%rbp) #constant assign diff --git a/tests/sprint4/expected/sp4_cg_sub.expected b/tests/sprint4/expected/sp4_cg_sub.expected new file mode 100644 index 0000000..743ef59 --- /dev/null +++ b/tests/sprint4/expected/sp4_cg_sub.expected @@ -0,0 +1,11 @@ + movl $1, -4(%rbp) #constant assign + movl -4(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end + movl $3, -12(%rbp) #constant assign + movl -12(%rbp), %eax #assign start + movl %eax, -16(%rbp) #assign end + movl -16(%rbp), %eax #subtraction start + subl -8(%rbp), %eax + movl %eax, -20(%rbp) #subtraction end + movl -20(%rbp), %eax #assign start + movl %eax, -8(%rbp) #assign end diff --git a/tests/sprint4/test/sp4_cg_add.alpha b/tests/sprint4/test/sp4_cg_add.alpha new file mode 100644 index 0000000..f4f8138 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_add.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x + y; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_and.alpha b/tests/sprint4/test/sp4_cg_and.alpha new file mode 100644 index 0000000..5017e35 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_and.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean:b; Boolean: c; Boolean: d] + c := true; + d := false; + d := c & d; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_div.alpha b/tests/sprint4/test/sp4_cg_div.alpha new file mode 100644 index 0000000..32d3537 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_div.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x / y; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_equal_to.alpha b/tests/sprint4/test/sp4_cg_equal_to.alpha new file mode 100644 index 0000000..a3da50c --- /dev/null +++ b/tests/sprint4/test/sp4_cg_equal_to.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean: b; integer: x; integer: y] + x := 1; + y := 2; + b := x = y; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_less_than.alpha b/tests/sprint4/test/sp4_cg_less_than.alpha new file mode 100644 index 0000000..8f41ced --- /dev/null +++ b/tests/sprint4/test/sp4_cg_less_than.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean: b; integer: x; integer: y] + x := 1; + y := 2; + b := x < y; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_mod.alpha b/tests/sprint4/test/sp4_cg_mod.alpha new file mode 100644 index 0000000..1b579d5 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_mod.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x % y; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_mult.alpha b/tests/sprint4/test/sp4_cg_mult.alpha new file mode 100644 index 0000000..c151a6b --- /dev/null +++ b/tests/sprint4/test/sp4_cg_mult.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x * x; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_neg.alpha b/tests/sprint4/test/sp4_cg_neg.alpha new file mode 100644 index 0000000..345980b --- /dev/null +++ b/tests/sprint4/test/sp4_cg_neg.alpha @@ -0,0 +1,9 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + x := 3; + y := -x; + return y; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_not.alpha b/tests/sprint4/test/sp4_cg_not.alpha new file mode 100644 index 0000000..40252f9 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_not.alpha @@ -0,0 +1,9 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean: c; Boolean: d] + c := true; + d := !c; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_or.alpha b/tests/sprint4/test/sp4_cg_or.alpha new file mode 100644 index 0000000..b6d6766 --- /dev/null +++ b/tests/sprint4/test/sp4_cg_or.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [Boolean:b; Boolean: c; Boolean: d] + c := true; + d := false; + d := c | d; + return 1; +} \ No newline at end of file diff --git a/tests/sprint4/test/sp4_cg_sub.alpha b/tests/sprint4/test/sp4_cg_sub.alpha new file mode 100644 index 0000000..f280c9d --- /dev/null +++ b/tests/sprint4/test/sp4_cg_sub.alpha @@ -0,0 +1,10 @@ +type main: integer -> integer +function test: main + +test (a) := { + [integer:x; integer:y] + y := 1; + x := 3; + y := x - y; + return y; +} \ No newline at end of file From 3e54a72f38d99d3a03ba11b8204c18a4844acf7a Mon Sep 17 00:00:00 2001 From: Scarlett Date: Fri, 25 Apr 2025 23:54:37 -0400 Subject: [PATCH 18/18] updated expected --- .../expected/sp3_and_or_type_check.expected | 84 +++++++++++-------- .../sp3_boolean_binary_op_typecheck.expected | 36 ++++---- .../sp3_boolean_unary_op_typecheck.expected | 33 +++----- .../sp3_integer_binary_op_typecheck.expected | 51 ++++++----- .../sp3_integer_unary_op_typecheck.expected | 34 ++++---- tests/sprint3/test/sp3_multiple_args.alpha | 5 +- tests/sprint3/test/sp3_multiple_args.alpha~ | 17 ---- 7 files changed, 121 insertions(+), 139 deletions(-) delete mode 100644 tests/sprint3/test/sp3_multiple_args.alpha~ diff --git a/tests/sprint3/expected/sp3_and_or_type_check.expected b/tests/sprint3/expected/sp3_and_or_type_check.expected index 600a1f9..493f53b 100644 --- a/tests/sprint3/expected/sp3_and_or_type_check.expected +++ b/tests/sprint3/expected/sp3_and_or_type_check.expected @@ -1,34 +1,50 @@ -NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -test : 001001 : : undefined : Function Definition -main : 001001 : : rec -> integer : Type of Function -rec : 001001 : : Record Type : elements-2 size-8 bytes -integer : 001001 : : Primitive Type : size-4 bytes -address : 001001 : : Primitive Type : size-8 bytes -character : 001001 : : Primitive Type : size-1 bytes -string : 001001 : : 1 -> character : Type of Array -Boolean : 001001 : : Primitive Type : size-4 bytes -reserve type : 001001 : : integer -> address : Type of Function -reserve : 001001 : : undefined : Function Definition -release type : 001001 : : address -> integer : Type of Function -release : 001001 : : undefined : Function Definition -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -b : 005000 : 001001 : Boolean : Primitive Instance -x : 005000 : 001001 : integer : Primitive Instance -arg : 005000 : 001001 : integer : Primitive Instance -undefined : 005000 : 001001 : integer : Primitive Instance -------------------------------:--------:--------:-----------------------------------:-----------------------------------: - : 023009 : 005000 : : Empty Scope -------------------------------:--------:--------:-----------------------------------:-----------------------------------: - : 021014 : 005000 : : Empty Scope -------------------------------:--------:--------:-----------------------------------:-----------------------------------: - : 017009 : 005000 : : Empty Scope -------------------------------:--------:--------:-----------------------------------:-----------------------------------: - : 015017 : 005000 : : Empty Scope -------------------------------:--------:--------:-----------------------------------:-----------------------------------: - : 011012 : 005000 : : Empty Scope -------------------------------:--------:--------:-----------------------------------:-----------------------------------: - : 007015 : 005000 : : Empty Scope -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -y : 001000 : 001001 : integer : Primitive Instance -x : 001000 : 001001 : integer : Primitive Instance +001: type rec: [integer: x; integer: y] +002: type main: rec -> integer +003: function test: main +004: +005: test (arg) := { +006: [integer:x; Boolean: b] +007: while (true) { +008: x := 0; +009: } +010: +011: while (7) { +012: x := 1; +013: } +014: +015: if (true) then { +016: x := 1; +017: } else { +018: x := 0; +019: } +020: +021: if (x) then { +022: x := 0; +023: } else { +024: x := 1; +025: } +026: +027: b := b | b; +028: b := b & b; +029: b := 1 | b; + LINE (29:12) ** TYPE ERROR: b != undefined + +030: b := b | 1; + LINE (30:12) ** TYPE ERROR: b != undefined + +031: b := b & 1; + LINE (31:12) ** TYPE ERROR: b != undefined + +032: b := 1 & b; + LINE (32:12) ** TYPE ERROR: b != undefined + +033: b := 1 = 1; +034: +035: +036: +037: b := 1 = b; + LINE (37:12) ** TYPE ERROR: b != undefined + +038: +039: return 0; +040: } diff --git a/tests/sprint3/expected/sp3_boolean_binary_op_typecheck.expected b/tests/sprint3/expected/sp3_boolean_binary_op_typecheck.expected index 1653f88..f95e765 100644 --- a/tests/sprint3/expected/sp3_boolean_binary_op_typecheck.expected +++ b/tests/sprint3/expected/sp3_boolean_binary_op_typecheck.expected @@ -1,20 +1,16 @@ -NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -entry : 001001 : : undefined : Function Definition -main : 001001 : : string -> integer : Type of Function -integer : 001001 : : Primitive Type : size-4 bytes -address : 001001 : : Primitive Type : size-8 bytes -character : 001001 : : Primitive Type : size-1 bytes -string : 001001 : : 1 -> character : Type of Array -Boolean : 001001 : : Primitive Type : size-4 bytes -reserve type : 001001 : : integer -> address : Type of Function -reserve : 001001 : : undefined : Function Definition -release type : 001001 : : address -> integer : Type of Function -release : 001001 : : undefined : Function Definition -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -b1 : 004000 : 001001 : Boolean : Primitive Instance -b2 : 004000 : 001001 : Boolean : Primitive Instance -arr2 : 004000 : 001001 : address : Primitive Instance -arr : 004000 : 001001 : address : Primitive Instance -x : 004000 : 001001 : integer : Primitive Instance -arg : 004000 : 001001 : string : Array Instance +001: type main: string -> integer +002: function entry: main +003: +004: entry (arg) := { +005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] +006: +007: b2 := 3 < x; +008: b1 := arr = 2; + LINE (8:18) ** TYPE ERROR: b1 != undefined + +009: b1 := 6<7 & arr2=7; + LINE (9:23) ** TYPE ERROR: b1 != undefined + +010: +011: return 0; +012: } diff --git a/tests/sprint3/expected/sp3_boolean_unary_op_typecheck.expected b/tests/sprint3/expected/sp3_boolean_unary_op_typecheck.expected index 1653f88..39237bc 100644 --- a/tests/sprint3/expected/sp3_boolean_unary_op_typecheck.expected +++ b/tests/sprint3/expected/sp3_boolean_unary_op_typecheck.expected @@ -1,20 +1,13 @@ -NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -entry : 001001 : : undefined : Function Definition -main : 001001 : : string -> integer : Type of Function -integer : 001001 : : Primitive Type : size-4 bytes -address : 001001 : : Primitive Type : size-8 bytes -character : 001001 : : Primitive Type : size-1 bytes -string : 001001 : : 1 -> character : Type of Array -Boolean : 001001 : : Primitive Type : size-4 bytes -reserve type : 001001 : : integer -> address : Type of Function -reserve : 001001 : : undefined : Function Definition -release type : 001001 : : address -> integer : Type of Function -release : 001001 : : undefined : Function Definition -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -b1 : 004000 : 001001 : Boolean : Primitive Instance -b2 : 004000 : 001001 : Boolean : Primitive Instance -arr2 : 004000 : 001001 : address : Primitive Instance -arr : 004000 : 001001 : address : Primitive Instance -x : 004000 : 001001 : integer : Primitive Instance -arg : 004000 : 001001 : string : Array Instance +001: type main: string -> integer +002: function entry: main +003: +004: entry (arg) := { +005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] +006: +007: b2 := !(3 < 2); +008: b1 := !5; + LINE (8:13) ** TYPE ERROR: b1 != undefined + +009: +010: return 0; +011: } diff --git a/tests/sprint3/expected/sp3_integer_binary_op_typecheck.expected b/tests/sprint3/expected/sp3_integer_binary_op_typecheck.expected index 8344120..0b4c83f 100644 --- a/tests/sprint3/expected/sp3_integer_binary_op_typecheck.expected +++ b/tests/sprint3/expected/sp3_integer_binary_op_typecheck.expected @@ -1,26 +1,25 @@ -NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -entry : 001001 : : undefined : Function Definition -rec : 001001 : : Record Type : elements-2 size-8 bytes -main : 001001 : : string -> integer : Type of Function -integer : 001001 : : Primitive Type : size-4 bytes -address : 001001 : : Primitive Type : size-8 bytes -character : 001001 : : Primitive Type : size-1 bytes -string : 001001 : : 1 -> character : Type of Array -Boolean : 001001 : : Primitive Type : size-4 bytes -reserve type : 001001 : : integer -> address : Type of Function -reserve : 001001 : : undefined : Function Definition -release type : 001001 : : address -> integer : Type of Function -release : 001001 : : undefined : Function Definition -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -r : 006000 : 001001 : rec : Record Instance -a : 006000 : 001001 : character : Primitive Instance -b1 : 006000 : 001001 : Boolean : Primitive Instance -b2 : 006000 : 001001 : Boolean : Primitive Instance -arr2 : 006000 : 001001 : address : Primitive Instance -arr : 006000 : 001001 : address : Primitive Instance -x : 006000 : 001001 : integer : Primitive Instance -arg : 006000 : 001001 : string : Array Instance -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -y : 003000 : 001001 : integer : Primitive Instance -x : 003000 : 001001 : integer : Primitive Instance +001: type main: string -> integer +002: +003: type rec: [integer: x; integer: y] +004: function entry: main +005: +006: entry (arg) := { +007: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1; character : a; rec : r] +008: +009: x := 3 + 2 * 8; +010: x := 3 - 2 / 8; +011: x := a * 2 % 8; + LINE (11:20) ** TYPE ERROR: x != undefined + +012: b2 := 3 * 2 % 8; +013: x := 3 % 2 * 8; +014: x := 3 + arr - 8; + LINE (14:22) ** TYPE ERROR: x != undefined + +015: x := r.x; + LINE (15:10) ** TYPE ERROR: x != r + +016: x := a.x; +017: +018: return 0; +019: } diff --git a/tests/sprint3/expected/sp3_integer_unary_op_typecheck.expected b/tests/sprint3/expected/sp3_integer_unary_op_typecheck.expected index 1653f88..18bd5a7 100644 --- a/tests/sprint3/expected/sp3_integer_unary_op_typecheck.expected +++ b/tests/sprint3/expected/sp3_integer_unary_op_typecheck.expected @@ -1,20 +1,14 @@ -NAME : SCOPE : PARENT : TYPE : EXTRA ANNOTATION : -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -entry : 001001 : : undefined : Function Definition -main : 001001 : : string -> integer : Type of Function -integer : 001001 : : Primitive Type : size-4 bytes -address : 001001 : : Primitive Type : size-8 bytes -character : 001001 : : Primitive Type : size-1 bytes -string : 001001 : : 1 -> character : Type of Array -Boolean : 001001 : : Primitive Type : size-4 bytes -reserve type : 001001 : : integer -> address : Type of Function -reserve : 001001 : : undefined : Function Definition -release type : 001001 : : address -> integer : Type of Function -release : 001001 : : undefined : Function Definition -------------------------------:--------:--------:-----------------------------------:-----------------------------------: -b1 : 004000 : 001001 : Boolean : Primitive Instance -b2 : 004000 : 001001 : Boolean : Primitive Instance -arr2 : 004000 : 001001 : address : Primitive Instance -arr : 004000 : 001001 : address : Primitive Instance -x : 004000 : 001001 : integer : Primitive Instance -arg : 004000 : 001001 : string : Array Instance +001: type main: string -> integer +002: function entry: main +003: +004: entry (arg) := { +005: [integer:x; address: arr; address: arr2; Boolean : b2; Boolean : b1] +006: +007: x := -8; +008: x := -b1; + LINE (8:10) ** TYPE ERROR: x != undefined + +009: b2 := -x; +010: +011: return 0; +012: } diff --git a/tests/sprint3/test/sp3_multiple_args.alpha b/tests/sprint3/test/sp3_multiple_args.alpha index e59c4b6..8475d92 100644 --- a/tests/sprint3/test/sp3_multiple_args.alpha +++ b/tests/sprint3/test/sp3_multiple_args.alpha @@ -6,12 +6,13 @@ type main: string -> integer function entry: main function bar: T2 -bar2 (r,s) := { - return r; +bar (r,s) := { + return 0; } entry (arg) := { [ integer: result ; rec: w] + result := bar(1,2); result := bar('c', 7); return 0; } \ No newline at end of file diff --git a/tests/sprint3/test/sp3_multiple_args.alpha~ b/tests/sprint3/test/sp3_multiple_args.alpha~ deleted file mode 100644 index 641c654..0000000 --- a/tests/sprint3/test/sp3_multiple_args.alpha~ +++ /dev/null @@ -1,17 +0,0 @@ -type rec: [character: x; integer: y] - -type T2: rec -> integer - -type main: string -> integer -function entry: main -function bar: T2 - -bar2 (r,s) := { - return s; -} - -entry (arg) := { - [ integer: result ; rec: w] - result := bar('c', 7); - return 0; -} \ No newline at end of file