nss: upgrade to release 3.73
[LibreOffice.git] / basic / source / comp / exprnode.cxx
blob4192ceb8d49dc3fdc55eefa2f7377ea0b6fbb804
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 <cmath>
23 #include <o3tl/temporary.hxx>
24 #include <parser.hxx>
25 #include <expr.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 ) :
33 pLeft(std::move(l)),
34 pRight(std::move(r)),
35 pWithParent(nullptr),
36 eNodeType(SbxNODE),
37 eType(SbxVARIANT), // Nodes are always Variant
38 eTok(t),
39 bError(false)
43 SbiExprNode::SbiExprNode( double n, SbxDataType t ):
44 nVal(n),
45 pWithParent(nullptr),
46 eNodeType(SbxNUMVAL),
47 eType(t),
48 eTok(NIL),
49 bError(false)
53 SbiExprNode::SbiExprNode( const OUString& rVal ):
54 aStrVal(rVal),
55 pWithParent(nullptr),
56 eNodeType(SbxSTRVAL),
57 eType(SbxSTRING),
58 eTok(NIL),
59 bError(false)
63 SbiExprNode::SbiExprNode( const SbiSymDef& r, SbxDataType t, SbiExprListPtr l ) :
64 pWithParent(nullptr),
65 eNodeType(SbxVARVAL),
66 eTok(NIL),
67 bError(false)
69 eType = ( t == SbxVARIANT ) ? r.GetType() : t;
70 aVar.pDef = const_cast<SbiSymDef*>(&r);
71 aVar.pPar = l.release();
72 aVar.pvMorePar = nullptr;
73 aVar.pNext= nullptr;
76 // #120061 TypeOf
77 SbiExprNode::SbiExprNode( std::unique_ptr<SbiExprNode> l, sal_uInt16 nId ) :
78 nTypeStrId(nId),
79 pLeft(std::move(l)),
80 pWithParent(nullptr),
81 eNodeType(SbxTYPEOF),
82 eType(SbxBOOL),
83 eTok(NIL),
84 bError(false)
88 // new <type>
89 SbiExprNode::SbiExprNode( sal_uInt16 nId ) :
90 nTypeStrId(nId),
91 pWithParent(nullptr),
92 eNodeType(SbxNEW),
93 eType(SbxOBJECT),
94 eTok(NIL),
95 bError(false)
99 SbiExprNode::SbiExprNode() :
100 pWithParent(nullptr),
101 eNodeType(SbxDUMMY),
102 eType(SbxVARIANT),
103 eTok(NIL),
104 bError(false)
108 SbiExprNode::~SbiExprNode()
110 if( IsVariable() )
112 delete aVar.pPar;
113 delete aVar.pNext;
114 delete aVar.pvMorePar;
118 SbiSymDef* SbiExprNode::GetVar()
120 if( eNodeType == SbxVARVAL )
121 return aVar.pDef;
122 else
123 return nullptr;
126 SbiSymDef* SbiExprNode::GetRealVar()
128 SbiExprNode* p = GetRealNode();
129 if( p )
130 return p->GetVar();
131 else
132 return nullptr;
135 // From 1995-12-18
136 SbiExprNode* SbiExprNode::GetRealNode()
138 if( eNodeType == SbxVARVAL )
140 SbiExprNode* p = this;
141 while( p->aVar.pNext )
142 p = p->aVar.pNext;
143 return p;
145 else
146 return nullptr;
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 )
159 eType = SbxINTEGER;
165 bool SbiExprNode::IsNumber() const
167 return eNodeType == SbxNUMVAL;
170 bool SbiExprNode::IsVariable() const
172 return eNodeType == SbxVARVAL;
175 bool SbiExprNode::IsLvalue() const
177 return IsVariable();
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);
189 CollectBits();
192 // Lifting of the error-bits
194 void SbiExprNode::CollectBits()
196 if( pLeft )
198 pLeft->CollectBits();
199 bError = bError || pLeft->bError;
201 if( pRight )
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()) ) )
226 eType = SbxLONG;
228 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
229 eType = SbxINTEGER;
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) )
239 return;
241 CollectBits();
242 if( eTok == CAT )
243 // CAT affiliate also two numbers!
244 eType = SbxSTRING;
245 if( pLeft->eType == SbxSTRING )
246 // No Type Mismatch!
247 eType = SbxSTRING;
248 if( eType == SbxSTRING )
250 OUString rl( pLeft->GetString() );
251 OUString rr( pRight->GetString() );
252 pLeft.reset();
253 pRight.reset();
254 if( eTok == PLUS || eTok == CAT )
256 eTok = CAT;
257 // Linking:
258 aStrVal = rl;
259 aStrVal += rr;
260 eType = SbxSTRING;
261 eNodeType = SbxSTRVAL;
263 else
265 eType = SbxDOUBLE;
266 eNodeType = SbxNUMVAL;
267 int eRes = rr.compareTo( rl );
268 switch( eTok )
270 case EQ:
271 nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
272 break;
273 case NE:
274 nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
275 break;
276 case LT:
277 nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
278 break;
279 case GT:
280 nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
281 break;
282 case LE:
283 nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
284 break;
285 case GE:
286 nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
287 break;
288 default:
289 pParser->Error( ERRCODE_BASIC_CONVERSION );
290 bError = true;
291 break;
295 else
297 double nl = pLeft->nVal;
298 double nr = pRight->nVal;
299 // tdf#141201 - round MOD literals to Integer values
300 if (eTok == MOD)
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
310 bool bErr = false;
311 if( nl > SbxMAXLNG )
313 bErr = true;
314 nl = SbxMAXLNG;
316 else if( nl < SbxMINLNG )
318 bErr = true;
319 nl = SbxMINLNG;
321 if( nr > SbxMAXLNG )
323 bErr = true;
324 nr = SbxMAXLNG;
326 else if( nr < SbxMINLNG )
328 bErr = true;
329 nr = SbxMINLNG;
331 ll = static_cast<tools::Long>(nl); lr = static_cast<tools::Long>(nr);
332 if( bErr )
334 pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
335 bError = true;
338 bool bBothInt = ( pLeft->eType < SbxSINGLE
339 && pRight->eType < SbxSINGLE );
340 pLeft.reset();
341 pRight.reset();
342 nVal = 0;
343 eType = SbxDOUBLE;
344 eNodeType = SbxNUMVAL;
345 bool bCheckType = false;
346 switch( eTok )
348 case EXPON:
349 nVal = pow( nl, nr ); break;
350 case MUL:
351 bCheckType = true;
352 nVal = nl * nr; break;
353 case DIV:
354 if( !nr )
356 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
357 bError = true;
358 } else nVal = nl / nr;
359 break;
360 case PLUS:
361 bCheckType = true;
362 nVal = nl + nr; break;
363 case MINUS:
364 bCheckType = true;
365 nVal = nl - nr; break;
366 case EQ:
367 nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
368 eType = SbxINTEGER; break;
369 case NE:
370 nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
371 eType = SbxINTEGER; break;
372 case LT:
373 nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE;
374 eType = SbxINTEGER; break;
375 case GT:
376 nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE;
377 eType = SbxINTEGER; break;
378 case LE:
379 nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
380 eType = SbxINTEGER; break;
381 case GE:
382 nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
383 eType = SbxINTEGER; break;
384 case IDIV:
385 if( !lr )
387 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
388 bError = true;
389 } else nVal = ll / lr;
390 eType = SbxLONG; break;
391 case MOD:
392 if( !lr )
394 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
395 bError = true;
396 } else nVal = ll - lr * (ll/lr);
397 eType = SbxLONG; break;
398 case AND:
399 nVal = static_cast<double>( ll & lr ); eType = SbxLONG; break;
400 case OR:
401 nVal = static_cast<double>( ll | lr ); eType = SbxLONG; break;
402 case XOR:
403 nVal = static_cast<double>( ll ^ lr ); eType = SbxLONG; break;
404 case EQV:
405 nVal = static_cast<double>( ~ll ^ lr ); eType = SbxLONG; break;
406 case IMP:
407 nVal = static_cast<double>( ~ll | lr ); eType = SbxLONG; break;
408 default: 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);
420 nVal = n;
421 eType = ( n >= SbxMININT && n <= SbxMAXINT )
422 ? SbxINTEGER : SbxLONG;
427 void SbiExprNode::FoldConstantsUnaryNode(SbiParser* pParser)
429 pLeft->FoldConstants(pParser);
430 if (pLeft->IsNumber())
432 nVal = pLeft->nVal;
433 pLeft.reset();
434 eType = SbxDOUBLE;
435 eNodeType = SbxNUMVAL;
436 switch( eTok )
438 case NEG:
439 nVal = -nVal; break;
440 case NOT: {
441 // Integer operation!
442 bool bErr = false;
443 if( nVal > SbxMAXLNG )
445 bErr = true;
446 nVal = SbxMAXLNG;
448 else if( nVal < SbxMINLNG )
450 bErr = true;
451 nVal = SbxMINLNG;
453 if( bErr )
455 pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
456 bError = true;
458 nVal = static_cast<double>(~static_cast<tools::Long>(nVal));
459 eType = SbxLONG;
460 } break;
461 default: break;
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()) ) )
471 eType = SbxLONG;
473 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
474 eType = SbxINTEGER;
479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */