xref: /trunk/main/basic/source/comp/exprnode.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 
31 #include <math.h>
32 
33 #include <rtl/math.hxx>
34 #include "sbcomp.hxx"
35 #include "expr.hxx"
36 
37 //////////////////////////////////////////////////////////////////////////
38 
39 SbiExprNode::SbiExprNode( void )
40 {
41     pLeft = NULL;
42     pRight = NULL;
43     eNodeType = SbxDUMMY;
44 }
45 
46 SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
47 {
48     BaseInit( p );
49 
50     pLeft     = l;
51     pRight    = r;
52     eTok      = t;
53     nVal      = 0;
54     eType     = SbxVARIANT;     // Nodes sind immer Variant
55     eNodeType = SbxNODE;
56     bComposite= sal_True;
57 }
58 
59 SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
60 {
61     BaseInit( p );
62 
63     eType     = t;
64     eNodeType = SbxNUMVAL;
65     nVal      = n;
66 }
67 
68 SbiExprNode::SbiExprNode( SbiParser* p, const String& rVal )
69 {
70     BaseInit( p );
71 
72     eType     = SbxSTRING;
73     eNodeType = SbxSTRVAL;
74     aStrVal   = rVal;
75 }
76 
77 SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
78 {
79     BaseInit( p );
80 
81     eType     = ( t == SbxVARIANT ) ? r.GetType() : t;
82     eNodeType = SbxVARVAL;
83     aVar.pDef = (SbiSymDef*) &r;
84     aVar.pPar = l;
85     aVar.pvMorePar = NULL;
86     aVar.pNext= NULL;
87 
88     // Funktionsergebnisse sind nie starr
89     bComposite= sal_Bool( aVar.pDef->GetProcDef() != NULL );
90 }
91 
92 // #120061 TypeOf
93 SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId )
94 {
95     BaseInit( p );
96 
97     pLeft      = l;
98     eType      = SbxBOOL;
99     eNodeType  = SbxTYPEOF;
100     nTypeStrId = nId;
101 }
102 
103 // new <type>
104 SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId )
105 {
106     BaseInit( p );
107 
108     eType     = SbxOBJECT;
109     eNodeType = SbxNEW;
110     nTypeStrId = nId;
111 }
112 
113 // AB: 17.12.95, Hilfsfunktion fuer Ctor fuer einheitliche Initialisierung
114 void SbiExprNode::BaseInit( SbiParser* p )
115 {
116     pGen = &p->aGen;
117     eTok = NIL;
118     pLeft       = NULL;
119     pRight      = NULL;
120     pWithParent = NULL;
121     bComposite  = sal_False;
122     bError      = sal_False;
123 }
124 
125 SbiExprNode::~SbiExprNode()
126 {
127     delete pLeft;
128     delete pRight;
129     if( IsVariable() )
130     {
131         delete aVar.pPar;
132         delete aVar.pNext;
133         SbiExprListVector* pvMorePar = aVar.pvMorePar;
134         if( pvMorePar )
135         {
136             SbiExprListVector::iterator it;
137             for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
138                 delete *it;
139             delete pvMorePar;
140         }
141     }
142 }
143 
144 SbiSymDef* SbiExprNode::GetVar()
145 {
146     if( eNodeType == SbxVARVAL )
147         return aVar.pDef;
148     else
149         return NULL;
150 }
151 
152 SbiSymDef* SbiExprNode::GetRealVar()
153 {
154     SbiExprNode* p = GetRealNode();
155     if( p )
156         return p->GetVar();
157     else
158         return NULL;
159 }
160 
161 // AB: 18.12.95
162 SbiExprNode* SbiExprNode::GetRealNode()
163 {
164     if( eNodeType == SbxVARVAL )
165     {
166         SbiExprNode* p = this;
167         while( p->aVar.pNext )
168             p = p->aVar.pNext;
169         return p;
170     }
171     else
172         return NULL;
173 }
174 
175 // Diese Methode setzt den Typ um, falls er in den Integer-Bereich hineinpasst
176 
177 sal_Bool SbiExprNode::IsIntConst()
178 {
179     if( eNodeType == SbxNUMVAL )
180     {
181         if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
182         {
183             double n;
184             if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
185             {
186                 nVal = (double) (short) nVal;
187                 eType = SbxINTEGER;
188                 return sal_True;
189             }
190         }
191     }
192     return sal_False;
193 }
194 
195 sal_Bool SbiExprNode::IsNumber()
196 {
197     return sal_Bool( eNodeType == SbxNUMVAL );
198 }
199 
200 sal_Bool SbiExprNode::IsString()
201 {
202     return sal_Bool( eNodeType == SbxSTRVAL );
203 }
204 
205 sal_Bool SbiExprNode::IsVariable()
206 {
207     return sal_Bool( eNodeType == SbxVARVAL );
208 }
209 
210 sal_Bool SbiExprNode::IsLvalue()
211 {
212     return IsVariable();
213 }
214 
215 // Ermitteln der Tiefe eines Baumes
216 
217 short SbiExprNode::GetDepth()
218 {
219     if( IsOperand() ) return 0;
220     else
221     {
222         short d1 = pLeft->GetDepth();
223         short d2 = pRight->GetDepth();
224         return( (d1 < d2 ) ? d2 : d1 ) + 1;
225     }
226 }
227 
228 
229 // Abgleich eines Baumes:
230 // 1. Constant Folding
231 // 2. Typabgleich
232 // 3. Umwandlung der Operanden in Strings
233 // 4. Hochziehen der Composite- und Error-Bits
234 
235 void SbiExprNode::Optimize()
236 {
237     FoldConstants();
238     CollectBits();
239 }
240 
241 // Hochziehen der Composite- und Fehlerbits
242 
243 void SbiExprNode::CollectBits()
244 {
245     if( pLeft )
246     {
247         pLeft->CollectBits();
248         bError |= pLeft->bError;
249         bComposite |= pLeft->bComposite;
250     }
251     if( pRight )
252     {
253         pRight->CollectBits();
254         bError |= pRight->bError;
255         bComposite |= pRight->bComposite;
256     }
257 }
258 
259 // Kann ein Zweig umgeformt werden, wird sal_True zurueckgeliefert. In diesem
260 // Fall ist das Ergebnis im linken Zweig.
261 
262 void SbiExprNode::FoldConstants()
263 {
264     if( IsOperand() || eTok == LIKE ) return;
265     if( pLeft )
266         pLeft->FoldConstants();
267     if( pRight )
268     {
269         pRight->FoldConstants();
270         if( pLeft->IsConstant() && pRight->IsConstant()
271             && pLeft->eNodeType == pRight->eNodeType )
272         {
273             CollectBits();
274             if( eTok == CAT )
275                 // CAT verbindet auch zwei Zahlen miteinander!
276                 eType = SbxSTRING;
277             if( pLeft->eType == SbxSTRING )
278                 // Kein Type Mismatch!
279                 eType = SbxSTRING;
280             if( eType == SbxSTRING )
281             {
282                 String rl( pLeft->GetString() );
283                 String rr( pRight->GetString() );
284                 delete pLeft; pLeft = NULL;
285                 delete pRight; pRight = NULL;
286                 bComposite = sal_False;
287                 if( eTok == PLUS || eTok == CAT )
288                 {
289                     eTok = CAT;
290                     // Verkettung:
291                     aStrVal = rl;
292                     aStrVal += rr;
293                     eType = SbxSTRING;
294                     eNodeType = SbxSTRVAL;
295                 }
296                 else
297                 {
298                     eType = SbxDOUBLE;
299                     eNodeType = SbxNUMVAL;
300                     StringCompare eRes = rr.CompareTo( rl );
301                     switch( eTok )
302                     {
303                         case EQ:
304                             nVal = ( eRes == COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE;
305                             break;
306                         case NE:
307                             nVal = ( eRes != COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE;
308                             break;
309                         case LT:
310                             nVal = ( eRes == COMPARE_LESS ) ? SbxTRUE : SbxFALSE;
311                             break;
312                         case GT:
313                             nVal = ( eRes == COMPARE_GREATER ) ? SbxTRUE : SbxFALSE;
314                             break;
315                         case LE:
316                             nVal = ( eRes != COMPARE_GREATER ) ? SbxTRUE : SbxFALSE;
317                             break;
318                         case GE:
319                             nVal = ( eRes != COMPARE_LESS ) ? SbxTRUE : SbxFALSE;
320                             break;
321                         default:
322                             pGen->GetParser()->Error( SbERR_CONVERSION );
323                             bError = sal_True;
324                     }
325                 }
326             }
327             else
328             {
329                 double nl = pLeft->nVal;
330                 double nr = pRight->nVal;
331                 long ll = 0, lr = 0;
332                 long llMod = 0, lrMod = 0;
333                 if( ( eTok >= AND && eTok <= IMP )
334                    || eTok == IDIV || eTok == MOD )
335                 {
336                     // Integer-Operationen
337                     sal_Bool err = sal_False;
338                     if( nl > SbxMAXLNG ) err = sal_True, nl = SbxMAXLNG;
339                     else
340                     if( nl < SbxMINLNG ) err = sal_True, nl = SbxMINLNG;
341                     if( nr > SbxMAXLNG ) err = sal_True, nr = SbxMAXLNG;
342                     else
343                     if( nr < SbxMINLNG ) err = sal_True, nr = SbxMINLNG;
344                     ll = (long) nl; lr = (long) nr;
345                     llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
346                     lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
347                     if( err )
348                     {
349                         pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
350                         bError = sal_True;
351                     }
352                 }
353                 sal_Bool bBothInt = sal_Bool( pLeft->eType < SbxSINGLE
354                                    && pRight->eType < SbxSINGLE );
355                 delete pLeft; pLeft = NULL;
356                 delete pRight; pRight = NULL;
357                 nVal = 0;
358                 eType = SbxDOUBLE;
359                 eNodeType = SbxNUMVAL;
360                 bComposite = sal_False;
361                 sal_Bool bCheckType = sal_False;
362                 switch( eTok )
363                 {
364                     case EXPON:
365                         nVal = pow( nl, nr ); break;
366                     case MUL:
367                         bCheckType = sal_True;
368                         nVal = nl * nr; break;
369                     case DIV:
370                         if( !nr )
371                         {
372                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
373                             bError = sal_True;
374                         } else nVal = nl / nr;
375                         break;
376                     case PLUS:
377                         bCheckType = sal_True;
378                         nVal = nl + nr; break;
379                     case MINUS:
380                         bCheckType = sal_True;
381                         nVal = nl - nr; break;
382                     case EQ:
383                         nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
384                         eType = SbxINTEGER; break;
385                     case NE:
386                         nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
387                         eType = SbxINTEGER; break;
388                     case LT:
389                         nVal = ( nl <  nr ) ? SbxTRUE : SbxFALSE;
390                         eType = SbxINTEGER; break;
391                     case GT:
392                         nVal = ( nl >  nr ) ? SbxTRUE : SbxFALSE;
393                         eType = SbxINTEGER; break;
394                     case LE:
395                         nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
396                         eType = SbxINTEGER; break;
397                     case GE:
398                         nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
399                         eType = SbxINTEGER; break;
400                     case IDIV:
401                         if( !lr )
402                         {
403                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
404                             bError = sal_True;
405                         } else nVal = ll / lr;
406                         eType = SbxLONG; break;
407                     case MOD:
408                         if( !lr )
409                         {
410                             pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
411                             bError = sal_True;
412                         } else nVal = llMod % lrMod;
413                         eType = SbxLONG; break;
414                     case AND:
415                         nVal = (double) ( ll & lr ); eType = SbxLONG; break;
416                     case OR:
417                         nVal = (double) ( ll | lr ); eType = SbxLONG; break;
418                     case XOR:
419                         nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
420                     case EQV:
421                         nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
422                     case IMP:
423                         nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
424                     default: break;
425                 }
426 
427                 if( !::rtl::math::isFinite( nVal ) )
428                     pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
429 
430                 // Den Datentyp wiederherstellen, um Rundungsfehler
431                 // zu killen
432                 if( bCheckType && bBothInt
433                  && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
434                 {
435                     // NK-Stellen weg
436                     long n = (long) nVal;
437                     nVal = n;
438                     eType = ( n >= SbxMININT && n <= SbxMAXINT )
439                           ? SbxINTEGER : SbxLONG;
440                 }
441             }
442         }
443     }
444     else if( pLeft && pLeft->IsNumber() )
445     {
446         nVal = pLeft->nVal;
447         delete pLeft;
448         pLeft = NULL;
449         eType = SbxDOUBLE;
450         eNodeType = SbxNUMVAL;
451         bComposite = sal_False;
452         switch( eTok )
453         {
454             case NEG:
455                 nVal = -nVal; break;
456             case NOT: {
457                 // Integer-Operation!
458                 sal_Bool err = sal_False;
459                 if( nVal > SbxMAXLNG ) err = sal_True, nVal = SbxMAXLNG;
460                 else
461                 if( nVal < SbxMINLNG ) err = sal_True, nVal = SbxMINLNG;
462                 if( err )
463                 {
464                     pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
465                     bError = sal_True;
466                 }
467                 nVal = (double) ~((long) nVal);
468                 eType = SbxLONG;
469                 } break;
470             default: break;
471         }
472     }
473     if( eNodeType == SbxNUMVAL )
474     {
475         // Evtl auf INTEGER falten (wg. besserem Opcode)?
476         if( eType == SbxSINGLE || eType == SbxDOUBLE )
477         {
478             double x;
479             if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
480             && !modf( nVal, &x ) )
481                 eType = SbxLONG;
482         }
483         if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
484             eType = SbxINTEGER;
485     }
486 }
487 
488 
489