struct memorycontainer* createArrayExpression(struct stack_t* arrayVals, struct memorycontainer* repetitionExpr) { int lenOfArray=getStackSize(arrayVals); struct memorycontainer* expressionContainer=NULL; int i; for (i=0;i<lenOfArray;i++) { if (expressionContainer == NULL) { expressionContainer=getExpressionAt(arrayVals, i); } else { expressionContainer=concatenateMemory(expressionContainer, getExpressionAt(arrayVals, i)); } } struct memorycontainer* memoryContainer = (struct memorycontainer*) malloc(sizeof(struct memorycontainer)); memoryContainer->length=sizeof(unsigned char)*2 + sizeof(int); memoryContainer->data=(char*) malloc(memoryContainer->length); memoryContainer->lineDefns=NULL; int location=appendStatement(memoryContainer, ARRAY_TOKEN, 0); memcpy(&memoryContainer->data[location], &lenOfArray, sizeof(int)); location+=sizeof(int); unsigned char hasRepetitionExpr=repetitionExpr == NULL ? 0 : 1; memcpy(&memoryContainer->data[location], &hasRepetitionExpr, sizeof(unsigned char)); if (repetitionExpr != NULL) memoryContainer=concatenateMemory(memoryContainer, repetitionExpr); return concatenateMemory(memoryContainer, expressionContainer); }
/** * Appends and returns the setting of an array element (assignment) statement */ struct memorycontainer* appendArraySetStatement( char* identifier, struct stack_t* indexContainer, struct memorycontainer* expressionContainer) { struct memorycontainer* memoryContainer = (struct memorycontainer*) malloc(sizeof(struct memorycontainer)); memoryContainer->length=(sizeof(unsigned char)*2)+sizeof(unsigned short); memoryContainer->data=(char*) malloc(memoryContainer->length); memoryContainer->lineDefns=NULL; unsigned int position=0; position=appendStatement(memoryContainer, ARRAYSET_TOKEN, position); position=appendVariable(memoryContainer, getVariableId(identifier, 1), position); unsigned char numIndexes=(unsigned char) getStackSize(indexContainer); memcpy(&memoryContainer->data[position], &numIndexes, sizeof(unsigned char)); position+=sizeof(unsigned char); int i; for (i=0;i<numIndexes;i++) { memoryContainer=concatenateMemory(memoryContainer, getExpressionAt(indexContainer, i)); } memoryContainer=concatenateMemory(memoryContainer, expressionContainer); return memoryContainer; }
/** * Appends and returns a for iteration. This puts in the assignment of the initial value to the variable, the normal stuff and then * termination check at each iteration along with jumping to next iteration if applicable */ struct memorycontainer* appendForStatement(char * identifier, struct memorycontainer* exp, struct memorycontainer* block) { struct memorycontainer* initialLet=appendLetStatement("epy_i_ctr", createIntegerExpression(0)); struct memorycontainer* variantLet=appendLetStatement(identifier, createIntegerExpression(0)); struct memorycontainer* incrementLet=appendLetStatement("epy_i_ctr", createAddExpression(createIdentifierExpression("epy_i_ctr"), createIntegerExpression(1))); struct memorycontainer* memoryContainer = (struct memorycontainer*) malloc(sizeof(struct memorycontainer)); memoryContainer->length=sizeof(unsigned char)*2+sizeof(unsigned short) * 4 + exp->length + (block != NULL ? block->length : 0) + initialLet->length + variantLet->length + incrementLet->length; memoryContainer->data=(char*) malloc(memoryContainer->length); memoryContainer->lineDefns=NULL; struct memorycontainer* combinedBlock=block != NULL ? concatenateMemory(block, incrementLet) : incrementLet; unsigned int position=0; struct lineDefinition * defn = (struct lineDefinition*) malloc(sizeof(struct lineDefinition)); defn->next=memoryContainer->lineDefns; defn->type=0; defn->linenumber=currentForLine; defn->currentpoint=initialLet->length; memoryContainer->lineDefns=defn; position=appendMemory(memoryContainer, initialLet, position); position=appendMemory(memoryContainer, variantLet, position); position=appendStatement(memoryContainer, FOR_TOKEN, position); position=appendVariable(memoryContainer, getVariableId("epy_i_ctr", 0), position); position=appendVariable(memoryContainer, getVariableId(identifier, 0), position); position=appendMemory(memoryContainer, exp, position); unsigned short length=(unsigned short) combinedBlock->length; memcpy(&memoryContainer->data[position], &length, sizeof(unsigned short)); position+=sizeof(unsigned short); position=appendMemory(memoryContainer, combinedBlock, position); position=appendStatement(memoryContainer, GOTO_TOKEN, position); defn = (struct lineDefinition*) malloc(sizeof(struct lineDefinition)); defn->next=memoryContainer->lineDefns; defn->type=1; defn->linenumber=currentForLine; defn->currentpoint=position; memoryContainer->lineDefns=defn; currentForLine--; return memoryContainer; }
/** * Creates an expression wrapping an identifier array access */ struct memorycontainer* createIdentifierArrayAccessExpression(char* identifier, struct stack_t* index_expressions) { int lenOfIndexes=getStackSize(index_expressions); struct memorycontainer* memoryContainer = (struct memorycontainer*) malloc(sizeof(struct memorycontainer)); memoryContainer->length=sizeof(unsigned short)+(sizeof(unsigned char)*2); memoryContainer->data=(char*) malloc(memoryContainer->length); memoryContainer->lineDefns=NULL; unsigned int position=0; position=appendStatement(memoryContainer, ARRAYACCESS_TOKEN, position); position=appendVariable(memoryContainer, getVariableId(identifier, 1), position); unsigned char packageNumDims=(unsigned char) lenOfIndexes; memcpy(&memoryContainer->data[position], &packageNumDims, sizeof(unsigned char)); position+=sizeof(unsigned char); int i; for (i=0;i<lenOfIndexes;i++) { memoryContainer=concatenateMemory(memoryContainer, getExpressionAt(index_expressions, i)); } return memoryContainer; }
/** * Compiles the memory by going through and resolving relative links (i.e. gotos) and adds a stop at the end */ void compileMemory(struct memorycontainer* memory) { struct memorycontainer* stopStatement=appendStopStatement(); if (memory != NULL) { struct memorycontainer* compiledMem=concatenateMemory(memory, stopStatement); struct lineDefinition * root=compiledMem->lineDefns, *r2; while (root != NULL) { if (root->type==1) { unsigned short lineLocation=findLocationOfLineNumber(compiledMem->lineDefns, root->linenumber); memcpy(&compiledMem->data[root->currentpoint], &lineLocation, sizeof(unsigned short)); } root=root->next; } // Clear up the memory used for these line definition nodes root=compiledMem->lineDefns; while (root != NULL) { r2=root->next; free(root); root=r2; } assembledMemory=compiledMem; } else { assembledMemory=stopStatement; } }
/** * Appends a new function statement to the function list which is held by the memory manager. * This also appends a return statement to the end of the function body and registers * the current goto point as the function name */ void appendNewFunctionStatement(char* functionName, struct stack_t * args, struct memorycontainer* functionContents) { struct functionDefinition * fn=(struct functionDefinition*) malloc(sizeof(struct functionDefinition)); fn->name=(char*) malloc(strlen(functionName) + 1); strcpy(fn->name, functionName); fn->called=0; unsigned short numberArgs=(unsigned short) getStackSize(args); struct memorycontainer* numberArgsContainer = (struct memorycontainer*) malloc(sizeof(struct memorycontainer)); numberArgsContainer->length=sizeof(unsigned short) * (numberArgs + 1); numberArgsContainer->data=(char*) malloc(sizeof(unsigned short) * (numberArgs + 1)); numberArgsContainer->lineDefns=NULL; ((unsigned short *) numberArgsContainer->data)[0]=numberArgs; struct memorycontainer* assignmentContainer=NULL; int i; for (i=0;i<numberArgs;i++) { if (getTypeAt(args, i) == 2) { ((unsigned short *) numberArgsContainer->data)[i+1]=getVariableId(getIdentifierAt(args, i), 1); } else { struct identifier_exp * idexp=getExpressionIdentifierAt(args, i); if (assignmentContainer == NULL) { assignmentContainer=appendLetIfNoAliasStatement(idexp->identifier, idexp->exp); } else { assignmentContainer=concatenateMemory(assignmentContainer, appendLetIfNoAliasStatement(idexp->identifier, idexp->exp)); } ((unsigned short *) numberArgsContainer->data)[i+1]=getVariableId(idexp->identifier, 1); } } clearStack(args); if (assignmentContainer != NULL) numberArgsContainer=concatenateMemory(numberArgsContainer, assignmentContainer); struct memorycontainer* completedFunction=concatenateMemory(concatenateMemory(numberArgsContainer, functionContents), appendReturnStatement()); struct lineDefinition * defn = (struct lineDefinition*) malloc(sizeof(struct lineDefinition)); defn->next=completedFunction->lineDefns; defn->type=2; defn->currentpoint=0; defn->name=(char*) malloc(strlen(functionName) + 1); strcpy(defn->name, functionName); completedFunction->lineDefns=defn; fn->contents=completedFunction; fn->numberEntriesInSymbolTable=current_var_id - currentSymbolTableId; fn->recursive=isFnRecursive; fn->number_of_fn_calls=currentCall->number_of_calls; if (currentCall->number_of_calls == 0) { fn->functionCalls=NULL; } else { fn->functionCalls=(char**) malloc(sizeof(char*) * currentCall->number_of_calls); memcpy(fn->functionCalls, currentCall->calledFunctions, sizeof(char*) * currentCall->number_of_calls); } free(currentFunctionName); currentFunctionName=NULL; currentCall=NULL; addFunction(fn); }
/** * Appends and returns a call function, this is added as a placeholder and then resolved at the end to point to the absolute byte code location * which is needed as the function might appear at any point */ struct memorycontainer* appendCallFunctionStatement(char* functionName, struct stack_t* args) { char * last_dot=strrchr(functionName,'.'); if (last_dot != NULL) functionName=last_dot+1; if (currentFunctionName != NULL && strcmp(currentFunctionName, functionName) == 0) isFnRecursive=1; struct memorycontainer* assignmentContainer=NULL; unsigned short numArgs=(unsigned short) getStackSize(args); char *isArgIdentifier=(char*) malloc(numArgs); unsigned short *varIds=(unsigned short*) malloc(sizeof(unsigned short) * numArgs); char * varname=(char*) malloc(strlen(functionName)+5); int i; for (i=0;i<numArgs;i++) { struct memorycontainer* expression=getExpressionAt(args, i); unsigned char command=((unsigned char*) expression->data)[0]; if (command != IDENTIFIER_TOKEN) { isArgIdentifier[i]=0; sprintf(varname,"%s#%d", functionName, i); if (assignmentContainer == NULL) { assignmentContainer=appendLetStatement(varname, getExpressionAt(args, i)); } else { assignmentContainer=concatenateMemory(assignmentContainer, appendLetStatement(varname, getExpressionAt(args, i))); } } else { isArgIdentifier[i]=1; varIds[i]=*((unsigned short*) (&((char*) expression->data)[1])); free(expression->data); } } struct memorycontainer* memoryContainer = (struct memorycontainer*) malloc(sizeof(struct memorycontainer)); memoryContainer->length=sizeof(unsigned short)*(2+numArgs)+sizeof(unsigned char); memoryContainer->data=(char*) malloc(memoryContainer->length); unsigned int position=0; if (doesVariableExist(functionName)) { memoryContainer->lineDefns=NULL; position=appendStatement(memoryContainer, FNCALL_BY_VAR_TOKEN, position); position=appendVariable(memoryContainer, getVariableId(functionName, 0), position); } else { struct lineDefinition * defn = (struct lineDefinition*) malloc(sizeof(struct lineDefinition)); defn->next=NULL; defn->type=3; defn->linenumber=line_num; defn->name=(char*) malloc(strlen(functionName)+1); strcpy(defn->name, functionName); defn->currentpoint=sizeof(unsigned char); memoryContainer->lineDefns=defn; position=appendStatement(memoryContainer, FNCALL_TOKEN, position); position+=sizeof(unsigned short); } position=appendVariable(memoryContainer, numArgs, position); for (i=0;i<numArgs;i++) { if (isArgIdentifier[i]) { position=appendVariable(memoryContainer, varIds[i], position); } else { sprintf(varname,"%s#%d", functionName, i); position=appendVariable(memoryContainer, getVariableId(varname, 0), position); } } clearStack(args); free(varname); free(isArgIdentifier); free(varIds); if (currentCall==NULL) { mainCodeCallTree.calledFunctions[mainCodeCallTree.number_of_calls]=(char*)malloc(strlen(functionName)+1); strcpy(mainCodeCallTree.calledFunctions[mainCodeCallTree.number_of_calls++], functionName); } else { currentCall->calledFunctions[currentCall->number_of_calls]=(char*)malloc(strlen(functionName)+1); strcpy(currentCall->calledFunctions[currentCall->number_of_calls++], functionName); } if (assignmentContainer != NULL) { return concatenateMemory(assignmentContainer, memoryContainer); } else { return memoryContainer; } }
struct memorycontainer* appendNativeCallFunctionStatement(char* functionName, struct stack_t* args, struct memorycontainer* singleArg) { struct memorycontainer* memoryContainer = (struct memorycontainer*) malloc(sizeof(struct memorycontainer)); memoryContainer->length=(sizeof(unsigned char)*2) + sizeof(unsigned short); memoryContainer->data=(char*) malloc(memoryContainer->length); memoryContainer->lineDefns=NULL; unsigned int position=0; position=appendStatement(memoryContainer, NATIVE_TOKEN, position); if (strcmp(functionName, NATIVE_RTL_ISHOST_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_ISHOST, position); } else if (strcmp(functionName, NATIVE_RTL_ISDEVICE_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_ISDEVICE, position); } else if (strcmp(functionName, NATIVE_RTL_PRINT_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_PRINT, position); } else if (strcmp(functionName, NATIVE_RTL_NUMDIMS_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_NUMDIMS, position); } else if (strcmp(functionName, NATIVE_RTL_DSIZE_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_DSIZE, position); } else if (strcmp(functionName, NATIVE_RTL_INPUT_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_INPUT, position); } else if (strcmp(functionName, NATIVE_RTL_INPUTPRINT_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_INPUTPRINT, position); } else if (strcmp(functionName, NATIVE_RTL_SYNC_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_SYNC, position); } else if (strcmp(functionName, NATIVE_RTL_GC_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_GC, position); } else if (strcmp(functionName, NATIVE_RTL_FREE_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_FREE, position); } else if (strcmp(functionName, NATIVE_RTL_SEND_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_SEND, position); } else if (strcmp(functionName, NATIVE_RTL_RECV_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_RECV, position); } else if (strcmp(functionName, NATIVE_RTL_SENDRECV_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_SENDRECV, position); } else if (strcmp(functionName, NATIVE_RTL_BCAST_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_BCAST, position); } else if (strcmp(functionName, NATIVE_RTL_NUMCORES_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_NUMCORES, position); } else if (strcmp(functionName, NATIVE_RTL_COREID_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_COREID, position); } else if (strcmp(functionName, NATIVE_RTL_REDUCE_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_REDUCE, position); } else if (strcmp(functionName, NATIVE_RTL_ALLOCATEARRAY_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_ALLOCARRAY, position); } else if (strcmp(functionName, NATIVE_RTL_ALLOCATESHAREDARRAY_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_ALLOCSHAREDARRAY, position); } else if (strcmp(functionName, NATIVE_RTL_MATH_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_MATH, position); } else if (strcmp(functionName, NATIVE_RTL_PROBE_FOR_MESSAGE_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_PROBE_FOR_MESSAGE, position); } else if (strcmp(functionName, NATIVE_RTL_TEST_FOR_SEND_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_TEST_FOR_SEND, position); } else if (strcmp(functionName, NATIVE_RTL_WAIT_FOR_SEND_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_WAIT_FOR_SEND, position); } else if (strcmp(functionName, NATIVE_RTL_SEND_NB_STR)==0) { position=appendStatement(memoryContainer, NATIVE_FN_RTL_SEND_NB, position); } else { fprintf(stderr, "Native function call of '%s' is not found\n", functionName); exit(EXIT_FAILURE); } unsigned short numArgs=args !=NULL ? (unsigned short) getStackSize(args) : singleArg != NULL ? 1 : 0; position=appendVariable(memoryContainer, numArgs, position); if (args != NULL) { int i; for (i=0;i<numArgs;i++) { struct memorycontainer* expression=getExpressionAt(args, i); memoryContainer=concatenateMemory(memoryContainer, expression); } } if (singleArg != NULL) memoryContainer=concatenateMemory(memoryContainer, singleArg); return memoryContainer; }