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>
33 SbiExprNode::SbiExprNode( std::unique_ptr
<SbiExprNode
> l
, SbiToken t
, std::unique_ptr
<SbiExprNode
> r
) :
38 eType(SbxVARIANT
), // Nodes are always Variant
44 SbiExprNode::SbiExprNode( double n
, SbxDataType t
):
54 SbiExprNode::SbiExprNode( OUString aVal
):
55 aStrVal(std::move(aVal
)),
64 SbiExprNode::SbiExprNode( const SbiSymDef
& r
, SbxDataType t
, SbiExprListPtr l
) :
70 eType
= ( t
== SbxVARIANT
) ? r
.GetType() : t
;
71 aVar
.pDef
= const_cast<SbiSymDef
*>(&r
);
72 aVar
.pPar
= l
.release();
73 aVar
.pvMorePar
= nullptr;
78 SbiExprNode::SbiExprNode( std::unique_ptr
<SbiExprNode
> l
, sal_uInt16 nId
) :
90 SbiExprNode::SbiExprNode( sal_uInt16 nId
) :
100 SbiExprNode::SbiExprNode() :
101 pWithParent(nullptr),
109 SbiExprNode::~SbiExprNode()
115 delete aVar
.pvMorePar
;
119 SbiSymDef
* SbiExprNode::GetVar()
127 SbiSymDef
* SbiExprNode::GetRealVar()
129 SbiExprNode
* p
= GetRealNode();
137 SbiExprNode
* SbiExprNode::GetRealNode()
141 SbiExprNode
* p
= this;
142 while( p
->aVar
.pNext
)
150 // This method transform the type, if it fits into the Integer range
152 void SbiExprNode::ConvertToIntConstIfPossible()
154 if( eNodeType
== SbxNUMVAL
)
156 if( eType
>= SbxINTEGER
&& eType
<= SbxDOUBLE
)
158 if( nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
&& modf( nVal
, &o3tl::temporary(double()) ) == 0 )
166 bool SbiExprNode::IsNumber() const
168 return eNodeType
== SbxNUMVAL
;
171 bool SbiExprNode::IsVariable() const
173 return eNodeType
== SbxVARVAL
;
176 bool SbiExprNode::IsLvalue() const
181 // Adjustment of a tree:
182 // 1. Constant Folding
183 // 2. Type-Adjustment
184 // 3. Conversion of the operands into Strings
185 // 4. Lifting of the composite- and error-bits
187 void SbiExprNode::Optimize(SbiParser
* pParser
)
189 FoldConstants(pParser
);
193 // Lifting of the error-bits
195 void SbiExprNode::CollectBits()
199 pLeft
->CollectBits();
200 bError
= bError
|| pLeft
->bError
;
204 pRight
->CollectBits();
205 bError
= bError
|| pRight
->bError
;
209 // If a twig can be converted, True will be returned. In this case
210 // the result is in the left twig.
211 void SbiExprNode::FoldConstants(SbiParser
* pParser
)
213 if( IsOperand() || eTok
== LIKE
) return;
215 if (pLeft
&& !pRight
)
216 FoldConstantsUnaryNode(pParser
);
217 else if (pLeft
&& pRight
)
218 FoldConstantsBinaryNode(pParser
);
220 if( eNodeType
== SbxNUMVAL
)
222 // Potentially convolve in INTEGER (because of better opcode)?
223 if( eType
== SbxSINGLE
|| eType
== SbxDOUBLE
)
225 if( nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
226 && !modf( nVal
, &o3tl::temporary(double()) ) )
229 if( eType
== SbxLONG
&& nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
)
234 void SbiExprNode::FoldConstantsBinaryNode(SbiParser
* pParser
)
236 pLeft
->FoldConstants(pParser
);
237 pRight
->FoldConstants(pParser
);
238 if( !(pLeft
->IsConstant() && pRight
->IsConstant()
239 && pLeft
->eNodeType
== pRight
->eNodeType
) )
244 // CAT affiliate also two numbers!
246 if( pLeft
->eType
== SbxSTRING
)
249 if( eType
== SbxSTRING
)
251 OUString
rl( pLeft
->GetString() );
252 OUString
rr( pRight
->GetString() );
255 if( eTok
== PLUS
|| eTok
== CAT
)
262 eNodeType
= SbxSTRVAL
;
267 eNodeType
= SbxNUMVAL
;
268 int eRes
= rr
.compareTo( rl
);
272 nVal
= ( eRes
== 0 ) ? SbxTRUE
: SbxFALSE
;
275 nVal
= ( eRes
!= 0 ) ? SbxTRUE
: SbxFALSE
;
278 nVal
= ( eRes
> 0 ) ? SbxTRUE
: SbxFALSE
;
281 nVal
= ( eRes
< 0 ) ? SbxTRUE
: SbxFALSE
;
284 nVal
= ( eRes
>= 0 ) ? SbxTRUE
: SbxFALSE
;
287 nVal
= ( eRes
<= 0 ) ? SbxTRUE
: SbxFALSE
;
290 pParser
->Error( ERRCODE_BASIC_CONVERSION
);
298 double nl
= pLeft
->nVal
;
299 double nr
= pRight
->nVal
;
300 // tdf#141201, tdf#147089 - round MOD/IDIV literals to Integer values
301 if (eTok
== MOD
|| eTok
== IDIV
)
303 nl
= rtl::math::round(nl
);
304 nr
= rtl::math::round(nr
);
306 tools::Long ll
= 0, lr
= 0;
307 if( ( eTok
>= AND
&& eTok
<= IMP
)
308 || eTok
== IDIV
|| eTok
== MOD
)
310 // Integer operations
317 else if( nl
< SbxMINLNG
)
327 else if( nr
< SbxMINLNG
)
332 ll
= static_cast<tools::Long
>(nl
); lr
= static_cast<tools::Long
>(nr
);
335 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
339 bool bBothInt
= ( pLeft
->eType
< SbxSINGLE
340 && pRight
->eType
< SbxSINGLE
);
345 eNodeType
= SbxNUMVAL
;
346 bool bCheckType
= false;
350 nVal
= pow( nl
, nr
); break;
353 nVal
= nl
* nr
; break;
357 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
359 } else nVal
= nl
/ nr
;
363 nVal
= nl
+ nr
; break;
366 nVal
= nl
- nr
; break;
368 nVal
= ( nl
== nr
) ? SbxTRUE
: SbxFALSE
;
369 eType
= SbxBOOL
; break;
371 nVal
= ( nl
!= nr
) ? SbxTRUE
: SbxFALSE
;
372 eType
= SbxBOOL
; break;
374 nVal
= ( nl
< nr
) ? SbxTRUE
: SbxFALSE
;
375 eType
= SbxBOOL
; break;
377 nVal
= ( nl
> nr
) ? SbxTRUE
: SbxFALSE
;
378 eType
= SbxBOOL
; break;
380 nVal
= ( nl
<= nr
) ? SbxTRUE
: SbxFALSE
;
381 eType
= SbxBOOL
; break;
383 nVal
= ( nl
>= nr
) ? SbxTRUE
: SbxFALSE
;
384 eType
= SbxBOOL
; break;
388 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
390 } else nVal
= ll
/ lr
;
391 eType
= SbxLONG
; break;
395 pParser
->Error( ERRCODE_BASIC_ZERODIV
); nVal
= HUGE_VAL
;
397 } else nVal
= ll
- lr
* (ll
/lr
);
398 eType
= SbxLONG
; break;
400 nVal
= static_cast<double>( ll
& lr
); eType
= SbxLONG
; break;
402 nVal
= static_cast<double>( ll
| lr
); eType
= SbxLONG
; break;
404 nVal
= static_cast<double>( ll
^ lr
); eType
= SbxLONG
; break;
406 nVal
= static_cast<double>( ~ll
^ lr
); eType
= SbxLONG
; break;
408 nVal
= static_cast<double>( ~ll
| lr
); eType
= SbxLONG
; break;
412 if( !std::isfinite( nVal
) )
413 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
415 // Recover the data type to kill rounding error
416 if( bCheckType
&& bBothInt
417 && nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
)
419 // Decimal place away
420 tools::Long n
= static_cast<tools::Long
>(nVal
);
422 eType
= ( n
>= SbxMININT
&& n
<= SbxMAXINT
)
423 ? SbxINTEGER
: SbxLONG
;
428 void SbiExprNode::FoldConstantsUnaryNode(SbiParser
* pParser
)
430 pLeft
->FoldConstants(pParser
);
431 if (pLeft
->IsNumber())
436 eNodeType
= SbxNUMVAL
;
442 // Integer operation!
444 if( nVal
> SbxMAXLNG
)
449 else if( nVal
< SbxMINLNG
)
456 pParser
->Error( ERRCODE_BASIC_MATH_OVERFLOW
);
459 nVal
= static_cast<double>(~static_cast<tools::Long
>(nVal
));
465 if( eNodeType
== SbxNUMVAL
)
467 // Potentially convolve in INTEGER (because of better opcode)?
468 if( eType
== SbxSINGLE
|| eType
== SbxDOUBLE
)
470 if( nVal
>= SbxMINLNG
&& nVal
<= SbxMAXLNG
471 && !modf( nVal
, &o3tl::temporary(double()) ) )
474 if( eType
== SbxLONG
&& nVal
>= SbxMININT
&& nVal
<= SbxMAXINT
)
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */