diff --git a/src/grammar.h b/src/grammar.h index 94384d8..43272b7 100644 --- a/src/grammar.h +++ b/src/grammar.h @@ -8,9 +8,11 @@ #include "../src/symbol_table.h" extern FILE *asc_flag; extern bool tc_flag; +extern bool entry_flag; extern void insert_code_line(char *error_message, int line_number); extern bool contains_errors; - +extern int context; +//extern TableNode* comparator; typedef enum { ERROR_RUNTIME = 1, ERROR_SYNTAX = 2, diff --git a/src/grammar.y b/src/grammar.y index ccdd9da..fa74029 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -170,6 +170,10 @@ definition: } | ID { + if(strcmp($1, "entry") == 0){ + //seen entry function + entry_flag = true; + } emit_function_start(table_lookup(cur,$1)); //printf("ID: %s\n", $1); //printf("Type: %s\n", getType(table_lookup(getAncestor(cur), $1))); @@ -222,7 +226,7 @@ definition: } if(type_of_param_type == TYPE_PRIMITIVE_TYPE){ - CreateEntry(cur, TYPE_PRIMITIVE, parameter,NULL, getAdInfo(parameter))==undefined; + CreateEntry(cur, TYPE_PRIMITIVE, parameter,NULL, getAdInfo(parameter));//==undefined; // throw_error(ERROR_TYPE, "Duplicate defination of parameter in function definition.");} } @@ -309,6 +313,7 @@ function_declaration: if (CreateEntry(cur,TYPE_FUNCTION_DECLARATION, table_lookup(cur, $4), $2, CreateFunctionDeclarationInfo(-1, false,NULL)) == undefined) { throw_error(ERROR_TYPE, "Duplicate defination of function in function declaration"); } + } else{ throw_error(ERROR_TYPE, "Function declatation (%s) is not a valid function type", $2); @@ -679,6 +684,11 @@ compound_statement: simple_statement: assignable{ + //updating context for reserve/release + if(getAdInfoType((TableNode*)$1) == TYPE_ARRAY || getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION){ + PushContext(getTypeEntry((TableNode*)$1)); + printdebug("pushed %s to context stack in simple statement assignable rule\n",getName(getTypeEntry((TableNode*)$1))); + } S_Push(TrueList, S_Init(), 0); S_Push(FalseList, S_Init(), 0); } ASSIGN expression @@ -722,15 +732,23 @@ simple_statement: throw_error(ERROR_TYPE, "Assignable Assign Expression - Object %s of type %s != Object %s of type %s", getName(node), getType(node), getName((TableNode*)$4), getType((TableNode*)$4)); } $$ = undefined; + //resetting context + if(getAdInfoType((TableNode*)$1) == TYPE_ARRAY || getAdInfoType((TableNode*)$1) == TYPE_FUNCTION_DECLARATION){ + PopContext(); + printdebug("popped a context off in simplestatement assignable rule\n"); + } } | RETURN expression { $$ = getTypeEntry((TableNode*)$2); emit_return(tn_or_const(NODE,(TableNode*)$2));} + + // | assignable ASSIGN RESERVE assignable{ } |simple_statement error {yyerrok; yyclearin; printdebug("error in simple statement");} + ; @@ -762,10 +780,17 @@ ablock: ; - argument_list: + expression{ + PopContext(); + printdebug("popped a context off in argument list\n"); + incrementArgumentNumber(function_head); + TableNode* typeOfArg = getFunctionNumberType(getFunctionType(function_head), getArgumentNumber(function_head)); + PushContext(typeOfArg); + printdebug("pushed %s to context stack\n",getName(typeOfArg)); TableNode * arg = CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), arg_var_gen(), NULL); + //inside a scope of an array call if line number is -2 if(getLine(cur)==-2){ if(getTypeEntry(arg) != integ){ throw_error(ERROR_TYPE, "Argument %s of type %s is not of type integer for an array argument", getName(arg), getType(arg)); @@ -790,7 +815,10 @@ argument_list: | expression { + PopContext(); + printdebug("popped a context off in argument list (single arg rule)\n"); TableNode* arg = CreateEntry(cur, getAdInfoType((TableNode*)$1), getTypeEntry((TableNode*)$1), arg_var_gen(), NULL); + //inside a scope of an array call if line number is -2 if(getLine(cur)==-2){ if(getTypeEntry(arg) != integ){ throw_error(ERROR_TYPE, "Argument %s of type %s is not of type integer for an array argument", getName(arg), getType(arg)); @@ -1110,7 +1138,7 @@ expression: } // TODO: We need to type check this. - | RESERVE ID { + /*| RESERVE ID { char* temp = temp_var_gen(); TableNode* node = CreateEntry(cur,TYPE_PRIMITIVE, addr, temp, NULL); TableNode * n = look_up(cur, $2); @@ -1157,50 +1185,67 @@ expression: $$=undefined; } cur = getParent(cur); + }*/ + | RESERVE assignable{ + if(getTypeEntry((TableNode*)$2) == getContextTypeEntry(context_head) + && (/*getAdInfoType((TableNode*)$2)==TYPE_ARRAY ||*/ getAdInfoType(getTypeEntry((TableNode*)$2)) == TYPE_RECORD)){ + char* temp = temp_var_gen(); + //does this have integer? + TableNode* node = CreateEntry(cur,TYPE_RECORD, getContextTypeEntry(context_head), temp, NULL); + emit_reserve(node, tn_or_const(NODE,$2)); + $$ = node; + } + if(((getTypeEntry((TableNode*)$2)) == getArrType(getContextTypeEntry(context_head))) + && (getAdInfoType(getContextTypeEntry(context_head)) == TYPE_ARRAY_TYPE)){ + char* temp = temp_var_gen(); + //does this have integer? + TableNode* node = CreateEntry(cur,TYPE_ARRAY, getContextTypeEntry(context_head), temp, NULL); + emit_reserve(node, tn_or_const(NODE,$2)); + $$ = node; + }else{ + $$ = undefined; + } + } + | RELEASE assignable{ - /*TableNode * t = getFirstEntry(cur); - TableNode * n = look_up(cur, $2); - if(getAdInfoType(n) == TYPE_ARRAY){ - int array_dims = getNumArrDim(getTypeEntry(n)); - if ($5 != array_dims) { - throw_error(ERROR_SYNTAX, "expected %d dimensions for this array but got %d", array_dims, $5); - }else{ - int traverse = 0; - while(t != NULL && t != undefined && getName(t)[0] != '&'){ - t = getNextEntry(t); - } - if(getTypeEntry(t) != integ){ - throw_error(ERROR_TYPE, "Arg for an array is not of type integer"); - $$= undefined; - }else{ - //seen first number - traverse++; - t = getNextEntry(t); - while(traversecon = context; + cs->typeToCompare = typeToCompare; + if (context_head == NULL) { + context_head = cs; + cs->next = NULL; + } else { + cs->next = context_head; + context_head = cs; + } + return cs; +} + +Function_Stack *PushFunction(int arg, TableNode* FunctionType) { + if (FunctionType == NULL) { + printdebug( + "passed a NULL reference to PushFunction. Invalid."); + return NULL; + } + if(FunctionType == undefined) { + printdebug( + "passed an undefined reference to PushFunction. Invalid."); + return NULL; + } + Function_Stack *fs = (Function_Stack *)calloc(1,sizeof(Function_Stack)); + fs->arg = arg; + fs->FunctionType = FunctionType; + if (function_head == NULL) { + function_head = fs; + fs->next = NULL; + } else { + fs->next = function_head; + function_head = fs; + } + return fs; +} + +Function_Stack *PopFunction() { + if (function_head == NULL) { + printf("cannot pop from an empty stack from popfunction. Invalid.\n"); + return NULL; + } + Function_Stack *fs = function_head; + function_head = function_head->next; + return fs; +} + +int getArgumentNumber(Function_Stack *fs) { + if (fs == NULL) { + printdebug( + "passed a NULL reference to getArgumentNumber. Invalid."); + return -1; + } + return fs->arg; +} + +int getTotalNumberArguments(TableNode* function) { + if (function == NULL) { + printdebug( + "passed a NULL reference to getTotalNumberArguments. Invalid."); + return -1; + } + if (getAdInfoType(function) != TYPE_FUNCTION_DECLARATION) { + printdebug( + "passed an invalid reference to getTotalNumberArguments. Invalid."); + return -1; + } + TableNode* functionType = getParameter(getTypeEntry(function)); + if(functionType != undefined){ + return -1; + } + if(getAdInfoType(functionType) != TYPE_RECORD_TYPE){ + return 1; + }else{ + return getRecLength(functionType); + } +} + +Function_Stack* setArgumentNumber(Function_Stack *fs, int arg) { + if (fs == NULL) { + printdebug( + "passed a NULL reference to setArgumentNumber. Invalid."); + return NULL; + } + + if(argFunctionType)){ + //case where invalid argument number is being passed + return NULL; + } + fs->arg = arg; + return fs; +} +Function_Stack* setFunctionType(Function_Stack *fs, TableNode* functionType) { + if (fs == NULL) { + printdebug( + "passed a NULL reference to setFunctionType. Invalid."); + return NULL; + } + if (functionType == NULL) { + printdebug( + "passed a NULL reference to setFunctionType. Invalid."); + return NULL; + } + fs->FunctionType = functionType; + return fs; +} +TableNode* getFunctionType(Function_Stack *fs) { + if (fs == NULL) { + printdebug( + "passed a NULL reference to getFunctionType. Invalid."); + return undefined; + } + TableNode* tn = fs->FunctionType; + return tn; +} + +Function_Stack* incrementArgumentNumber(Function_Stack *fs) { + if (fs == NULL) { + printdebug( + "passed a NULL reference to incrementArgumentNumber. Invalid."); + return NULL; + } + int cur=getArgumentNumber(fs); + setArgumentNumber(fs, cur+1); + //setFunctionType(fs, getFunctionNumberType(getFunctionType(fs), cur+1)); + return fs; +} + +TableNode* getRecordNumberType(TableNode* record, int arg){ + if(record == NULL){ + //case where NULL is being passed in + return undefined; + } + if(getAdInfoType(record) != TYPE_RECORD_TYPE){ + //case where invalid argument number is being passed + return undefined; + } + if(argFunctionType; + return tn; +} + +Context_stack *PopContext() { + if (context_head == NULL) { + printf("cannot pop from an empty stack from popcontext. Invalid.\n"); + return NULL; + } + Context_stack *cs = context_head; + context_head = context_head->next; + //printf("Popped context off stack: number %d\n", cs->con); + return cs; +} +/* +int getContextType(Context_stack *cs) { + if (cs == NULL) { + printdebug( + "passed a NULL reference to getContextType. Invalid."); + return -1; + } + return cs->con; +} +*/ +TableNode *getContextTypeEntry(Context_stack *cs) { + if (cs == NULL) { + printdebug( + "passed a NULL reference to getContextTypeEntry. Invalid."); + return undefined; + } + TableNode* tn = cs->typeToCompare; + return NULL; +} Constant_Stack *Pop() { if (head == NULL) { printf("cannot pop from an empty stack. Invalid.\n"); diff --git a/src/symbol_table.h b/src/symbol_table.h index e6da226..35d6b81 100644 --- a/src/symbol_table.h +++ b/src/symbol_table.h @@ -17,10 +17,12 @@ extern FILE *ir_flag; -struct TableNode; +typedef struct TableNode TableNode; typedef struct TFList TFList; typedef struct CGNode CGNode; typedef struct SymbolTable SymbolTable; +typedef struct Function_Stack Function_Stack; +typedef struct Context_stack Context_stack; typedef struct Constant_Stack { struct TableNode *theType; @@ -28,6 +30,32 @@ typedef struct Constant_Stack { struct Constant_Stack *next; bool isConst; } Constant_Stack; +//explanation about context stack +//If we have an array context, it means that we are expecting an array, either on the left side of assignable or as the (one of the) arguments that needs to be passed in for a function +//with the array context, either we are initializing the array OR we are reserving space for an element of the array. Can only reserve a record or an array so that element must be a record or an array. +//if we have a record context, that means we are expecting a record on the left side of the assignable assignment or we are expecting a record passed as an argument for a function call. +//we push and pop these contexts as needed. +//we can also push the table node of the thing that we are trying to look at. If it is supposed to be an array, for example, we can push that array onto the stack +//if it is a record, we can push that record onto the stack so that we can approperiately type check +//0 - no expecting array or record +//1 - expecting an array +//2 - expecting a record +//we also have a function call stack to look at what function call we are inside (what parameters it is expecting) +//This is distinct from the context stack. We don't necessarily add to the function call stack. After every valid argument, we simply add one to what argument we are seeing +//This lets us update the context stack as needed with the next tablenode type that we are comparing against +//we can also simply add to the function call stack if we have functions inside functions and then update as needed + +typedef struct Context_stack { + //int con; + TableNode *typeToCompare; + struct Context_stack *next; +} Context_stack; + +typedef struct Function_Stack{ + int arg; + TableNode *FunctionType; + struct Function_Stack *next; +} Function_Stack; typedef struct { int size; @@ -106,14 +134,28 @@ void printdebug_impl(char *file, int line, const char *format, ...); char *temp_var_gen(); char *arg_var_gen(); +int getTotalNumberArguments(TableNode* function); +Function_Stack* incrementArgumentNumber(Function_Stack *fs); +Function_Stack* setArgumentNumber(Function_Stack *fs, int arg); Constant_Stack *Push(TableNode *type, void *value, bool isConst); +Context_stack *PushContext(/*int context,*/TableNode *typeToCompare); +Function_Stack *PushFunction(int arg, TableNode* FunctionType); Constant_Stack *Pop(); +Context_stack *PopContext(); +Function_Stack* setFunctionType(Function_Stack *fs, TableNode* functionType); +Function_Stack *PopFunction(); +TableNode* getFunctionTypeContext(Function_Stack *fs); +TableNode* getFunctionType(Function_Stack *fs); +//int getContextType(Context_stack *cs); Constant_Stack *Print_Stack(); +int getArgumentNumber(Function_Stack *fs); AdInfo *CreatePrimitiveInfo(int size); int getPrimSize(TableNode *definition); AdInfo *CreateArrayInfo(int dim, TableNode *type); int getNumArrDim(TableNode *definition); TableNode *getArrType(TableNode *definition); +TableNode* getRecordNumberType(TableNode* record, int arg); +TableNode* getFunctionNumberType(TableNode* function, int arg); AdInfo *CreateRecordInfo(int length, SymbolTable *recordScope); int getRecTotal(TableNode *node); TableNode *setRecOffsetInfo(SymbolTable *scope, TableNode *node); @@ -161,10 +203,14 @@ ListOfTable *getRestOfChildren(ListOfTable *lt); TableNode *getFirstEntry(SymbolTable *st); TableNode *getNextEntry(TableNode *tn); TableNode *printTableNode(TableNode *tn); + +TableNode *getContextTypeEntry(Context_stack *cs); + int getElementOffset(TableNode *rec, char* id); int getRecPosition(TableNode* rec, char* id); int getStackSize(); + extern int yylex(void); extern char *yytext; extern int yyleng; @@ -188,6 +234,8 @@ extern TableNode *recprime; extern TableNode *funtypeprime; extern TableNode *undefined; extern Constant_Stack *head; +extern Context_stack *context_head; +extern Function_Stack *function_head; extern char *COLOR_RED; extern char *COLOR_GREEN;