LCOV - code coverage report
Current view: top level - libreoffice/basic/source/comp - exprnode.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 84 254 33.1 %
Date: 2012-12-27 Functions: 15 21 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <math.h>
      22             : 
      23             : #include <rtl/math.hxx>
      24             : #include "sbcomp.hxx"
      25             : #include "expr.hxx"
      26             : 
      27             : 
      28           0 : SbiExprNode::SbiExprNode( void )
      29             : {
      30           0 :     pLeft = NULL;
      31           0 :     pRight = NULL;
      32           0 :     eNodeType = SbxDUMMY;
      33           0 : }
      34             : 
      35           5 : SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
      36             : {
      37           5 :     BaseInit( p );
      38             : 
      39           5 :     pLeft     = l;
      40           5 :     pRight    = r;
      41           5 :     eTok      = t;
      42           5 :     nVal      = 0;
      43           5 :     eType     = SbxVARIANT;     // Nodes are always Variant
      44           5 :     eNodeType = SbxNODE;
      45           5 : }
      46             : 
      47          14 : SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
      48             : {
      49          14 :     BaseInit( p );
      50             : 
      51          14 :     eType     = t;
      52          14 :     eNodeType = SbxNUMVAL;
      53          14 :     nVal      = n;
      54          14 : }
      55             : 
      56           4 : SbiExprNode::SbiExprNode( SbiParser* p, const OUString& rVal )
      57             : {
      58           4 :     BaseInit( p );
      59             : 
      60           4 :     eType     = SbxSTRING;
      61           4 :     eNodeType = SbxSTRVAL;
      62           4 :     aStrVal   = rVal;
      63           4 : }
      64             : 
      65          76 : SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
      66             : {
      67          76 :     BaseInit( p );
      68             : 
      69          76 :     eType     = ( t == SbxVARIANT ) ? r.GetType() : t;
      70          76 :     eNodeType = SbxVARVAL;
      71          76 :     aVar.pDef = (SbiSymDef*) &r;
      72          76 :     aVar.pPar = l;
      73          76 :     aVar.pvMorePar = NULL;
      74          76 :     aVar.pNext= NULL;
      75          76 : }
      76             : 
      77             : // #120061 TypeOf
      78           0 : SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId )
      79             : {
      80           0 :     BaseInit( p );
      81             : 
      82           0 :     pLeft      = l;
      83           0 :     eType      = SbxBOOL;
      84           0 :     eNodeType  = SbxTYPEOF;
      85           0 :     nTypeStrId = nId;
      86           0 : }
      87             : 
      88             : // new <type>
      89           0 : SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId )
      90             : {
      91           0 :     BaseInit( p );
      92             : 
      93           0 :     eType     = SbxOBJECT;
      94           0 :     eNodeType = SbxNEW;
      95           0 :     nTypeStrId = nId;
      96           0 : }
      97             : 
      98             : // From 1995-12-17, auxiliary function for Ctor for the uniform initialisation
      99          99 : void SbiExprNode::BaseInit( SbiParser* p )
     100             : {
     101          99 :     pGen = &p->aGen;
     102          99 :     eTok = NIL;
     103          99 :     pLeft       = NULL;
     104          99 :     pRight      = NULL;
     105          99 :     pWithParent = NULL;
     106          99 :     bError      = false;
     107          99 : }
     108             : 
     109         297 : SbiExprNode::~SbiExprNode()
     110             : {
     111          99 :     delete pLeft;
     112          99 :     delete pRight;
     113          99 :     if( IsVariable() )
     114             :     {
     115          76 :         delete aVar.pPar;
     116          76 :         delete aVar.pNext;
     117          76 :         SbiExprListVector* pvMorePar = aVar.pvMorePar;
     118          76 :         if( pvMorePar )
     119             :         {
     120           0 :             SbiExprListVector::iterator it;
     121           0 :             for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
     122           0 :                 delete *it;
     123           0 :             delete pvMorePar;
     124             :         }
     125             :     }
     126         198 : }
     127             : 
     128          27 : SbiSymDef* SbiExprNode::GetVar()
     129             : {
     130          27 :     if( eNodeType == SbxVARVAL )
     131          27 :         return aVar.pDef;
     132             :     else
     133           0 :         return NULL;
     134             : }
     135             : 
     136          27 : SbiSymDef* SbiExprNode::GetRealVar()
     137             : {
     138          27 :     SbiExprNode* p = GetRealNode();
     139          27 :     if( p )
     140          27 :         return p->GetVar();
     141             :     else
     142           0 :         return NULL;
     143             : }
     144             : 
     145             : // From 1995-12-18
     146          27 : SbiExprNode* SbiExprNode::GetRealNode()
     147             : {
     148          27 :     if( eNodeType == SbxVARVAL )
     149             :     {
     150          27 :         SbiExprNode* p = this;
     151          64 :         while( p->aVar.pNext )
     152          10 :             p = p->aVar.pNext;
     153          27 :         return p;
     154             :     }
     155             :     else
     156           0 :         return NULL;
     157             : }
     158             : 
     159             : // This method transform the type, if it fits into the Integer range
     160             : 
     161           0 : bool SbiExprNode::IsIntConst()
     162             : {
     163           0 :     if( eNodeType == SbxNUMVAL )
     164             :     {
     165           0 :         if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
     166             :         {
     167             :             double n;
     168           0 :             if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
     169             :             {
     170           0 :                 nVal = (double) (short) nVal;
     171           0 :                 eType = SbxINTEGER;
     172           0 :                 return true;
     173             :             }
     174             :         }
     175             :     }
     176           0 :     return false;
     177             : }
     178             : 
     179           0 : bool SbiExprNode::IsNumber()
     180             : {
     181           0 :     return eNodeType == SbxNUMVAL;
     182             : }
     183             : 
     184         126 : bool SbiExprNode::IsVariable()
     185             : {
     186         126 :     return eNodeType == SbxVARVAL;
     187             : }
     188             : 
     189          27 : bool SbiExprNode::IsLvalue()
     190             : {
     191          27 :     return IsVariable();
     192             : }
     193             : 
     194             : // Identify of the depth of a tree
     195             : 
     196           0 : short SbiExprNode::GetDepth()
     197             : {
     198           0 :     if( IsOperand() ) return 0;
     199             :     else
     200             :     {
     201           0 :         short d1 = pLeft->GetDepth();
     202           0 :         short d2 = pRight->GetDepth();
     203           0 :         return( (d1 < d2 ) ? d2 : d1 ) + 1;
     204             :     }
     205             : }
     206             : 
     207             : 
     208             : // Adjustment of a tree:
     209             : // 1. Constant Folding
     210             : // 2. Type-Adjustment
     211             : // 3. Conversion of the operans into Strings
     212             : // 4. Lifting of the composite- and error-bits
     213             : 
     214          33 : void SbiExprNode::Optimize()
     215             : {
     216          33 :     FoldConstants();
     217          33 :     CollectBits();
     218          33 : }
     219             : 
     220             : // Lifting of the error-bits
     221             : 
     222          43 : void SbiExprNode::CollectBits()
     223             : {
     224          43 :     if( pLeft )
     225             :     {
     226           5 :         pLeft->CollectBits();
     227           5 :         bError = bError || pLeft->bError;
     228             :     }
     229          43 :     if( pRight )
     230             :     {
     231           5 :         pRight->CollectBits();
     232           5 :         bError = bError || pRight->bError;
     233             :     }
     234          43 : }
     235             : 
     236             : // If a twig can be converted, True will be returned. In this case
     237             : // the result is in the left twig.
     238             : 
     239          43 : void SbiExprNode::FoldConstants()
     240             : {
     241          86 :     if( IsOperand() || eTok == LIKE ) return;
     242           5 :     if( pLeft )
     243           5 :         pLeft->FoldConstants();
     244           5 :     if( pRight )
     245             :     {
     246           5 :         pRight->FoldConstants();
     247           5 :         if( pLeft->IsConstant() && pRight->IsConstant()
     248             :             && pLeft->eNodeType == pRight->eNodeType )
     249             :         {
     250           0 :             CollectBits();
     251           0 :             if( eTok == CAT )
     252             :                 // CAT affiliate also two numbers!
     253           0 :                 eType = SbxSTRING;
     254           0 :             if( pLeft->eType == SbxSTRING )
     255             :                 // No Type Mismatch!
     256           0 :                 eType = SbxSTRING;
     257           0 :             if( eType == SbxSTRING )
     258             :             {
     259           0 :                 OUString rl( pLeft->GetString() );
     260           0 :                 OUString rr( pRight->GetString() );
     261           0 :                 delete pLeft; pLeft = NULL;
     262           0 :                 delete pRight; pRight = NULL;
     263           0 :                 if( eTok == PLUS || eTok == CAT )
     264             :                 {
     265           0 :                     eTok = CAT;
     266             :                     // Linking:
     267           0 :                     aStrVal = rl;
     268           0 :                     aStrVal += rr;
     269           0 :                     eType = SbxSTRING;
     270           0 :                     eNodeType = SbxSTRVAL;
     271             :                 }
     272             :                 else
     273             :                 {
     274           0 :                     eType = SbxDOUBLE;
     275           0 :                     eNodeType = SbxNUMVAL;
     276           0 :                     int eRes = rr.compareTo( rl );
     277           0 :                     switch( eTok )
     278             :                     {
     279             :                     case EQ:
     280           0 :                         nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
     281           0 :                         break;
     282             :                     case NE:
     283           0 :                         nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
     284           0 :                         break;
     285             :                     case LT:
     286           0 :                         nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
     287           0 :                         break;
     288             :                     case GT:
     289           0 :                         nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
     290           0 :                         break;
     291             :                     case LE:
     292           0 :                         nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
     293           0 :                         break;
     294             :                     case GE:
     295           0 :                         nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
     296           0 :                         break;
     297             :                     default:
     298           0 :                         pGen->GetParser()->Error( SbERR_CONVERSION );
     299           0 :                         bError = true;
     300           0 :                         break;
     301             :                     }
     302           0 :                 }
     303             :             }
     304             :             else
     305             :             {
     306           0 :                 double nl = pLeft->nVal;
     307           0 :                 double nr = pRight->nVal;
     308           0 :                 long ll = 0, lr = 0;
     309           0 :                 long llMod = 0, lrMod = 0;
     310           0 :                 if( ( eTok >= AND && eTok <= IMP )
     311             :                    || eTok == IDIV || eTok == MOD )
     312             :                 {
     313             :                     // Integer operations
     314           0 :                     sal_Bool err = sal_False;
     315           0 :                     if( nl > SbxMAXLNG ) err = sal_True, nl = SbxMAXLNG;
     316             :                     else
     317           0 :                     if( nl < SbxMINLNG ) err = sal_True, nl = SbxMINLNG;
     318           0 :                     if( nr > SbxMAXLNG ) err = sal_True, nr = SbxMAXLNG;
     319             :                     else
     320           0 :                     if( nr < SbxMINLNG ) err = sal_True, nr = SbxMINLNG;
     321           0 :                     ll = (long) nl; lr = (long) nr;
     322           0 :                     llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
     323           0 :                     lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
     324           0 :                     if( err )
     325             :                     {
     326           0 :                         pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     327           0 :                         bError = true;
     328             :                     }
     329             :                 }
     330             :                 sal_Bool bBothInt = sal_Bool( pLeft->eType < SbxSINGLE
     331           0 :                                    && pRight->eType < SbxSINGLE );
     332           0 :                 delete pLeft; pLeft = NULL;
     333           0 :                 delete pRight; pRight = NULL;
     334           0 :                 nVal = 0;
     335           0 :                 eType = SbxDOUBLE;
     336           0 :                 eNodeType = SbxNUMVAL;
     337           0 :                 sal_Bool bCheckType = sal_False;
     338           0 :                 switch( eTok )
     339             :                 {
     340             :                     case EXPON:
     341           0 :                         nVal = pow( nl, nr ); break;
     342             :                     case MUL:
     343           0 :                         bCheckType = sal_True;
     344           0 :                         nVal = nl * nr; break;
     345             :                     case DIV:
     346           0 :                         if( !nr )
     347             :                         {
     348           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     349           0 :                             bError = true;
     350           0 :                         } else nVal = nl / nr;
     351           0 :                         break;
     352             :                     case PLUS:
     353           0 :                         bCheckType = sal_True;
     354           0 :                         nVal = nl + nr; break;
     355             :                     case MINUS:
     356           0 :                         bCheckType = sal_True;
     357           0 :                         nVal = nl - nr; break;
     358             :                     case EQ:
     359           0 :                         nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
     360           0 :                         eType = SbxINTEGER; break;
     361             :                     case NE:
     362           0 :                         nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
     363           0 :                         eType = SbxINTEGER; break;
     364             :                     case LT:
     365           0 :                         nVal = ( nl <  nr ) ? SbxTRUE : SbxFALSE;
     366           0 :                         eType = SbxINTEGER; break;
     367             :                     case GT:
     368           0 :                         nVal = ( nl >  nr ) ? SbxTRUE : SbxFALSE;
     369           0 :                         eType = SbxINTEGER; break;
     370             :                     case LE:
     371           0 :                         nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
     372           0 :                         eType = SbxINTEGER; break;
     373             :                     case GE:
     374           0 :                         nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
     375           0 :                         eType = SbxINTEGER; break;
     376             :                     case IDIV:
     377           0 :                         if( !lr )
     378             :                         {
     379           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     380           0 :                             bError = true;
     381           0 :                         } else nVal = ll / lr;
     382           0 :                         eType = SbxLONG; break;
     383             :                     case MOD:
     384           0 :                         if( !lr )
     385             :                         {
     386           0 :                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
     387           0 :                             bError = true;
     388           0 :                         } else nVal = llMod % lrMod;
     389           0 :                         eType = SbxLONG; break;
     390             :                     case AND:
     391           0 :                         nVal = (double) ( ll & lr ); eType = SbxLONG; break;
     392             :                     case OR:
     393           0 :                         nVal = (double) ( ll | lr ); eType = SbxLONG; break;
     394             :                     case XOR:
     395           0 :                         nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
     396             :                     case EQV:
     397           0 :                         nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
     398             :                     case IMP:
     399           0 :                         nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
     400           0 :                     default: break;
     401             :                 }
     402             : 
     403           0 :                 if( !::rtl::math::isFinite( nVal ) )
     404           0 :                     pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     405             : 
     406             :                 // Recover the data type to kill rounding error
     407           0 :                 if( bCheckType && bBothInt
     408             :                  && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
     409             :                 {
     410             :                     // Decimal place away
     411           0 :                     long n = (long) nVal;
     412           0 :                     nVal = n;
     413             :                     eType = ( n >= SbxMININT && n <= SbxMAXINT )
     414           0 :                           ? SbxINTEGER : SbxLONG;
     415             :                 }
     416             :             }
     417             :         }
     418             :     }
     419           0 :     else if( pLeft && pLeft->IsNumber() )
     420             :     {
     421           0 :         nVal = pLeft->nVal;
     422           0 :         delete pLeft;
     423           0 :         pLeft = NULL;
     424           0 :         eType = SbxDOUBLE;
     425           0 :         eNodeType = SbxNUMVAL;
     426           0 :         switch( eTok )
     427             :         {
     428             :             case NEG:
     429           0 :                 nVal = -nVal; break;
     430             :             case NOT: {
     431             :                 // Integer operation!
     432           0 :                 sal_Bool err = sal_False;
     433           0 :                 if( nVal > SbxMAXLNG ) err = sal_True, nVal = SbxMAXLNG;
     434             :                 else
     435           0 :                 if( nVal < SbxMINLNG ) err = sal_True, nVal = SbxMINLNG;
     436           0 :                 if( err )
     437             :                 {
     438           0 :                     pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
     439           0 :                     bError = true;
     440             :                 }
     441           0 :                 nVal = (double) ~((long) nVal);
     442           0 :                 eType = SbxLONG;
     443           0 :                 } break;
     444           0 :             default: break;
     445             :         }
     446             :     }
     447           5 :     if( eNodeType == SbxNUMVAL )
     448             :     {
     449             :         // Potentially convolve in INTEGER (because of better opcode)?
     450           0 :         if( eType == SbxSINGLE || eType == SbxDOUBLE )
     451             :         {
     452             :             double x;
     453           0 :             if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
     454           0 :             && !modf( nVal, &x ) )
     455           0 :                 eType = SbxLONG;
     456             :         }
     457           0 :         if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
     458           0 :             eType = SbxINTEGER;
     459             :     }
     460             : }
     461             : 
     462             : 
     463             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10