diff options
author | Arnaud Versini <arnaud.versini@gmail.com> | 2015-07-12 13:52:53 +0200 |
---|---|---|
committer | Arnaud Versini <arnaud.versini@libreoffice.org> | 2015-12-22 11:13:03 +0000 |
commit | 4251e676bb818cde1989b9077b1497f1d9b0cbdc (patch) | |
tree | e2165ce1a736fb99cb40dd29f6ea45022e23e08c | |
parent | a9db17aabc3ac970e6e4754e28310d20138144d9 (diff) |
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>
-rw-r--r-- | basic/source/comp/exprnode.cxx | 342 | ||||
-rw-r--r-- | basic/source/inc/expr.hxx | 6 |
2 files changed, 189 insertions, 159 deletions
diff --git a/basic/source/comp/exprnode.cxx b/basic/source/comp/exprnode.cxx index 52c2211fcfa3..9d77f6dba071 100644 --- a/basic/source/comp/exprnode.cxx +++ b/basic/source/comp/exprnode.cxx @@ -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! + 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 ) + { + eTok = CAT; + // Linking: + aStrVal = rl; + aStrVal += rr; eType = SbxSTRING; - if( eType == SbxSTRING ) + eNodeType = SbxSTRVAL; + } + else { - OUString rl( pLeft->GetString() ); - OUString rr( pRight->GetString() ); - pLeft.reset(); - pRight.reset(); - if( eTok == PLUS || eTok == CAT ) + eType = SbxDOUBLE; + eNodeType = SbxNUMVAL; + int eRes = rr.compareTo( rl ); + switch( eTok ) { - eTok = CAT; - // Linking: - aStrVal = rl; - aStrVal += rr; - eType = SbxSTRING; - eNodeType = SbxSTRVAL; + 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 + } + } + 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 ) { - 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; - } + pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW ); + bError = true; } } - else + bool bBothInt = ( pLeft->eType < SbxSINGLE + && pRight->eType < SbxSINGLE ); + pLeft.reset(); + pRight.reset(); + nVal = 0; + eType = SbxDOUBLE; + eNodeType = SbxNUMVAL; + bool bCheckType = false; + switch( eTok ) { - 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 ) + case EXPON: + nVal = pow( nl, nr ); break; + case MUL: + bCheckType = true; + nVal = nl * nr; break; + case DIV: + if( !nr ) { - pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW ); + pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL; 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; - } + } 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 ); + 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; - } + // 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(); diff --git a/basic/source/inc/expr.hxx b/basic/source/inc/expr.hxx index ac2cce82e3d2..6efa1509e0c5 100644 --- a/basic/source/inc/expr.hxx +++ b/basic/source/inc/expr.hxx @@ -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; } |