Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / basic / source / comp / exprnode.cxx
blob10c98942d492e3c6be89648da844e7b875c008fb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <math.h>
23 #include <rtl/math.hxx>
24 #include "sbcomp.hxx"
25 #include "expr.hxx"
28 SbiExprNode::SbiExprNode( void )
30 pLeft = NULL;
31 pRight = NULL;
32 eNodeType = SbxDUMMY;
35 SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
37 BaseInit( p );
39 pLeft = l;
40 pRight = r;
41 eTok = t;
42 nVal = 0;
43 eType = SbxVARIANT; // Nodes are always Variant
44 eNodeType = SbxNODE;
47 SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
49 BaseInit( p );
51 eType = t;
52 eNodeType = SbxNUMVAL;
53 nVal = n;
56 SbiExprNode::SbiExprNode( SbiParser* p, const OUString& rVal )
58 BaseInit( p );
60 eType = SbxSTRING;
61 eNodeType = SbxSTRVAL;
62 aStrVal = rVal;
65 SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
67 BaseInit( p );
69 eType = ( t == SbxVARIANT ) ? r.GetType() : t;
70 eNodeType = SbxVARVAL;
71 aVar.pDef = (SbiSymDef*) &r;
72 aVar.pPar = l;
73 aVar.pvMorePar = NULL;
74 aVar.pNext= NULL;
77 // #120061 TypeOf
78 SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId )
80 BaseInit( p );
82 pLeft = l;
83 eType = SbxBOOL;
84 eNodeType = SbxTYPEOF;
85 nTypeStrId = nId;
88 // new <type>
89 SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId )
91 BaseInit( p );
93 eType = SbxOBJECT;
94 eNodeType = SbxNEW;
95 nTypeStrId = nId;
98 // From 1995-12-17, auxiliary function for Ctor for the uniform initialisation
99 void SbiExprNode::BaseInit( SbiParser* p )
101 pGen = &p->aGen;
102 eTok = NIL;
103 pLeft = NULL;
104 pRight = NULL;
105 pWithParent = NULL;
106 bError = false;
109 SbiExprNode::~SbiExprNode()
111 delete pLeft;
112 delete pRight;
113 if( IsVariable() )
115 delete aVar.pPar;
116 delete aVar.pNext;
117 SbiExprListVector* pvMorePar = aVar.pvMorePar;
118 if( pvMorePar )
120 SbiExprListVector::iterator it;
121 for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
122 delete *it;
123 delete pvMorePar;
128 SbiSymDef* SbiExprNode::GetVar()
130 if( eNodeType == SbxVARVAL )
131 return aVar.pDef;
132 else
133 return NULL;
136 SbiSymDef* SbiExprNode::GetRealVar()
138 SbiExprNode* p = GetRealNode();
139 if( p )
140 return p->GetVar();
141 else
142 return NULL;
145 // From 1995-12-18
146 SbiExprNode* SbiExprNode::GetRealNode()
148 if( eNodeType == SbxVARVAL )
150 SbiExprNode* p = this;
151 while( p->aVar.pNext )
152 p = p->aVar.pNext;
153 return p;
155 else
156 return NULL;
159 // This method transform the type, if it fits into the Integer range
161 bool SbiExprNode::IsIntConst()
163 if( eNodeType == SbxNUMVAL )
165 if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
167 double n;
168 if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
170 nVal = (double) (short) nVal;
171 eType = SbxINTEGER;
172 return true;
176 return false;
179 bool SbiExprNode::IsNumber()
181 return eNodeType == SbxNUMVAL;
184 bool SbiExprNode::IsVariable()
186 return eNodeType == SbxVARVAL;
189 bool SbiExprNode::IsLvalue()
191 return IsVariable();
194 // Identify of the depth of a tree
196 short SbiExprNode::GetDepth()
198 if( IsOperand() ) return 0;
199 else
201 short d1 = pLeft->GetDepth();
202 short d2 = pRight->GetDepth();
203 return( (d1 < d2 ) ? d2 : d1 ) + 1;
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
214 void SbiExprNode::Optimize()
216 FoldConstants();
217 CollectBits();
220 // Lifting of the error-bits
222 void SbiExprNode::CollectBits()
224 if( pLeft )
226 pLeft->CollectBits();
227 bError = bError || pLeft->bError;
229 if( pRight )
231 pRight->CollectBits();
232 bError = bError || pRight->bError;
236 // If a twig can be converted, True will be returned. In this case
237 // the result is in the left twig.
239 void SbiExprNode::FoldConstants()
241 if( IsOperand() || eTok == LIKE ) return;
242 if( pLeft )
243 pLeft->FoldConstants();
244 if( pRight )
246 pRight->FoldConstants();
247 if( pLeft->IsConstant() && pRight->IsConstant()
248 && pLeft->eNodeType == pRight->eNodeType )
250 CollectBits();
251 if( eTok == CAT )
252 // CAT affiliate also two numbers!
253 eType = SbxSTRING;
254 if( pLeft->eType == SbxSTRING )
255 // No Type Mismatch!
256 eType = SbxSTRING;
257 if( eType == SbxSTRING )
259 OUString rl( pLeft->GetString() );
260 OUString rr( pRight->GetString() );
261 delete pLeft; pLeft = NULL;
262 delete pRight; pRight = NULL;
263 if( eTok == PLUS || eTok == CAT )
265 eTok = CAT;
266 // Linking:
267 aStrVal = rl;
268 aStrVal += rr;
269 eType = SbxSTRING;
270 eNodeType = SbxSTRVAL;
272 else
274 eType = SbxDOUBLE;
275 eNodeType = SbxNUMVAL;
276 int eRes = rr.compareTo( rl );
277 switch( eTok )
279 case EQ:
280 nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
281 break;
282 case NE:
283 nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
284 break;
285 case LT:
286 nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
287 break;
288 case GT:
289 nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
290 break;
291 case LE:
292 nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
293 break;
294 case GE:
295 nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
296 break;
297 default:
298 pGen->GetParser()->Error( SbERR_CONVERSION );
299 bError = true;
300 break;
304 else
306 double nl = pLeft->nVal;
307 double nr = pRight->nVal;
308 long ll = 0, lr = 0;
309 long llMod = 0, lrMod = 0;
310 if( ( eTok >= AND && eTok <= IMP )
311 || eTok == IDIV || eTok == MOD )
313 // Integer operations
314 sal_Bool err = sal_False;
315 if( nl > SbxMAXLNG ) err = sal_True, nl = SbxMAXLNG;
316 else
317 if( nl < SbxMINLNG ) err = sal_True, nl = SbxMINLNG;
318 if( nr > SbxMAXLNG ) err = sal_True, nr = SbxMAXLNG;
319 else
320 if( nr < SbxMINLNG ) err = sal_True, nr = SbxMINLNG;
321 ll = (long) nl; lr = (long) nr;
322 llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
323 lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
324 if( err )
326 pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
327 bError = true;
330 sal_Bool bBothInt = sal_Bool( pLeft->eType < SbxSINGLE
331 && pRight->eType < SbxSINGLE );
332 delete pLeft; pLeft = NULL;
333 delete pRight; pRight = NULL;
334 nVal = 0;
335 eType = SbxDOUBLE;
336 eNodeType = SbxNUMVAL;
337 sal_Bool bCheckType = sal_False;
338 switch( eTok )
340 case EXPON:
341 nVal = pow( nl, nr ); break;
342 case MUL:
343 bCheckType = sal_True;
344 nVal = nl * nr; break;
345 case DIV:
346 if( !nr )
348 pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
349 bError = true;
350 } else nVal = nl / nr;
351 break;
352 case PLUS:
353 bCheckType = sal_True;
354 nVal = nl + nr; break;
355 case MINUS:
356 bCheckType = sal_True;
357 nVal = nl - nr; break;
358 case EQ:
359 nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
360 eType = SbxINTEGER; break;
361 case NE:
362 nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
363 eType = SbxINTEGER; break;
364 case LT:
365 nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE;
366 eType = SbxINTEGER; break;
367 case GT:
368 nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE;
369 eType = SbxINTEGER; break;
370 case LE:
371 nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
372 eType = SbxINTEGER; break;
373 case GE:
374 nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
375 eType = SbxINTEGER; break;
376 case IDIV:
377 if( !lr )
379 pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
380 bError = true;
381 } else nVal = ll / lr;
382 eType = SbxLONG; break;
383 case MOD:
384 if( !lr )
386 pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
387 bError = true;
388 } else nVal = llMod % lrMod;
389 eType = SbxLONG; break;
390 case AND:
391 nVal = (double) ( ll & lr ); eType = SbxLONG; break;
392 case OR:
393 nVal = (double) ( ll | lr ); eType = SbxLONG; break;
394 case XOR:
395 nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
396 case EQV:
397 nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
398 case IMP:
399 nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
400 default: break;
403 if( !::rtl::math::isFinite( nVal ) )
404 pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
406 // Recover the data type to kill rounding error
407 if( bCheckType && bBothInt
408 && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
410 // Decimal place away
411 long n = (long) nVal;
412 nVal = n;
413 eType = ( n >= SbxMININT && n <= SbxMAXINT )
414 ? SbxINTEGER : SbxLONG;
419 else if( pLeft && pLeft->IsNumber() )
421 nVal = pLeft->nVal;
422 delete pLeft;
423 pLeft = NULL;
424 eType = SbxDOUBLE;
425 eNodeType = SbxNUMVAL;
426 switch( eTok )
428 case NEG:
429 nVal = -nVal; break;
430 case NOT: {
431 // Integer operation!
432 sal_Bool err = sal_False;
433 if( nVal > SbxMAXLNG ) err = sal_True, nVal = SbxMAXLNG;
434 else
435 if( nVal < SbxMINLNG ) err = sal_True, nVal = SbxMINLNG;
436 if( err )
438 pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
439 bError = true;
441 nVal = (double) ~((long) nVal);
442 eType = SbxLONG;
443 } break;
444 default: break;
447 if( eNodeType == SbxNUMVAL )
449 // Potentially convolve in INTEGER (because of better opcode)?
450 if( eType == SbxSINGLE || eType == SbxDOUBLE )
452 double x;
453 if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
454 && !modf( nVal, &x ) )
455 eType = SbxLONG;
457 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
458 eType = SbxINTEGER;
463 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */