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>
26 #include <tools/long.hxx>
28 #include <basic/sberrors.hxx>
30 #include <rtl/math.hxx>
32 SbiExprNode::SbiExprNode( std::unique_ptr
<SbiExprNode
> l
, SbiToken t
, std::unique_ptr
<SbiExprNode
> r
) :
37 eType(SbxVARIANT
), // Nodes are always Variant
43 SbiExprNode::SbiExprNode( double n
, SbxDataType t
):
53 SbiExprNode::SbiExprNode( const OUString
& rVal
):
63 SbiExprNode::SbiExprNode( const SbiSymDef
& r
, SbxDataType t
, SbiExprListPtr l
) :
69 eType
= ( t
== SbxVARIANT
) ? r
.GetType() : t
;
70 aVar
.pDef
= const_cast<SbiSymDef
*>(&r
);
71 aVar
.pPar
= l
.release();
72 aVar
.pvMorePar
= nullptr;
77 SbiExprNode::SbiExprNode( std::unique_ptr
<SbiExprNode
> l
, sal_uInt16 nId
) :
89 SbiExprNode::SbiExprNode( sal_uInt16 nId
) :
99 SbiExprNode::SbiExprNode() :
100 pWithParent(nullptr),
108 SbiExprNode::~SbiExprNode()
114 delete aVar
.pvMorePar
;
118 SbiSymDef
* SbiExprNode::GetVar()
120 if( eNodeType
== SbxVARVAL
)
126 SbiSymDef
* SbiExprNode::GetRealVar()
128 SbiExprNode
* p
= GetRealNode();
136 SbiExprNode
* SbiExprNode::GetRealNode()
138 if( eNodeType
== SbxVARVAL
)
140 SbiExprNode
* p
= this;
141 while( p
->aVar
.pNext
)
149 // This method transform the type, if it fits into the Integer range
151 void SbiExprNode::ConvertToIntConstIfPossible()
153 if( eNodeType
== SbxNUMVAL
)
155 if( eType
>= SbxINTEGER
&& eType
<= SbxDOUBLE
)
157 if( nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
&& modf( nVal
, &o3tl::temporary(double()) ) == 0 )
165 bool SbiExprNode::IsNumber() const
167 return eNodeType
== SbxNUMVAL
;
170 bool SbiExprNode::IsVariable() const
172 return eNodeType
== SbxVARVAL
;
175 bool SbiExprNode::IsLvalue() const
180 // Adjustment of a tree:
181 // 1. Constant Folding
182 // 2. Type-Adjustment
183 // 3. Conversion of the operands into Strings
184 // 4. Lifting of the composite- and error-bits
186 void SbiExprNode::Optimize(SbiParser
* pParser
)
188 FoldConstants(pParser
);
192 // Lifting of the error-bits
194 void SbiExprNode::CollectBits()
198 pLeft
->CollectBits();
199 bError
= bError
|| pLeft
->bError
;
203 pRight
->CollectBits();
204 bError
= bError
|| pRight
->bError
;
208 // If a twig can be converted, True will be returned. In this case
209 // the result is in the left twig.
210 void SbiExprNode::FoldConstants(SbiParser
* pParser
)
212 if( IsOperand() || eTok
== LIKE
) return;
214 if (pLeft
&& !pRight
)
215 FoldConstantsUnaryNode(pParser
);
216 else if (pLeft
&& pRight
)
217 FoldConstantsBinaryNode(pParser
);
219 if( eNodeType
== SbxNUMVAL
)
221 // Potentially convolve in INTEGER (because of better opcode)?
222 if( eType
== SbxSINGLE
|| eType
== SbxDOUBLE
)
224 if( nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
225 && !modf( nVal
, &o3tl::temporary(double()) ) )
228 if( eType
== SbxLONG
&& nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
)
233 void SbiExprNode::FoldConstantsBinaryNode(SbiParser
* pParser
)
235 pLeft
->FoldConstants(pParser
);
236 pRight
->FoldConstants(pParser
);
237 if( !(pLeft
->IsConstant() && pRight
->IsConstant()
238 && pLeft
->eNodeType
== pRight
->eNodeType
) )
243 // CAT affiliate also two numbers!
245 if( pLeft
->eType
== SbxSTRING
)
248 if( eType
== SbxSTRING
)
250 OUString
rl( pLeft
->GetString() );
251 OUString
rr( pRight
->GetString() );
254 if( eTok
== PLUS
|| eTok
== CAT
)
261 eNodeType
= SbxSTRVAL
;
266 eNodeType
= SbxNUMVAL
;
267 int eRes
= rr
.compareTo( rl
);
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 nVal
= ( eRes
<= 0 ) ? SbxTRUE
: SbxFALSE
;
289 pParser
->Error( ERRCODE_BASIC_CONVERSION
);
297 double nl
= pLeft
->nVal
;
298 double nr
= pRight
->nVal
;
299 // tdf#141201 - round MOD literals to Integer values
302 nl
= rtl::math::round(nl
);
303 nr
= rtl::math::round(nr
);
305 tools::Long ll
= 0, lr
= 0;
306 if( ( eTok
>= AND
&& eTok
<= IMP
)
307 || eTok
== IDIV
|| eTok
== MOD
)
309 // Integer operations
316 else if( nl
< SbxMINLNG
)
326 else if( nr
< SbxMINLNG
)
331 ll
= static_cast<tools::Long
>(nl
); lr
= static_cast<tools::Long
>(nr
);
334 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
338 bool bBothInt
= ( pLeft
->eType
< SbxSINGLE
339 && pRight
->eType
< SbxSINGLE
);
344 eNodeType
= SbxNUMVAL
;
345 bool bCheckType
= false;
349 nVal
= pow( nl
, nr
); break;
352 nVal
= nl
* nr
; break;
356 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
358 } else nVal
= nl
/ nr
;
362 nVal
= nl
+ nr
; break;
365 nVal
= nl
- nr
; 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;
379 nVal
= ( nl
<= nr
) ? SbxTRUE
: SbxFALSE
;
380 eType
= SbxINTEGER
; break;
382 nVal
= ( nl
>= nr
) ? SbxTRUE
: SbxFALSE
;
383 eType
= SbxINTEGER
; break;
387 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
389 } else nVal
= ll
/ lr
;
390 eType
= SbxLONG
; break;
394 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
396 } else nVal
= ll
- lr
* (ll
/lr
);
397 eType
= SbxLONG
; break;
399 nVal
= static_cast<double>( ll
& lr
); eType
= SbxLONG
; break;
401 nVal
= static_cast<double>( ll
| lr
); eType
= SbxLONG
; break;
403 nVal
= static_cast<double>( ll
^ lr
); eType
= SbxLONG
; break;
405 nVal
= static_cast<double>( ~ll
^ lr
); eType
= SbxLONG
; break;
407 nVal
= static_cast<double>( ~ll
| lr
); eType
= SbxLONG
; break;
411 if( !std::isfinite( nVal
) )
412 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
414 // Recover the data type to kill rounding error
415 if( bCheckType
&& bBothInt
416 && nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
)
418 // Decimal place away
419 tools::Long n
= static_cast<tools::Long
>(nVal
);
421 eType
= ( n
>= SbxMININT
&& n
<= SbxMAXINT
)
422 ? SbxINTEGER
: SbxLONG
;
427 void SbiExprNode::FoldConstantsUnaryNode(SbiParser
* pParser
)
429 pLeft
->FoldConstants(pParser
);
430 if (pLeft
->IsNumber())
435 eNodeType
= SbxNUMVAL
;
441 // Integer operation!
443 if( nVal
> SbxMAXLNG
)
448 else if( nVal
< SbxMINLNG
)
455 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
458 nVal
= static_cast<double>(~static_cast<tools::Long
>(nVal
));
464 if( eNodeType
== SbxNUMVAL
)
466 // Potentially convolve in INTEGER (because of better opcode)?
467 if( eType
== SbxSINGLE
|| eType
== SbxDOUBLE
)
469 if( nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
470 && !modf( nVal
, &o3tl::temporary(double()) ) )
473 if( eType
== SbxLONG
&& nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
)
479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */