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 <o3tl/temporary.hxx>
24 #include <rtl/math.hxx>
28 #include <basic/sberrors.hxx>
30 SbiExprNode::SbiExprNode( std::unique_ptr
<SbiExprNode
> l
, SbiToken t
, std::unique_ptr
<SbiExprNode
> r
) :
35 eType(SbxVARIANT
), // Nodes are always Variant
41 SbiExprNode::SbiExprNode( double n
, SbxDataType t
):
51 SbiExprNode::SbiExprNode( const OUString
& rVal
):
61 SbiExprNode::SbiExprNode( const SbiSymDef
& r
, SbxDataType t
, SbiExprListPtr l
) :
67 eType
= ( t
== SbxVARIANT
) ? r
.GetType() : t
;
68 aVar
.pDef
= const_cast<SbiSymDef
*>(&r
);
69 aVar
.pPar
= l
.release();
70 aVar
.pvMorePar
= nullptr;
75 SbiExprNode::SbiExprNode( std::unique_ptr
<SbiExprNode
> l
, sal_uInt16 nId
) :
87 SbiExprNode::SbiExprNode( sal_uInt16 nId
) :
97 SbiExprNode::SbiExprNode() :
106 SbiExprNode::~SbiExprNode()
112 delete aVar
.pvMorePar
;
116 SbiSymDef
* SbiExprNode::GetVar()
118 if( eNodeType
== SbxVARVAL
)
124 SbiSymDef
* SbiExprNode::GetRealVar()
126 SbiExprNode
* p
= GetRealNode();
134 SbiExprNode
* SbiExprNode::GetRealNode()
136 if( eNodeType
== SbxVARVAL
)
138 SbiExprNode
* p
= this;
139 while( p
->aVar
.pNext
)
147 // This method transform the type, if it fits into the Integer range
149 void SbiExprNode::ConvertToIntConstIfPossible()
151 if( eNodeType
== SbxNUMVAL
)
153 if( eType
>= SbxINTEGER
&& eType
<= SbxDOUBLE
)
155 if( nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
&& modf( nVal
, &o3tl::temporary(double()) ) == 0 )
163 bool SbiExprNode::IsNumber() const
165 return eNodeType
== SbxNUMVAL
;
168 bool SbiExprNode::IsVariable() const
170 return eNodeType
== SbxVARVAL
;
173 bool SbiExprNode::IsLvalue() const
178 // Adjustment of a tree:
179 // 1. Constant Folding
180 // 2. Type-Adjustment
181 // 3. Conversion of the operands into Strings
182 // 4. Lifting of the composite- and error-bits
184 void SbiExprNode::Optimize(SbiParser
* pParser
)
186 FoldConstants(pParser
);
190 // Lifting of the error-bits
192 void SbiExprNode::CollectBits()
196 pLeft
->CollectBits();
197 bError
= bError
|| pLeft
->bError
;
201 pRight
->CollectBits();
202 bError
= bError
|| pRight
->bError
;
206 // If a twig can be converted, True will be returned. In this case
207 // the result is in the left twig.
208 void SbiExprNode::FoldConstants(SbiParser
* pParser
)
210 if( IsOperand() || eTok
== LIKE
) return;
212 if (pLeft
&& !pRight
)
213 FoldConstantsUnaryNode(pParser
);
214 else if (pLeft
&& pRight
)
215 FoldConstantsBinaryNode(pParser
);
217 if( eNodeType
== SbxNUMVAL
)
219 // Potentially convolve in INTEGER (because of better opcode)?
220 if( eType
== SbxSINGLE
|| eType
== SbxDOUBLE
)
222 if( nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
223 && !modf( nVal
, &o3tl::temporary(double()) ) )
226 if( eType
== SbxLONG
&& nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
)
231 void SbiExprNode::FoldConstantsBinaryNode(SbiParser
* pParser
)
233 pLeft
->FoldConstants(pParser
);
234 pRight
->FoldConstants(pParser
);
235 if( pLeft
->IsConstant() && pRight
->IsConstant()
236 && pLeft
->eNodeType
== pRight
->eNodeType
)
240 // CAT affiliate also two numbers!
242 if( pLeft
->eType
== SbxSTRING
)
245 if( eType
== SbxSTRING
)
247 OUString
rl( pLeft
->GetString() );
248 OUString
rr( pRight
->GetString() );
251 if( eTok
== PLUS
|| eTok
== CAT
)
258 eNodeType
= SbxSTRVAL
;
263 eNodeType
= SbxNUMVAL
;
264 int eRes
= rr
.compareTo( rl
);
268 nVal
= ( eRes
== 0 ) ? SbxTRUE
: SbxFALSE
;
271 nVal
= ( eRes
!= 0 ) ? SbxTRUE
: SbxFALSE
;
274 nVal
= ( eRes
< 0 ) ? SbxTRUE
: SbxFALSE
;
277 nVal
= ( eRes
> 0 ) ? SbxTRUE
: SbxFALSE
;
280 nVal
= ( eRes
<= 0 ) ? SbxTRUE
: SbxFALSE
;
283 nVal
= ( eRes
>= 0 ) ? SbxTRUE
: SbxFALSE
;
286 pParser
->Error( ERRCODE_BASIC_CONVERSION
);
294 double nl
= pLeft
->nVal
;
295 double nr
= pRight
->nVal
;
297 long llMod
= 0, lrMod
= 0;
298 if( ( eTok
>= AND
&& eTok
<= IMP
)
299 || eTok
== IDIV
|| eTok
== MOD
)
301 // Integer operations
308 else if( nl
< SbxMINLNG
)
318 else if( nr
< SbxMINLNG
)
323 ll
= static_cast<long>(nl
); lr
= static_cast<long>(nr
);
324 llMod
= static_cast<long>(nl
);
325 lrMod
= static_cast<long>(nr
);
328 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
332 bool bBothInt
= ( pLeft
->eType
< SbxSINGLE
333 && pRight
->eType
< SbxSINGLE
);
338 eNodeType
= SbxNUMVAL
;
339 bool bCheckType
= false;
343 nVal
= pow( nl
, nr
); break;
346 nVal
= nl
* nr
; break;
350 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
352 } else nVal
= nl
/ nr
;
356 nVal
= nl
+ nr
; break;
359 nVal
= nl
- nr
; break;
361 nVal
= ( nl
== nr
) ? SbxTRUE
: SbxFALSE
;
362 eType
= SbxINTEGER
; break;
364 nVal
= ( nl
!= nr
) ? SbxTRUE
: SbxFALSE
;
365 eType
= SbxINTEGER
; break;
367 nVal
= ( nl
< nr
) ? SbxTRUE
: SbxFALSE
;
368 eType
= SbxINTEGER
; break;
370 nVal
= ( nl
> nr
) ? SbxTRUE
: SbxFALSE
;
371 eType
= SbxINTEGER
; break;
373 nVal
= ( nl
<= nr
) ? SbxTRUE
: SbxFALSE
;
374 eType
= SbxINTEGER
; break;
376 nVal
= ( nl
>= nr
) ? SbxTRUE
: SbxFALSE
;
377 eType
= SbxINTEGER
; break;
381 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
383 } else nVal
= ll
/ lr
;
384 eType
= SbxLONG
; break;
388 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
390 } else nVal
= llMod
- lrMod
* (llMod
/lrMod
);
391 eType
= SbxLONG
; break;
393 nVal
= static_cast<double>( ll
& lr
); eType
= SbxLONG
; break;
395 nVal
= static_cast<double>( ll
| lr
); eType
= SbxLONG
; break;
397 nVal
= static_cast<double>( ll
^ lr
); eType
= SbxLONG
; break;
399 nVal
= static_cast<double>( ~ll
^ lr
); eType
= SbxLONG
; break;
401 nVal
= static_cast<double>( ~ll
| lr
); eType
= SbxLONG
; break;
405 if( !::rtl::math::isFinite( nVal
) )
406 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
408 // Recover the data type to kill rounding error
409 if( bCheckType
&& bBothInt
410 && nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
)
412 // Decimal place away
413 long n
= static_cast<long>(nVal
);
415 eType
= ( n
>= SbxMININT
&& n
<= SbxMAXINT
)
416 ? SbxINTEGER
: SbxLONG
;
422 void SbiExprNode::FoldConstantsUnaryNode(SbiParser
* pParser
)
424 pLeft
->FoldConstants(pParser
);
425 if (pLeft
->IsNumber())
430 eNodeType
= SbxNUMVAL
;
436 // Integer operation!
438 if( nVal
> SbxMAXLNG
)
443 else if( nVal
< SbxMINLNG
)
450 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
453 nVal
= static_cast<double>(~static_cast<long>(nVal
));
459 if( eNodeType
== SbxNUMVAL
)
461 // Potentially convolve in INTEGER (because of better opcode)?
462 if( eType
== SbxSINGLE
|| eType
== SbxDOUBLE
)
464 if( nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
465 && !modf( nVal
, &o3tl::temporary(double()) ) )
468 if( eType
== SbxLONG
&& nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
)
474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */