Merge pull request #56 from UB-CSE443/DontBreakDev

Dont break dev
This commit is contained in:
Annie Slenker
2025-05-02 16:27:10 -04:00
committed by GitHub
20 changed files with 1311 additions and 733 deletions

View File

@ -3,8 +3,9 @@ CC := gcc
FLEX := flex
BISON = bison
CFLAGS := -ggdb
BISONFLAGS := -d
CFLAGS := -ggdb -g -O0 #-fsanitize=address
# LDFLAGS := -fsanitize=address
BISONFLAGS := -d -Wcounterexamples
LEX := src/lexicalStructure.lex
YACC := src/grammar.y
@ -24,7 +25,7 @@ TESTS-S4 := $(wildcard tests/sprint4/test/*.alpha)
all: compiler
compiler: clean tmp $(OBJS)
$(CC) $(CFLAGS) -o $(EXE) $(OBJS)
$(CC) $(CFLAGS) -o $(EXE) $(OBJS) $(LDFLAGS)
clean:
rm -f $(EXE)

View File

@ -502,7 +502,6 @@ int generateAssign(Instruction *inst) {
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;
}
@ -648,6 +647,7 @@ int generateCopyLeft(Instruction *inst){
int generateAddressOf(Instruction *inst){
return -1;
}
int generateParam(Instruction *inst){
TNodeOrConst *op1 = getOperand1(inst);
@ -686,5 +686,4 @@ int generateFunctionStart(Instruction *inst) {
fprintf(cg_flag, "\tmovq\t%%rsp, %%rbp\n");
return 0;
}

View File

@ -30,3 +30,7 @@ Instruction *current;
int offset;
int currentsp;
CGNode *cgList;
Stack* stack;
Stack* TrueList;
Stack* FalseList;

View File

@ -18,7 +18,6 @@
%{
#include "../src/grammar.h"
%}
%union {
int integ;
char* words;
@ -28,7 +27,7 @@
%locations
%token <integ> ACCESS 801
%type <integ> idlist
%type <tn> assignable
%type <tn> expression
@ -106,7 +105,6 @@
program:
prototype_or_definition_list
| error { yyerrok; }
;
@ -116,7 +114,8 @@ prototype_or_definition_list:
| definition prototype_or_definition_list
| prototype
| definition
| error { yyerrok; }
| prototype error { yyerrok; }
| definition error { yyerrok; }
;
@ -124,8 +123,6 @@ prototype_or_definition_list:
prototype:
L_PAREN EXTERNAL R_PAREN FUNCTION ID COLON ID
| error { yyerrok; }
;
@ -133,20 +130,11 @@ prototype:
definition:
TYPE ID COLON
{
printdebug("Currently see a record definition for %s", $2);
tn = CreateEntry(getAncestor(cur),TYPE_RECORD_TYPE, recprime, $2, CreateRecordInfo(0, cur = CreateScope(cur, 0, 0)));
printdebug("Created a new scope");
//if (look_up(cur, $2) == undefined) {
// printdebug("rec not found");
//}
}
dblock
{
//We are scanning through the dblock scope to get the length of the dblock (num of elements) from getRecSize
//and then putting it in the entry that we created above.
} dblock {
setRecSize(look_up(getParent(cur), $2), getRecSize(cur));
//putting in all the offsets
setRecOffsetInfo(cur, look_up(getParent(cur),$2));
printdebug("Moving up a scope after seeing a record definition");
cur = getParent(cur);
@ -158,9 +146,7 @@ definition:
CreateEntry(cur,TYPE_ARRAY_TYPE, arrayprim, $2, CreateArrayInfo($4, (TableNode*)$6));
printdebug("%sID: %s, dimensions: %d, typeOfArray: %s", COLOR_GREEN, $2, $4, getName((TableNode*)$6));
}
| function_declaration
| TYPE ID COLON id_or_types ARROW id_or_types
{
printdebug("Currently see a function type definition of name %s,parameter type %s, of return type %s", $2, getName((TableNode*)$4), getName((TableNode*)$6));
@ -168,6 +154,9 @@ definition:
}
| ID {
emit_function_start(table_lookup(cur,$1));
//printf("ID: %s\n", $1);
//printf("Type: %s\n", getType(table_lookup(getAncestor(cur), $1)));
printdebug("see function def rule 1\n");
TableNode *node = table_lookup(getAncestor(cur), $1);
if (node == undefined) {
@ -253,16 +242,23 @@ definition:
}
}
//counter = 0;
printdebug("Created a new scope after seeing a function definition");
} idlist R_PAREN ASSIGN sblock {
TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1)));
if ($8 == undefined) {
throw_error(ERROR_TYPE, "Expected %s as return type but got undefined (possibly NULL). Differing return types in function.", getName(expected));
} else if (getAdInfoType(expected)==TYPE_ARRAY_TYPE && $8 == addr){
printdebug("CORRECT RETURN TYPE!!!");
} else if (getAdInfoType(expected)==TYPE_RECORD_TYPE && $8 == addr){
printdebug("CORRECT RETURN TYPE!!!");
}else if ($8 != expected) {
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!!!");
}
//printf("Ending ID: %s\n", $1);
//printf("Ending Type: %s\n", getType(table_lookup(getAncestor(cur), $1)));
}
;
@ -270,8 +266,10 @@ definition:
function_declaration:
FUNCTION ID COLON ID
{
if(getAdInfoType(look_up(cur, $4))==TYPE_FUNCTION_TYPE){
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));
if(getAdInfoType(table_lookup(cur, $4))==TYPE_FUNCTION_TYPE){
//printf("%s\n",$2);
//printf("%s\n",getName(table_lookup(cur, $4)));
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, table_lookup(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false));
}
else{
throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $2);
@ -352,14 +350,13 @@ idlist:
printdebug("tag is %d", getAdInfoType(entry));
}
| error { yyerrok; }
;
sblock:
L_BRACE
{
// emit_label(label_gen());
if (getLine(cur) != 0) {
cur = CreateScope(cur,@1.first_line,@1.first_column);
printdebug("Created a new scope");
@ -402,8 +399,6 @@ sblock:
R_BRACE
{$$ = $5;}
| error { yyerrok; }
;
@ -423,7 +418,6 @@ dblock:
}
declaration_list R_BRACKET
| error { yyerrok; }
;
@ -432,8 +426,7 @@ dblock:
declaration_list:
declaration SEMI_COLON declaration_list
| declaration
| error { yyerrok; }
| error SEMI_COLON { yyerrok; } declaration_list //only perform error recovery once we see semi-colon
;
@ -474,8 +467,6 @@ declaration:
}
}
| error { yyerrok; }
;
@ -493,8 +484,6 @@ id_or_types:
$$ = (TableNode*)$1;
}
| error { yyerrok; }
;
@ -507,8 +496,16 @@ compound_statement statement_list {
$$ = $1;
} else if ($1 == $2) {
$$ = $1;
}else if((getAdInfoType((TableNode*)$1) == TYPE_ARRAY_TYPE) && ((TableNode*)$2)==addr){
$$ = $1;
}else if((getAdInfoType((TableNode*)$1) == TYPE_RECORD_TYPE) && ((TableNode*)$2)==addr){
$$ = $1;
}else if(((TableNode*)$1)==addr && (getAdInfoType((TableNode*)$2) == TYPE_ARRAY_TYPE)){
$$ = $2;
}else if(((TableNode*)$1)==addr && (getAdInfoType((TableNode*)$2) == TYPE_RECORD_TYPE)){
$$ = $2;
} else {
printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
printdebug("1 differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
$$ = undefined;
}
}
@ -522,32 +519,82 @@ compound_statement statement_list {
$$ = $1;
} else if ($1 == $3) {
$$ = $1;
}else if((getAdInfoType((TableNode*)$1) == TYPE_ARRAY_TYPE) && ((TableNode*)$3)==addr){
$$ = $1;
}else if((getAdInfoType((TableNode*)$1) == TYPE_RECORD_TYPE) && ((TableNode*)$3)==addr){
$$ = $1;
}else if(((TableNode*)$1)==addr && (getAdInfoType((TableNode*)$3) == TYPE_ARRAY_TYPE)){
$$ = $3;
}else if(((TableNode*)$1)==addr && (getAdInfoType((TableNode*)$3) == TYPE_RECORD_TYPE)){
$$ = $3;
} else {
printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
printdebug("2 differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
$$ = undefined;
}
}
| simple_statement SEMI_COLON {
$$ = $1;
}
| error SEMI_COLON { yyerrok; } statement_list { $$ = $4; }
;
compound_statement:
WHILE L_PAREN expression R_PAREN sblock {
$$ = $5;
WHILE L_PAREN {
S_Push(TrueList, S_Init(), 0);
S_Push(FalseList, S_Init(), 0);
int *l = calloc(1, sizeof(int));
*l = label_gen();
emit_label(*l);
S_Push(stack, l, 2);
} expression R_PAREN {
emit_label(label_gen());
emit_backpatch(S_Pop(TrueList), getLabel(current));
} sblock {
$$ = $7;
int l = label_gen();
emit_backpatch(S_Pop(FalseList), l);
emit_goto(*(int*)(S_Pop(stack)));
emit_label(l);
}
| IF L_PAREN expression R_PAREN THEN sblock ELSE sblock {
if ($6 == undefined && $8 != undefined) {
| IF L_PAREN {
S_Push(TrueList, S_Init(), 0);
S_Push(FalseList, S_Init(), 0);
}expression R_PAREN THEN {
emit_label(label_gen());
emit_backpatch(S_Pop(TrueList), getLabel(current));
} sblock ELSE {
// NOTE we are not going back to
int l = label_gen();
emit_backpatch(S_Pop(FalseList), l);
S_Push(FalseList, S_Init(), 0);
emit_goto(0);
S_Push(S_Peek(FalseList), current, 1);
emit_label(l);
} sblock {
int l = label_gen();
emit_backpatch(S_Pop(FalseList), l);
emit_label(l);
if ($8 == undefined && $11 != undefined) {
$$ = $11;
} else if ($8 != undefined && $11 == undefined) {
$$ = $8;
} else if ($6 != undefined && $8 == undefined) {
$$ = $6;
} else if ($6 == $8) {
$$ = $6;
} else if ($8 == $11) {
$$ = $8;
}else if((getAdInfoType((TableNode*)$8) == TYPE_ARRAY_TYPE) && ((TableNode*)$11)==addr){
$$ = $8;
}else if((getAdInfoType((TableNode*)$8) == TYPE_RECORD_TYPE) && ((TableNode*)$11)==addr){
$$ = $8;
}else if(((TableNode*)$8)==addr && (getAdInfoType((TableNode*)$11) == TYPE_ARRAY_TYPE)){
$$ = $11;
}else if(((TableNode*)$8)==addr && (getAdInfoType((TableNode*)$11) == TYPE_RECORD_TYPE)){
$$ = $11;
} else {
printdebug("differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
printdebug("3 differing return types within same function at line %d, column %d", @1.first_line, @1.first_column);
//printf("%s\n", getName((TableNode*)$6));
//printf("%s\n", getName((TableNode*)$8));
$$ = undefined;
}
}
@ -564,32 +611,51 @@ simple_statement:
assignable ASSIGN expression
{ printdebug("simple statement");
TableNode* node;
if((getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION)||
(getAdInfoType((TableNode*)$1) == TYPE_ARRAY)||
(getAdInfoType((TableNode*)$1) == TYPE_RECORD)||
(getAdInfoType((TableNode*)$1) == TYPE_PRIMITIVE)){
if((getAdInfoType((getTypeEntry((TableNode*)$1))) == TYPE_FUNCTION_TYPE)||
(getAdInfoType((getTypeEntry((TableNode*)$1))) == TYPE_ARRAY_TYPE)||
(getAdInfoType((getTypeEntry((TableNode*)$1))) == TYPE_RECORD_TYPE)||
(getAdInfoType((getTypeEntry((TableNode*)$1))) == TYPE_PRIMITIVE_TYPE)){
node = ((TableNode*)$1);
} else {
printdebug("Invalid type passed to assignable.");
//printf("%d\n",getAdInfoType((getTypeEntry((TableNode*)$1))));
throw_error(ERROR_TYPE, "Invalid type passed to assignable.");
//printf("%d, %d\n", @1.first_line, @1.first_column);
//printf("%s\n", getType(getTypeEntry((TableNode*)$1)));
//printf("%s\n\n", getType(getTypeEntry((TableNode*)$3)));
node = undefined;
}
if(getAdInfoType(node) == getAdInfoType((TableNode*)$3)){
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));
printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getType(node), getType((TableNode*)$3));
} else if (getTypeEntry(getTypeEntry(node)) == arrayprim && getTypeEntry((TableNode*)$3) == addr) {
emit_assignment($1, tn_or_const(NODE, $3));
printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getType(node), getType((TableNode*)$3));
} else if (getTypeEntry(getTypeEntry(node)) == recprime && getTypeEntry((TableNode*)$3) == addr) {
emit_assignment($1, tn_or_const(NODE, $3));
printdebug("%s[☺] Passed type check; %s = %s", COLOR_GREEN, getType(node), getType((TableNode*)$3));
}
else {
//printf("%d\n",getAdInfoType((TableNode*)$1));
//printf("%d\n",getAdInfoType((TableNode*)$3));
//printf("%d\n",getAdInfoType((TableNode*)$1));
//printf("%d\n",getAdInfoType((TableNode*)$3));
throw_error(ERROR_TYPE, "Assignable Assign Expression - Object %s of type %s != Object %s of type %s", getName(node), getType(node), getName((TableNode*)$3), getType((TableNode*)$3));
}
$$ = undefined;
}
| RETURN expression {$$ = getTypeEntry((TableNode*)$2);}
| RETURN expression {
$$ = getTypeEntry((TableNode*)$2);
emit_return(tn_or_const(NODE,(TableNode*)$2));}
|simple_statement error {yyerrok; yyclearin; printdebug("error in simple statement");}
| error { yyerrok; }
;
@ -598,40 +664,60 @@ simple_statement:
rec_op:
DOT
| error { yyerrok; }
;
ablock:
L_PAREN argument_list R_PAREN
L_PAREN{
if (stack == NULL){
stack = S_Init();
}
Stack * t = S_Init();
S_Push(stack, t, 0);
}
argument_list {
} R_PAREN
{
$$ = $2;
// here
$$ = $3;
printdebug("ablock is %d", $$);
}
| error { yyerrok; }
;
argument_list:
//NEED TO EMIT PARAMETERS HERE. MAYBE USE STACK STRUCTURE
expression COMMA argument_list
expression{
TableNode* arg = CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), arg_var_gen(), NULL);
// ----------------------------------------------------------------------------
// this is emitting the param withthe wrong TableNode
// We need to fiture out how to get the right one.
Stack * t = S_Peek(stack);
if(t==NULL){
t = S_Init();
S_Push(stack, t, 1);
}
emit_parameter(tn_or_const(NODE,$1));
S_Push(t, current, 1);
emit_detach();
// ----------------------------------------------------------------------------
}
COMMA argument_list
{$$ = $4 + 1;}
| expression
{
CreateEntry(cur,getAdInfoType((TableNode*)$1), (TableNode*)$1, getName((TableNode*)$1), NULL);
$$ = $3 + 1;
TableNode* arg = CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), arg_var_gen(), NULL);
emit_parameter(tn_or_const(NODE,$1));
$$ = 1;
printdebug("[ARGUMENT_LIST] argument list is %d", $$);
}
| expression
{
CreateEntry(cur,getAdInfoType((TableNode*)$1),(TableNode*)$1, getName((TableNode*)$1), NULL);
$$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$);
}
| error { yyerrok; }
;
@ -656,7 +742,7 @@ expression:
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName(getTypeEntry((TableNode*)$2)), getName(integ));
throw_error(ERROR_TYPE, "Object %s of type %s is not of type integer and can't be negated", getName((TableNode*)$2), getType((TableNode*)$2));
}
}
@ -672,7 +758,7 @@ expression:
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$2), getName(boo));
throw_error(ERROR_TYPE, "Object %s of type %s is not of type Boolean and can't be negated", getName((TableNode*)$2), getType((TableNode*)$2));
}
}
@ -687,6 +773,7 @@ expression:
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
@ -701,7 +788,7 @@ expression:
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
@ -715,7 +802,7 @@ expression:
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
@ -729,7 +816,7 @@ expression:
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
@ -743,7 +830,7 @@ expression:
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
@ -757,7 +844,7 @@ expression:
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be Boolean", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
@ -771,21 +858,39 @@ expression:
$$ = node;
} else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be Boolean", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
| expression LESS_THAN expression
{
emit_conditional_jump(E_LESS_THAN, 0, tn_or_const(NODE,$1), tn_or_const(NODE,$3));
Stack * t = S_Peek(TrueList);
if(t==NULL){
t = S_Init();
S_Push(TrueList, t, 1);
}
S_Push(t, current, 1);
emit_goto(0);
t = S_Peek(FalseList);
if(t==NULL){
t = S_Init();
S_Push(FalseList, t, 1);
}
S_Push(t, current, 1);
printdebug("less than 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);
$$ = node;
} else if(getTypeEntry((TableNode*)$1) == getTypeEntry((TableNode*)$3) && getTypeEntry((TableNode*)$1)==boo){
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, boo, temp, NULL);
emit_binary_op(E_LESS_THAN,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
$$ = node;
}else {
$$=undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be integers", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
@ -795,12 +900,25 @@ 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);
emit_binary_op(E_EQUAL_TO,node,tn_or_const(NODE,$1),tn_or_const(NODE,$3));
emit_conditional_jump(E_EQUAL_TO, 0, tn_or_const(NODE,$1), tn_or_const(NODE,$3));
Stack * t = S_Peek(TrueList);
if(t==NULL){
t = S_Init();
S_Push(TrueList, t, 1);
}
S_Push(t, current, 1);
emit_goto(0);
t = S_Peek(FalseList);
if(t==NULL){
t = S_Init();
S_Push(FalseList, t, 1);
}
S_Push(t, current, 1);
$$ = node;
} else {
$$ = undefined;
throw_error(ERROR_TYPE, "%s != %s", getName((TableNode*)$1), getName((TableNode*)$3));
throw_error(ERROR_TYPE, "Object %s of type %s and Object %s of type %s must both be the same type", getName((TableNode*)$1), getType((TableNode*)$1), getName((TableNode*)$3), getType((TableNode*)$3));
}
}
@ -815,21 +933,40 @@ expression:
$$=$2;
}
| memOp assignable
// TODO: We need to type check this.
| RESERVE ID {$$ = undefined; }
| RELEASE ID {$$ = undefined; }
| RESERVE ID L_PAREN argument_list R_PAREN {$$ = undefined; }
| RELEASE ID L_PAREN argument_list R_PAREN
{
int d = getAdInfoType((TableNode*)$2);
if(d == TYPE_ARRAY ||d == TYPE_RECORD) {
//commenting out type checks for now since assignable is being resolved to something before reserve is being applied which is tricky
//if(d == TYPE_ARRAY ||d == TYPE_RECORD) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
$$ = node;
} else {
throw_error(ERROR_TYPE, "Invalid memOp expression (%s).", getName((TableNode*)$2));
$$=undefined;
// } else {
// throw_error(ERROR_TYPE, "Invalid memOp expression with object %s of type %s.", getName((TableNode*)$2), getType((TableNode*)$2));
// $$=undefined;
// }
}
/*
| RELEASE assignable
{
int d = getAdInfoType((TableNode*)$2);
//commenting out type checks for now since assignable is being resolved to something before reserve is being applied which is tricky
//if(d == TYPE_ARRAY ||d == TYPE_RECORD) {
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL);
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK)
$$ = node;
// } else {
// throw_error(ERROR_TYPE, "Invalid memOp expression with object %s of type %s.", getName((TableNode*)$2), getType((TableNode*)$2));
// $$=undefined;
// }
}
| error { yyerrok; }
*/
;
@ -848,10 +985,11 @@ assignable:
$$ = pass;
printdebug("[ASSIGNABLE - RULE 1] assignable = type: %s | ID = %s", getType(pass), getName(pass));
}
| assignable
{
printdebug("%sBeginning rule 2 of assignable.", COLOR_CYAN);
//Creating a dummy scope where we create entries for all the arguments of a function call
//Must also consider that we might be in an array access
cur = CreateScope(cur, -1,-1);
}
//we have to consider emmissions in ablocks
@ -864,67 +1002,57 @@ assignable:
if (type == TYPE_FUNCTION_TYPE) {
printdebug("%sEntering function call", COLOR_LIGHTGREEN);
if (look_up(getParent(cur), getType((TableNode*)$1))->additionalinfo->FunDecAdInfo->regularoras) {
printdebug("as function");
//char *funtype = getType(look_up(cur, $1));
//printdebug("%s", getType(look_up(cur, getName((TableNode*)$1))));
TableNode * typeNode = getTypeEntry((TableNode*)$1);
TableNode *param = getParameter(typeNode);
printTableNode(param);
if (getAdInfoType(param) == TYPE_RECORD_TYPE) {
SymbolTable *recList = getRecList(param);
TableNode *lastCheckedRef = getFirstEntry(recList);
TableNode *lastCheckedAct = getFirstEntry(cur);
while (getNextEntry(lastCheckedRef) != NULL) {
lastCheckedRef = getNextEntry(lastCheckedRef);
}
if ($3 != getRecLength(param)) {
printdebug("expected %d arguments but got %d", getRecLength(param), $3);
}
//this isn't very efficient, but will hopefully work
while (lastCheckedAct != NULL && lastCheckedRef != NULL) {
if (getTypeEntry(lastCheckedRef) != getTypeEntry(lastCheckedAct)) {
printdebug("expected %s. expression in function call got %s. at line %d and column %d",getType(lastCheckedRef), getName(lastCheckedAct), @3.first_line, @3.first_column);
}
lastCheckedAct = getNextEntry(lastCheckedAct);
TableNode *tn = getFirstEntry(recList);
if (tn != lastCheckedRef) {
while (getNextEntry(tn) != lastCheckedRef) {
tn = getNextEntry(tn);
}
lastCheckedRef = tn;
} else {break;}
}
//getting the parameter. The type of assignable is a function type so we need to access the paramater of the type
TableNode *expected = getParameter(getTypeEntry((TableNode*)$1));
//Jump into case where the parameter is a record type
if(getAdInfoType(expected) == TYPE_RECORD_TYPE){
//int argument_size = getRecSize(cur);
int parameter_size = getRecSize(getRecList(expected));
printdebug("argument size is %d\n", $3);
printdebug("parameter size is %d\n", parameter_size);
if ($3 != parameter_size) {
throw_error(ERROR_SYNTAX, "expected %d arguments for this function but got %d", parameter_size, $3);
}else{
if (strcmp(getName(param), getName(getFirstEntry(cur))) != 0) {
printdebug("expected %s expression in function call but got %s", getName(param), getName(getFirstEntry(cur)));
TableNode* param_arg_type = getFirstEntry(getRecList(expected));
TableNode* arg_given = getFirstEntry(cur);
while(arg_given != NULL && arg_given != undefined && getName(arg_given)[0]!='&'){
arg_given = getNextEntry(arg_given);
}
if (getNextEntry(getFirstEntry(cur)) != NULL) {
printdebug("expected 1 parameter, but got multiple in function call");
if(getTypeEntry(arg_given) != getTypeEntry(param_arg_type)){
throw_error(ERROR_TYPE, "expected %s expression as first argument of a record in function call but got %s", getType(param_arg_type), getType(arg_given));
}
param_arg_type = getNextEntry(param_arg_type);
arg_given = getNextEntry(arg_given);
while(arg_given != NULL && arg_given != undefined && param_arg_type != NULL){
while(arg_given != NULL && getName(arg_given)[0]!='&'){
arg_given = getNextEntry(arg_given);
}
if(getTypeEntry(arg_given) != getTypeEntry(param_arg_type)){
throw_error(ERROR_TYPE, "expected type %s expression as argument of a record in function call but got type %s", getType(param_arg_type), getType(arg_given));
}
arg_given = getNextEntry(arg_given);
param_arg_type = getNextEntry(param_arg_type);
}
}
}else{
char *expected = getName(getParameter(look_up(getParent(cur), getType((TableNode*)$1))));
char *actual = getType(getFirstEntry(cur));
if (strcmp(expected, actual) != 0) {
printdebug("expected %s expression in function call but got %s at line %d and column %d",expected, actual, @3.first_line, @3.first_column);
TableNode*actual_instance = getFirstEntry(cur);
while(actual_instance != NULL && actual_instance != undefined && getName(actual_instance)[0] !='&'){
actual_instance = getNextEntry(actual_instance);
}
if(actual_instance == NULL){
throw_error(ERROR_TYPE, "Invalid function call. No arguments passed");
break;
}
TableNode *actual = getTypeEntry(actual_instance);
if (expected != actual) {
throw_error(ERROR_TYPE, "expected %s expression in single argument function call but got %s", getType(expected), getName(actual));
}
if ($3 != 1) {
printdebug("expected 1 argument but got %d", $3);
}
}
throw_error(ERROR_SYNTAX, "expected 1 argument but got %d", $3); }
printTableNode(getReturn(getTypeEntry((TableNode*)$1)));
//
}
char* temp = temp_var_gen();
TableNode* typeNode2 = getReturn(getTypeEntry($1));
TableNode* typeNode2 = getReturn(getTypeEntry((TableNode*)$1));
int t = -1;
if(getAdInfoType(typeNode2) == TYPE_PRIMITIVE_TYPE){
t = TYPE_PRIMITIVE;
@ -935,21 +1063,29 @@ assignable:
else if(getAdInfoType(typeNode2) == TYPE_RECORD_TYPE){
t = TYPE_RECORD;
}
//this may need to be updated to provide the correct name of things
else if(getAdInfoType(typeNode2) == TYPE_FUNCTION_TYPE){
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper.");
throw_error(ERROR_TYPE, "Undefined type returned by function.");
}
TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL);
//-----------------------------------------------------------------------------
// Please don't touch
// the + 1 is here because I don't detach the last param
int a = S_Size(S_Peek(stack)) + 1;
emit_push_all(S_Peek(stack));
S_Pop(stack);
emit_function_call(node, a, tn_or_const(NODE, $1));
//-----------------------------------------------------------------------------
$$ = node;
//NOTE ADD ASSIGNMENT EMIT HERE (MIGHT NEED TO PUSH TO STACK for function call)
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName(typeNode2), getName((TableNode*)$1));
} else if (type == TYPE_ARRAY_TYPE) {
printdebug("%sEntering array call", COLOR_LIGHTGREEN);
if (getNumArrDim(look_up(getParent(cur), getType((TableNode*)$1))) != $<integ>2) {
printdebug("expected %d arguments but had %d at line %d and column %d\n", getNumArrDim(look_up(cur, getName((TableNode*)$1))), $<integ>2, @2.first_line, @2.first_column);
if (getNumArrDim(getTypeEntry((TableNode*)$1)) != $3) {
throw_error(ERROR_SYNTAX, "expected %d arguments for this array but got %d", getNumArrDim(getTypeEntry((TableNode*)$1)), $3);
}
char* temp = temp_var_gen();
@ -968,25 +1104,42 @@ assignable:
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper.");
throw_error(ERROR_TYPE, "Undefined type stored in array.");
}
TableNode* node = CreateEntry(cur,t, typeNode2, temp, NULL);
//emit assign here
//emit_array_access(char* node, char* array, ...)
//TODO: emit assign here
//TODO: emit_array_access(char* node, char* array, ...)
$$ = node;
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getType((TableNode*)$1), getName((TableNode*)$1));
}
cur = getParent(cur);
}
| assignable rec_op ACCESS
{
if(getAdInfoType((TableNode*)$1) != TYPE_ARRAY){
throw_error(ERROR_TYPE, "Invalid type passed to array access");
$$ = undefined;
}else if($3>getNumArrDim(getTypeEntry((TableNode*)$1))){
throw_error(ERROR_TYPE, "Invalid trying to access the size of dimension %d but this array only has %d dimensions", $3, getNumArrDim(getTypeEntry((TableNode*)$1)));
$$ = undefined;
} else{
char* temp = temp_var_gen();
int t = 6;
//emission
$$ = CreateEntry(cur,t, integ, temp, NULL);
}
}
| assignable rec_op ID
{
if(getAdInfoType((TableNode*)$1) != TYPE_RECORD_TYPE){
printdebug("CHANGE ME [TYPE CHECK]Invalid type passed to record access");
}
else if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3)) {
TableNode* type = table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3);
if(getAdInfoType((TableNode*)$1) != TYPE_RECORD){
throw_error(ERROR_TYPE, "Invalid type passed to record access");
$$ = undefined;
}
else if(undefined != table_lookup(getRecList(getTypeEntry((TableNode*)$1)), $3)) {
TableNode* type = getTypeEntry(table_lookup(getRecList(getTypeEntry((TableNode*)$1)), $3));
char* temp = temp_var_gen();
int t = -1;
if(getAdInfoType(type) == TYPE_PRIMITIVE_TYPE){
@ -1002,7 +1155,7 @@ assignable:
t = TYPE_FUNCTION_DECLARATION;
}else{
t= TYPE_UNDEFINED;
printdebug("CHANGE ME [TYPE CHECK] Undefined type stored in record. improper.");
throw_error(ERROR_TYPE, "Undefined type stored in record.");
}
TableNode* node = CreateEntry(cur,t, type, temp, NULL);
@ -1010,30 +1163,12 @@ assignable:
//emit_field_access(char* node, char* record, $3)
$$=node;
}else{
printdebug("CHANGE ME [TYPE CHECK] undefined type (Field Access Lookup failed)");
throw_error(ERROR_TYPE, "Invalid field access %s", $3);
$$=undefined;
}
printdebug("[ASSIGNABLE - RULE 3] record = name: %s | field = %s", getName((TableNode*)($1)), getName((TableNode*)$3));
}
| error { yyerrok; }
;
memOp:
RESERVE
{
printdebug("reserve expression");
}
| RELEASE
{
printdebug("release expression");
}
| error { yyerrok; }
;
@ -1042,7 +1177,7 @@ constant:
C_STRING
{
char* temp = temp_var_gen();
TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, stri, temp, NULL);
TableNode* node = CreateEntry(cur,TYPE_ARRAY, stri, temp, NULL);
emit_assignment(node, tn_or_const(STRING,$1));
printdebug("string of C_STRING in constant is %s", $1);
$$ = node;
@ -1186,7 +1321,7 @@ void throw_error(ErrorType error_type, const char *format, ...) {
return;
}
snprintf(total_error_message, total_needed, "%s%s\n\n", error_message, error_message2);
snprintf(total_error_message, total_needed, "%s%s\n", error_message, error_message2);
if (tc_flag) {
insert_code_line(total_error_message, line);
} else {
@ -1208,9 +1343,9 @@ void yyerror(const char *err) {
// Grammar Fallback Case
if (strcmp(err, "syntax error") == 0) {
if (asc_flag != NULL) {
int needed = snprintf(NULL, 0, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n\n", line, column, yytext);
int needed = snprintf(NULL, 0, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\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);
snprintf(error_message, needed + 1, " LINE (%d:%d) ** SYNTAX ERROR: Incorrect syntax at token '%s'\n", line, column, yytext);
insert_code_line(error_message, line);
}
else {
@ -1218,3 +1353,4 @@ void yyerror(const char *err) {
}
}
}

View File

@ -3,9 +3,99 @@
#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.
Stack * S_Init(){
Stack * s = calloc(1, sizeof(*s));
return s;
}
void S_Free(Stack *s){
// since we are not responsible for the values we can just pop until
// NULL
for (void * p = S_Pop(s); p != NULL; p = S_Pop(s));
free(s);
}
void S_Push(Stack * s, void *v, int i) {
__Node * n = calloc(1, sizeof(*n));
n->v = v;
n->next = s->n;
s->n = n;
s->w = i;
s->size = s->size + 1;
}
void * S_Pop(Stack *s) {
if (s == NULL || S_IsEmpty(s)) {
return NULL;
}
__Node * node = s->n;
s->n = node->next;
s->size = s->size - 1;
void * r = node->v;
free(node);
return r;
}
void * S_Peek(Stack *s){
if (s == NULL || S_IsEmpty(s)) {
return NULL;
}
return s->n->v;
}
bool S_IsEmpty(Stack *s){
if(s == NULL || s->size == 0) {
return true;
}
return false;
}
int S_Size(Stack *s){
if (s == NULL || S_IsEmpty(s)) {
return 0;
}
return s->size;
}
void emit_backpatch(Stack * s, int l){
for (Instruction * i = S_Pop(s); i; i = S_Pop(s)){
i->label = l;
}
}
//_______________________________________________________________________
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.
*/
void emit_push_all(Stack * s){
for (Instruction * i = S_Pop(s); i; i = S_Pop(s)){
current->next = i;
i->prev = current;
i->index = current->index + 1;
current = i;
current->next = NULL;
}
}
void emit_detach(){
current = current->prev;
current->next = NULL;
}
void backpatch(Stack *s, int l){
while (!S_IsEmpty(s)){
Instruction * i = S_Pop(s);
set_label(i, l);
}
}
TNodeOrConst * getOperand1(Instruction * i){
return i->operand1;
}
@ -78,7 +168,12 @@ static void emit_helper(void) {
}
}
void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst* arg2) {
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
@ -87,6 +182,12 @@ void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst*
current->operand2 = arg2;
}
void emit_goto(int i){
emit_helper();
current->opcode = E_GOTO;
current->label = i;
}
void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg){
emit_helper();
current->opcode = op;
@ -126,119 +227,6 @@ char* get_string(TNodeOrConst* tc) {
}
}
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;
@ -262,13 +250,11 @@ void emit_conditional_jump(Op condition, int label, ...) {
TNodeOrConst * n1;
TNodeOrConst * n2;
switch (condition) {
case E_IF_X_TRUE:
case E_IF_X_FALSE:
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:
case E_LESS_THAN: case E_EQUAL_TO:
n1 = va_arg(argptr, TNodeOrConst *);
n2 = va_arg(argptr, TNodeOrConst *);
current->operand1 = n1;
@ -278,11 +264,10 @@ void emit_conditional_jump(Op condition, int label, ...) {
va_end(argptr);
}
void emit_function_start(TNodeOrConst * name) {
void emit_function_start(TableNode * name){
emit_helper();
current->opcode = E_LABEL; // I think this is right TODO: ask
current->operand1 = name;
// this is probabaly a func declaration
current->opcode = E_FUNC_START;
current->result = name;
}
void emit_parameter(TNodeOrConst * param){
@ -291,11 +276,15 @@ void emit_parameter(TNodeOrConst* param) {
current->operand1 = param;
}
void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name) {
void emit_function_call(
TableNode * result,
int param_count,
TNodeOrConst * name
){
emit_helper();
current->opcode = E_CALL;
current->operand1 = tn_or_const(INTEGER, &param_count);
current->operand2 = name;
current->operand1 = name;
current->operand2 = tn_or_const(INTEGER, &param_count);
current->result = result;
}
@ -315,12 +304,25 @@ void emit_release(TableNode* pointer) {
emit_function_call(pointer, 1, tn_or_const(NODE, look_up(cur, "release")));
}
void emit_deref_right() {
return;
void emit_deref_right(TableNode * x, TNodeOrConst * y){
emit_helper();
current->opcode = E_DEREF_RIGHT;
current->result = x;
current->operand1 = y;
}
void emit_deref_left() {
return;
void emit_deref_left(TableNode * x, TNodeOrConst * y){
emit_helper();
current->opcode = E_DEREF_LEFT;
current->result = x;
current->operand1 = y;
}
void emit_address_of(TableNode * x, TNodeOrConst * y){
emit_helper();
current->opcode = E_ADDRESS_OF;
current->result = x;
current->operand1 = y;
}
void emit_field_access(char* result, char* record, char* field){
@ -329,7 +331,7 @@ void emit_field_access(char* result, char* record, char* field) {
void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index){
emit_helper();
current->opcode;
current->opcode = op;
current->result = result;
current->operand1 = array;
current->operand2 = index;
@ -365,26 +367,244 @@ void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr) {
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
emit_conditional_jump(E_LESS_THAN, );
emit_conditional_jump(E_LESS_THAN, );
emit_jump();
*/
}
/*// * 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;
}
*/
// * Implement temp variable generator function that produces unique names (t1, t2, etc.)
int label_gen(){
label_count++;
return label_count;
}
void emit_as_file(FILE * out_file, Instruction * i){
if (out_file == NULL){
fprintf(stderr, "Error: output file is NULL\n");
return;
}
if(i == NULL){
return;
}
switch(i->opcode){
case E_FUNC_START:
fprintf(out_file,
"%4.d: func : %s\n",
i->index,
getName(i->result)
);
break;
case E_LABEL:
fprintf(out_file,
"%4.d: Label : %d\n",
i->index,
i->label
);
break;
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:
fprintf(out_file,
"%4.d: GOTO : %d\n",
i->index,
i->label
);
break;
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:
// this feels wrong I need to TODO: this
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:
// this feels wrong I need to TODO: this
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:
fprintf(out_file,
"%4.d: return : %s\n",
i->index,
get_string(i->operand1)
);
break;
case E_INDEX_COPY_RIGHT:
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_INDEX_COPY_LEFT:
fprintf(out_file,
"%4.d: %s[ %s ] = %s\n",
i->index,
getName(i->result),
get_string(i->operand2),
get_string(i->operand1));
break;
case E_ADDRESS_OF:
fprintf(out_file,
"%4.d: %s = &%s\n",
i->index,
getName(i->result),
get_string(i->operand1)
);
break;
case E_DEREF_RIGHT:
fprintf(out_file,
"%4.d: %s = *%s\n",
i->index,
getName(i->result),
get_string(i->operand1)
);
case E_DEREF_LEFT:
fprintf(out_file,
"%4.d: *%s = %s\n",
i->index,
getName(i->result),
get_string(i->operand1)
);
}
emit_as_file(out_file, i->next);
}
TableNode* getTN(TNodeOrConst* tnc) {
if (tnc->d == NODE) {
return tnc->tnc_union->node;

View File

@ -12,7 +12,35 @@
#include "symbol_table.h"
typedef struct Stack Stack;
typedef struct __Node __Node;
typedef struct __Node {
void * v;
__Node * next;
} __Node;
typedef struct Stack {
__Node * n;
int w;
int size;
} Stack;
Stack * S_Init();
void S_Free(Stack *s);
void S_Push(Stack * s, void *v, int i);
void * S_Pop(Stack *s);
void * S_Peek(Stack *s);
bool S_IsEmpty(Stack *s);
int S_Size(Stack *s);
//______________________________________________________________________________________________
typedef union TNConstUnion TNConstUnion;
typedef struct Instruction Instruction;
typedef struct TNodeOrConst TNodeOrConst;
// these are from page 364
typedef enum { // these are from page 364
E_LABEL = 10000, // this is not in the book
E_FUNC_START,
@ -51,7 +79,7 @@ typedef enum {
BOOLEAN // bool
} Discriminant;
typedef union {
typedef union TNConstUnion {
TableNode * node;
int integer;
char * string;
@ -60,12 +88,11 @@ typedef union {
bool Boolean;
} TNConstUnion;
typedef struct {
typedef struct TNodeOrConst {
Discriminant d;
TNConstUnion * tnc_union;
} TNodeOrConst;
typedef struct Instruction Instruction;
typedef struct Instruction {
Op opcode;
TableNode * result;
@ -78,11 +105,59 @@ typedef struct Instruction {
Instruction * next;
} Instruction;
// NOTE We are not using this We are using the Stack api
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
// void bp_temp(int n);
extern Instruction * begin;
extern Instruction * current;
extern int label_count;
extern bool code_gen;
extern FILE * ir_flag;
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(TableNode* 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);
void emit_goto(int i);
void emit_detach();
void emit_push_all(Stack * s);
int getLabel(Instruction * i);
TableNode* getTN(TNodeOrConst* tnc);
int getConst(TNodeOrConst* tnc);
TNodeOrConst * getOperand1(Instruction * i);
TNodeOrConst * getOperand2(Instruction * i);
TableNode * getResult(Instruction * i);
@ -91,35 +166,9 @@ 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(TNodeOrConst * 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);
int label_gen();
TableNode* getTN(TNodeOrConst* tnc);
int getConst(TNodeOrConst* tnc);
extern int label_count;
extern Instruction* begin;
extern Instruction* current;
void backpatch(Stack *s, int l);
void emit_backpatch(Stack *s, int l);
extern int offset;
extern int currentsp;
extern CGNode* cgList;

View File

@ -59,7 +59,7 @@ SCHAR \\n|\\t|\\\"|[^\"\n\\]
'{CHAR}' {if(tok_flag != NULL){print_tok(C_CHARACTER);}incr(line_number,column_number,C_CHARACTER);char* token = strdup(yytext)/*yylval.tn = chara*/;yylval.letter = token[1];return C_CHARACTER;}
\"{SCHAR}*\" {if(tok_flag != NULL){print_tok(C_STRING);}incr(line_number,column_number,C_STRING);int k = strlen(yytext);yytext[k-1] = '\0';yylval.words = strdup(&yytext[1]);return C_STRING;}
{COMMENT} {if(tok_flag != NULL){print_tok(COMMENT);}incr(line_number,column_number,COMMENT);/*return COMMENT;*/}
_{DIGIT}+ {if(tok_flag != NULL){print_tok(ACCESS);}incr(line_number,column_number,ACCESS);yylval.integ = atoi(&yytext[1])/*words = strdup("integer")*/;return ACCESS;}
"(" { 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; }

View File

@ -103,6 +103,7 @@ int run(FILE *alpha) {
int token;
top = cur = init(CreateScope(NULL, 1, 1));
// If file is not found
if (alpha == NULL) {
fprintf(stderr, "INPUT FILE NOT FOUND\n");
@ -126,6 +127,9 @@ int run(FILE *alpha) {
fseek(alpha, 0, SEEK_SET);
yyin = alpha;
stack = S_Init();
TrueList = S_Init();
FalseList = S_Init();
yyparse();
if (tok_flag != NULL) {
@ -191,7 +195,7 @@ int new_file(char *arg, char *alpha) {
mkdir("./out", 0777);
char *new_basename = calloc(strlen(basename) + 5, sizeof(char));
char *new_basename = calloc(strlen(basename) + 7, sizeof(char));
strcpy(new_basename, "./out/");
strcat(new_basename, basename);
basename = new_basename;
@ -259,12 +263,15 @@ void insert_code_line(char * error_message, int line_number) {
int line = error_line->line_number;
CodeLine *current = code_head;
while (current != NULL) {
if (current->line_number == line) {
if (current->is_error == false) {
CodeLine *next_code_line = current->next;
current->next = error_line;
error_line->next = next_code_line;
}
}
current = current->next;
}
}

View File

@ -70,6 +70,9 @@ TableNode *recprime;
TableNode *funtypeprime;
TableNode *undefined;
extern Instruction *begin;
extern Stack* stack;
extern Stack* TrueList;
extern Stack* FalseList;
int main(int argc, char *argv[]);
int check_flag(char *arg, char *alpha);

View File

@ -5,6 +5,7 @@
Constant_Stack *head = NULL;
int temp2_count = 0;
int temp3_count = 0;
void printdebug_impl(char *file, int line, const char *format, ...) {
if (DEBUG) {
@ -24,6 +25,12 @@ char *temp_var_gen() {
temp2_count++;
return ret;
}
char *arg_var_gen() {
char *ret = calloc(9, sizeof(*ret));
sprintf(ret, "&%d", temp3_count);
temp3_count++;
return ret;
}
Constant_Stack *Push(TableNode *type, void *value, bool isConst) {
if (type == NULL || type == undefined) {
@ -623,6 +630,7 @@ TableNode *getReturn(TableNode *definition) {
"node has NULL additionalinfo. Invalid.");
return undefined;
}
printdebug("function:%s with return type %s\n",getName(definition),getName(definition->additionalinfo->FunTypeAdInfo->returntype));
return definition->additionalinfo->FunTypeAdInfo->returntype;
}
@ -1208,6 +1216,9 @@ void print_symbol_table(SymbolTable *table, FILE *file_ptr) {
}
for (; entry != NULL; entry = getNextEntry(entry)) {
if((getName(entry)[0] == '$' || getName(entry)[0] == '&') && ir_flag == NULL){
continue;
}
if (getAdInfoType(entry) == TYPE_ARRAY_TYPE) {
char *arrayType = (char *)malloc(100);
sprintf(arrayType, " %d -> %s", getNumArrDim(entry),
@ -1286,7 +1297,7 @@ void print_symbol_table(SymbolTable *table, FILE *file_ptr) {
if (getAdInfoType(entry) == TYPE_FUNCTION_DECLARATION) {
char *functiontype = (char *)malloc(100);
sprintf(functiontype, " %s", getName(getReturn(entry)));
sprintf(functiontype, " %s", getName(getTypeEntry(entry)));
if (parentScopeNum == 0) {
st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, " Function Definition");
} else {

View File

@ -15,6 +15,8 @@
#define SIZE_CHAR 1
#define SIZE_BOOL 1
extern FILE *ir_flag;
struct TableNode;
typedef struct TFList TFList;
typedef struct CGNode CGNode;
@ -101,6 +103,7 @@ void printdebug_impl(char *file, int line, const char *format, ...);
printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__)
char *temp_var_gen();
char *arg_var_gen();
Constant_Stack *Push(TableNode *type, void *value, bool isConst);
Constant_Stack *Pop();
Constant_Stack *Print_Stack();
@ -165,6 +168,7 @@ extern int column_number;
extern FILE *yyin;
extern bool DEBUG;
extern int temp2_count;
extern int temp3_count;
extern TableNode *funprime;
extern TableNode *arrayprim;
extern TableNode *integ;

View File

@ -55,3 +55,5 @@
#define RELEASE 614
// comments
#define COMMENT 700
//Additional tokens
#define ACCESS 801

View File

@ -56,11 +56,11 @@ c(x) := {
entry is the first function called
*)
entry(arg) := {
[integer: result; string2int: f; integer: temp]
[integer: result; string2int: f; integer: temp; character: char]
temp := a("Hello");
f := b(temp);
result := c(f);
if (d(1,2,'c'))
if (d(1,2,char))
then {
result := 0;
}

View File

@ -0,0 +1,6 @@
type main: string -> integer
function entry: main
entry(arg) := {
return 0;
}

View File

@ -15,7 +15,6 @@ function make_list : list
make_list (a) := {
[integer:orig_a; llnode: ret; llnode: curr; llnode: temp]
if (a < 0 | a = 0) then {
return null;
} else {
@ -73,7 +72,7 @@ entry (arg) := {
w := reserve w;
w.x := 5;
w.y := 7;
result := bar1(w);
(* result := bar1(w); *)
result := bar2(5,7);
return 0;

View File

@ -0,0 +1,80 @@
type main: string -> integer
function entry: main
type rec: [integer: x; integer: y]
type T1: integer -> integer
type T2: rec -> integer
type llnode: [llnode: prev; integer: val; llnode: next]
type list: integer -> llnode
function foo : T1
function bar1 : T2
function bar2 : T2
function make_list : list
make_list (a) := {
[integer:orig_a; llnode: ret; llnode: curr; llnode: temp]
if (a < 0 | a = 0) then {
return null;
} else {
ret := reserve ret;
ret.prev := null;
ret.next := null;
ret.val := a;
while (0 < a) {
temp := reserve temp;
temp.prev := null;
temp.next := null;
temp.val := ret.val;
if (a = orig_a) then {
ret.next := temp;
temp.prev := ret;
curr := temp;
} else {
curr.next := temp;
temp.prev := curr;
curr := temp;
}
a := a - 1;
}
return ret;
}
}
foo (x) := {
return x * x;
}
bar1(a,b) := {
return a * b;
}
bar2(r,s) := {
if (r < s) then {
while (!(r < s)) {
r := r + 1;
}
} else {
[integer: x]
x := 0;
while (x < 10) {
r := r + s;
}
}
return r * s;
}
entry (arg) := {
[ integer: result ; rec: w; llnode: li; boolean: b]
li := make_list(6, 7);
result := foo(5);
w := reserve w;
w.x := 5;
w.y := 7;
result := bar1(w);
result := bar2(5,7);
return 'a';
}

View File

@ -0,0 +1,25 @@
type rec: [character: x; integer: y]
type T2: rec -> integer
type main: string -> integer
function entry: main
function bar: T2
bar (r,s) := {
return 0;
}
entry (arg) := {
[ integer: result ; rec: w]
if ( result = result ) then {
if ( result < w.y ) then {
result := 8;
} else {
result := 9;
}(* *)
} else {
result := bar('c', 7);
}
return 0;
}

View File

@ -0,0 +1,27 @@
type rec: [character: x; integer: y]
type T2: rec -> integer
type main: string -> integer
function entry: main
function bar: T2
bar (r,s) := {
return 0;
}
entry (arg) := {
[ integer: result ; rec: w]
while ( result = result ) {
result := result + 8;
if ( result < w.y ) then {
while (true) {
result := 8;
}
} else {
result := 9;
}
result := bar('c', 7);
}
return 0;
}

View File

@ -12,7 +12,12 @@ bar (r,s) := {
entry (arg) := {
[ integer: result ; rec: w]
result := bar(1,2);
while ( result = result ) {
while ( result < w.y ) {
result := 8;
}
result := 9;
}
result := bar('c', 7);
return 0;
}