Beispiel #1
0
void LuaStack::pushLuaValue(const LuaValue& value)
{
    const LuaValueType type = value.getType();
    if (type == LuaValueTypeInt)
    {
        return pushInt(value.intValue());
    }
    else if (type == LuaValueTypeFloat)
    {
        return pushFloat(value.floatValue());
    }
    else if (type == LuaValueTypeBoolean)
    {
        return pushBoolean(value.booleanValue());
    }
    else if (type == LuaValueTypeString)
    {
        return pushString(value.stringValue().c_str());
    }
    else if (type == LuaValueTypeDict)
    {
        pushLuaValueDict(value.dictValue());
    }
    else if (type == LuaValueTypeArray)
    {
        pushLuaValueArray(value.arrayValue());
    }
    else if (type == LuaValueTypeObject)
    {
        pushObject(value.ccobjectValue(), value.getObjectTypename().c_str());
    }
}
Beispiel #2
0
primitiveDotProduct(void)
{
    sqInt arg;
    float *argPtr;
    sqInt i;
    sqInt length;
    sqInt rcvr;
    float *rcvrPtr;
    double result;

	arg = stackValue(0);
	rcvr = stackValue(1);
	if (!((isWords(arg))
		 && ((isWords(rcvr))
		 && (((length = stSizeOf(arg))) == (stSizeOf(rcvr)))))) {
		return primitiveFail();
	}
	rcvrPtr = ((float *) (firstIndexableField(rcvr)));
	argPtr = ((float *) (firstIndexableField(arg)));
	result = 0.0;
	for (i = 0; i < length; i += 1) {
		result += (((double) (rcvrPtr[i]))) * (((double) (argPtr[i])));
	}
	pop(2);
	pushFloat(result);
	return 0;
}
Beispiel #3
0
int CCLuaEngine::pushCCLuaValue(const CCLuaValue& value)
{
    const CCLuaValueType type = value.getType();
    if (type == CCLuaValueTypeInt)
    {
        return pushInt(value.intValue());
    }
    else if (type == CCLuaValueTypeFloat)
    {
        return pushFloat(value.floatValue());
    }
    else if (type == CCLuaValueTypeBoolean)
    {
        return pushBoolean(value.booleanValue());
    }
    else if (type == CCLuaValueTypeString)
    {
        return pushString(value.stringValue().c_str());
    }
    else if (type == CCLuaValueTypeDict)
    {
        pushCCLuaValueDict(value.dictValue());
    }
    else if (type == CCLuaValueTypeArray)
    {
        pushCCLuaValueArray(value.arrayValue());
    }
    else if (type == CCLuaValueTypeCCObject)
    {
        pushCCObject(value.ccobjectValue(), value.getCCObjectTypename().c_str());
    }
    
    return lua_gettop(m_state);
}
Beispiel #4
0
void Stack::pushVariable(const Variable &var) {
	switch (var.getType()) {
		case kTypeNil:
			pushNil();
			break;
		case kTypeBoolean:
			pushBoolean(var.getBool());
			break;
		case kTypeNumber:
			pushFloat(var.getFloat());
			break;
		case kTypeString:
			pushString(var.getString());
			break;
		case kTypeTable:
			pushTable(var.getTable());
			break;
		case kTypeFunction:
			pushFunction(var.getFunction());
			break;
		case kTypeUserType:
			pushRawUserType(var.getRawUserType(), var.getExactType());
			break;
		default:
			warning("Pushing a varible of type \"%s\" not supported",
			        var.getExactType().c_str());
			break;
	}
}
primitiveDotProduct(void)
{
	// FloatArrayPlugin>>#primitiveDotProduct
    sqInt arg;
    float *argPtr;
    sqInt i;
    sqInt length;
    sqInt rcvr;
    float *rcvrPtr;
    double  result;

	arg = stackObjectValue(0);
	rcvr = stackObjectValue(1);
	if (failed()) {
		return null;
	}
	success(isWords(arg));
	success(isWords(rcvr));
	if (failed()) {
		return null;
	}
	length = stSizeOf(arg);
	success(length == (stSizeOf(rcvr)));
	if (failed()) {
		return null;
	}
	rcvrPtr = ((float *) (firstIndexableField(rcvr)));
	argPtr = ((float *) (firstIndexableField(arg)));
	result = 0.0;
	for (i = 0; i <= (length - 1); i += 1) {
		result += (((double) (rcvrPtr[i]))) * (((double) (argPtr[i])));
	}
	pop(2);
	pushFloat(result);
}
Beispiel #6
0
int Viewport::pushValueToLua(CXLUAFUNC handler,const float value)
{
    int ret = -1;
    if (0 == handler) {
        return ret;
    }
    auto stack = LuaEngine::getInstance()->getLuaStack();

    stack->pushFloat(value);
    ret = stack->executeFunctionByHandler(handler, 1);
    stack->clean();
    return ret;
}
Beispiel #7
0
int CCLuaEngine::executeSchedule(CCTimer* pTimer, float dt, CCNode* pNode/* = NULL*/)
{
    int ret = 0;
    do 
    {
        int nScriptHandler = pTimer->getScriptHandler();
        CC_BREAK_IF(0 == nScriptHandler);

        cleanStack();
        pushFloat(dt);
        ret = executeFunctionByHandler(nScriptHandler, 1);
    } while (0);
    return ret;
}
primitiveTanH(void)
{
	// FloatMathPlugin>>#primitiveTanH
    double rcvr;
    double result;

	rcvr = stackFloatValue(0);
	if (failed()) {
		return null;
	}
	result = __ieee754_tanh(rcvr);
	if (isnan(result)) {
		return primitiveFail();
	}
	pop((methodArgumentCount()) + 1);
	pushFloat(result);
}
primitiveFractionalPart(void)
{
	// FloatMathPlugin>>#primitiveFractionalPart
    double rcvr;
    double result;
    double trunc;

	rcvr = stackFloatValue(0);
	if (failed()) {
		return null;
	}
	result = __ieee754_modf(rcvr, &trunc);
	if (isnan(result)) {
		return primitiveFail();
	}
	pop((methodArgumentCount()) + 1);
	pushFloat(result);
}
primitiveTimesTwoPower(void)
{
	// FloatMathPlugin>>#primitiveTimesTwoPower
    sqInt arg;
    double rcvr;
    double result;

	arg = stackIntegerValue(0);
	rcvr = stackFloatValue(1);
	if (failed()) {
		return null;
	}
	result = __ieee754_ldexp(rcvr, arg);
	if (isnan(result)) {
		return primitiveFail();
	}
	pop((methodArgumentCount()) + 1);
	pushFloat(result);
}
primitiveRaisedToPower(void)
{
	// FloatMathPlugin>>#primitiveRaisedToPower
    double arg;
    double rcvr;
    double result;

	arg = stackFloatValue(0);
	rcvr = stackFloatValue(1);
	if (failed()) {
		return null;
	}
	result = __ieee754_pow(rcvr, arg);
	if (isnan(result)) {
		return primitiveFail();
	}
	pop((methodArgumentCount()) + 1);
	pushFloat(result);
}
Beispiel #12
0
primitiveAt(void)
{
    float *floatPtr;
    double floatValue;
    sqInt index;
    sqInt rcvr;

	index = stackIntegerValue(0);
	rcvr = stackValue(1);
	if (!((!(failed()))
		 && ((isWords(rcvr))
		 && ((index > 0)
		 && (index <= (slotSizeOf(rcvr))))))) {
		return primitiveFail();
	}
	floatPtr = firstIndexableField(rcvr);
	floatValue = ((double) (floatPtr[index - 1]) );
	pop(2);
	pushFloat(floatValue);
	return 0;
}
primitiveAt(void)
{
	// FloatArrayPlugin>>#primitiveAt
    float *floatPtr;
    double  floatValue;
    sqInt index;
    sqInt rcvr;

	index = stackIntegerValue(0);
	rcvr = stackObjectValue(1);
	if (failed()) {
		return null;
	}
	success(isWords(rcvr));
	success((index > 0)
	 && (index <= (slotSizeOf(rcvr))));
	if (failed()) {
		return null;
	}
	floatPtr = firstIndexableField(rcvr);
	floatValue = ((double) (floatPtr[index - 1]) );
	pop(2);
	pushFloat(floatValue);
}
Beispiel #14
0
void Operators::doOperator(Context *context, OperatorType oper) {
	Token token1, token2, token3;
	stutskFloat f1, f2;
	stutskInteger i1, i2;
	string s1, s2;

	switch (oper) {
	case OP_ASSIG:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Variable
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Value
		setVariable(token1, token2); 
		break;
	case OP_ASSIG_REF:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Variable
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Value
		setVariable(token1, token2, true); 
		break;
	case OP_FUNC:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Name
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		recurseVariables(token2);
		if (token2.tokenType != T_CODEBLOCK) {
			throw StutskException(ET_ERROR, "Token is not a codeblock");
		}
		else {
			OperatorType dummy;
			string functionName = *giveString(token1);
			if (readOperator(functionName, dummy))
				throw StutskException(ET_ERROR, "Cannot override an operator");
			if (functionName.substr(0,10) == "__builtin_")
				throw StutskException(ET_ERROR, "Cannot override an internal function");
			userFunctions[functionName] = *token2.asTokenList;
		}

		break;
	case OP_UNSET:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		if (token1.tokenType == T_VARIABLE) {
			struct Token::_un_TokenData::_un_VariableData *var = & token1.data.asVariable;
			TokenMap::iterator iter = var->context->variables.find(var->name);
			if (iter != var->context->variables.end())
				var->context->variables.erase(iter);
		}
		else {
			UserFunctionsMap::iterator iter = userFunctions.find(*giveString(token1));
			if (iter != userFunctions.end())
				userFunctions.erase(iter);
		}
		break;
	case OP_DEREF:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		if (token1.tokenType != T_VARIABLE) {
			throw StutskException(ET_ERROR, "Token is not a variable");
		}
		else {
			recurseVariables(token1, true);
			stutskStack.push_back(copy_token(token1));
		}
		break;
	case OP_PLUSPLUS:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Name
		if (token1.tokenType == T_VARIABLE) {
			switch (giveGCD(token1, f1, i1, s1)) {
			case NT_INVALID:
			case NT_STRING:
				throw StutskException(ET_ERROR,
					"Variable is not a numeric type");
			case NT_INTEGER:
				token2.tokenType = T_INTEGER;
				token2.data.asInteger = i1 + 1;
				setVariable(token1, token2);
				break;
			case NT_FLOAT:
				token2.tokenType = T_FLOAT;
				token2.data.asFloat = f1 + 1.;
				setVariable(token1, token2); 
				break;
			}
		}
		else {
			switch (giveGCD(token1, f1, i1, s1)) {
			case NT_INVALID:
			case NT_STRING:
				throw StutskException(ET_ERROR, "Token is not a numeric type");
			case NT_INTEGER:
				pushInteger(++i1);
				break;
			case NT_FLOAT:
				pushFloat(++f1);
				break;
			}
		}
		break;
	case OP_MINMIN:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Name
		if (token1.tokenType == T_VARIABLE) {
			switch (giveGCD(token1, f1, i1, s1)) {
			case NT_INVALID:
			case NT_STRING:
				throw StutskException(ET_ERROR,
					"Variable is not a numeric type");
			case NT_INTEGER:
				token2.tokenType = T_INTEGER;
				token2.data.asInteger = i1 - 1;
				setVariable(token1, token2); 
				break;
			case NT_FLOAT:
				token2.tokenType = T_FLOAT;
				token2.data.asFloat = f1 - 1.;
				setVariable(token1, token2); 
				break;
			}
		}
		else {
			switch (giveGCD(token1, f1, i1, s1)) {
			case NT_INVALID:
			case NT_STRING:
				throw StutskException(ET_ERROR, "Token is not a numeric type");
			case NT_INTEGER:
				pushInteger(--i1);
				break;
			case NT_FLOAT:
				pushFloat(--f1);
				break;
			}
		}
		break;
	case OP_PLUS:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		switch (giveGCD(token1, f1, i1, s1)) {
		case NT_STRING:
		case NT_INVALID:
			throw StutskException(ET_ERROR, "Token is not a numeric type");
		case NT_INTEGER:
			switch (giveGCD(token2, f2, i2, s1)) {
			case NT_STRING:
			case NT_INVALID:
				throw StutskException(ET_ERROR, "Token is not a numeric type");
			case NT_INTEGER:
				i1 += i2;
				pushInteger(i1);
				break;
			case NT_FLOAT:
				f2 += i1;
				pushFloat(f2);
				break;
			}
			break;
		case NT_FLOAT:
			f1 += giveFloat(token2);
			pushFloat(f1);
			break;
		}

		break;
	case OP_MINUS:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		switch (giveGCD(token1, f1, i1, s1)) {
		case NT_STRING:
		case NT_INVALID:
			throw StutskException(ET_ERROR, "Token is not a numeric type");
		case NT_INTEGER:
			switch (giveGCD(token2, f2, i2, s1)) {
			case NT_STRING:
			case NT_INVALID:
				throw StutskException(ET_ERROR, "Token is not a numeric type");
			case NT_INTEGER:
				i2 -= i1;
				pushInteger(i2);
				break;
			case NT_FLOAT:
				f2 -= i1;
				pushFloat(f2);
				break;
			}
			break;
		case NT_FLOAT:
			f2 = giveFloat(token2) - f1;
			pushFloat(f2);
			break;
		}

		break;
	case OP_MULTIP:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		switch (giveGCD(token1, f1, i1, s1)) {
		case NT_STRING:
		case NT_INVALID:
			throw StutskException(ET_ERROR, "Token is not a numeric type");
		case NT_INTEGER:
			switch (giveGCD(token2, f2, i2, s1)) {
			case NT_STRING:
			case NT_INVALID:
				throw StutskException(ET_ERROR, "Token is not a numeric type");
			case NT_INTEGER:
				i1 *= i2;
				pushInteger(i1);
				break;
			case NT_FLOAT:
				f2 *= i1;
				pushFloat(f2);
				break;
			}
			break;
		case NT_FLOAT:
			f1 *= giveFloat(token2);
			pushFloat(f1);
			break;
		}
		break;
	case OP_DIV:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		switch (giveGCD(token1, f1, i1, s1)) {
		case NT_STRING:
		case NT_INVALID:
			throw StutskException(ET_ERROR, "Token is not a numeric type");
		case NT_INTEGER:
			if (i1 == 0)
				throw StutskException(ET_ERROR, "Division by zero");
			switch (giveGCD(token2, f2, i2, s1)) {
			case NT_STRING:
			case NT_INVALID:
				throw StutskException(ET_ERROR, "Token is not a numeric type");
			case NT_INTEGER:
				f1 = (stutskFloat)i2 / (stutskFloat)i1;
				pushFloat(f1);
				break;
			case NT_FLOAT:
				f2 /= (stutskFloat)i1;
				pushFloat(f2);
				break;
			}
			break;
		case NT_FLOAT:
			if (f1 == 0.)
				throw StutskException(ET_ERROR, "Division by zero");
			f2 = giveFloat(token2) / f1;
			pushFloat(f2);
			break;
		}
		break;
	case OP_DIVINT:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		switch (giveGCD(token1, f1, i1, s1)) {
		case NT_STRING:
		case NT_INVALID:
			throw StutskException(ET_ERROR, "Token is not a numeric type");
		case NT_INTEGER:
			switch (giveGCD(token2, f2, i2, s1)) {
			case NT_STRING:
			case NT_INVALID:
				throw StutskException(ET_ERROR, "Token is not a numeric type");
			case NT_INTEGER:
				i1 = (stutskInteger)i2 / i1;
				pushInteger(i1);
				break;
			case NT_FLOAT:
				i2 = (stutskInteger)f2 / i1;
				pushInteger(i2);
				break;
			}
			break;
		case NT_FLOAT:
			i2 = giveInteger(token2) / (stutskInteger)f1;
			pushInteger(i2);
			break;
		}
		break;
	case OP_MOD:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		switch (giveGCD(token1, f1, i1, s1)) {
		case NT_STRING:
		case NT_INVALID:
			throw StutskException(ET_ERROR, "Token is not a numeric type");
		case NT_INTEGER:
			switch (giveGCD(token2, f2, i2, s1)) {
			case NT_STRING:
			case NT_INVALID:
				throw StutskException(ET_ERROR, "Token is not a numeric type");
			case NT_INTEGER:
				i1 = (stutskInteger)i2 % i1;
				pushInteger(i1);
				break;
			case NT_FLOAT:
				i2 = (stutskInteger)f2 % i1;
				pushInteger(i2);
				break;
			}
			break;
		case NT_FLOAT:
			i2 = giveInteger(token2) % (stutskInteger)f1;
			pushInteger(i2);
			break;
		}
		break;
	case OP_LESSTHAN:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		pushBool(tokenNumericCompare(token1, token2) == CN_SMALLER);
		break;
	case OP_MORETHAN:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		pushBool(tokenNumericCompare(token1, token2) == CN_LARGER);
		break;
	case OP_LESSTHAN_EQ:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		pushBool(tokenNumericCompare(token1, token2) != CN_LARGER);
		break;
	case OP_MORETHAN_EQ:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		pushBool(tokenNumericCompare(token1, token2) != CN_SMALLER);
		break;
	case OP_EQ:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		pushBool(tokenEqual(token1, token2));	
		break;
	case OP_SAME:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();
		pushBool(tokenSame(token1, token2));
		break;
	case OP_NOTEQ:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();

		pushBool(!tokenEqual(token1, token2));	
		break;
	case OP_GLOBAL:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Variable
		if (token1.tokenType != T_VARIABLE) {
			throw StutskException(ET_ERROR, "Token is not a variable");
		}
		else {
			context->variableScopeMap[token1.data.asVariable.name] = VS_GLOBAL;
		}
		break;
	case OP_AUTO:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Variable
		if (token1.tokenType != T_VARIABLE) {
			throw StutskException(ET_ERROR, "Token is not a variable");
		}
		else {
			context->variableScopeMap[token1.data.asVariable.name] = VS_AUTO;
		}
		break;
	case OP_STATIC:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Variable
		if (token1.tokenType != T_VARIABLE) {
			throw StutskException(ET_ERROR, "Token is not a variable");
		}
		else {
			context->variableScopeMap[token1.data.asVariable.name] = VS_STATIC;
		}
		break;
	case OP_FOREVER:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		recurseVariables(token1);
		if (token1.tokenType != T_CODEBLOCK) {
			throw StutskException(ET_ERROR, "Token is not a codeblock");
		}
		else {
			while (true) {
				context->run(*token1.asTokenList, "forever");
				if (exitVar == OP_CONTINUE)
					exitVar = OP_INVALID;
				if (exitVar != OP_INVALID)
					break;
			}
			if (exitVar == OP_BREAK)
				exitVar = OP_INVALID;
		}
		break;
	case OP_FOREACH:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		recurseVariables(token1);
		if (token1.tokenType != T_CODEBLOCK)
			throw StutskException(ET_ERROR, "Token is not a codeblock");

		recurseVariables(token2);
		if (token2.tokenType == T_ARRAY) {
			for (TokenList::const_iterator it = token2.asTokenList->begin();
				it != token2.asTokenList->end(); ++it) {
					stutskStack.push_back(*it);
					stringstream ss;
					ss << "foreach [" << 
						std::distance(token2.asTokenList->cbegin(), it) << "]";
					context->run(*token1.asTokenList, ss.str());
					if (exitVar == OP_CONTINUE)
						exitVar = OP_INVALID;
					if (exitVar != OP_INVALID)
						break;
			}
		}
		else
			if (token2.tokenType == T_DICTIONARY) {
				for (TokenMap::const_iterator it = token2.asDictionary->begin();
					it != token2.asDictionary->end(); ++it) {
						stutskStack.push_back(it->second);
						StringPtr f = pushString();
						*f =  it->first;

						stringstream ss;
						ss << "foreach [" << it->first << "]";
						context->run(*token1.asTokenList, ss.str());
						if (exitVar == OP_CONTINUE)
							exitVar = OP_INVALID;
						if (exitVar != OP_INVALID)
							break;
				}
			}
			else 
			{
				StringPtr s1_ptr = giveString(token2);
				for (int i = 0; i < (signed)s1_ptr->length(); i++) {
					*pushString() = (*s1_ptr)[i];
					stringstream ss;
					ss << "foreach [" << i << "]";
					context->run(*token1.asTokenList, ss.str());
					if (exitVar == OP_CONTINUE)
						exitVar = OP_INVALID;
					if (exitVar != OP_INVALID)
						break;
				}
			}

			if (exitVar == OP_BREAK)
				exitVar = OP_INVALID;
			break;

	case OP_REPEAT:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		i1 = giveInteger(token2);
		recurseVariables(token1);

		if (token1.tokenType != T_CODEBLOCK) {
			throw StutskException(ET_ERROR, "Token is not a codeblock");
		}
		else {
			while (i1 > 0) {
				stringstream ss;
				ss << "repeat [" << i1 << "]";
				context->run(*token1.asTokenList, ss.str());
				if (exitVar == OP_CONTINUE)
					exitVar = OP_INVALID;
				if (exitVar != OP_INVALID)
					break;
				i1--;
			}
			if (exitVar == OP_BREAK)
				exitVar = OP_INVALID;
		}
		break;
	case OP_TRY:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		recurseVariables(token1);
		recurseVariables(token2);
		if ((token2.tokenType != T_CODEBLOCK) ||
			(token2.tokenType != T_CODEBLOCK)) {
				throw StutskException(ET_ERROR, "Token is not a codeblock");
		}
		else {
			try {
				context->run(*token2.asTokenList, "try");
			}
			catch (StutskException &e) {
				*pushString() = e.getMessage();
				pushInteger(e.getLineNumber());
				*pushString() = e.getFileName();

				context->run(*token1.asTokenList, "try");
			}
			catch (std::exception &e) {
				*pushString() = e.what();
				pushInteger(errorToken.lineNum);
				*pushString() = ParseContext::get_by_id(errorToken.context_id).FileName;

				context->run(*token1.asTokenList, "try");
			}
		}
		break;
	case OP_POWER:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		f1 = pow(giveFloat(token2), giveFloat(token1));
		pushFloat(f1);

		break;
	case OP_THROW:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Error name
		throw StutskException(ET_CUSTOM, *giveString(token1));
		break;
	case OP_NOT:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		pushBool(!giveBool(token1));
		break;
	case OP_AND:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();
		pushBool(giveBool(token1) && giveBool(token2));
		break;
	case OP_OR:
		token1 = stack_back_safe();
		stutskStack.pop_back();
		token2 = stack_back_safe();
		stutskStack.pop_back();
		pushBool(giveBool(token1) || giveBool(token2));
		break;
	case OP_IF:
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		recurseVariables(token2);

		if (token2.tokenType != T_CODEBLOCK) {
			throw StutskException(ET_ERROR, "Token is not a codeblock");
		}
		else {
			if (giveBool(token1)) {
				context->run(*token2.asTokenList, "if");
			}
		}
		break;
	case OP_IFELSE:
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token3 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		recurseVariables(token2);
		recurseVariables(token3);

		if ((token2.tokenType != T_CODEBLOCK) ||
			(token3.tokenType != T_CODEBLOCK)) {
				throw StutskException(ET_ERROR, "Token is not a codeblock");
		}
		else {
			if (giveBool(token1)) {
				context->run(*token3.asTokenList, "ifelse");
			}
			else {
				context->run(*token2.asTokenList, "ifelse");
			}
		}
		break;
	case OP_TERNARY:
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token3 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		stutskStack.push_back((giveBool(token1) ? token3 : token2));
		break;
	case OP_CONCAT:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		// Be careful NOT to recurse variable here because we wouldn't want
		// to overwrite the saved value.

		if (token2.tokenType == T_STRING) // Performance optimization
		{
			token2.asString->append(*giveString(token1));
			stutskStack.push_back(token2);
		}
		else
			// Should be fast enough ...	
			*pushString() = *giveString(token2) + 
			*giveString(token1);

		break;
	case OP_SWITCH:
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		recurseVariables(token2);

		if (token2.tokenType != T_ARRAY)
			throw StutskException(ET_ERROR, "Token is not an array");
		else
		{	
			for (TokenList::iterator it = token2.asTokenList->begin();
				it != token2.asTokenList->end(); ++it) 
			{
				token3 = *it;
				recurseVariables(token3);
				if (token3.tokenType != T_ARRAY)
					throw StutskException(ET_ERROR, "Token is not an array");
				else
				{
					if (token3.asTokenList->size() != 2)
						throw StutskException(ET_ERROR, "Array of wrong length");
					if ((*token3.asTokenList)[1].tokenType != T_CODEBLOCK)
						throw StutskException(ET_ERROR, "Token is not a codeblock");
					if (tokenEqual(token1, (*token3.asTokenList)[0]))
					{
						context->run(*(*token3.asTokenList)[1].asTokenList, "switch");
						break;
					}
				}
			}
		}
		break;
	case OP_BREAK:
	case OP_CONTINUE:
	case OP_HALT:
	case OP_EXIT:
		exitVar = oper;
		break;
	case OP_ARRAY:
		token1 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock
		token2 = stack_back_safe();
		stutskStack.pop_back(); // Codeblock

		recurseVariables(token1);

		if (token2.tokenType == T_VARIABLE) {
			if (token1.tokenType == T_ARRAY) {
				for (TokenList::iterator it = token1.asTokenList->begin();
					it != token1.asTokenList->end(); ++it)
					token2.index.push_back(giveInteger(*it));
			}
			else
				token2.index.push_back(giveInteger(token1));
			stutskStack.push_back(token2);
		}
		else if (token2.tokenType == T_ARRAY) {
			if (token1.tokenType == T_ARRAY) {
				for (TokenList::iterator it = token1.asTokenList->begin();
					it != token1.asTokenList->end(); ++it) {
						i1 = giveInteger(*it);
						if (i1 < 0)
							throw StutskException(ET_ERROR, "Array index underflow");
						if ((signed)token2.asTokenList->size() >= i1 + 1) {
							token2 = (*token2.asTokenList)[i1];
						}
						else
							throw StutskException(ET_ERROR, "Array index overflow");
				}
				stutskStack.push_back(token2);
			}
			else {
				i1 = giveInteger(token1);
				if (i1 < 0)
					throw StutskException(ET_ERROR, "Array index underflow");
				if ((signed)token2.asTokenList->size() >= i1 + 1) {
					stutskStack.push_back((*token2.asTokenList)[i1]);
				}
				else
					throw StutskException(ET_ERROR, "Array index overflow");
			}
		}
		else {
			i1 = giveInteger(token1);
			StringPtr s1_ptr = giveString(token2);
			if (i1 < 0)
				throw StutskException(ET_ERROR, "String index underflow");
			if ((signed)s1_ptr->length() >= i1 + 1) {
				*pushString() = (*s1_ptr)[i1];
			}
			else
				throw StutskException(ET_ERROR, "String index overflow");
		}
	}
}
Beispiel #15
0
//------------------------------------------------------------------------------
// An adaptation of a function of the same name in the original Babuino code.
//------------------------------------------------------------------------------
void
Babuino::code_exec()
{
	//Serial.println("code_exec()");
	
	if (!_storage.getReadyToRead())
	{
		// TO DO: What now? How do I report an error?
	}
	
	while (_states.getRunRequest() == RUNNING)
	{
		_storage.readByte(_regs.pc, _regs.opCode);
		_regs.pc++; 
		switch (_regs.opCode)
		{
			case OP_CONFIG:
				withConfig();
				break;

			case OP_MATH:
				withMath();
				break;

			case OP_BYTE:
			case OP_INT8:
			case OP_SPAN:
				{
					//Serial.println("int8 ");
					uint8_t value;
					_regs.pc = _storage.readByte(_regs.pc, value);
					pushUint8(_stack, value);
				}
				break;
			

			case OP_SHORT:
			case OP_UINT16:
				{
					//Serial.print("int16: ");
					uint16_t value;
					_regs.pc = _storage.read<uint16_t>(_regs.pc, value);
					//Serial.println(value);
					pushUint16(_stack, value);
				}
				break;

			case OP_GLOBAL:
				{
					//Serial.print("global: ");
					STACKPTR value;
					_regs.pc = _storage.read<STACKPTR>(_regs.pc, value);
					//Serial.println(value);
					pushStackPtr(_stack, value); //_stack.push(_stack.getBottom() - value);
				}
				break;

			case OP_INT32:
			case OP_UINT32:
				{
					//Serial.print("int32 ");

					uint32_t value;
					_regs.pc = _storage.read<uint32_t>(_regs.pc, value);
#ifdef SUPPORT_32BIT
					pushUint32(_stack, value);
#else
					pushUint16(_stack, (value >> 16) & 0xFFFF);	// High 16 bits
					pushUint16(_stack, value & 0xFFFF);	// Low 16 bits
#endif
				}
				break;

#ifdef SUPPORT_FLOAT
			case OP_FLOAT:
				{
					//Serial.print("float ");
					float value;
					_regs.pc = _storage.read<float>(_regs.pc, value);
					pushFloat(_stack, value);
				}
				break;
#endif
#ifdef SUPPORT_DOUBLE
			case OP_DOUBLE:
				{	
					//Serial.print("double ");
					double value;
					_regs.pc = _storage.read<double>(_regs.pc, value);
					pushDouble(_stack, value);
				}
				break;
#endif
			case OP_BOOL:
				{
					//Serial.print("bool  ");
					bool value;
					_regs.pc = _storage.read<bool>(_regs.pc, value);
					pushUint8(_stack, (uint8_t)value);
				}
				break;

			case OP_CPTR:
				{
					//Serial.print("cptr  ");
					PROGPTR value;
					_regs.pc = _storage.read<PROGPTR>(_regs.pc, value);
					pushProgPtr(_stack, value);
				}
				break;
#ifdef SUPPORT_STRING
			case OP_STRING:
				{
					//Serial.print("string: \"");
						// ***KLUDGE WARNING***
						// Borrowing unused (hopefully) stack space as a buffer!
						// (To avoid having to allocate another buffer.
					uint8_t* psz = (uint8_t*)getTopAddress(_stack);
					uint8_t nextChar;
					int16_t i = -1;
					do
					{
						i++;
						_regs.pc = _storage.readByte(_regs.pc, nextChar);
						psz[i] = nextChar;
					}
					while (nextChar);
					//Serial.print((char *)psz);
					//Serial.print("\" ");
						// Logically this is wrong because I'm apparently 
						// pushing a string to a location that it already 
						// occupies. However, the stack implementation 
						// pushes strings onto a separate stack, then
						// pushes the location onto the main stack. So
						// the string doesn't get copied over itself, and
						// is already copied before the first characters are
						// overwritten by pushing the said location onto the
						// main stack.
					//STACKSTATE state;
					//getStackState(_stack, &state);
					//Serial.print("[("); Serial.print(state.top); Serial.print(","); Serial.print(state.stringTop);Serial.print(") -> (");
					pushString(_stack, psz);
					//getStackState(_stack, &state);
					//Serial.print(state.top); Serial.print(","); Serial.print(state.stringTop);Serial.println(")]");
				}
				break;
	
			case OP_ASCII:
				{
					uint8_t* psz;
					topString(_stack, &psz);
					uint8_t ascii = psz[0];
					popString(_stack);
					pushUint8(_stack, ascii);
				}
				break;

			case OP_STRLEN:
				{
					uint8_t* psz;
					topString(_stack, &psz);
					uint8_t len = strlen((char*)psz);
					popString(_stack);
					pushUint8(_stack, len);
				}
				break;
#endif
			case OP_BEEP:
				//Serial.println("---beep---");
				beep();
				break;

			case OP_LEDON:
				//Serial.println("---LED on---");
				userLed(true);	// set the correct bit
				break;

			case OP_LEDOFF:
				//Serial.println("---LED off---");
				userLed(false);
				break;


			case OP_WITHINT8:
			case OP_WITHUINT8:
			case OP_WITHINT16:
			case OP_WITHUINT16:
			case OP_WITHBOOL:
			case OP_WITHPTR:
#ifdef SUPPORT_32BIT
			case OP_WITHINT32:
			case OP_WITHUINT32:
#endif
#ifdef SUPPORT_FLOAT
			case OP_WITHFLOAT:
#endif
#ifdef SUPPORT_DOUBLE
			case OP_WITHDOUBLE:
#endif
#ifdef SUPPORT_STRING			
			case OP_WITHSTRING:
#endif			
				_regs.withCode = _regs.opCode;
				break;

			case OP_LOCAL:
				{
					//Serial.print("local: local frame (");
					//Serial.print(_regs.localFrame);
					//Serial.print(") - ");

					STACKPTR varOffset;
					_regs.pc = _storage.read<uint16_t>(_regs.pc, (uint16_t&)varOffset);
					pushStackPtr(_stack, (STACKPTR)_regs.localFrame.top + varOffset);

					//Serial.print(varOffset);
					//Serial.print(" = global ");
					//Serial.println(_regs.localFrame + varOffset);
				}
				break;

			case OP_PARAM:
				{
					//Serial.print("param: ");
					STACKPTR varOffset;
					_regs.pc = _storage.read<uint16_t>(_regs.pc, (uint16_t&)varOffset);
						// We have an index into the parameters, which were put on
						// the stack in reverse order before the function call.
						// Calculate the absolute stack offset using the local
						// stack frame offset.
						// Also, the total size of the arguments was pushed last,
						// so we need to step past that too.
						// TODO: Check against the total argument size.
					pushStackPtr(_stack, 
									getArgsLocation() 
									- sizeof(uint8_t) 	// Number of args
									- varOffset		// Offset to the required param 
					);
				}
				break;

			case OP_BLOCK:
				{
					//Serial.print("block ");
					descendBlock();	// Shift the flag to the next block bit
					//char psz[10]; 
					//utoa(_regs.blockDepthMask, psz, 2);
					//Serial.println(psz);
					uint16_t blockLength;
						// Push address of next instruction (following the block
						// length data)
					pushProgPtr(_stack, (PROGPTR)_regs.pc + sizeof(uint16_t));
					_storage.read<uint16_t>(_regs.pc, blockLength);
						// Step past the block (tests there will bring execution back)
					_regs.pc.increment(blockLength);	

				}
				break;

			case OP_EOB:	
				//Serial.println("--eob--");
				setBlockExecuted();	// Set the bit to indicate that this block has executed
				break;
				
			case OP_DO:
				{
					//Serial.println("---do---");
					// OP_DO is like OP_BLOCK except that execution falls through to
					// the top of the block of code unconditionally rather than jump 
					// to the end where some condition is tested.
					// Need to:
					//  - Push the address that the following OP_BLOCK would push
					//  - Step past the:
					//	  - The OP_BLOCK code (uint8_t)
					//    - The block size (uint16_t)
					// After going through the code block it should jump back to 
					// the beginning of the OP_BLOCK and loop as usual.
					descendBlock();	// Shift the flag to the next block bit (normally done by OP_BLOCK)
					PROGPTR startOfBlock = (PROGPTR)_regs.pc + sizeof(uint8_t) +sizeof(uint16_t);
					pushProgPtr(_stack, startOfBlock); 
					_regs.pc.set(startOfBlock);
				}
				break;

			case OP_WHILE:
				{
					//Serial.print("while ");
					bool  condition;
					PROGPTR blockAddr;
					popUint8(_stack, (uint8_t*)&condition);
					//Serial.println(condition ? "true" : "false");
					//_stack.pop(blockAddr);
					if (condition) // if true then go to the block start address
					{
						topProgPtr(_stack, &blockAddr);
						_regs.pc = blockAddr;
					}
					else
					{
						popProgPtr(_stack, &blockAddr); // Throw it away
						ascendBlock();	// Finished with this block now
					}
				}	
				break;
				
			case OP_REPEAT:
				{
					//Serial.print("repeat ");
					PROGPTR blockAddr;
					uint16_t max;
					popProgPtr(_stack, &blockAddr);
					popUint16(_stack, &max);
					uint16_t repcount;
					if (!hasBlockExecuted()) // First time around?
					{
						repcount = 1;
						pushUint16(_stack, repcount);
							// point to the counter we just pushed
						STACKPTR slot = getTop(_stack);
							// Save outer loop's repcount pointer
						pushStackPtr(_stack, _regs.repcountLocation);
							// Set it to ours 
						_regs.repcountLocation = slot;
					}
					else
					{
						getUint16(_stack, _regs.repcountLocation, &repcount); // Get counter value
						repcount++;
					}
					//Serial.println(repcount);
					if (repcount <= max)
					{
						setUint16(_stack, _regs.repcountLocation, repcount);
						pushUint16(_stack, max);
						pushProgPtr(_stack, blockAddr);
						_regs.pc = blockAddr;
					}
					else
					{
							// Restore the outer loop's repcount pointer
						popStackPtr(_stack, &_regs.repcountLocation);
						popUint16(_stack, &repcount);			// Dispose of counter
						ascendBlock();	// Finished with this block now
					}
				}
				break;

			case OP_REPCOUNT:
				{
					uint16_t repcount;
					getUint16(_stack, _regs.repcountLocation, &repcount);
					pushUint16(_stack, repcount);
				}
				break;

			case OP_FOR:
				{
					//Serial.println("for ");
						// The counter variable has already been set to the from
						// value, so the from value isn't on the stack.
					PROGPTR blockAddr;
					int16_t  step, to, from;
					STACKPTR counterOff;
					int16_t  counterVal;
					popProgPtr(_stack, &blockAddr); 		
					popUint16(_stack, (uint16_t*)&step); 
					popUint16(_stack, (uint16_t*)&to);
					popUint16(_stack, (uint16_t*)&from); 
					popStackPtr(_stack, &counterOff); 
					getUint16(_stack, counterOff, (uint16_t*)&counterVal);

					//Serial.print(counterVal); 
					//Serial.print(" ");
					//Serial.print(to); 
					//Serial.print(" ");
					//Serial.println(step); 

					bool keepGoing;
						// See if this is the first time around
					if (!hasBlockExecuted())
					{
						counterVal = from;
						keepGoing = true;
					}
					else
					{
						// If step > 0 then assume from < to otherwise assume from > to
						keepGoing = (step > 0) ? (counterVal < to) : (counterVal > to); 
						counterVal += step;
					}
					if (keepGoing)
					{
						setUint16(_stack, counterOff, (uint16_t)counterVal);
						_regs.pc = blockAddr; // reiterate
						pushStackPtr(_stack, counterOff);	// Var offset
						pushUint16(_stack, (uint16_t)from);	// to
						pushUint16(_stack, (uint16_t)to);	// to
						pushUint16(_stack, (uint16_t)step);	// step
						pushProgPtr(_stack, blockAddr);
					}
					else
					{
						ascendBlock();
					}
				}
				break;


			case OP_IF:
				{
					//Serial.print("if ");
						// If it's the first time through then check the
						// condition
					if (!hasBlockExecuted())
					{
						PROGPTR blockAddr;
						bool     condition;
						popProgPtr(_stack, &blockAddr);  // Block initial address
						popUint8(_stack, (uint8_t*)&condition); // argument to test
						//Serial.println(condition ? "true" : "false");
						if (condition)
						{
							_regs.pc = blockAddr;
						}
						else
						{
							ascendBlock();
						}
					}
					else

					{
						ascendBlock();
					}
				}
				break;

				// IFELSE starts with address of THEN and ELSE lists (and 
				// CONDITIONAL) on the stack. CONDITIONAL is tested and 
				// appropriate list is run. 
			case OP_IFELSE:
				{
					//Serial.print("ifelse ");
					PROGPTR elseBlock;
					popProgPtr(_stack, &elseBlock);  // ELSE block start
						// Note that descendBlock() will have been called twice
						// the first time around (once for each block).
					ascendBlock(); // Remove the else block...
						// ...and use the then block flag for both purposes
					if (!hasBlockExecuted())
					{
						PROGPTR thenBlock;
						bool     condition;
						popProgPtr(_stack, &thenBlock); // THEN block start
						popUint8(_stack, (uint8_t*)&condition); 	  // argument to test
						if (condition)
						{
							//Serial.println("(then)");
							_regs.pc = thenBlock;
								// The ELSE address will get pushed again when
								// execution falls into the ELSE block after
								// exiting the THEN block.
								// Another else block will be descended into  
								// as well, and ascended away again above.
								// The eob code will be encountered at the end
								// of the then block, and that will set the
								// executed flag.
						}
						else
						{
							//Serial.println("(else)");
							_regs.pc = elseBlock;	  // the "ELSE" list
							pushProgPtr(_stack, (PROGPTR)0); // Push fake ELSE to balance
								// Borrow the then block flag and set it now as
								// executed since it won't actually be set
								// otherwise.
							setBlockExecuted();
								// Descend the else block now, as 
								// this also won't be done in the block's code.
							descendBlock();
						}
					}
					else
					{
						//popProgPtr(_stack, &elseBlock);  // dispose of unrequired address
						ascendBlock(); // ie. the then block
					}
				}
				break;

			case OP_PUSH:
				{
					//Serial.print("push ");
					uint8_t amount;
					popUint8(_stack, &amount);
					pushn(_stack, (STACKPTR)amount);
				}
				break;
			
			case OP_POP:
				{
					//Serial.print("pop ");
					uint8_t amount;
					popUint8(_stack, &amount);
					popn(_stack, (STACKPTR)amount);
				}
				break;
			
			case OP_CHKPOINT:
				getStackState(_stack, &_regs.checkPoint);
				break;

			case OP_ROLLBACK:
				setStackState(_stack, &_regs.checkPoint);
				break;
				
			case OP_CALL:
				{
					//Serial.println("call");
					PROGPTR procAddr;
					popProgPtr(_stack, &procAddr);			// Get the function location
						// Save the args location used by the calling function, and
						// set it to what was the stack top before it was pushed.
					/* 
					_regs.argsLoc = _stack.push(_regs.argsLoc);
					//Serial.print("args location: ");		
					//Serial.println(_regs.argsLoc);
					*/
					pushProgPtr(_stack, (PROGPTR)_regs.pc);	// Save the current code location for the return
					_regs.pc.set(procAddr);		        // Now jump to the function
				}
				break;

			case OP_BEGIN:
				//Serial.println("begin");
				pushRegisters();	// Save state of the caller
				
				_regs.blockDepthMask   = 0;
				_regs.blocksExecuted   = 0;
				getStackState(_stack, &_regs.localFrame); // = getTop(_stack);
				
				//Serial.println(_regs.localFrame);
				break;

			case OP_RETURN:
				{
					//Serial.print("return ");

						//Unwind the stack to the beginning of the local frame
					setStackState(_stack, &_regs.localFrame);
					popRegisters();
					
					PROGPTR returnAddr;
					popProgPtr(_stack, &returnAddr);	// Get the return address
					//_stack.pop(_regs.argsLoc);	// Restore the param location for the calling function
					_regs.pc.set(returnAddr);
				}
				break;
			
			case OP_EXIT:
				reset();
				//Serial.println("---exit---");
				break;

			case OP_LOOP:
				{
					//Serial.println("---loop---");
					PROGPTR blockAddr;
					topProgPtr(_stack, &blockAddr); 
					_regs.pc.set(blockAddr);

				}
				break;


			case OP_WAIT:
				{
					//Serial.println("---wait---");
					uint16_t tenths;
					popUint16(_stack, &tenths);
					delay(100 * tenths);
				}
				break;

			case OP_TIMER:
				//Serial.print("timer ");
				pushUint16(_stack, _timerCount); // TODO: implement timer!!
				break;

			case OP_RESETT:
				//Serial.println("---resett---");
				_timerCount = 0;
				break;

			case OP_RANDOM:
				//Serial.print("random ");
				pushUint16(_stack, (uint16_t)random(0, 32767));
				break;

			case OP_RANDOMXY:
				{
					//Serial.print("randomxy ");
					int16_t x;
					int16_t y;
					popUint16(_stack, (uint16_t*)&y);
					popUint16(_stack, (uint16_t*)&x);
					pushUint16(_stack, (uint16_t)random(x, y));
				}
				break;

			case OP_MOTORS:
				{
					//Serial.print("motors ");
					uint8_t selected;
					popUint8(_stack, &selected);
					_selectedMotors = (Motors::Selected)selected;
				}
				break;
				
			case OP_THISWAY:
				//Serial.print("---thisway---");
				_motors.setDirection(_selectedMotors, MotorBase::THIS_WAY);
				break;


			case OP_THATWAY:
				//Serial.print("---thatway---");
				_motors.setDirection(_selectedMotors, MotorBase::THAT_WAY);
				break;

			case OP_RD:
				//Serial.print("---rd---");
				_motors.reverseDirection(_selectedMotors);
				break;
				
			case OP_SETPOWER:
				{
					//Serial.print("setpower ");
					uint8_t power;
					popUint8(_stack, &power);
					if (power > 7)	
						power = 7;
					_motors.setPower(_selectedMotors, power);
				}
				break;


			case OP_BRAKE:
				//Serial.println("---brake---");
				_motors.setBrake(_selectedMotors, MotorBase::BRAKE_ON);
				break;

			case OP_ON:
				//Serial.println("---on---");
				_motors.on(_selectedMotors);
				break;

			case OP_ONFOR:
				{
					//Serial.print("onfor");
					uint16_t tenths;
					popUint16(_stack, &tenths);
					_motors.on(_selectedMotors);
					delay(100 * tenths);
					_motors.off(_selectedMotors);
				}
				break;

			case OP_OFF:
				//Serial.println("---off---");
				_motors.off(_selectedMotors);
				break;
			

			case OP_SENSOR1:
			case OP_SENSOR2:
			case OP_SENSOR3:
			case OP_SENSOR4:
			case OP_SENSOR5:
			case OP_SENSOR6:
			case OP_SENSOR7:
			case OP_SENSOR8:
				//Serial.print("sensor ");
				//Serial.print(_regs.opCode - OP_SENSOR1);
				//Serial.print(" ");
				pushUint16(_stack, (uint16_t)readAnalog(_regs.opCode - OP_SENSOR1));
				break;

			case OP_AIN:
				{
					//Serial.print("ain ");
					uint8_t input;
					popUint8(_stack, &input);
					pushUint16(_stack, (uint16_t)readAnalog(input));
				}
				break;

			case OP_AOUT:
				{
					//Serial.print("aout ");
					uint8_t output;
					uint8_t value;
					popUint8(_stack, &output);
					popUint8(_stack, &value);
					writeAnalog(output, value);
				}
				break;

			case OP_SWITCH1:
			case OP_SWITCH2:
			case OP_SWITCH3:
			case OP_SWITCH4:
			case OP_SWITCH5:
			case OP_SWITCH6:
			case OP_SWITCH7:
			case OP_SWITCH8:
				{
					//Serial.print("switch ");
					//Serial.print(_regs.opCode - OP_SWITCH1);
					//Serial.print(" ");
					int16_t val = readAnalog(_regs.opCode - OP_SWITCH1);
					if (val < 0)
						pushUint8(_stack, (uint8_t)false);
					else
						pushUint8(_stack, (uint8_t)!!(val >> 7));
				}
				break;
			
			case OP_NOT:
				break;
			
			case OP_AND:
				break;

			case OP_OR:
				break;

			case OP_XOR:
				break;

			case OP_DIN:
				{
					//Serial.print("din ");
					uint8_t input;
					popUint8(_stack, &input);
					pushUint8(_stack, (uint8_t)readDigital(input));
				}
				break;

			case OP_DOUT:
				{
					//Serial.print("dout ");
					uint8_t output;
					bool value;
					popUint8(_stack, &output);
					popUint8(_stack, (uint8_t*)&value);
					writeDigital(output, value);
				}
				break;
			
			case OP_BTOS:
				{
					int8_t value;
					popUint8(_stack, (uint8_t*)&value);
					pushUint16(_stack,(uint16_t)value);
				}
				break;
			case OP_UBTOS:
				{
					uint8_t value;
					popUint8(_stack, &value);
					pushUint16(_stack,(uint16_t)value);
				}
				break;
			case OP_STOB:	// and OP_USTOB
				{
					//Serial.print("stob: ");
					uint16_t value;
					popUint16(_stack, (uint16_t*)&value);
					//Serial.println(value);
					pushUint8(_stack, (uint8_t)value);
					
				}
				break;
#ifdef SUPPORT_32BIT
			case OP_BTOI:
				{
					int8_t value;
					popUint8(_stack, (uint8_t*)&value);
					pushUint32(_stack,(uint32_t)value);
				}
				break;
			case OP_UBTOI:
				{
					uint8_t value;
					popUint8(_stack, &value);
					pushUint32(_stack,(uint32_t)value);
				}
				break;
			case OP_STOI:
				{
					int16_t value;
					popUint16(_stack, (uint16_t*)&value);
					pushUint32(_stack,(uint32_t)value);
				}
				break;
			case OP_USTOI:
				{
					uint16_t value;
					popUint16(_stack, &value);
					pushUint32(_stack,(uint32_t)value);
				}
				break;
			case OP_ITOB: // and OP_UITOB
				{
					int32_t value;
					popUint32(_stack, (uint32_t*)&value);
					pushUint8(_stack, (uint8_t)value);
				}
				break;
			case OP_ITOS: //and OP_UITOS

				{
					int32_t value;
					popUint32(_stack, (uint32_t*)&value);
					pushUint16(_stack, (uint16_t)value);
				}
				break;
#endif
#ifdef SUPPORT_FLOAT
			case OP_BTOF:
				{
					int8_t value;
					popUint8(_stack, (uint8_t*)&value);
					pushFloat(_stack, (float)value);
				}
				break;
			case OP_UBTOF:
				{
					uint8_t value;
					popUint8(_stack, &value);
					pushFloat(_stack, (float)value);
				}
				break;
			case OP_STOF:
				{
					int16_t value;
					popUint16(_stack, (uint16_t*)&value);
					pushFloat(_stack, (float)value);
				}
				break;
			case OP_USTOF:
				{
					uint16_t value;
					popUint16(_stack, &value);
					pushFloat(_stack, (float)value);
				}
				break;
			case OP_FTOB:
				{
					float value;
					popFloat(_stack, &value);
					pushUint8(_stack, (uint8_t)value);
				}
				break;
			case OP_FTOS:
				{
					float value;
					popFloat(_stack, &value);
					pushUint16(_stack, (uint16_t)value);
				}
				break;
#endif
#ifdef SUPPORT_DOUBLE
			case OP_BTOD:
				{
					int8_t value;
					popUint8(_stack, (uint8_t*)&value);
					pushDouble(_stack, (double)value);
				}
				break;
			case OP_UBTOD:
				{
					uint8_t value;
					popUint8(_stack, &value);
					pushDouble(_stack, (double)value);
				}
				break;
			case OP_STOD:
				{
					int16_t value;
					popUint16(_stack, (uint16_t*)&value);
					pushDouble(_stack, (double)value);
				}
				break;
			case OP_USTOD:
				{
					uint16_t value;
					popUint8(_stack, (uint8_t*)&value);
					pushDouble(_stack, (double)value);
				}
				break;
			case OP_DTOB:
				{
					double value;
					popDouble(_stack, &value);
					pushUint8(_stack, (uint8_t)value);
				}
				break;
			case OP_DTOS:
				{
					double value;
					popDouble(_stack, &value);
					pushUint16(_stack, (uint16_t)value);
				}
				break;
#endif
#if defined(SUPPORT_DOUBLE) && defined(SUPPORT_32BIT)
			case OP_ITOD:
				{
					int32_t value;
					popUint32(_stack, (uint32_t*)&value);
					pushDouble(_stack, (double)value);
				}
				break;
			case OP_UITOD:
				{
					uint32_t value;
					popUint32(_stack, &value);
					pushDouble(_stack, (double)value);
				}
				break;
			case OP_DTOI:
				{
					double value;
					popDouble(_stack, &value);
					pushUint32(_stack, (uint32_t)value);
				}
				break;
#endif
#if defined(SUPPORT_DOUBLE) && defined(SUPPORT_FLOAT)
			case OP_FTOD:
				{
					float value;
					popFloat(_stack, &value);
					pushDouble(_stack, (double)value);
				}
				break;
			case OP_DTOF:
				{
					double value;
					popDouble(_stack, &value);
					pushFloat(_stack, (float)value);
				}
				break;
#endif
#if defined(SUPPORT_FLOAT) && defined(SUPPORT_32BIT)			
			case OP_ITOF:
				{
					int32_t value;
					popUint32(_stack, (uint32_t*)&value);
					pushFloat(_stack, (float)value);
				}
				break;
			case OP_UITOF:
				{
					uint32_t value;
					popUint32(_stack, &value);
					pushFloat(_stack, (float)value);
				}
				break;
			case OP_FTOI:
				{
					float value;
					popFloat(_stack, &value);
					pushUint32(_stack, (uint32_t)value);
				}
				break;
#endif			

			case OP_I2CSTART:
				i2cStart();
				break;

			case OP_I2CSTOP:
				i2cStop();
				break;

			case OP_I2CTXRX:
				{
					uint16_t i2cAddr;
					uint16_t txBuffOffset;
					uint8_t  txBuffLen;
					uint16_t rxBuffOffset;
					uint8_t  rxBuffLen;
					uint16_t timeout;
					popUint16(_stack, &i2cAddr);
					popUint16(_stack, &txBuffOffset);
					popUint8(_stack, &txBuffLen);
					popUint16(_stack, &rxBuffOffset);
					popUint8(_stack, &rxBuffLen);
					popUint16(_stack, &timeout);
					i2cTxRx(i2cAddr, 
							(uint8_t*)getStackAddress(_stack, txBuffOffset), 
							txBuffLen,
							(uint8_t*)getStackAddress(_stack, rxBuffOffset), 
							rxBuffLen,
							timeout);
				}
				break;

			case OP_I2CRX:
				{
					uint16_t addr;
					uint16_t rxBuffOffset;
					uint8_t  rxBuffLen;
					uint16_t timeout;
					popUint16(_stack, &addr);
					popUint16(_stack, &rxBuffOffset);
					popUint8(_stack, &rxBuffLen);
					popUint16(_stack, &timeout);
					i2cRx(addr, (uint8_t*)getStackAddress(_stack, rxBuffOffset), rxBuffLen, timeout);
				}
				break;
#ifdef SUPPORT_32BIT
			case OP_I2CERR:
				{
					//Serial.println("---i2cerr---");
					uint32_t errors = i2cErrors();
					pushUint32(_stack, errors);
				}
				break;
#endif
			case OP_WAITUNTIL:
			case OP_RECORD:
			case OP_RECALL:
			case OP_RESETDP:
			case OP_SETDP:
			case OP_ERASE:
			case OP_SETSVH:
			case OP_SVR:
			case OP_SVL:
					// TODO!!!
				break;
				
			default:
					// All of the type specific codes are dealt with here
				if (!withCurrentType())
				{
					//beep();	// Just an indication for now.
					Serial.print("unrecognised opcode: ");
					Serial.println(_regs.opCode);
				}
				break;

		}
	}
}
Beispiel #16
0
int CCLuaEngine::executeSchedule(int nHandler, float dt, CCNode* pNode/* = NULL*/)
{
    cleanStack();
    pushFloat(dt);
    return executeFunctionByHandler(nHandler, 1);
}