/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
/*************************************************************
*
*
* PURPOSE:
*
*
* COMMENTS:
*
************************************************************/
static const char rcsid[] = "@(#)qlparser, QtBinaryInduce: $Id: qtbinaryinduce2.cc,v 1.25 2002/09/11 14:48:51 hoefner Exp $";
#include "raslib/rmdebug.hh"
#include "qlparser/qtbinaryinduce2.hh"
#include "qlparser/qtatomicdata.hh"
#include "qlparser/qtconst.hh"
#include "mddmgr/mddobj.hh"
#include "catalogmgr/typefactory.hh"
#include
#include
#include
using namespace std;
const QtNode::QtNodeType QtIs::nodeType = QT_IS;
QtIs::QtIs( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_EQUAL )
{
}
/*
void
QtIs::checkIdempotency()
{
if( input1->getSpelling().compare( input2->getSpelling() ) == 0 )
{
RMInit::logOut << "> rule (idempotency): A IS A -> TRUE" << endl;
getParent()->setInput( this, new QtConst( new QtAtomicData( 1 ) ) );
// delete the node itself and its descendants
delete this;
};
}
*/
void
QtIs::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtIs Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtIs::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << " is ";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtNode::QtNodeType QtAnd::nodeType = QT_AND;
QtAnd::QtAnd( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_AND )
{
}
/*
void
QtAnd::checkIdempotency()
{
if( input2->getNodeType() == QtNode::QT_CONST &&
((QtConst*)input2)->getDataObj()->getDataType() == QT_BOOL )
{
QtAtomicData* boolData = (QtAtomicData*)((QtConst*)input2)->getDataObj();
if( boolData->getUnsignedValue() )
{
RMInit::logOut << "> rule (idempotency): A AND TRUE -> A" << endl;
getParent()->setInput( this, input1 );
// delete the node itself and its descendants but not input1
setInput1(NULL);
delete this;
}
else
{
if( input1->getAreaType() == QtNode::QT_AREA_SCALAR )
{
RMInit::logOut << "> rule (idempotency): A (scalar) AND FALSE -> FALSE" << endl;
getParent()->setInput( this, input2 );
// delete the node itself and its descendants but not input2
setInput2(NULL);
delete this;
};
}
}
else
if( input1->getNodeType() == QtNode::QT_CONST &&
((QtConst*)input1)->getDataObj()->getDataType() == QT_BOOL )
{
QtAtomicData* boolData = (QtAtomicData*)((QtConst*)input1)->getDataObj();
if( boolData->getUnsignedValue() )
{
RMInit::logOut << "> rule (idempotency): TRUE AND A -> A" << endl;
getParent()->setInput( this, input2 );
// delete the node itself and its descendants but not input2
setInput2(NULL);
delete this;
}
else
{
if( input2->getAreaType() == QtNode::QT_AREA_SCALAR )
{
RMInit::logOut << "> rule (idempotency): FALSE AND A (scalar) -> FALSE" << endl;
getParent()->setInput( this, input1 );
// delete the node itself and its descendants but not input1
setInput1(NULL);
delete this;
};
};
}
else
if( input1->getSpelling().compare( input2->getSpelling() ) == 0 )
{
RMInit::logOut << "> rule (idempotency): A AND A -> A" << endl;
getParent()->setInput( this, input1 );
// delete the node itself and its descendants but not input1
setInput1(NULL);
delete this;
}
}
*/
/*
void
QtAnd::rewriteOps()
{
if( input1 && input2 )
{
if( input1->getNodeType() == QtNode::QT_SOME &&
input2->getNodeType() == QtNode::QT_ALL )
{
RMInit::logOut << "> rule (condenser order): SOME_CELLS AND ALL_CELLS -> ALL_CELLS AND SOME_CELLS" << endl;
// order condenser expressions
QtOperation* node1 = getInput1();
QtOperation* node2 = getInput2();
setInput1( node2 );
setInput2( node1 );
};
}
else
RMInit::logOut << "Error: QtAnd::rewriteOps() - the operand branch is invalid." << endl;
}
*/
QtData*
QtAnd::evaluate( QtDataList* inputList )
{
/*
// RUNTIME OPTIMIZATION: FALSE AND A -> MDD(FALSE)
// A AND FALSE -> MDD(FALSE)
// TRUE AND A -> A
// A AND TRUE -> A
*/
QtData* returnValue = NULL;
if( input1->getDataStreamType().getDataType() == QT_BOOL &&
input2->getDataStreamType().getDataType() == QT_BOOL )
{
// RUNTIME OPTIMIZATION: FALSE AND A -> FALSE
// TRUE AND A -> A
QtData* operand1=NULL;
if( getOperand( inputList, operand1, 1 ) )
{
bool op1 = ((QtAtomicData*)operand1)->getUnsignedValue();
if( op1 )
{
// first operand is obsolete
if( operand1 ) operand1->deleteRef();
QtData* operand2=NULL;
if( getOperand( inputList, operand2, 2 ) )
{
returnValue = operand2;
}
}
else
{
returnValue = operand1;
RMDBGONCE(1, RMDebug::module_qlparser, "QtAnd", " -> FALSE AND A evaluates FALSE")
}
}
}
else
returnValue = QtBinaryInduce::evaluate( inputList );
return returnValue;
}
void
QtAnd::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtAnd Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtAnd::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << " and ";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtNode::QtNodeType QtOr::nodeType = QT_OR;
QtOr::QtOr( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_OR )
{
}
/*
void
QtOr::checkIdempotency()
{
if( input2->getNodeType() == QtNode::QT_CONST &&
((QtConst*)input2)->getDataObj()->getDataType() == QT_BOOL )
{
QtAtomicData* boolData = (QtAtomicData*)((QtConst*)input2)->getDataObj();
if( boolData->getUnsignedValue() )
{
if( input1->getAreaType() == QtNode::QT_AREA_SCALAR )
{
RMInit::logOut << "> rule (idempotency): A (scalar) OR TRUE -> TRUE" << endl;
getParent()->setInput( this, input2 );
// delete the node itself and its descendants but not input2
setInput2(NULL);
delete this;
};
}
else
{
RMInit::logOut << "> rule (idempotency): A OR FALSE -> A" << endl;
getParent()->setInput( this, input1 );
// delete the node itself and its descendants but not input1
setInput1(NULL);
delete this;
}
}
else
if( input1->getNodeType() == QtNode::QT_CONST &&
((QtConst*)input1)->getDataObj()->getDataType() == QT_BOOL )
{
QtAtomicData* boolData = (QtAtomicData*)((QtConst*)input1)->getDataObj();
if( boolData->getUnsignedValue() )
{
if( input2->getAreaType() == QtNode::QT_AREA_SCALAR )
{
RMInit::logOut << "> rule (idempotency): TRUE OR A (scalar) -> TRUE" << endl;
getParent()->setInput( this, input1 );
// delete the node itself and its descendants but not input1
setInput1(NULL);
delete this;
};
}
else
{
RMInit::logOut << "> rule (idempotency): FALSE OR A -> A" << endl;
getParent()->setInput( this, input2 );
// delete the node itself and its descendants but not input2
setInput2(NULL);
delete this;
};
}
else
if( input1->getSpelling().compare( input2->getSpelling() ) == 0 )
{
RMInit::logOut << "> rule (idempotency): A OR A -> A" << endl;
getParent()->setInput( this, input1 );
// delete the node itself and its descendants but not input1
setInput1(NULL);
delete this;
};
}
*/
/*
void
QtOr::rewriteOps()
{
if( input1 && input2 )
{
if( input1->getNodeType() == QtNode::QT_ALL &&
input2->getNodeType() == QtNode::QT_SOME )
{
RMInit::logOut << "> rule (condenser order): ALL_CELLS OR SOME_CELLS -> SOME_CELLS OR ALL_CELLS" << endl;
// order condenser expressions
QtOperation* node1 = getInput1();
QtOperation* node2 = getInput2();
setInput1( node2 );
setInput2( node1 );
};
}
else
RMInit::logOut << "Error: QtOr::rewriteOps() - the operand branch is invalid." << endl;
}
*/
QtData*
QtOr::evaluate( QtDataList* inputList )
{
/*
// RUNTIME OPTIMIZATION: TRUE OR A -> MDD(TRUE)
// A OR TRUE -> MDD(TRUE)
// FALSE OR A -> A
// A OR FALSE -> A
*/
QtData* returnValue = NULL;
if( input1->getDataStreamType().getDataType() == QT_BOOL &&
input2->getDataStreamType().getDataType() == QT_BOOL )
{
// RUNTIME OPTIMIZATION: FALSE OR A -> A
// TRUE OR A -> TRUE
QtData* operand1=NULL;
if( getOperand( inputList, operand1, 1 ) )
{
bool op1 = ((QtAtomicData*)operand1)->getUnsignedValue();
if( !op1 )
{
// first operand is obsolete
if( operand1 ) operand1->deleteRef();
QtData* operand2=NULL;
if( getOperand( inputList, operand2, 2 ) )
{
returnValue = operand2;
}
}
else
{
returnValue = operand1;
RMDBGONCE(1, RMDebug::module_qlparser, "QtOr", " -> TRUE OR A evaluates TRUE")
}
}
}
else
returnValue = QtBinaryInduce::evaluate( inputList );
return returnValue;
}
void
QtOr::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtOr Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtOr::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << " or ";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtNode::QtNodeType QtXor::nodeType = QT_XOR;
QtXor::QtXor( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_XOR )
{
}
/*
void
QtXor::checkIdempotency()
{
RMDBGENTER(1, RMDebug::module_qlparser, "QtXor", "enter Xor::checkIdempotency()" )
if( input1->getSpelling().compare( input2->getSpelling() ) == 0 )
{
RMInit::logOut << "> rule (idempotency): A XOR A -> FALSE" << endl;
getParent()->setInput( this, new QtConst( new QtAtomicData( 0 ) ) );
// delete the node itself and its descendants
delete this;
};
RMDBGEXIT(1, RMDebug::module_qlparser, "QtXor", "exit Xor::checkIdempotency()" )
}
*/
void
QtXor::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtXor Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtXor::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << " xor ";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtNode::QtNodeType QtEqual::nodeType = QT_EQUAL;
QtEqual::QtEqual( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_EQUAL )
{
}
/*
void
QtEqual::checkIdempotency()
{
if( input1->getSpelling().compare( input2->getSpelling() ) == 0 )
{
RMInit::logOut << "> rule (idempotency): A == A -> TRUE" << endl;
getParent()->setInput( this, new QtConst( new QtAtomicData( 1 ) ) );
// delete the node itself and its descendants
delete this;
};
}
*/
void
QtEqual::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtEqual Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtEqual::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << " = ";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtNode::QtNodeType QtLess::nodeType = QT_LESS;
QtLess::QtLess( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_LESS )
{
}
bool
QtLess::isCommutative() const
{
return false; // NOT commutative
}
void
QtLess::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtLess Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtLess::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << " < ";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtNode::QtNodeType QtLessEqual::nodeType = QT_LESS_EQUAL;
QtLessEqual::QtLessEqual( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_LESSEQUAL )
{
}
bool
QtLessEqual::isCommutative() const
{
return false; // NOT commutative
}
void
QtLessEqual::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtLessEqual Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtLessEqual::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << " <= ";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtNode::QtNodeType QtNotEqual::nodeType = QT_NOT_EQUAL;
QtNotEqual::QtNotEqual( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_NOTEQUAL )
{
}
/*
void
QtNotEqual::checkIdempotency()
{
if( input1->getSpelling().compare( input2->getSpelling() ) == 0 )
{
RMInit::logOut << "> rule (idempotency): A != A -> FALSE" << endl;
getParent()->setInput( this, new QtConst( new QtAtomicData( 0 ) ) );
// delete the node itself and its descendants
delete this;
};
}
*/
void
QtNotEqual::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtNotEqual Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtNotEqual::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << " != ";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
const QtNode::QtNodeType QtOverlay::nodeType = QT_OVERLAY;
QtOverlay::QtOverlay( QtOperation* initInput1, QtOperation* initInput2 )
: QtBinaryInduce( initInput1, initInput2, Ops::OP_OVERLAY )
{
}
/*
void QtOverlay::checkIdempotency()
{
}
*/
bool QtOverlay::isCommutative() const
{
return false; // NOT commutative
}
void
QtOverlay::printTree( int tab, ostream& s, QtChildType mode )
{
s << SPACE_STR(tab).c_str() << "QtOverlay Object " << getNodeType() << endl;
QtBinaryInduce::printTree( tab, s, mode );
}
void
QtOverlay::printAlgebraicExpression( ostream& s )
{
s << "(";
if( input2 )
input2->printAlgebraicExpression( s );
else
s << "";
s << " overlay ";
if( input1 )
input1->printAlgebraicExpression( s );
else
s << "";
s << ")";
}
/********************************************************
* QtBit
********************************************************
*/
const QtNode::QtNodeType QtBit::nodeType = QT_BIT;
QtBit::QtBit(QtOperation* initInput1, QtOperation* initInput2)
: QtBinaryInduce(initInput1, initInput2, Ops::OP_BIT) {}
bool QtBit::isCommutative() const {
return false;
}
void QtBit::printTree(int tab, ostream& s, QtChildType mode) {
s << SPACE_STR(tab).c_str() << "QtBit Object " << getNodeType() << endl;
QtBinaryInduce::printTree(tab, s, mode);
}
void QtBit::printAlgebraicExpression(ostream& s) {
s << "(";
if( input2 )
input2->printAlgebraicExpression(s);
else
s << "";
s << " bit ";
if( input1 )
input1->printAlgebraicExpression(s);
else
s << "";
s << ")";
}
const QtTypeElement& QtBit::checkType(QtTypeTuple* typeTuple) {
RMDBCLASS( "QtBit", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ )
dataStreamType.setDataType(QT_TYPE_UNKNOWN);
// check operand branches
if(input1 && input2)
{
// get input types
const QtTypeElement& inputType1 = input1->checkType(typeTuple);
const QtTypeElement& inputType2 = input2->checkType(typeTuple);
if(RManDebug >= 4) {
RMInit::dbgOut << "Operand 1: " << flush;
inputType1.printStatus( RMInit::dbgOut );
RMInit::dbgOut << endl;
RMInit::dbgOut << "Operand 2: " << flush;
inputType2.printStatus( RMInit::dbgOut );
RMInit::dbgOut << endl;
RMDBGONCE( 4, RMDebug::module_qlparser, "QtBit", "Operation " << opType )
}
if(inputType2.getDataType() < QT_BOOL || inputType2.getDataType() > QT_LONG) {
RMInit::logOut << "Error: QtBit::checkType() - second operand must be of integral type." << endl;
parseInfo.setErrorNo(418);
throw parseInfo;
}
if(inputType1.getDataType() == QT_MDD) {
const BaseType* baseType1 = ((MDDBaseType*)(inputType1.getType()))->getBaseType();
BaseType* baseType2 = (BaseType*)(inputType2.getType());
const BaseType* resultBaseType = Ops::getResultType(opType, baseType1, baseType2);
if(!resultBaseType) {
RMInit::logOut << "Error: QtBit::checkType() - unary induce: operand types are incompatible." << endl;
parseInfo.setErrorNo(364);
throw parseInfo;
}
MDDBaseType* resultMDDType = new MDDBaseType("tmp", resultBaseType);
TypeFactory::addTempType(resultMDDType);
dataStreamType.setType(resultMDDType);
}
else if(inputType1.isBaseType()) {
BaseType* baseType1 = (BaseType*)(inputType1.getType());
BaseType* baseType2 = (BaseType*)(inputType2.getType());
const BaseType* resultBaseType = Ops::getResultType(opType, baseType1, baseType2);
if(!resultBaseType) {
RMInit::logOut << "Error: QtBit::computeOp() - operand types are incompatible." << endl;
parseInfo.setErrorNo(365);
throw parseInfo;
}
dataStreamType.setType(resultBaseType);
}
else {
RMInit::logOut << "Error: QtBit::checkType() - operation is not supported on these data types." << endl;
parseInfo.setErrorNo(403);
throw parseInfo;
}
}
else
RMInit::logOut << "Error: QtBit::checkType() - operand branch invalid." << endl;
return dataStreamType;
}