| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_basic.hxx" |
| |
| #include <math.h> |
| |
| #include <rtl/math.hxx> |
| #include "sbcomp.hxx" |
| #include "expr.hxx" |
| |
| ////////////////////////////////////////////////////////////////////////// |
| |
| SbiExprNode::SbiExprNode( void ) |
| { |
| pLeft = NULL; |
| pRight = NULL; |
| eNodeType = SbxDUMMY; |
| } |
| |
| SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r ) |
| { |
| BaseInit( p ); |
| |
| pLeft = l; |
| pRight = r; |
| eTok = t; |
| nVal = 0; |
| eType = SbxVARIANT; // Nodes sind immer Variant |
| eNodeType = SbxNODE; |
| bComposite= sal_True; |
| } |
| |
| SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t ) |
| { |
| BaseInit( p ); |
| |
| eType = t; |
| eNodeType = SbxNUMVAL; |
| nVal = n; |
| } |
| |
| SbiExprNode::SbiExprNode( SbiParser* p, const String& rVal ) |
| { |
| BaseInit( p ); |
| |
| eType = SbxSTRING; |
| eNodeType = SbxSTRVAL; |
| aStrVal = rVal; |
| } |
| |
| SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l ) |
| { |
| BaseInit( p ); |
| |
| eType = ( t == SbxVARIANT ) ? r.GetType() : t; |
| eNodeType = SbxVARVAL; |
| aVar.pDef = (SbiSymDef*) &r; |
| aVar.pPar = l; |
| aVar.pvMorePar = NULL; |
| aVar.pNext= NULL; |
| |
| // Funktionsergebnisse sind nie starr |
| bComposite= sal_Bool( aVar.pDef->GetProcDef() != NULL ); |
| } |
| |
| // #120061 TypeOf |
| SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId ) |
| { |
| BaseInit( p ); |
| |
| pLeft = l; |
| eType = SbxBOOL; |
| eNodeType = SbxTYPEOF; |
| nTypeStrId = nId; |
| } |
| |
| // new <type> |
| SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId ) |
| { |
| BaseInit( p ); |
| |
| eType = SbxOBJECT; |
| eNodeType = SbxNEW; |
| nTypeStrId = nId; |
| } |
| |
| // AB: 17.12.95, Hilfsfunktion fuer Ctor fuer einheitliche Initialisierung |
| void SbiExprNode::BaseInit( SbiParser* p ) |
| { |
| pGen = &p->aGen; |
| eTok = NIL; |
| pLeft = NULL; |
| pRight = NULL; |
| pWithParent = NULL; |
| bComposite = sal_False; |
| bError = sal_False; |
| } |
| |
| SbiExprNode::~SbiExprNode() |
| { |
| delete pLeft; |
| delete pRight; |
| if( IsVariable() ) |
| { |
| delete aVar.pPar; |
| delete aVar.pNext; |
| SbiExprListVector* pvMorePar = aVar.pvMorePar; |
| if( pvMorePar ) |
| { |
| SbiExprListVector::iterator it; |
| for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it ) |
| delete *it; |
| delete pvMorePar; |
| } |
| } |
| } |
| |
| SbiSymDef* SbiExprNode::GetVar() |
| { |
| if( eNodeType == SbxVARVAL ) |
| return aVar.pDef; |
| else |
| return NULL; |
| } |
| |
| SbiSymDef* SbiExprNode::GetRealVar() |
| { |
| SbiExprNode* p = GetRealNode(); |
| if( p ) |
| return p->GetVar(); |
| else |
| return NULL; |
| } |
| |
| // AB: 18.12.95 |
| SbiExprNode* SbiExprNode::GetRealNode() |
| { |
| if( eNodeType == SbxVARVAL ) |
| { |
| SbiExprNode* p = this; |
| while( p->aVar.pNext ) |
| p = p->aVar.pNext; |
| return p; |
| } |
| else |
| return NULL; |
| } |
| |
| // Diese Methode setzt den Typ um, falls er in den Integer-Bereich hineinpasst |
| |
| sal_Bool SbiExprNode::IsIntConst() |
| { |
| if( eNodeType == SbxNUMVAL ) |
| { |
| if( eType >= SbxINTEGER && eType <= SbxDOUBLE ) |
| { |
| double n; |
| if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 ) |
| { |
| nVal = (double) (short) nVal; |
| eType = SbxINTEGER; |
| return sal_True; |
| } |
| } |
| } |
| return sal_False; |
| } |
| |
| sal_Bool SbiExprNode::IsNumber() |
| { |
| return sal_Bool( eNodeType == SbxNUMVAL ); |
| } |
| |
| sal_Bool SbiExprNode::IsString() |
| { |
| return sal_Bool( eNodeType == SbxSTRVAL ); |
| } |
| |
| sal_Bool SbiExprNode::IsVariable() |
| { |
| return sal_Bool( eNodeType == SbxVARVAL ); |
| } |
| |
| sal_Bool SbiExprNode::IsLvalue() |
| { |
| return IsVariable(); |
| } |
| |
| // Ermitteln der Tiefe eines Baumes |
| |
| short SbiExprNode::GetDepth() |
| { |
| if( IsOperand() ) return 0; |
| else |
| { |
| short d1 = pLeft->GetDepth(); |
| short d2 = pRight->GetDepth(); |
| return( (d1 < d2 ) ? d2 : d1 ) + 1; |
| } |
| } |
| |
| |
| // Abgleich eines Baumes: |
| // 1. Constant Folding |
| // 2. Typabgleich |
| // 3. Umwandlung der Operanden in Strings |
| // 4. Hochziehen der Composite- und Error-Bits |
| |
| void SbiExprNode::Optimize() |
| { |
| FoldConstants(); |
| CollectBits(); |
| } |
| |
| // Hochziehen der Composite- und Fehlerbits |
| |
| void SbiExprNode::CollectBits() |
| { |
| if( pLeft ) |
| { |
| pLeft->CollectBits(); |
| bError |= pLeft->bError; |
| bComposite |= pLeft->bComposite; |
| } |
| if( pRight ) |
| { |
| pRight->CollectBits(); |
| bError |= pRight->bError; |
| bComposite |= pRight->bComposite; |
| } |
| } |
| |
| // Kann ein Zweig umgeformt werden, wird sal_True zurueckgeliefert. In diesem |
| // Fall ist das Ergebnis im linken Zweig. |
| |
| void SbiExprNode::FoldConstants() |
| { |
| if( IsOperand() || eTok == LIKE ) return; |
| if( pLeft ) |
| pLeft->FoldConstants(); |
| if( pRight ) |
| { |
| pRight->FoldConstants(); |
| if( pLeft->IsConstant() && pRight->IsConstant() |
| && pLeft->eNodeType == pRight->eNodeType ) |
| { |
| CollectBits(); |
| if( eTok == CAT ) |
| // CAT verbindet auch zwei Zahlen miteinander! |
| eType = SbxSTRING; |
| if( pLeft->eType == SbxSTRING ) |
| // Kein Type Mismatch! |
| eType = SbxSTRING; |
| if( eType == SbxSTRING ) |
| { |
| String rl( pLeft->GetString() ); |
| String rr( pRight->GetString() ); |
| delete pLeft; pLeft = NULL; |
| delete pRight; pRight = NULL; |
| bComposite = sal_False; |
| if( eTok == PLUS || eTok == CAT ) |
| { |
| eTok = CAT; |
| // Verkettung: |
| aStrVal = rl; |
| aStrVal += rr; |
| eType = SbxSTRING; |
| eNodeType = SbxSTRVAL; |
| } |
| else |
| { |
| eType = SbxDOUBLE; |
| eNodeType = SbxNUMVAL; |
| StringCompare eRes = rr.CompareTo( rl ); |
| switch( eTok ) |
| { |
| case EQ: |
| nVal = ( eRes == COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE; |
| break; |
| case NE: |
| nVal = ( eRes != COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE; |
| break; |
| case LT: |
| nVal = ( eRes == COMPARE_LESS ) ? SbxTRUE : SbxFALSE; |
| break; |
| case GT: |
| nVal = ( eRes == COMPARE_GREATER ) ? SbxTRUE : SbxFALSE; |
| break; |
| case LE: |
| nVal = ( eRes != COMPARE_GREATER ) ? SbxTRUE : SbxFALSE; |
| break; |
| case GE: |
| nVal = ( eRes != COMPARE_LESS ) ? SbxTRUE : SbxFALSE; |
| break; |
| default: |
| pGen->GetParser()->Error( SbERR_CONVERSION ); |
| bError = sal_True; |
| } |
| } |
| } |
| 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-Operationen |
| sal_Bool err = sal_False; |
| if( nl > SbxMAXLNG ) err = sal_True, nl = SbxMAXLNG; |
| else |
| if( nl < SbxMINLNG ) err = sal_True, nl = SbxMINLNG; |
| if( nr > SbxMAXLNG ) err = sal_True, nr = SbxMAXLNG; |
| else |
| if( nr < SbxMINLNG ) err = sal_True, nr = SbxMINLNG; |
| ll = (long) nl; lr = (long) nr; |
| llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5); |
| lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5); |
| if( err ) |
| { |
| pGen->GetParser()->Error( SbERR_MATH_OVERFLOW ); |
| bError = sal_True; |
| } |
| } |
| sal_Bool bBothInt = sal_Bool( pLeft->eType < SbxSINGLE |
| && pRight->eType < SbxSINGLE ); |
| delete pLeft; pLeft = NULL; |
| delete pRight; pRight = NULL; |
| nVal = 0; |
| eType = SbxDOUBLE; |
| eNodeType = SbxNUMVAL; |
| bComposite = sal_False; |
| sal_Bool bCheckType = sal_False; |
| switch( eTok ) |
| { |
| case EXPON: |
| nVal = pow( nl, nr ); break; |
| case MUL: |
| bCheckType = sal_True; |
| nVal = nl * nr; break; |
| case DIV: |
| if( !nr ) |
| { |
| pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL; |
| bError = sal_True; |
| } else nVal = nl / nr; |
| break; |
| case PLUS: |
| bCheckType = sal_True; |
| nVal = nl + nr; break; |
| case MINUS: |
| bCheckType = sal_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 ) |
| { |
| pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL; |
| bError = sal_True; |
| } else nVal = ll / lr; |
| eType = SbxLONG; break; |
| case MOD: |
| if( !lr ) |
| { |
| pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL; |
| bError = sal_True; |
| } else nVal = 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 ) ) |
| pGen->GetParser()->Error( SbERR_MATH_OVERFLOW ); |
| |
| // Den Datentyp wiederherstellen, um Rundungsfehler |
| // zu killen |
| if( bCheckType && bBothInt |
| && nVal >= SbxMINLNG && nVal <= SbxMAXLNG ) |
| { |
| // NK-Stellen weg |
| long n = (long) nVal; |
| nVal = n; |
| eType = ( n >= SbxMININT && n <= SbxMAXINT ) |
| ? SbxINTEGER : SbxLONG; |
| } |
| } |
| } |
| } |
| else if( pLeft && pLeft->IsNumber() ) |
| { |
| nVal = pLeft->nVal; |
| delete pLeft; |
| pLeft = NULL; |
| eType = SbxDOUBLE; |
| eNodeType = SbxNUMVAL; |
| bComposite = sal_False; |
| switch( eTok ) |
| { |
| case NEG: |
| nVal = -nVal; break; |
| case NOT: { |
| // Integer-Operation! |
| sal_Bool err = sal_False; |
| if( nVal > SbxMAXLNG ) err = sal_True, nVal = SbxMAXLNG; |
| else |
| if( nVal < SbxMINLNG ) err = sal_True, nVal = SbxMINLNG; |
| if( err ) |
| { |
| pGen->GetParser()->Error( SbERR_MATH_OVERFLOW ); |
| bError = sal_True; |
| } |
| nVal = (double) ~((long) nVal); |
| eType = SbxLONG; |
| } break; |
| default: break; |
| } |
| } |
| if( eNodeType == SbxNUMVAL ) |
| { |
| // Evtl auf INTEGER falten (wg. besserem Opcode)? |
| if( eType == SbxSINGLE || eType == SbxDOUBLE ) |
| { |
| double x; |
| if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG |
| && !modf( nVal, &x ) ) |
| eType = SbxLONG; |
| } |
| if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT ) |
| eType = SbxINTEGER; |
| } |
| } |
| |
| |