int l_userdata_op( lua_State* L, int op )
{
	GACompute::Operand* leftOperand = 0;
	GACompute::Operand* rightOperand = 0;

	const UserData* leftUserData = l_grabuserdata( L, -2 );
	const UserData* rightUserData = l_grabuserdata( L, -1 );

	if( leftUserData && leftUserData->operand )
		leftOperand = leftUserData->operand->Clone();
	else if( lua_isnumber( L, -2 ) )
	{
		GACompute::NumericScalar* numericScalar = new GACompute::NumericScalar();
		numericScalar->SetReal( lua_tonumber( L, -2 ) );
		leftOperand = numericScalar;
	}

	if( rightUserData && rightUserData->operand )
		rightOperand = rightUserData->operand->Clone();
	else if( lua_isnumber( L, -1 ) )
	{
		GACompute::NumericScalar* numericScalar = new GACompute::NumericScalar();
		numericScalar->SetReal( lua_tonumber( L, -1 ) );
		rightOperand = numericScalar;
	}

	AutoDelete< GACompute::Operand > autoDeleteLeftOperand( leftOperand );
	AutoDelete< GACompute::Operand > autoDeleteRightOperand( rightOperand );

	if( !( leftOperand && rightOperand ) )
		return 0;

	UserData* userData = l_newuserdata( L );
	if( !userData )
		return 0;

	switch( op )
	{
		case OP_ADD:
		{
			GACompute::Sum* sum = new GACompute::Sum();
			sum->operandList->InsertAfter()->data = leftOperand;
			sum->operandList->InsertAfter()->data = rightOperand;

			userData->operand = sum;

			autoDeleteLeftOperand.Release();
			autoDeleteRightOperand.Release();
			break;
		}
		case OP_SUB:
		{
			GACompute::NumericScalar* numericScalar = new GACompute::NumericScalar();
			numericScalar->SetReal( -1.0 );

			GACompute::GeometricProduct* geometricProduct = new GACompute::GeometricProduct();
			geometricProduct->operandList->InsertAfter()->data = numericScalar;
			geometricProduct->operandList->InsertAfter()->data = rightOperand;

			GACompute::Sum* sum = new GACompute::Sum();
			sum->operandList->InsertAfter()->data = leftOperand;
			sum->operandList->InsertAfter()->data = geometricProduct;

			userData->operand = sum;

			autoDeleteLeftOperand.Release();
			autoDeleteRightOperand.Release();
			break;
		}
		case OP_MUL:
		{
			GACompute::GeometricProduct* geometricProduct = new GACompute::GeometricProduct();
			geometricProduct->operandList->InsertAfter()->data = leftOperand;
			geometricProduct->operandList->InsertAfter()->data = rightOperand;

			userData->operand = geometricProduct;

			autoDeleteLeftOperand.Release();
			autoDeleteRightOperand.Release();
			break;
		}
		case OP_MOD:
		{
			//...
			break;
		}
		case OP_CAT:
		{
			GACompute::InnerProduct* innerProduct = new GACompute::InnerProduct();
			innerProduct->operandList->InsertAfter()->data = leftOperand;
			innerProduct->operandList->InsertAfter()->data = rightOperand;

			userData->operand = innerProduct;

			autoDeleteLeftOperand.Release();
			autoDeleteRightOperand.Release();
			break;
		}
		case OP_POW:
		{
			GACompute::OuterProduct* outerProduct = new GACompute::OuterProduct();
			outerProduct->operandList->InsertAfter()->data = leftOperand;
			outerProduct->operandList->InsertAfter()->data = rightOperand;

			userData->operand = outerProduct;

			autoDeleteLeftOperand.Release();
			autoDeleteRightOperand.Release();
			break;
		}
		case OP_DIV:
		{
			//...
			break;
		}
	}

	if( !userData->operand )
	{
		lua_pop( L, 1 );
		lua_pushnil( L );
	}

	return 1;
}
Exemple #2
0
 void newuserdata( const T& copy )
 {
    void* lua_mem = l_newuserdata( sizeof(T) );
    new(lua_mem) T(copy);
 }