1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
23 #include <rtl/math.hxx>
28 SbiExprNode::SbiExprNode( void )
35 SbiExprNode::SbiExprNode( SbiParser
* p
, SbiExprNode
* l
, SbiToken t
, SbiExprNode
* r
)
43 eType
= SbxVARIANT
; // Nodes are always Variant
47 SbiExprNode::SbiExprNode( SbiParser
* p
, double n
, SbxDataType t
)
52 eNodeType
= SbxNUMVAL
;
56 SbiExprNode::SbiExprNode( SbiParser
* p
, const OUString
& rVal
)
61 eNodeType
= SbxSTRVAL
;
65 SbiExprNode::SbiExprNode( SbiParser
* p
, const SbiSymDef
& r
, SbxDataType t
, SbiExprList
* l
)
69 eType
= ( t
== SbxVARIANT
) ? r
.GetType() : t
;
70 eNodeType
= SbxVARVAL
;
71 aVar
.pDef
= (SbiSymDef
*) &r
;
73 aVar
.pvMorePar
= NULL
;
78 SbiExprNode::SbiExprNode( SbiParser
* p
, SbiExprNode
* l
, sal_uInt16 nId
)
84 eNodeType
= SbxTYPEOF
;
89 SbiExprNode::SbiExprNode( SbiParser
* p
, sal_uInt16 nId
)
98 // From 1995-12-17, auxiliary function for Ctor for the uniform initialisation
99 void SbiExprNode::BaseInit( SbiParser
* p
)
109 SbiExprNode::~SbiExprNode()
117 SbiExprListVector
* pvMorePar
= aVar
.pvMorePar
;
120 SbiExprListVector::iterator it
;
121 for( it
= pvMorePar
->begin() ; it
!= pvMorePar
->end() ; ++it
)
128 SbiSymDef
* SbiExprNode::GetVar()
130 if( eNodeType
== SbxVARVAL
)
136 SbiSymDef
* SbiExprNode::GetRealVar()
138 SbiExprNode
* p
= GetRealNode();
146 SbiExprNode
* SbiExprNode::GetRealNode()
148 if( eNodeType
== SbxVARVAL
)
150 SbiExprNode
* p
= this;
151 while( p
->aVar
.pNext
)
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
)
168 if( nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
&& modf( nVal
, &n
) == 0 )
170 nVal
= (double) (short) nVal
;
179 bool SbiExprNode::IsNumber()
181 return eNodeType
== SbxNUMVAL
;
184 bool SbiExprNode::IsVariable()
186 return eNodeType
== SbxVARVAL
;
189 bool SbiExprNode::IsLvalue()
194 // Identify of the depth of a tree
196 short SbiExprNode::GetDepth()
198 if( IsOperand() ) return 0;
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()
220 // Lifting of the error-bits
222 void SbiExprNode::CollectBits()
226 pLeft
->CollectBits();
227 bError
= bError
|| pLeft
->bError
;
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;
243 pLeft
->FoldConstants();
246 pRight
->FoldConstants();
247 if( pLeft
->IsConstant() && pRight
->IsConstant()
248 && pLeft
->eNodeType
== pRight
->eNodeType
)
252 // CAT affiliate also two numbers!
254 if( pLeft
->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
)
270 eNodeType
= SbxSTRVAL
;
275 eNodeType
= SbxNUMVAL
;
276 int eRes
= rr
.compareTo( rl
);
280 nVal
= ( eRes
== 0 ) ? SbxTRUE
: SbxFALSE
;
283 nVal
= ( eRes
!= 0 ) ? SbxTRUE
: SbxFALSE
;
286 nVal
= ( eRes
< 0 ) ? SbxTRUE
: SbxFALSE
;
289 nVal
= ( eRes
> 0 ) ? SbxTRUE
: SbxFALSE
;
292 nVal
= ( eRes
<= 0 ) ? SbxTRUE
: SbxFALSE
;
295 nVal
= ( eRes
>= 0 ) ? SbxTRUE
: SbxFALSE
;
298 pGen
->GetParser()->Error( SbERR_CONVERSION
);
306 double nl
= pLeft
->nVal
;
307 double nr
= pRight
->nVal
;
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
;
317 if( nl
< SbxMINLNG
) err
= sal_True
, nl
= SbxMINLNG
;
318 if( nr
> SbxMAXLNG
) err
= sal_True
, nr
= SbxMAXLNG
;
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);
326 pGen
->GetParser()->Error( SbERR_MATH_OVERFLOW
);
330 sal_Bool bBothInt
= sal_Bool( pLeft
->eType
< SbxSINGLE
331 && pRight
->eType
< SbxSINGLE
);
332 delete pLeft
; pLeft
= NULL
;
333 delete pRight
; pRight
= NULL
;
336 eNodeType
= SbxNUMVAL
;
337 sal_Bool bCheckType
= sal_False
;
341 nVal
= pow( nl
, nr
); break;
343 bCheckType
= sal_True
;
344 nVal
= nl
* nr
; break;
348 pGen
->GetParser()->Error( SbERR_ZERODIV
); nVal
= HUGE_VAL
;
350 } else nVal
= nl
/ nr
;
353 bCheckType
= sal_True
;
354 nVal
= nl
+ nr
; break;
356 bCheckType
= sal_True
;
357 nVal
= nl
- nr
; break;
359 nVal
= ( nl
== nr
) ? SbxTRUE
: SbxFALSE
;
360 eType
= SbxINTEGER
; break;
362 nVal
= ( nl
!= nr
) ? SbxTRUE
: SbxFALSE
;
363 eType
= SbxINTEGER
; break;
365 nVal
= ( nl
< nr
) ? SbxTRUE
: SbxFALSE
;
366 eType
= SbxINTEGER
; break;
368 nVal
= ( nl
> nr
) ? SbxTRUE
: SbxFALSE
;
369 eType
= SbxINTEGER
; break;
371 nVal
= ( nl
<= nr
) ? SbxTRUE
: SbxFALSE
;
372 eType
= SbxINTEGER
; break;
374 nVal
= ( nl
>= nr
) ? SbxTRUE
: SbxFALSE
;
375 eType
= SbxINTEGER
; break;
379 pGen
->GetParser()->Error( SbERR_ZERODIV
); nVal
= HUGE_VAL
;
381 } else nVal
= ll
/ lr
;
382 eType
= SbxLONG
; break;
386 pGen
->GetParser()->Error( SbERR_ZERODIV
); nVal
= HUGE_VAL
;
388 } else nVal
= llMod
% lrMod
;
389 eType
= SbxLONG
; break;
391 nVal
= (double) ( ll
& lr
); eType
= SbxLONG
; break;
393 nVal
= (double) ( ll
| lr
); eType
= SbxLONG
; break;
395 nVal
= (double) ( ll
^ lr
); eType
= SbxLONG
; break;
397 nVal
= (double) ( ~ll
^ lr
); eType
= SbxLONG
; break;
399 nVal
= (double) ( ~ll
| lr
); eType
= SbxLONG
; 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
;
413 eType
= ( n
>= SbxMININT
&& n
<= SbxMAXINT
)
414 ? SbxINTEGER
: SbxLONG
;
419 else if( pLeft
&& pLeft
->IsNumber() )
425 eNodeType
= SbxNUMVAL
;
431 // Integer operation!
432 sal_Bool err
= sal_False
;
433 if( nVal
> SbxMAXLNG
) err
= sal_True
, nVal
= SbxMAXLNG
;
435 if( nVal
< SbxMINLNG
) err
= sal_True
, nVal
= SbxMINLNG
;
438 pGen
->GetParser()->Error( SbERR_MATH_OVERFLOW
);
441 nVal
= (double) ~((long) nVal
);
447 if( eNodeType
== SbxNUMVAL
)
449 // Potentially convolve in INTEGER (because of better opcode)?
450 if( eType
== SbxSINGLE
|| eType
== SbxDOUBLE
)
453 if( nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
454 && !modf( nVal
, &x
) )
457 if( eType
== SbxLONG
&& nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
)
463 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */