Merge pull request #53 from UB-CSE443/MoreTypeCheck

More type check
This commit is contained in:
Moroseui
2025-04-29 23:31:19 -04:00
committed by GitHub
8 changed files with 758 additions and 502 deletions

View File

@ -30,3 +30,5 @@ Instruction *current;
int offset; int offset;
int currentsp; int currentsp;
CGNode *cgList; CGNode *cgList;
extern Stack* stack;

View File

@ -18,7 +18,6 @@
%{ %{
#include "../src/grammar.h" #include "../src/grammar.h"
%} %}
%union { %union {
int integ; int integ;
char* words; char* words;
@ -28,7 +27,7 @@
%locations %locations
%token <integ> ACCESS 801
%type <integ> idlist %type <integ> idlist
%type <tn> assignable %type <tn> assignable
%type <tn> expression %type <tn> expression
@ -166,6 +165,9 @@ definition:
} }
| ID { | 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"); printdebug("see function def rule 1\n");
TableNode *node = table_lookup(getAncestor(cur), $1); TableNode *node = table_lookup(getAncestor(cur), $1);
if (node == undefined) { if (node == undefined) {
@ -251,6 +253,7 @@ definition:
} }
} }
//counter = 0; //counter = 0;
printdebug("Created a new scope after seeing a function definition"); printdebug("Created a new scope after seeing a function definition");
} idlist R_PAREN ASSIGN sblock { } idlist R_PAREN ASSIGN sblock {
TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1))); TableNode *expected = getReturn(getTypeEntry(look_up(cur, $1)));
@ -265,6 +268,8 @@ definition:
} else { } else {
printdebug("CORRECT RETURN TYPE!!!"); printdebug("CORRECT RETURN TYPE!!!");
} }
//printf("Ending ID: %s\n", $1);
//printf("Ending Type: %s\n", getType(table_lookup(getAncestor(cur), $1)));
} }
; ;
@ -272,8 +277,10 @@ definition:
function_declaration: function_declaration:
FUNCTION ID COLON ID FUNCTION ID COLON ID
{ {
if(getAdInfoType(look_up(cur, $4))==TYPE_FUNCTION_TYPE){ if(getAdInfoType(table_lookup(cur, $4))==TYPE_FUNCTION_TYPE){
CreateEntry(cur,TYPE_FUNCTION_DECLARATION, look_up(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false)); //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{ else{
throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $2); throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $2);
@ -565,8 +572,8 @@ WHILE L_PAREN expression R_PAREN sblock {
$$ = $8; $$ = $8;
} else { } else {
printdebug("3 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*)$6));
printf("%s\n", getName((TableNode*)$8)); //printf("%s\n", getName((TableNode*)$8));
$$ = undefined; $$ = undefined;
} }
} }
@ -590,11 +597,11 @@ simple_statement:
node = ((TableNode*)$1); node = ((TableNode*)$1);
} else { } else {
printf("%d\n",getAdInfoType((getTypeEntry((TableNode*)$1)))); //printf("%d\n",getAdInfoType((getTypeEntry((TableNode*)$1))));
throw_error(ERROR_TYPE, "Invalid type passed to assignable."); throw_error(ERROR_TYPE, "Invalid type passed to assignable.");
printf("%d, %d\n", @1.first_line, @1.first_column); //printf("%d, %d\n", @1.first_line, @1.first_column);
printf("%s\n", getType(getTypeEntry((TableNode*)$1))); //printf("%s\n", getType(getTypeEntry((TableNode*)$1)));
printf("%s\n\n", getType(getTypeEntry((TableNode*)$3))); //printf("%s\n\n", getType(getTypeEntry((TableNode*)$3)));
node = undefined; node = undefined;
} }
@ -619,7 +626,9 @@ simple_statement:
} }
| RETURN expression {$$ = getTypeEntry((TableNode*)$2);} | RETURN expression {
$$ = getTypeEntry((TableNode*)$2);
emit_return(tn_or_const(NODE,(TableNode*)$2));}
|simple_statement error {yyerrok; printdebug("error in simple statement");} |simple_statement error {yyerrok; printdebug("error in simple statement");}
@ -648,18 +657,27 @@ ablock:
argument_list: argument_list:
//NEED TO EMIT PARAMETERS HERE. MAYBE USE STACK STRUCTURE //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);
emit_parameter(tn_or_const(NODE,arg));
//S_Push(stack,current);
//emit_detach();
//printdebug("[ARGUMENT_LIST] argument list is %d", $$);
}
COMMA argument_list
{$$ = $4 + 1;}
| expression
{ {
CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), arg_var_gen(), NULL); TableNode* arg = CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), arg_var_gen(), NULL);
$$ = $3 + 1; emit_parameter(tn_or_const(NODE,arg));
//S_Push(stack,current);
//emit_detach();
$$ = 1;
printdebug("[ARGUMENT_LIST] argument list is %d", $$); printdebug("[ARGUMENT_LIST] argument list is %d", $$);
} }
| expression
{
CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), getName((TableNode*)$1), NULL);
$$ = 1; printdebug("[ARGUMENT_LIST] argument list is %d", $$);
}
; ;
@ -845,7 +863,20 @@ expression:
$$=$2; $$=$2;
} }
| memOp assignable | RESERVE assignable
{
int d = getAdInfoType((TableNode*)$2);
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;
}
}
| RELEASE assignable
{ {
int d = getAdInfoType((TableNode*)$2); int d = getAdInfoType((TableNode*)$2);
if(d == TYPE_ARRAY ||d == TYPE_RECORD) { if(d == TYPE_ARRAY ||d == TYPE_RECORD) {
@ -910,8 +941,8 @@ assignable:
while(arg_given != NULL && getName(arg_given)[0]!='&'){ while(arg_given != NULL && getName(arg_given)[0]!='&'){
arg_given = getNextEntry(arg_given); arg_given = getNextEntry(arg_given);
} }
if(getTypeEntry(arg_given) != param_arg_type){ if(getTypeEntry(arg_given) != getTypeEntry(param_arg_type)){
throw_error(ERROR_TYPE, "expected %s expression as first argument in function call but got %s", getName(param_arg_type), getType(arg_given)); throw_error(ERROR_TYPE, "expected %s expression as first argument in function call but got %s", getType(param_arg_type), getType(arg_given));
} }
param_arg_type = getNextEntry(param_arg_type); param_arg_type = getNextEntry(param_arg_type);
arg_given = getNextEntry(arg_given); arg_given = getNextEntry(arg_given);
@ -919,8 +950,8 @@ assignable:
while(arg_given != NULL && getName(arg_given)[0]=='&'){ while(arg_given != NULL && getName(arg_given)[0]=='&'){
arg_given = getNextEntry(arg_given); arg_given = getNextEntry(arg_given);
} }
if(getTypeEntry(arg_given) != param_arg_type){ if(getTypeEntry(arg_given) != getTypeEntry(param_arg_type)){
throw_error(ERROR_TYPE, "expected %s expression as argument in function call but got %s", getName(param_arg_type), getType(arg_given)); throw_error(ERROR_TYPE, "expected %s expression as argument in function call but got %s", getType(param_arg_type), getType(arg_given));
} }
arg_given = getNextEntry(arg_given); arg_given = getNextEntry(arg_given);
param_arg_type = getNextEntry(param_arg_type); param_arg_type = getNextEntry(param_arg_type);
@ -937,7 +968,7 @@ assignable:
} }
TableNode *actual = getTypeEntry(actual_instance); TableNode *actual = getTypeEntry(actual_instance);
if (expected != actual) { if (expected != actual) {
throw_error(ERROR_TYPE, "expected %s expression in function call but got %s", getName(expected), getName(actual)); throw_error(ERROR_TYPE, "expected %s expression in function call but got %s", getType(expected), getName(actual));
} }
if ($3 != 1) { if ($3 != 1) {
throw_error(ERROR_SYNTAX, "expected 1 argument but got %d", $3); } throw_error(ERROR_SYNTAX, "expected 1 argument but got %d", $3); }
@ -968,8 +999,8 @@ assignable:
printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName(typeNode2), getName((TableNode*)$1)); printdebug("[ASSIGNABLE - RULE 2] assignable = type: %s | name_func = %s", getName(typeNode2), getName((TableNode*)$1));
} else if (type == TYPE_ARRAY_TYPE) { } else if (type == TYPE_ARRAY_TYPE) {
printdebug("%sEntering array call", COLOR_LIGHTGREEN); printdebug("%sEntering array call", COLOR_LIGHTGREEN);
if (getNumArrDim(look_up(getParent(cur), getType((TableNode*)$1))) != $<integ>2) { if (getNumArrDim(getTypeEntry((TableNode*)$1)) != $3) {
throw_error(ERROR_SYNTAX, "expected %d arguments for this array but got %d", getNumArrDim(look_up(cur, getName((TableNode*)$1))), $<integ>2); throw_error(ERROR_SYNTAX, "expected %d arguments for this array but got %d", getNumArrDim(getTypeEntry((TableNode*)$1)), $3);
} }
char* temp = temp_var_gen(); char* temp = temp_var_gen();
@ -998,15 +1029,32 @@ assignable:
} }
cur = getParent(cur); 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 | assignable rec_op ID
{ {
if(getAdInfoType((TableNode*)$1) != TYPE_RECORD){ if(getAdInfoType((TableNode*)$1) != TYPE_RECORD){
throw_error(ERROR_TYPE, "Invalid type passed to record access"); throw_error(ERROR_TYPE, "Invalid type passed to record access");
$$ = undefined;
} }
else if(undefined != table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3)) { else if(undefined != table_lookup(getRecList(getTypeEntry((TableNode*)$1)), $3)) {
TableNode* type = getTypeEntry(table_lookup(getRecList(table_lookup(getAncestor(cur), getName(getTypeEntry((TableNode*)$1)))), $3)); TableNode* type = getTypeEntry(table_lookup(getRecList(getTypeEntry((TableNode*)$1)), $3));
char* temp = temp_var_gen(); char* temp = temp_var_gen();
int t = -1; int t = -1;
if(getAdInfoType(type) == TYPE_PRIMITIVE_TYPE){ if(getAdInfoType(type) == TYPE_PRIMITIVE_TYPE){
@ -1040,22 +1088,6 @@ assignable:
; ;
memOp:
RESERVE
{
printdebug("reserve expression");
}
| RELEASE
{
printdebug("release expression");
}
;
constant: constant:
C_STRING C_STRING
{ {

View File

@ -3,43 +3,106 @@
#include "intermediate_code.h" #include "intermediate_code.h"
// TODO: this is here to bring your attention to the comment bellow. Stack * S_Init(){
// check if start is NULL if it is assign it to the start globle variable Stack * s = calloc(1, sizeof(*s));
// otherwise make it next of current and set cur to your instruction. return s;
TNodeOrConst* getOperand1(Instruction* i) { }
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) {
__Node * n = calloc(1, sizeof(*n));
n->v = v;
n->next = s->n;
s->n = n;
s->size = s->size + 1;
}
void * S_Pop(Stack *s) {
if (s->size == 0) {
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_IsEmpty(s)) {
return NULL;
}
return s->n->v;
}
bool S_IsEmpty(Stack *s){
if(!s->size) {
return true;
}
return false;
}
int S_Size(Stack *s){
return s->size;
}
//_______________________________________________________________________
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_detach(){
current = current->prev;
current->next = NULL;
}
TNodeOrConst * getOperand1(Instruction * i){
return i->operand1; return i->operand1;
} }
TNodeOrConst* getOperand2(Instruction* i) { TNodeOrConst * getOperand2(Instruction * i){
return i->operand2; return i->operand2;
} }
TableNode* getResult(Instruction* i) { TableNode * getResult(Instruction * i){
return i->result; return i->result;
} }
Op getOp(Instruction* i) { Op getOp(Instruction * i){
return i->opcode; return i->opcode;
} }
int getLabel(Instruction* i) { int getLabel(Instruction * i){
return i->label; return i->label;
} }
int get_index(Instruction* i) { int get_index(Instruction * i){
return i->index; return i->index;
} }
void set_label(Instruction* i, int label) { void set_label(Instruction * i, int label){
i->label = label; i->label = label;
} }
bool isConst(TNodeOrConst* tnc) { bool isConst(TNodeOrConst * tnc) {
return tnc->d != NODE; return tnc->d != NODE;
} }
TNodeOrConst* tn_or_const(Discriminant d, void* tnc) { TNodeOrConst * tn_or_const(Discriminant d, void * tnc) {
TNodeOrConst* count = calloc(1, sizeof(*count)); TNodeOrConst * count = calloc(1, sizeof(*count));
count->d = d; count->d = d;
count->tnc_union = calloc(1, sizeof(*count->tnc_union)); count->tnc_union = calloc(1, sizeof(*count->tnc_union));
switch (d) { switch (d) {
@ -65,9 +128,9 @@ TNodeOrConst* tn_or_const(Discriminant d, void* tnc) {
return count; return count;
} }
static void emit_helper(void) { static void emit_helper(void){
Instruction* inst = calloc(1, sizeof(*inst)); Instruction * inst = calloc(1, sizeof(*inst));
if (begin == NULL) { if(begin == NULL){
begin = current = inst; begin = current = inst;
current->index = 1; current->index = 1;
} else { } else {
@ -78,31 +141,36 @@ 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(); emit_helper();
current->opcode = op; current->opcode = op;
// TODO: create temp and remove result from param list // TODO: create temp and remove result from param list
current->result = result; current->result = result;
current->operand1 = arg1; current->operand1 = arg1;
current->operand2 = arg2; current->operand2 = arg2;
} }
void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg) { void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg){
emit_helper(); emit_helper();
current->opcode = op; current->opcode = op;
current->result = result; current->result = result;
current->operand1 = arg; current->operand1 = arg;
} }
void emit_assignment(TableNode* target, TNodeOrConst* source) { void emit_assignment(TableNode * target, TNodeOrConst * source){
emit_helper(); emit_helper();
current->opcode = E_ASSIGN; current->opcode = E_ASSIGN;
current->result = target; current->result = target;
current->operand1 = source; current->operand1 = source;
} }
char* get_string(TNodeOrConst* tc) { char * get_string(TNodeOrConst * tc){
char* s; char * s;
switch (tc->d) { switch (tc->d) {
case NODE: case NODE:
return getName(tc->tnc_union->node); return getName(tc->tnc_union->node);
@ -119,139 +187,26 @@ char* get_string(TNodeOrConst* tc) {
sprintf(s, "%c", tc->tnc_union->character); sprintf(s, "%c", tc->tnc_union->character);
return s; return s;
case BOOLEAN: case BOOLEAN:
if (tc->tnc_union->Boolean) { if(tc->tnc_union->Boolean){
return strdup("true"); return strdup("true");
} }
return strdup("false"); return strdup("false");
} }
} }
void emit_as_file(FILE* out_file, Instruction* i) { void emit_label(int label){
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(); emit_helper();
current->opcode = E_LABEL; current->opcode = E_LABEL;
current->label = label; current->label = label;
} }
void emit_jump(int label) { void emit_jump(int label){
emit_helper(); emit_helper();
current->opcode = E_GOTO; current->opcode = E_GOTO;
current->label = label; current->label = label;
} }
void emit_conditional_jump(Op condition, int 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 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 *) // when the inst is a cond with a Relational operation then the input looks like (Op, int, TNodeOrConst *, TNodeOrConst *)
emit_helper(); emit_helper();
@ -259,18 +214,16 @@ void emit_conditional_jump(Op condition, int label, ...) {
va_start(argptr, label); va_start(argptr, label);
current->opcode = condition; current->opcode = condition;
current->label = label; current->label = label;
TNodeOrConst* n1; TNodeOrConst * n1;
TNodeOrConst* n2; TNodeOrConst * n2;
switch (condition) { switch (condition) {
case E_IF_X_TRUE: case E_IF_X_TRUE: case E_IF_X_FALSE:
case E_IF_X_FALSE: n1 = va_arg(argptr, TNodeOrConst *);
n1 = va_arg(argptr, TNodeOrConst*);
current->operand1 = n1; current->operand1 = n1;
break; break;
case E_LESS_THAN: case E_LESS_THAN: case E_EQUAL_TO:
case E_EQUAL_TO: n1 = va_arg(argptr, TNodeOrConst *);
n1 = va_arg(argptr, TNodeOrConst*); n2 = va_arg(argptr, TNodeOrConst *);
n2 = va_arg(argptr, TNodeOrConst*);
current->operand1 = n1; current->operand1 = n1;
current->operand2 = n2; current->operand2 = n2;
break; break;
@ -278,20 +231,23 @@ void emit_conditional_jump(Op condition, int label, ...) {
va_end(argptr); va_end(argptr);
} }
void emit_function_start(TNodeOrConst * name) { void emit_function_start(TableNode * name){
emit_helper(); emit_helper();
current->opcode = E_LABEL; // I think this is right TODO: ask current->opcode = E_FUNC_START;
current->operand1 = name; current->result = name;
// this is probabaly a func declaration
} }
void emit_parameter(TNodeOrConst* param) { void emit_parameter(TNodeOrConst * param){
emit_helper(); emit_helper();
current->opcode = E_PARAM; current->opcode = E_PARAM;
current->operand1 = 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(); emit_helper();
current->opcode = E_CALL; current->opcode = E_CALL;
current->operand1 = tn_or_const(INTEGER, &param_count); current->operand1 = tn_or_const(INTEGER, &param_count);
@ -299,44 +255,57 @@ void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name)
current->result = result; current->result = result;
} }
void emit_return(TNodeOrConst* value) { void emit_return(TNodeOrConst * value){
emit_helper(); emit_helper();
current->opcode = E_RETURN; current->opcode = E_RETURN;
current->operand1 = value; current->operand1 = value;
} }
void emit_reserve(TableNode* result, TNodeOrConst* size) { void emit_reserve(TableNode * result, TNodeOrConst * size){
emit_parameter(size); emit_parameter(size);
emit_function_call(result, 1, tn_or_const(NODE, look_up(cur, "reserve"))); emit_function_call(result, 1, tn_or_const(NODE, look_up(cur, "reserve")));
} }
void emit_release(TableNode* pointer) { void emit_release(TableNode * pointer){
emit_parameter(tn_or_const(NODE, pointer)); emit_parameter(tn_or_const(NODE, pointer));
emit_function_call(pointer, 1, tn_or_const(NODE, look_up(cur, "release"))); emit_function_call(pointer, 1, tn_or_const(NODE, look_up(cur, "release")));
} }
void emit_deref_right() { void emit_deref_right(TableNode * x, TNodeOrConst * y){
return; emit_helper();
current->opcode = E_DEREF_RIGHT;
current->result = x;
current->operand1 = y;
} }
void emit_deref_left() { void emit_deref_left(TableNode * x, TNodeOrConst * y){
return; emit_helper();
current->opcode = E_DEREF_LEFT;
current->result = x;
current->operand1 = y;
} }
void emit_field_access(char* result, char* record, char* field) { 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){
emit_helper(); emit_helper();
} }
void emit_array_access(Op op, TableNode* result, TNodeOrConst* array, TNodeOrConst* index) { void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index){
emit_helper(); emit_helper();
current->opcode; current->opcode = op;
current->result = result; current->result = result;
current->operand1 = array; current->operand1 = array;
current->operand2 = index; current->operand2 = index;
// TODO: Still don't know what to do with the dimentions // TODO: Still don't know what to do with the dimentions
} }
void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr) { void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr){
/* /*
{[string: 5] {[string: 5]
. .
@ -365,36 +334,249 @@ void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr) {
if t_0 < s._1 GOTO access array if t_0 < s._1 GOTO access array
GOTO ERROR GOTO ERROR
*/ */
//emit_conditional_jump(E_LESS_THAN, );
//emit_conditional_jump(E_LESS_THAN, );
//emit_jump();
/* We need a label ERROR to jump to /* 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.) // * 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;
}
*/
int label_gen(){ int label_gen(){
label_count++; label_count++;
return label_count; return label_count;
} }
void emit_as_file(FILE * out_file, Instruction * i){
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: %s = %s < %s\n",
i->index,
getName(i->result),
get_string(i->operand1),
get_string(i->operand2)
);
break;
case E_EQUAL_TO:
// this feels wrong I need to TODO: this
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_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) { TableNode* getTN(TNodeOrConst* tnc) {
if (tnc->d == NODE) { if (tnc->d == NODE) {
return tnc->tnc_union->node; return tnc->tnc_union->node;
} }
return NULL; return NULL;
} }
int getConst(TNodeOrConst* tnc) { int getConst(TNodeOrConst* tnc) {
if (tnc->d == INTEGER) { if (tnc->d == INTEGER) {
return tnc->tnc_union->integer; return tnc->tnc_union->integer;
} }
return -1; return -1;
} }

View File

@ -12,14 +12,39 @@
#include "symbol_table.h" #include "symbol_table.h"
// these are from page 364 typedef struct Stack Stack;
typedef enum { typedef struct __Node __Node;
typedef struct __Node {
void * v;
__Node * next;
} __Node;
typedef struct Stack {
__Node * n;
int size;
} Stack;
Stack * S_Init();
void S_Free(Stack *s);
void S_Push(Stack * s, void *v);
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;
typedef enum { // these are from page 364
E_LABEL = 10000, // this is not in the book E_LABEL = 10000, // this is not in the book
E_FUNC_START,
E_ADD, // 1 from the list E_ADD, // 1 from the list
E_SUB, // 1 E_SUB, // 1
E_MUL, // 1 E_MUL, // 1
E_DIV, // 1 E_DIV, // 1
E_MOD, // 1 E_MOD, // 1 TODO: Please change to REM
E_OR, // 1 E_OR, // 1
E_AND, // 1 E_AND, // 1
E_NEG, // 2 E_NEG, // 2
@ -50,75 +75,87 @@ typedef enum {
BOOLEAN // bool BOOLEAN // bool
} Discriminant; } Discriminant;
typedef union { typedef union TNConstUnion {
TableNode* node; TableNode * node;
int integer; int integer;
char* string; char * string;
char character; char character;
void* address; void * address;
bool Boolean; bool Boolean;
} TNConstUnion; } TNConstUnion;
typedef struct { typedef struct TNodeOrConst {
Discriminant d; Discriminant d;
TNConstUnion* tnc_union; TNConstUnion * tnc_union;
} TNodeOrConst; } TNodeOrConst;
typedef struct Instruction Instruction;
typedef struct Instruction { typedef struct Instruction {
Op opcode; Op opcode;
TableNode* result; TableNode * result;
TNodeOrConst* operand1; TNodeOrConst * operand1;
TNodeOrConst* operand2; TNodeOrConst * operand2;
int label; int label;
int index; int index;
Instruction* prev; Instruction * prev;
Instruction* next; Instruction * next;
} Instruction; } Instruction;
// NOTE We are not using this We are using the Stack api
typedef struct TFList { typedef struct TFList {
Instruction* i; Instruction * i;
TFList* next; TFList * next;
} TFList; } TFList;
TNodeOrConst* getOperand1(Instruction* i); TFList * make_list(Instruction * i);
TNodeOrConst* getOperand2(Instruction* i); // - makelist(i) function to create instruction lists
TableNode* getResult(Instruction* i); void merge(TFList * l1, TFList * l2);
Op getOp(Instruction* i); // - merge(p1,p2) function to concatenate lists
int getLabel(Instruction* i); void backpatch(TFList * l, int label);
int get_index(Instruction* i); // - backpatch(p,i) function to fill in jump targets
void set_label(Instruction* i, int label); void bp_temp(int n);
bool isConst(TNodeOrConst* tnc);
TNodeOrConst* tn_or_const(Discriminant d, void* tnc);
static void emit_helper(void); extern Instruction * begin;
void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst* arg2); extern Instruction * current;
void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg); extern int label_count;
void emit_assignment(TableNode* target, TNodeOrConst* source); extern bool code_gen;
char* get_string(TNodeOrConst* tc);
void emit_as_file(FILE* out_file, Instruction* i);
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_label(int label);
void emit_jump(int label); void emit_jump(int label);
void emit_conditional_jump(Op condition, int label, ...); void emit_conditional_jump(Op condition, int label, ...);
void emit_function_start(TNodeOrConst * name);
void emit_parameter(TNodeOrConst* param); void emit_function_start(TableNode* name);
void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name); void emit_parameter(TNodeOrConst * param);
void emit_return(TNodeOrConst* value); void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name);
void emit_reserve(TableNode* result, TNodeOrConst* size); void emit_return(TNodeOrConst * value);
void emit_release(TableNode* pointer); void emit_reserve(TableNode * result, TNodeOrConst * size);
void emit_deref_right(); void emit_release(TableNode * pointer);
void emit_deref_left();
void emit_field_access(char* result, char* record, char* field); void emit_field_access(char* result, char* record, char* field);
void emit_array_access(Op op, TableNode* result, TNodeOrConst* array, TNodeOrConst* index); void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index);
void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr); void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr);
int label_gen();
int getLabel(Instruction * i);
TableNode* getTN(TNodeOrConst* tnc); TableNode* getTN(TNodeOrConst* tnc);
int getConst(TNodeOrConst* tnc); int getConst(TNodeOrConst* tnc);
extern int label_count;
extern Instruction* begin;
extern Instruction* current;
extern int offset;
extern int currentsp; TNodeOrConst * getOperand1(Instruction * i);
extern CGNode* cgList; 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);
int label_gen();

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;} '{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;} \"{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;*/} {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(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(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(L_BRACKET);} incr(line_number,column_number,L_BRACKET); return L_BRACKET; }

View File

@ -102,6 +102,7 @@ void print_tok(int tok) {
int run(FILE *alpha) { int run(FILE *alpha) {
int token; int token;
top = cur = init(CreateScope(NULL, 1, 1)); top = cur = init(CreateScope(NULL, 1, 1));
Stack *s = S_Init();
// If file is not found // If file is not found
if (alpha == NULL) { if (alpha == NULL) {

View File

@ -1293,7 +1293,7 @@ void print_symbol_table(SymbolTable *table, FILE *file_ptr) {
if (getAdInfoType(entry) == TYPE_FUNCTION_DECLARATION) { if (getAdInfoType(entry) == TYPE_FUNCTION_DECLARATION) {
char *functiontype = (char *)malloc(100); char *functiontype = (char *)malloc(100);
sprintf(functiontype, " %s", getName(getReturn(entry))); sprintf(functiontype, " %s", getName(getTypeEntry(entry)));
if (parentScopeNum == 0) { if (parentScopeNum == 0) {
st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, " Function Definition"); st_fprint(file_ptr, getName(entry), currentScopeNum, -100, functiontype, " Function Definition");
} else { } else {

View File

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