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