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; }
void newuserdata( const T& copy ) { void* lua_mem = l_newuserdata( sizeof(T) ); new(lua_mem) T(copy); }