Ejemplo n.º 1
0
static int handleSend(char * assembled, int currentPoint, int threadId) {
	struct value_defn to_send_expression=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn target_expression=getExpressionValue(assembled, &currentPoint, threadId);
	sendData(to_send_expression, getInt(target_expression.data), threadId, hostCoresBasePid);
#else
static int handleSend(char * assembled, int currentPoint) {
	struct value_defn to_send_expression=getExpressionValue(assembled, &currentPoint);
	struct value_defn target_expression=getExpressionValue(assembled, &currentPoint);
	sendData(to_send_expression, getInt(target_expression.data));
#endif
	return currentPoint;
}

/**
 * A reduction operation - collective communication between cores
 */
#ifdef HOST_INTERPRETER
static int handleReduction(char * assembled, int currentPoint, int threadId) {
#else
static int handleReduction(char * assembled, int currentPoint) {
#endif
	unsigned short reductionOperator=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn broadcast_expression=getExpressionValue(assembled, &currentPoint, threadId);
	variableSymbol->value=reduceData(broadcast_expression, reductionOperator, threadId, numActiveCores[threadId], hostCoresBasePid);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn broadcast_expression=getExpressionValue(assembled, &currentPoint);
	variableSymbol->value=reduceData(broadcast_expression, reductionOperator, numActiveCores);
#endif
	return currentPoint;
}

/**
 * Broadcast collective communication
 */
#ifdef HOST_INTERPRETER
static int handleBcast(char * assembled, int currentPoint, int threadId) {
#else
static int handleBcast(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn broadcast_expression=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn source_expression=getExpressionValue(assembled, &currentPoint, threadId);
	variableSymbol->value=bcastData(broadcast_expression, getInt(source_expression.data), threadId, numActiveCores[threadId], hostCoresBasePid);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn broadcast_expression=getExpressionValue(assembled, &currentPoint);
	struct value_defn source_expression=getExpressionValue(assembled, &currentPoint);
	variableSymbol->value=bcastData(broadcast_expression, getInt(source_expression.data), numActiveCores);
#endif
	return currentPoint;
}

/**
 * Receiving some data from another core
 */
#ifdef HOST_INTERPRETER
static int handleRecv(char * assembled, int currentPoint, int threadId) {
#else
static int handleRecv(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn source_expression=getExpressionValue(assembled, &currentPoint, threadId);
	variableSymbol->value=recvData(getInt(source_expression.data), threadId, hostCoresBasePid);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn source_expression=getExpressionValue(assembled, &currentPoint);
	variableSymbol->value=recvData(getInt(source_expression.data));
#endif
	return currentPoint;
}

/**
 * Receiving some data from another core and placing this into an array structure
 */
#ifdef HOST_INTERPRETER
static int handleRecvToArray(char * assembled, int currentPoint, int threadId) {
#else
static int handleRecvToArray(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn index=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn source_expression=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn retrievedData=recvData(getInt(source_expression.data), threadId, hostCoresBasePid);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn index=getExpressionValue(assembled, &currentPoint);
	struct value_defn source_expression=getExpressionValue(assembled, &currentPoint);
	struct value_defn retrievedData=recvData(getInt(source_expression.data));
#endif

	variableSymbol->value.type=retrievedData.type;
	char * ptr;
	cpy(&ptr, variableSymbol->value.data, sizeof(int*));
	cpy(ptr+(getInt(index.data) *4), retrievedData.data, 4);
	return currentPoint;
}

/**
 * Handles the sendrecv call, which does both P2P in one action with 1 synchronisation
 */
#ifdef HOST_INTERPRETER
static int handleSendRecv(char * assembled, int currentPoint, int threadId) {
#else
static int handleSendRecv(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn tosend_expression=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn target_expression=getExpressionValue(assembled, &currentPoint, threadId);
	variableSymbol->value=sendRecvData(tosend_expression, getInt(target_expression.data), threadId, hostCoresBasePid);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn tosend_expression=getExpressionValue(assembled, &currentPoint);
	struct value_defn target_expression=getExpressionValue(assembled, &currentPoint);
	variableSymbol->value=sendRecvData(tosend_expression, getInt(target_expression.data));
#endif
	return currentPoint;
}

/**
 * Handles the sendrecv call into an array, which does both P2P in one action with 1 synchronisation
 */
#ifdef HOST_INTERPRETER
static int handleSendRecvArray(char * assembled, int currentPoint, int threadId) {
#else
static int handleSendRecvArray(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn index=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn tosend_expression=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn target_expression=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn retrievedData=sendRecvData(tosend_expression, getInt(target_expression.data), threadId, hostCoresBasePid);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn index=getExpressionValue(assembled, &currentPoint);
	struct value_defn tosend_expression=getExpressionValue(assembled, &currentPoint);
	struct value_defn target_expression=getExpressionValue(assembled, &currentPoint);
	struct value_defn retrievedData=sendRecvData(tosend_expression, getInt(target_expression.data));
#endif

	variableSymbol->value.type=retrievedData.type;
	char * ptr;
	cpy(&ptr, variableSymbol->value.data, sizeof(int*));
	cpy(ptr+(getInt(index.data) *4), retrievedData.data, 4);
	return currentPoint;
}

/**
 * Goto some absolute location in the byte code
 */
#ifdef HOST_INTERPRETER
static int handleGoto(char * assembled, int currentPoint, int threadId) {
#else
static int handleGoto(char * assembled, int currentPoint) {
#endif
	return getUShort(&assembled[currentPoint]);
}

/**
 * Loop iteration
 */
#ifdef HOST_INTERPRETER
static int handleFor(char * assembled, int currentPoint, int threadId) {
#else
static int handleFor(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn to_expression=getExpressionValue(assembled, &currentPoint, threadId);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn to_expression=getExpressionValue(assembled, &currentPoint);
#endif
	unsigned short blockLen=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);

	if (getInt(variableSymbol->value.data) <= getInt(to_expression.data)) return currentPoint;
	currentPoint+=blockLen+sizeof(unsigned short)*2;
	return currentPoint;
}

/**
 * Conditional, with or without else block
 */
#ifdef HOST_INTERPRETER
static int handleIf(char * assembled, int currentPoint, int threadId) {
	int conditionalResult=determine_logical_expression(assembled, &currentPoint, threadId);
#else
static int handleIf(char * assembled, int currentPoint) {
	int conditionalResult=determine_logical_expression(assembled, &currentPoint);
#endif
	if (conditionalResult) return currentPoint+sizeof(unsigned short);
	unsigned short blockLen=getUShort(&assembled[currentPoint]);
	return currentPoint+sizeof(unsigned short)+blockLen;
}

/**
 * Input from user without string to display
 */
#ifdef HOST_INTERPRETER
static int handleInput(char * assembled, int currentPoint, int threadId) {
#else
static int handleInput(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	variableSymbol->value=getInputFromUser(threadId);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	variableSymbol->value=getInputFromUser();
#endif
	return currentPoint;
}

/**
 * Input from user with string to display
 */
#ifdef HOST_INTERPRETER
static int handleInputWithString(char * assembled, int currentPoint, int threadId) {
#else
static int handleInputWithString(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn string_display=getExpressionValue(assembled, &currentPoint, threadId);
	variableSymbol->value=getInputFromUserWithString(string_display, threadId);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn string_display=getExpressionValue(assembled, &currentPoint);
	variableSymbol->value=getInputFromUserWithString(string_display);
#endif
	return currentPoint;
}

/**
 * Print some value to the user
 */
#ifdef HOST_INTERPRETER
static int handlePrint(char * assembled, int currentPoint, int threadId) {
	struct value_defn result=getExpressionValue(assembled, &currentPoint, threadId);
	displayToUser(result, threadId);
#else
static int handlePrint(char * assembled, int currentPoint) {
	struct value_defn result=getExpressionValue(assembled, &currentPoint);
	displayToUser(result);
#endif
	return currentPoint;
}

/**
 * Declaration of an array and whether it is to be in default (core local) or shared memory
 */
#ifdef HOST_INTERPRETER
static int handleDimArray(char * assembled, int currentPoint, char inSharedMemory, int threadId) {
#else
static int handleDimArray(char * assembled, int currentPoint, char inSharedMemory) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn size=getExpressionValue(assembled, &currentPoint, threadId);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn size=getExpressionValue(assembled, &currentPoint);
#endif
	variableSymbol->value.type=INT_TYPE;
	int * address=getArrayAddress(getInt(size.data), inSharedMemory);
	cpy(variableSymbol->value.data, &address, sizeof(int*));
	return currentPoint;
}

/**
 * Set an individual element of an array
 */
#ifdef HOST_INTERPRETER
static int handleArraySet(char * assembled, int currentPoint, int threadId) {
#else
static int handleArraySet(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	struct value_defn index=getExpressionValue(assembled, &currentPoint, threadId);
	struct value_defn value=getExpressionValue(assembled, &currentPoint, threadId);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	struct value_defn index=getExpressionValue(assembled, &currentPoint);
	struct value_defn value=getExpressionValue(assembled, &currentPoint);
#endif
	variableSymbol->value.type=value.type;
	char * ptr;
	cpy(&ptr, variableSymbol->value.data, sizeof(int*));
	cpy(ptr+(getInt(index.data) *4), value.data, 4);
	return currentPoint;
}

/**
 * Set a scalar value (held in the symbol table)
 */
#ifdef HOST_INTERPRETER
static int handleLet(char * assembled, int currentPoint, int threadId) {
#else
static int handleLet(char * assembled, int currentPoint) {
#endif
	unsigned short varId=getUShort(&assembled[currentPoint]);
	currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
	struct symbol_node* variableSymbol=getVariableSymbol(varId, threadId);
	variableSymbol->value=getExpressionValue(assembled, &currentPoint, threadId);
#else
	struct symbol_node* variableSymbol=getVariableSymbol(varId);
	variableSymbol->value=getExpressionValue(assembled, &currentPoint);
#endif
	return currentPoint;
}

/**
 * Determines a logical expression based upon two operands and an operator
 */
#ifdef HOST_INTERPRETER
static int determine_logical_expression(char * assembled, int * currentPoint, int threadId) {
#else
static int determine_logical_expression(char * assembled, int * currentPoint) {
#endif
	unsigned short expressionId=getUShort(&assembled[*currentPoint]);
	*currentPoint+=sizeof(unsigned short);
	if (expressionId == AND_TOKEN || expressionId == OR_TOKEN) {
#ifdef HOST_INTERPRETER
		int s1=determine_logical_expression(assembled, currentPoint, threadId);
		int s2=determine_logical_expression(assembled, currentPoint, threadId);
#else
		int s1=determine_logical_expression(assembled, currentPoint);
		int s2=determine_logical_expression(assembled, currentPoint);
#endif
		if (expressionId == AND_TOKEN) return s1 && s2;
		if (expressionId == OR_TOKEN) return s1 || s2;
	} else if (expressionId == EQ_TOKEN || expressionId == NEQ_TOKEN || expressionId == GT_TOKEN || expressionId == GEQ_TOKEN ||
			expressionId == LT_TOKEN || expressionId == LEQ_TOKEN) {
#ifdef HOST_INTERPRETER
		struct value_defn expression1=getExpressionValue(assembled, currentPoint, threadId);
		struct value_defn expression2=getExpressionValue(assembled, currentPoint, threadId);
#else
		struct value_defn expression1=getExpressionValue(assembled, currentPoint);
		struct value_defn expression2=getExpressionValue(assembled, currentPoint);
#endif
		if (expression1.type == expression2.type && expression1.type == INT_TYPE) {
			int value1=getInt(expression1.data);
			int value2=getInt(expression2.data);
			if (expressionId == EQ_TOKEN) return value1 == value2;
			if (expressionId == NEQ_TOKEN) return value1 != value2;
			if (expressionId == GT_TOKEN) return value1 > value2;
			if (expressionId == GEQ_TOKEN) return value1 >= value2;
			if (expressionId == LT_TOKEN) return value1 < value2;
			if (expressionId == LEQ_TOKEN) return value1 <= value2;
		} else if ((expression1.type == REAL_TYPE || expression1.type == INT_TYPE) &&
				(expression2.type == REAL_TYPE || expression2.type == INT_TYPE)) {
			float value1=getFloat(expression1.data);
			float value2=getFloat(expression2.data);
			if (expression1.type==INT_TYPE) value1=(float) getInt(expression1.data);
			if (expression2.type==INT_TYPE) value2=(float) getInt(expression2.data);
			if (expressionId == EQ_TOKEN) return value1 == value2;
			if (expressionId == NEQ_TOKEN) return value1 != value2;
			if (expressionId == GT_TOKEN) return value1 > value2;
			if (expressionId == GEQ_TOKEN) return value1 >= value2;
			if (expressionId == LT_TOKEN) return value1 < value2;
			if (expressionId == LEQ_TOKEN) return value1 <= value2;
		} else if (expression1.type == expression2.type && expression1.type == STRING_TYPE) {
			if (expressionId == EQ_TOKEN) {
				return checkStringEquality(expression1, expression2);
			} else {
				raiseError("Can only test for equality with strings");
			}
		}
	} else if (expressionId == ISHOST_TOKEN) {
#ifdef HOST_INTERPRETER
		return 1;
#else
		return 0;
#endif
	} else if (expressionId == ISDEVICE_TOKEN) {
#ifdef HOST_INTERPRETER
		return 0;
#else
		return 1;
#endif
	}
	return 0;
}

/**
 * Gets the value of an expression, which is number, string, identifier or mathematical
 */
#ifdef HOST_INTERPRETER
static struct value_defn getExpressionValue(char * assembled, int * currentPoint, int threadId) {
#else
static struct value_defn getExpressionValue(char * assembled, int * currentPoint) {
#endif
	struct value_defn value;

	unsigned short expressionId=getUShort(&assembled[*currentPoint]);
	*currentPoint+=sizeof(unsigned short);
	if (expressionId == INTEGER_TOKEN) {
		value.type=INT_TYPE;
		cpy(value.data, &assembled[*currentPoint], sizeof(int));
		*currentPoint+=sizeof(int);
	} else if (expressionId == REAL_TOKEN) {
		value.type=REAL_TYPE;
		cpy(value.data, &assembled[*currentPoint], sizeof(float));
		*currentPoint+=sizeof(float);
	} else if (expressionId == STRING_TOKEN) {
		value.type=STRING_TYPE;
		char * strPtr=assembled + *currentPoint;
		cpy(&value.data, &strPtr, sizeof(char*));
		*currentPoint+=(slength(strPtr)+1);
	} else if (expressionId == COREID_TOKEN) {
		value.type=INT_TYPE;
#ifdef HOST_INTERPRETER
		cpy(value.data, &localCoreId[threadId], sizeof(int));
#else
		cpy(value.data, &localCoreId, sizeof(int));
#endif
	} else if (expressionId == NUMCORES_TOKEN) {
		value.type=INT_TYPE;
#ifdef HOST_INTERPRETER
		cpy(value.data, &numActiveCores[threadId], sizeof(int));
#else
		cpy(value.data, &numActiveCores, sizeof(int));
#endif
	} else if (expressionId == RANDOM_TOKEN) {
		value=performMathsOp(RANDOM_MATHS_OP, value);
	} else if (expressionId == MATHS_TOKEN) {
		unsigned short maths_op=getUShort(&assembled[*currentPoint]);
		*currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
		value=performMathsOp(maths_op, getExpressionValue(assembled, currentPoint, threadId));
#else
		value=performMathsOp(maths_op, getExpressionValue(assembled, currentPoint));
#endif
	} else if (expressionId == IDENTIFIER_TOKEN || expressionId == ARRAYACCESS_TOKEN) {
		unsigned short variable_id=getUShort(&assembled[*currentPoint]);
		*currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
		struct symbol_node* variableSymbol=getVariableSymbol(variable_id, threadId);
#else
		struct symbol_node* variableSymbol=getVariableSymbol(variable_id);
#endif
		value=variableSymbol->value;
		if (expressionId == ARRAYACCESS_TOKEN) {
#ifdef HOST_INTERPRETER
			struct value_defn index=getExpressionValue(assembled, currentPoint, threadId);
#else
			struct value_defn index=getExpressionValue(assembled, currentPoint);
#endif
			char * ptr;
			cpy(&ptr, variableSymbol->value.data, sizeof(int*));
			cpy(&value.data, ptr+(getInt(index.data) *4), sizeof(int));
		}
	} else if (expressionId == ADD_TOKEN || expressionId == SUB_TOKEN || expressionId == MUL_TOKEN ||
			expressionId == DIV_TOKEN || expressionId == MOD_TOKEN || expressionId == POW_TOKEN) {
#ifdef HOST_INTERPRETER
		value=computeExpressionResult(expressionId, assembled, currentPoint, threadId);
#else
		value=computeExpressionResult(expressionId, assembled, currentPoint);
#endif
	}
	return value;
}

/**
 * Computes the result of a simple mathematical expression, if one is a real and the other an integer
 * then raises to be a real
 */
#ifdef HOST_INTERPRETER
static struct value_defn computeExpressionResult(unsigned short operator, char * assembled, int * currentPoint, int threadId) {
#else
static struct value_defn computeExpressionResult(unsigned short operator, char * assembled, int * currentPoint) {
#endif
	struct value_defn value;
#ifdef HOST_INTERPRETER
	struct value_defn v1=getExpressionValue(assembled, currentPoint, threadId);
	struct value_defn v2=getExpressionValue(assembled, currentPoint, threadId);
#else
	struct value_defn v1=getExpressionValue(assembled, currentPoint);
	struct value_defn v2=getExpressionValue(assembled, currentPoint);
#endif
	value.type=v1.type==INT_TYPE && v2.type==INT_TYPE ? INT_TYPE : v1.type==STRING_TYPE || v2.type==STRING_TYPE ? STRING_TYPE : REAL_TYPE;
	if (value.type==INT_TYPE) {
		int i, value1=getInt(v1.data), value2=getInt(v2.data), result;
		if (operator==ADD_TOKEN) result=value1+value2;
		if (operator==SUB_TOKEN) result=value1-value2;
		if (operator==MUL_TOKEN) result=value1*value2;
		if (operator==DIV_TOKEN) result=value1/value2;
		if (operator==MOD_TOKEN) result=value1%value2;
		if (operator==POW_TOKEN) {
			result=value1;
			for (i=1;i<value2;i++) result=result*value1;
		}
		cpy(&value.data, &result, sizeof(int));
	} else if (value.type==REAL_TYPE) {
		float value1=getFloat(v1.data);
		float value2=getFloat(v2.data);
		float result;
		if (v1.type==INT_TYPE) value1=(float) getInt(v1.data);
		if (v2.type==INT_TYPE) {
			value2=(float) getInt(v2.data);
			if (operator == POW_TOKEN) {
				int i;
				result=value1;
				for (i=1;i<(int) value2;i++) result=result*value1;
			}
		}
		if (operator == ADD_TOKEN) result=value1+value2;
		if (operator == SUB_TOKEN) result=value1-value2;
		if (operator == MUL_TOKEN) result=value1*value2;
		if (operator == DIV_TOKEN) result=value1/value2;
		cpy(&value.data, &result, sizeof(float));
	} else if (value.type==STRING_TYPE) {
		if (operator == ADD_TOKEN) {
			return performStringConcatenation(v1, v2);
		} else {
			raiseError("Can only perform addition with strings");
		}
	}
	return value;
}

/**
 * Retrieves the symbol entry of a variable based upon its id
 */
#ifdef HOST_INTERPRETER
static struct symbol_node* getVariableSymbol(unsigned short id, int threadId) {
#else
static struct symbol_node* getVariableSymbol(unsigned short id) {
#endif
	int i;
#ifdef HOST_INTERPRETER
	for (i=0;i<currentSymbolEntries[threadId];i++) {
		if (symbolTable[threadId][i].id == id) return &(symbolTable[threadId])[i];
#else
	for (i=0;i<currentSymbolEntries;i++) {
		if (symbolTable[i].id == id) return &symbolTable[i];
#endif
	}
	int zero=0;
#ifdef HOST_INTERPRETER
	symbolTable[threadId][currentSymbolEntries[threadId]].id=id;
	symbolTable[threadId][currentSymbolEntries[threadId]].value.type=INT_TYPE;
	cpy(symbolTable[threadId][currentSymbolEntries[threadId]].value.data, &zero, sizeof(int));
	return &symbolTable[threadId][currentSymbolEntries[threadId]++];
#else
	symbolTable[currentSymbolEntries].id=id;
	symbolTable[currentSymbolEntries].value.type=INT_TYPE;
	cpy(symbolTable[currentSymbolEntries].value.data, &zero, sizeof(int));
	return &symbolTable[currentSymbolEntries++];
#endif
}

/**
 * Helper method to get an integer from data (needed as casting to integer directly requires 4 byte alignment which we
 * do not want to enforce as it wastes memory.)
 */
static int getInt(void* data) {
	int v;
	cpy(&v, data, sizeof(int));
	return v;
}

/**
 * Helper method to get a float from data (needed as casting to integer directly requires 4 byte alignment which we
 * do not want to enforce as it wastes memory.)
 */
static float getFloat(void* data) {
	float v;
	cpy(&v, data, sizeof(float));
	return v;
}

/**
 * Helper method to get an unsigned short from data (needed as casting to integer directly requires 4 byte alignment
 * which we do not want to enforce as it wastes memory.)
 */
static unsigned short getUShort(void* data) {
	unsigned short v;
	cpy(&v, data, sizeof(unsigned short));
	return v;
}
Ejemplo n.º 2
0
static struct value_defn getExpressionValue(char * assembled, unsigned int * currentPoint, unsigned int length, int threadId) {
#else
static struct value_defn getExpressionValue(char * assembled, unsigned int * currentPoint, unsigned int length) {
#endif
    struct value_defn value;

    unsigned char expressionId=getUChar(&assembled[*currentPoint]);
    *currentPoint+=sizeof(unsigned char);
    if (expressionId == INTEGER_TOKEN) {
        value.type=INT_TYPE;
        value.dtype=SCALAR;
        cpy(value.data, &assembled[*currentPoint], sizeof(int));
        *currentPoint+=sizeof(int);
    } else if (expressionId == REAL_TOKEN) {
        value.type=REAL_TYPE;
        value.dtype=SCALAR;
        cpy(value.data, &assembled[*currentPoint], sizeof(float));
        *currentPoint+=sizeof(float);
    } else if (expressionId == BOOLEAN_TOKEN) {
        value.type=BOOLEAN_TYPE;
        value.dtype=SCALAR;
        cpy(value.data, &assembled[*currentPoint], sizeof(int));
        *currentPoint+=sizeof(int);
    } else if (expressionId == STRING_TOKEN) {
        value.type=STRING_TYPE;
        char * strPtr=assembled + *currentPoint;
        cpy(&value.data, &strPtr, sizeof(char*));
        *currentPoint+=(slength(strPtr)+1);
        value.dtype=SCALAR;
    } else if (expressionId == NONE_TOKEN) {
        value.type=NONE_TYPE;
        value.dtype=SCALAR;
    } else if (expressionId ==FN_ADDR_TOKEN) {
        value.type=FN_ADDR_TYPE;
        value.dtype=SCALAR;
        cpy(value.data, &assembled[*currentPoint], sizeof(unsigned short));
        *currentPoint+=sizeof(unsigned short);
    } else if (expressionId == LET_TOKEN) {
#ifdef HOST_INTERPRETER
        *currentPoint=handleLet(assembled, *currentPoint, length, 0, threadId);
        value=getExpressionValue(assembled, currentPoint, length, threadId);
#else
        *currentPoint=handleLet(assembled, *currentPoint, length, 0);
        value=getExpressionValue(assembled, currentPoint, length);
#endif
    } else if (expressionId == ARRAY_TOKEN) {
        int i, j, repetitionMultiplier=1, numItems=getInt(&assembled[*currentPoint]), totalSize=numItems;
        *currentPoint+=sizeof(int);
        unsigned char hasRepetition=getUChar(&assembled[*currentPoint]), ndims=1;
        *currentPoint+=sizeof(unsigned char);
        if (hasRepetition) {
#ifdef HOST_INTERPRETER
            struct value_defn repetitionV=getExpressionValue(assembled, currentPoint, length, threadId);
#else
            struct value_defn repetitionV=getExpressionValue(assembled, currentPoint, length);
#endif
            cpy(&repetitionMultiplier, repetitionV.data, sizeof(int));
            totalSize*=repetitionMultiplier;
        }
#ifdef HOST_INTERPRETER
        char * address=getHeapMemory(sizeof(unsigned char) + (sizeof(int)*(totalSize+1)), 0, threadId);
#else
        char * address=getHeapMemory(sizeof(unsigned char) + (sizeof(int)*(totalSize+1)), 0, currentSymbolEntries, symbolTable);
#endif
        cpy(value.data, &address, sizeof(char*));
        ndims=ndims | (1 << 4);
        cpy(address, &ndims, sizeof(unsigned char));
        address+=sizeof(unsigned char);
        cpy(address, &totalSize, sizeof(int));
        unsigned int prevCP=*currentPoint;
        for (j=0; j<repetitionMultiplier; j++) {
            *currentPoint=prevCP;
            for (i=0; i<numItems; i++) {
#ifdef HOST_INTERPRETER
                struct value_defn itemV=getExpressionValue(assembled, currentPoint, length, threadId);
#else
                struct value_defn itemV=getExpressionValue(assembled, currentPoint, length);
#endif
                cpy(address+((i+(j*numItems)+1) * sizeof(int)), itemV.data, sizeof(int));
                value.type=itemV.type;
            }
        }
        value.dtype=ARRAY;
    } else if (expressionId == FNCALL_TOKEN || expressionId == FNCALL_BY_VAR_TOKEN) {
#ifdef HOST_INTERPRETER
        unsigned int fnAddr;
        *currentPoint=handleFnCall(assembled, *currentPoint, &fnAddr, length, expressionId == FNCALL_BY_VAR_TOKEN ? 1:0, threadId);
        fnLevel[threadId]++;
        value=processAssembledCode(assembled, fnAddr, length, threadId);
        clearVariablesToLevel(fnLevel[threadId], threadId);
        fnLevel[threadId]--;
#else
        unsigned int fnAddr;
        *currentPoint=handleFnCall(assembled, *currentPoint, &fnAddr, length, expressionId == FNCALL_BY_VAR_TOKEN ? 1:0);
        fnLevel++;
        value=processAssembledCode(assembled, fnAddr, length);
        clearVariablesToLevel(fnLevel);
        fnLevel--;
#endif
    } else if (expressionId == NATIVE_TOKEN) {
#ifdef HOST_INTERPRETER
        *currentPoint=handleNative(assembled, *currentPoint, length, &value, threadId);
#else
        *currentPoint=handleNative(assembled, *currentPoint, length, &value);
#endif
    } else if (expressionId == IDENTIFIER_TOKEN || expressionId == ARRAYACCESS_TOKEN) {
        unsigned short variable_id=getUShort(&assembled[*currentPoint]);
        *currentPoint+=sizeof(unsigned short);
#ifdef HOST_INTERPRETER
        struct symbol_node* variableSymbol=getVariableSymbol(variable_id, fnLevel[threadId], threadId, 1);
#else
        struct symbol_node* variableSymbol=getVariableSymbol(variable_id, fnLevel, 1);
#endif
        if (expressionId == IDENTIFIER_TOKEN) {
            if (variableSymbol->value.dtype==SCALAR) {
                value=getVariableValue(variableSymbol, -1);
            } else if (variableSymbol->value.dtype==ARRAY) {
                value.dtype=ARRAY;
                value.type=variableSymbol->value.type;
                cpy(value.data, variableSymbol->value.data, sizeof(char*));
            }
        } else if (expressionId == ARRAYACCESS_TOKEN) {
#ifdef HOST_INTERPRETER
            int targetIndex=getArrayAccessorIndex(variableSymbol, assembled, currentPoint, length, threadId);
#else
            int targetIndex=getArrayAccessorIndex(variableSymbol, assembled, currentPoint, length);
#endif
            value=getVariableValue(variableSymbol, targetIndex);
        }
    } else if (expressionId == ADD_TOKEN || expressionId == SUB_TOKEN || expressionId == MUL_TOKEN ||
               expressionId == DIV_TOKEN || expressionId == MOD_TOKEN || expressionId == POW_TOKEN) {
#ifdef HOST_INTERPRETER
        value=computeExpressionResult(expressionId, assembled, currentPoint, length, threadId);
#else
        value=computeExpressionResult(expressionId, assembled, currentPoint, length);
#endif
    } else if (expressionId == EQ_TOKEN || expressionId == NEQ_TOKEN || expressionId == GT_TOKEN || expressionId == GEQ_TOKEN ||
               expressionId == LT_TOKEN || expressionId == LEQ_TOKEN || expressionId == IS_TOKEN) {
        *currentPoint-=sizeof(unsigned char);
#ifdef HOST_INTERPRETER
        int retVal=determine_logical_expression(assembled, currentPoint, length, threadId);
#else
        int retVal=determine_logical_expression(assembled, currentPoint, length);
#endif
        value.type=BOOLEAN_TYPE;
        value.dtype=SCALAR;
        cpy(value.data, &retVal, sizeof(int));
    }
    return value;
}

/**
 * Computes the result of a simple mathematical expression, if one is a real and the other an integer
 * then raises to be a real
 */
#ifdef HOST_INTERPRETER
static struct value_defn computeExpressionResult(unsigned char operator, char * assembled, unsigned int * currentPoint,
        unsigned int length, int threadId) {
#else
static struct value_defn computeExpressionResult(unsigned char operator, char * assembled, unsigned int * currentPoint,
        unsigned int length) {
#endif
    struct value_defn value;
#ifdef HOST_INTERPRETER
    struct value_defn v1=getExpressionValue(assembled, currentPoint, length, threadId);
    struct value_defn v2=getExpressionValue(assembled, currentPoint, length, threadId);
#else
    struct value_defn v1=getExpressionValue(assembled, currentPoint, length);
    struct value_defn v2=getExpressionValue(assembled, currentPoint, length);
#endif
    value.type=v1.type==INT_TYPE && v2.type==INT_TYPE ? INT_TYPE : v1.type==STRING_TYPE || v2.type==STRING_TYPE ? STRING_TYPE : REAL_TYPE;
    value.dtype=SCALAR;
    if (value.type==INT_TYPE) {
        int i, value1=getInt(v1.data), value2=getInt(v2.data), result;
        if (operator==ADD_TOKEN) result=value1+value2;
        if (operator==SUB_TOKEN) result=value1-value2;
        if (operator==MUL_TOKEN) result=value1*value2;
        if (operator==DIV_TOKEN) result=value1/value2;
        if (operator==MOD_TOKEN) result=value1%value2;
        if (operator==POW_TOKEN) {
            result=value2 == 0 ? 1 : value1;
            for (i=1; i<value2; i++) result=result*value1;
        }
        cpy(&value.data, &result, sizeof(int));
    } else if (value.type==REAL_TYPE) {
        float value1=getFloat(v1.data);
        float value2=getFloat(v2.data);
        float result;
        if (v1.type==INT_TYPE) value1=(float) getInt(v1.data);
        if (v2.type==INT_TYPE) {
            value2=(float) getInt(v2.data);
            if (operator == POW_TOKEN) {
                int i;
                result=value2 == 0 ? 1 : value1;
                for (i=1; i<(int) value2; i++) result=result*value1;
            }
        }
        if (operator == ADD_TOKEN) result=value1+value2;
        if (operator == SUB_TOKEN) result=value1-value2;
        if (operator == MUL_TOKEN) result=value1*value2;
        if (operator == DIV_TOKEN) result=value1/value2;
        cpy(&value.data, &result, sizeof(float));
    } else if (value.type==STRING_TYPE) {
        if (operator == ADD_TOKEN) {
#ifdef HOST_INTERPRETER
            return performStringConcatenation(v1, v2, threadId);
#else
            return performStringConcatenation(v1, v2, currentSymbolEntries, symbolTable);
#endif
        } else {
            raiseError(ERR_ONLY_ADDITION_STR);
        }
    }
    return value;
}

/**
 * Retrieves the absolute array target index based upon the provided index expression(s) and dimensions of the array itself. Does some error checking
 * to ensure that the configured values do not exceed the size
 */
#ifdef HOST_INTERPRETER
static int getArrayAccessorIndex(struct symbol_node* variableSymbol, char * assembled, unsigned int * currentPoint, unsigned int length, int threadId) {
#else
static int getArrayAccessorIndex(struct symbol_node* variableSymbol, char * assembled, unsigned int * currentPoint, unsigned int length) {
#endif
    struct value_defn index;
    int i, j, runningWeight, spec_weight, num_weights, specificIndex=0, provIdx;
    unsigned int totSize=1;
    unsigned char num_dims=getUChar(&assembled[*currentPoint]), array_dims, needsExtension=0, allowedExtension;
    *currentPoint+=sizeof(unsigned char);

    char * arraymemory;
    cpy(&arraymemory, variableSymbol->value.data, sizeof(char*));
    cpy(&array_dims, arraymemory, sizeof(unsigned char));
    allowedExtension=(array_dims >> 4) & 1;
    array_dims=array_dims&0xF;
    arraymemory+=sizeof(unsigned char);

    if (num_dims > array_dims) raiseError(ERR_TOO_MANY_ARR_INDEX);

    for (i=0; i<num_dims; i++) {
        num_weights=array_dims-(i+1);
        runningWeight=1;
        for (j=num_weights; j<0; j--) {
            cpy(&spec_weight, &arraymemory[sizeof(int) * (array_dims-j)], sizeof(int));
            runningWeight*=spec_weight;
        }
#ifdef HOST_INTERPRETER
        index=getExpressionValue(assembled, currentPoint, length, threadId);
#else
        index=getExpressionValue(assembled, currentPoint, length);
#endif
        cpy(&spec_weight, &arraymemory[sizeof(int) * i], sizeof(int));
        totSize*=spec_weight;
        provIdx=getInt(index.data);
        if (provIdx < 0) {
            raiseError(ERR_NEG_ARR_INDEX);
        } else if (provIdx >= spec_weight) {
            if (!allowedExtension) raiseError(ERR_ARR_INDEX_EXCEED_SIZE);
            spec_weight=provIdx+1;
            cpy(&arraymemory[sizeof(int) * i], &spec_weight, sizeof(int));
            needsExtension=1;
        }
        specificIndex+=(runningWeight * provIdx);
    }
    if (needsExtension) {
        unsigned int newSize=1;
        for (i=0; i<num_dims; i++) {
            cpy(&spec_weight, &arraymemory[sizeof(int) * i], sizeof(int));
            newSize*=spec_weight;
        }
#ifdef HOST_INTERPRETER
        char * newmem=getHeapMemory((sizeof(int) * newSize) + (sizeof(int) * num_dims) + sizeof(unsigned char), 0, threadId);
#else
        char * newmem=getHeapMemory((sizeof(int) * newSize) + (sizeof(int) * num_dims) + sizeof(unsigned char), 0, currentSymbolEntries, symbolTable);
#endif
        arraymemory-=sizeof(unsigned char);
        cpy(newmem, arraymemory, (sizeof(int) * totSize) + (sizeof(int) * num_dims) + sizeof(unsigned char));
#ifdef HOST_INTERPRETER
        freeMemoryInHeap(arraymemory, threadId);
#else
        freeMemoryInHeap(arraymemory);
#endif
        cpy(variableSymbol->value.data, &newmem, sizeof(char*));
    }
    return specificIndex;
}

/**
 * Retrieves the symbol entry of a variable based upon its id
 */
#ifdef HOST_INTERPRETER
static struct symbol_node* getVariableSymbol(unsigned short id, unsigned char lvl, int threadId, int followAlias) {
#else
static struct symbol_node* getVariableSymbol(unsigned short id, unsigned char lvl, int followAlias) {
#endif
    int i;
#ifdef HOST_INTERPRETER
    for (i=0; i<=currentSymbolEntries[threadId]; i++) {
        if (symbolTable[threadId][i].id == id && symbolTable[threadId][i].state != UNALLOCATED && (symbolTable[threadId][i].level == 0 || symbolTable[threadId][i].level==lvl)) {
            if (followAlias && symbolTable[threadId][i].state == ALIAS) {
                return getVariableSymbol(symbolTable[threadId][i].alias, lvl-1, threadId, 1);
            } else {
                return &(symbolTable[threadId])[i];
            }
        }
#else
    for (i=0; i<=currentSymbolEntries; i++) {
        if (symbolTable[i].id == id && symbolTable[i].state != UNALLOCATED && (symbolTable[i].level == 0 || symbolTable[i].level==lvl)) {
            if (followAlias && symbolTable[i].state == ALIAS) {
                return getVariableSymbol(symbolTable[i].alias, lvl-1, 1);
            } else {
                return &symbolTable[i];
            }
        }
#endif
    }
    int zero=0;
#ifdef HOST_INTERPRETER
    int newEntryLocation=getSymbolTableEntryId(threadId);
    symbolTable[threadId][newEntryLocation].id=id;
    symbolTable[threadId][newEntryLocation].state=ALLOCATED;
    symbolTable[threadId][newEntryLocation].level=lvl;
    symbolTable[threadId][newEntryLocation].value.type=INT_TYPE;
    cpy(symbolTable[threadId][newEntryLocation].value.data, &zero, sizeof(int));
    return &symbolTable[threadId][newEntryLocation];
#else
    int newEntryLocation=getSymbolTableEntryId();
    symbolTable[newEntryLocation].id=id;
    symbolTable[newEntryLocation].level=lvl;
    symbolTable[newEntryLocation].state=ALLOCATED;
    symbolTable[newEntryLocation].value.type=INT_TYPE;
    symbolTable[newEntryLocation].value.dtype=SCALAR;
    cpy(symbolTable[newEntryLocation].value.data, &zero, sizeof(int));
    return &symbolTable[newEntryLocation];
#endif
}
#ifdef HOST_INTERPRETER
static int getSymbolTableEntryId(int threadId) {
#else
static int getSymbolTableEntryId(void) {
#endif
    int i;
#ifdef HOST_INTERPRETER
    for (i=0; i<=currentSymbolEntries[threadId]; i++) {
        if (symbolTable[threadId][i].state == UNALLOCATED) return i;
    }
    return ++currentSymbolEntries[threadId];
#else
    for (i=0; i<=currentSymbolEntries; i++) {
        if (symbolTable[i].state == UNALLOCATED) return i;
    }
    return ++currentSymbolEntries;
#endif
}

#ifdef HOST_INTERPRETER
static void clearVariablesToLevel(unsigned char clearLevel, int threadId) {
#else
static void clearVariablesToLevel(unsigned char clearLevel) {
#endif
    int i;
    char * smallestMemoryAddress=0, *ptr;
#ifdef HOST_INTERPRETER
    for (i=0; i<=currentSymbolEntries[threadId]; i++) {
        if (symbolTable[threadId][i].level >= clearLevel && symbolTable[threadId][i].state != UNALLOCATED) {
            symbolTable[threadId][i].state=UNALLOCATED;
            if (symbolTable[threadId][i].value.dtype==SCALAR && symbolTable[threadId][i].value.type != STRING_TYPE) {
                cpy(&ptr, symbolTable[threadId][i].value.data, sizeof(int*));
                if (ptr != 0 && (smallestMemoryAddress == 0 || smallestMemoryAddress > ptr)) smallestMemoryAddress=ptr;
            }
        }
    }
#else
    for (i=0; i<=currentSymbolEntries; i++) {
        if (symbolTable[i].level >= clearLevel && symbolTable[i].state != UNALLOCATED) {
            symbolTable[i].state=UNALLOCATED;
            if (symbolTable[i].value.dtype==SCALAR && symbolTable[i].value.type != STRING_TYPE) {
                cpy(&ptr, symbolTable[i].value.data, sizeof(char*));
                if (ptr != 0 && (smallestMemoryAddress == 0 || smallestMemoryAddress > ptr)) smallestMemoryAddress=ptr;
            }
        }
    }
#endif
    if (smallestMemoryAddress != 0) clearFreedStackFrames(smallestMemoryAddress);
}

/**
 * Sets a variables value in memory as pointed to by symbol table
 */
void setVariableValue(struct symbol_node* variableSymbol, struct value_defn value, int index) {
    variableSymbol->value.type=value.type;
    if (value.type == STRING_TYPE) {
        cpy(&variableSymbol->value.data, &value.data, sizeof(char*));
    } else {
        int currentAddress=getInt(variableSymbol->value.data);
        if (currentAddress == 0) {
            char * address=getStackMemory(sizeof(int) * index, 0);
            cpy(variableSymbol->value.data, &address, sizeof(char*));
            cpy(address+((index+1) *4), value.data, sizeof(int));
        } else {
            char * ptr;
            cpy(&ptr, variableSymbol->value.data, sizeof(char*));
            if (variableSymbol->value.dtype == ARRAY) {
                unsigned char num_dims;
                cpy(&num_dims, ptr, sizeof(unsigned char));
                num_dims=num_dims & 0xF;
                ptr+=((index+num_dims)*sizeof(int)) + sizeof(unsigned char);
            } else {
                ptr+=(index+1)*sizeof(int);
            }
            cpy(ptr, value.data, sizeof(int));
        }
    }
}

/**
 * Retrieves a variable value from memory, which the symbol table points to
 */
struct value_defn getVariableValue(struct symbol_node* variableSymbol, int index) {
    struct value_defn val;
    val.type=variableSymbol->value.type;
    val.dtype=SCALAR;
    if (variableSymbol->value.type == STRING_TYPE) {
        cpy(&val.data, &variableSymbol->value.data, sizeof(int*));
    } else {
        char * ptr;
        cpy(&ptr, variableSymbol->value.data, sizeof(char*));
        if (variableSymbol->value.dtype == ARRAY) {
            unsigned char num_dims;
            cpy(&num_dims, ptr, sizeof(unsigned char));
            num_dims=num_dims & 0xF;
            ptr+=((index+num_dims)*sizeof(int)) + sizeof(unsigned char);
        } else {
            ptr+=(index+1)*sizeof(int);
        }
        cpy(val.data, ptr, sizeof(char*));
    }
    return val;
}

static unsigned char getUChar(void* data) {
    unsigned char v;
    cpy(&v, data, sizeof(unsigned char));
    return v;
}

/**
 * Helper method to get an unsigned short from data (needed as casting to integer directly requires 4 byte alignment
 * which we do not want to enforce as it wastes memory.)
 */
static unsigned short getUShort(void* data) {
    unsigned short v;
    cpy(&v, data, sizeof(unsigned short));
    return v;
}