BASIC : Refactor FoldConstants for extracting it from SwExprNode.
Change-Id: Ia47597b26d63db216dd3ab71acbb18449ece7b1a Reviewed-on: https://gerrit.libreoffice.org/16963 Reviewed-by: Arnaud Versini <arnaud.versini@libreoffice.org> Tested-by: Arnaud Versini <arnaud.versini@libreoffice.org>
This commit is contained in:
committed by
Arnaud Versini
parent
a9db17aabc
commit
4251e676bb
@@ -231,182 +231,206 @@ void SbiExprNode::CollectBits()
|
||||
void SbiExprNode::FoldConstants(SbiParser* pParser)
|
||||
{
|
||||
if( IsOperand() || eTok == LIKE ) return;
|
||||
if( pLeft )
|
||||
pLeft->FoldConstants(pParser);
|
||||
if (pLeft && pRight)
|
||||
|
||||
if (IsUnary())
|
||||
FoldConstantsUnaryNode(pParser);
|
||||
else if (IsBinary())
|
||||
FoldConstantsBinaryNode(pParser);
|
||||
|
||||
if( eNodeType == SbxNUMVAL )
|
||||
{
|
||||
pRight->FoldConstants(pParser);
|
||||
if( pLeft->IsConstant() && pRight->IsConstant()
|
||||
&& pLeft->eNodeType == pRight->eNodeType )
|
||||
// Potentially convolve in INTEGER (because of better opcode)?
|
||||
if( eType == SbxSINGLE || eType == SbxDOUBLE )
|
||||
{
|
||||
CollectBits();
|
||||
if( eTok == CAT )
|
||||
// CAT affiliate also two numbers!
|
||||
eType = SbxSTRING;
|
||||
if( pLeft->eType == SbxSTRING )
|
||||
// No Type Mismatch!
|
||||
eType = SbxSTRING;
|
||||
if( eType == SbxSTRING )
|
||||
double x;
|
||||
if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
|
||||
&& !modf( nVal, &x ) )
|
||||
eType = SbxLONG;
|
||||
}
|
||||
if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
|
||||
eType = SbxINTEGER;
|
||||
}
|
||||
}
|
||||
|
||||
void SbiExprNode::FoldConstantsBinaryNode(SbiParser* pParser)
|
||||
{
|
||||
pLeft->FoldConstants(pParser);
|
||||
pRight->FoldConstants(pParser);
|
||||
if( pLeft->IsConstant() && pRight->IsConstant()
|
||||
&& pLeft->eNodeType == pRight->eNodeType )
|
||||
{
|
||||
CollectBits();
|
||||
if( eTok == CAT )
|
||||
// CAT affiliate also two numbers!
|
||||
eType = SbxSTRING;
|
||||
if( pLeft->eType == SbxSTRING )
|
||||
// No Type Mismatch!
|
||||
eType = SbxSTRING;
|
||||
if( eType == SbxSTRING )
|
||||
{
|
||||
OUString rl( pLeft->GetString() );
|
||||
OUString rr( pRight->GetString() );
|
||||
pLeft.reset();
|
||||
pRight.reset();
|
||||
if( eTok == PLUS || eTok == CAT )
|
||||
{
|
||||
OUString rl( pLeft->GetString() );
|
||||
OUString rr( pRight->GetString() );
|
||||
pLeft.reset();
|
||||
pRight.reset();
|
||||
if( eTok == PLUS || eTok == CAT )
|
||||
{
|
||||
eTok = CAT;
|
||||
// Linking:
|
||||
aStrVal = rl;
|
||||
aStrVal += rr;
|
||||
eType = SbxSTRING;
|
||||
eNodeType = SbxSTRVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
eType = SbxDOUBLE;
|
||||
eNodeType = SbxNUMVAL;
|
||||
int eRes = rr.compareTo( rl );
|
||||
switch( eTok )
|
||||
{
|
||||
case EQ:
|
||||
nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case NE:
|
||||
nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case LT:
|
||||
nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case GT:
|
||||
nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case LE:
|
||||
nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case GE:
|
||||
nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
default:
|
||||
pParser->Error( ERRCODE_BASIC_CONVERSION );
|
||||
bError = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
eTok = CAT;
|
||||
// Linking:
|
||||
aStrVal = rl;
|
||||
aStrVal += rr;
|
||||
eType = SbxSTRING;
|
||||
eNodeType = SbxSTRVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
double nl = pLeft->nVal;
|
||||
double nr = pRight->nVal;
|
||||
long ll = 0, lr = 0;
|
||||
long llMod = 0, lrMod = 0;
|
||||
if( ( eTok >= AND && eTok <= IMP )
|
||||
|| eTok == IDIV || eTok == MOD )
|
||||
{
|
||||
// Integer operations
|
||||
bool bErr = false;
|
||||
if( nl > SbxMAXLNG ) bErr = true, nl = SbxMAXLNG;
|
||||
else if( nl < SbxMINLNG ) bErr = true, nl = SbxMINLNG;
|
||||
if( nr > SbxMAXLNG ) bErr = true, nr = SbxMAXLNG;
|
||||
else if( nr < SbxMINLNG ) bErr = true, nr = SbxMINLNG;
|
||||
ll = static_cast<long>(nl); lr = static_cast<long>(nr);
|
||||
llMod = static_cast<long>(nl);
|
||||
lrMod = static_cast<long>(nr);
|
||||
if( bErr )
|
||||
{
|
||||
pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
|
||||
bError = true;
|
||||
}
|
||||
}
|
||||
bool bBothInt = ( pLeft->eType < SbxSINGLE
|
||||
&& pRight->eType < SbxSINGLE );
|
||||
pLeft.reset();
|
||||
pRight.reset();
|
||||
nVal = 0;
|
||||
eType = SbxDOUBLE;
|
||||
eNodeType = SbxNUMVAL;
|
||||
bool bCheckType = false;
|
||||
int eRes = rr.compareTo( rl );
|
||||
switch( eTok )
|
||||
{
|
||||
case EXPON:
|
||||
nVal = pow( nl, nr ); break;
|
||||
case MUL:
|
||||
bCheckType = true;
|
||||
nVal = nl * nr; break;
|
||||
case DIV:
|
||||
if( !nr )
|
||||
{
|
||||
pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
|
||||
bError = true;
|
||||
} else nVal = nl / nr;
|
||||
break;
|
||||
case PLUS:
|
||||
bCheckType = true;
|
||||
nVal = nl + nr; break;
|
||||
case MINUS:
|
||||
bCheckType = true;
|
||||
nVal = nl - nr; break;
|
||||
case EQ:
|
||||
nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case NE:
|
||||
nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case LT:
|
||||
nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case GT:
|
||||
nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case LE:
|
||||
nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case GE:
|
||||
nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case IDIV:
|
||||
if( !lr )
|
||||
{
|
||||
pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
|
||||
bError = true;
|
||||
} else nVal = ll / lr;
|
||||
eType = SbxLONG; break;
|
||||
case MOD:
|
||||
if( !lr )
|
||||
{
|
||||
pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
|
||||
bError = true;
|
||||
} else nVal = llMod - lrMod * (llMod/lrMod);
|
||||
eType = SbxLONG; break;
|
||||
case AND:
|
||||
nVal = (double) ( ll & lr ); eType = SbxLONG; break;
|
||||
case OR:
|
||||
nVal = (double) ( ll | lr ); eType = SbxLONG; break;
|
||||
case XOR:
|
||||
nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
|
||||
case EQV:
|
||||
nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
|
||||
case IMP:
|
||||
nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( !::rtl::math::isFinite( nVal ) )
|
||||
pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
|
||||
|
||||
// Recover the data type to kill rounding error
|
||||
if( bCheckType && bBothInt
|
||||
&& nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
|
||||
{
|
||||
// Decimal place away
|
||||
long n = (long) nVal;
|
||||
nVal = n;
|
||||
eType = ( n >= SbxMININT && n <= SbxMAXINT )
|
||||
? SbxINTEGER : SbxLONG;
|
||||
case EQ:
|
||||
nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case NE:
|
||||
nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case LT:
|
||||
nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case GT:
|
||||
nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case LE:
|
||||
nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
case GE:
|
||||
nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
|
||||
break;
|
||||
default:
|
||||
pParser->Error( ERRCODE_BASIC_CONVERSION );
|
||||
bError = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double nl = pLeft->nVal;
|
||||
double nr = pRight->nVal;
|
||||
long ll = 0, lr = 0;
|
||||
long llMod = 0, lrMod = 0;
|
||||
if( ( eTok >= AND && eTok <= IMP )
|
||||
|| eTok == IDIV || eTok == MOD )
|
||||
{
|
||||
// Integer operations
|
||||
bool bErr = false;
|
||||
if( nl > SbxMAXLNG ) bErr = true, nl = SbxMAXLNG;
|
||||
else if( nl < SbxMINLNG ) bErr = true, nl = SbxMINLNG;
|
||||
if( nr > SbxMAXLNG ) bErr = true, nr = SbxMAXLNG;
|
||||
else if( nr < SbxMINLNG ) bErr = true, nr = SbxMINLNG;
|
||||
ll = static_cast<long>(nl); lr = static_cast<long>(nr);
|
||||
llMod = static_cast<long>(nl);
|
||||
lrMod = static_cast<long>(nr);
|
||||
if( bErr )
|
||||
{
|
||||
pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
|
||||
bError = true;
|
||||
}
|
||||
}
|
||||
bool bBothInt = ( pLeft->eType < SbxSINGLE
|
||||
&& pRight->eType < SbxSINGLE );
|
||||
pLeft.reset();
|
||||
pRight.reset();
|
||||
nVal = 0;
|
||||
eType = SbxDOUBLE;
|
||||
eNodeType = SbxNUMVAL;
|
||||
bool bCheckType = false;
|
||||
switch( eTok )
|
||||
{
|
||||
case EXPON:
|
||||
nVal = pow( nl, nr ); break;
|
||||
case MUL:
|
||||
bCheckType = true;
|
||||
nVal = nl * nr; break;
|
||||
case DIV:
|
||||
if( !nr )
|
||||
{
|
||||
pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
|
||||
bError = true;
|
||||
} else nVal = nl / nr;
|
||||
break;
|
||||
case PLUS:
|
||||
bCheckType = true;
|
||||
nVal = nl + nr; break;
|
||||
case MINUS:
|
||||
bCheckType = true;
|
||||
nVal = nl - nr; break;
|
||||
case EQ:
|
||||
nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case NE:
|
||||
nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case LT:
|
||||
nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case GT:
|
||||
nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case LE:
|
||||
nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case GE:
|
||||
nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
|
||||
eType = SbxINTEGER; break;
|
||||
case IDIV:
|
||||
if( !lr )
|
||||
{
|
||||
pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
|
||||
bError = true;
|
||||
} else nVal = ll / lr;
|
||||
eType = SbxLONG; break;
|
||||
case MOD:
|
||||
if( !lr )
|
||||
{
|
||||
pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
|
||||
bError = true;
|
||||
} else nVal = llMod - lrMod * (llMod/lrMod);
|
||||
eType = SbxLONG; break;
|
||||
case AND:
|
||||
nVal = (double) ( ll & lr ); eType = SbxLONG; break;
|
||||
case OR:
|
||||
nVal = (double) ( ll | lr ); eType = SbxLONG; break;
|
||||
case XOR:
|
||||
nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
|
||||
case EQV:
|
||||
nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
|
||||
case IMP:
|
||||
nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if( !::rtl::math::isFinite( nVal ) )
|
||||
pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
|
||||
|
||||
// Recover the data type to kill rounding error
|
||||
if( bCheckType && bBothInt
|
||||
&& nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
|
||||
{
|
||||
// Decimal place away
|
||||
long n = (long) nVal;
|
||||
nVal = n;
|
||||
eType = ( n >= SbxMININT && n <= SbxMAXINT )
|
||||
? SbxINTEGER : SbxLONG;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pLeft && pLeft->IsNumber())
|
||||
|
||||
}
|
||||
void SbiExprNode::FoldConstantsUnaryNode(SbiParser* pParser)
|
||||
{
|
||||
pLeft->FoldConstants(pParser);
|
||||
if (pLeft->IsNumber())
|
||||
{
|
||||
nVal = pLeft->nVal;
|
||||
pLeft.reset();
|
||||
|
@@ -105,6 +105,8 @@ class SbiExprNode { // operators (and operands)
|
||||
SbiToken eTok;
|
||||
bool bError; // true: error
|
||||
void FoldConstants(SbiParser*);
|
||||
void FoldConstantsBinaryNode(SbiParser*);
|
||||
void FoldConstantsUnaryNode(SbiParser*);
|
||||
void CollectBits(); // converting numbers to strings
|
||||
bool IsOperand()
|
||||
{ return eNodeType != SbxNODE && eNodeType != SbxTYPEOF && eNodeType != SbxNEW; }
|
||||
@@ -131,6 +133,10 @@ public:
|
||||
{ return eNodeType == SbxSTRVAL || eNodeType == SbxNUMVAL; }
|
||||
bool IsIntConst();
|
||||
bool IsVariable();
|
||||
bool IsUnary()
|
||||
{ return pLeft && !pRight; }
|
||||
bool IsBinary()
|
||||
{ return pLeft && pRight; }
|
||||
|
||||
SbiExprNode* GetWithParent() { return pWithParent; }
|
||||
void SetWithParent( SbiExprNode* p ) { pWithParent = p; }
|
||||
|
Reference in New Issue
Block a user