Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / basic / source / comp / exprnode.cxx
blob3d2cee0d20fcc199ef64f0369641c90b0b83b9dc
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 <math.h>
23 #include <o3tl/temporary.hxx>
24 #include <rtl/math.hxx>
25 #include <parser.hxx>
26 #include <expr.hxx>
28 #include <basic/sberrors.hxx>
30 SbiExprNode::SbiExprNode( std::unique_ptr<SbiExprNode> l, SbiToken t, std::unique_ptr<SbiExprNode> r ) :
31 pLeft(std::move(l)),
32 pRight(std::move(r)),
33 pWithParent(nullptr),
34 eNodeType(SbxNODE),
35 eType(SbxVARIANT), // Nodes are always Variant
36 eTok(t),
37 bError(false)
41 SbiExprNode::SbiExprNode( double n, SbxDataType t ):
42 nVal(n),
43 pWithParent(nullptr),
44 eNodeType(SbxNUMVAL),
45 eType(t),
46 eTok(NIL),
47 bError(false)
51 SbiExprNode::SbiExprNode( const OUString& rVal ):
52 aStrVal(rVal),
53 pWithParent(nullptr),
54 eNodeType(SbxSTRVAL),
55 eType(SbxSTRING),
56 eTok(NIL),
57 bError(false)
61 SbiExprNode::SbiExprNode( const SbiSymDef& r, SbxDataType t, SbiExprListPtr l ) :
62 pWithParent(nullptr),
63 eNodeType(SbxVARVAL),
64 eTok(NIL),
65 bError(false)
67 eType = ( t == SbxVARIANT ) ? r.GetType() : t;
68 aVar.pDef = const_cast<SbiSymDef*>(&r);
69 aVar.pPar = l.release();
70 aVar.pvMorePar = nullptr;
71 aVar.pNext= nullptr;
74 // #120061 TypeOf
75 SbiExprNode::SbiExprNode( std::unique_ptr<SbiExprNode> l, sal_uInt16 nId ) :
76 nTypeStrId(nId),
77 pLeft(std::move(l)),
78 pWithParent(nullptr),
79 eNodeType(SbxTYPEOF),
80 eType(SbxBOOL),
81 eTok(NIL),
82 bError(false)
86 // new <type>
87 SbiExprNode::SbiExprNode( sal_uInt16 nId ) :
88 nTypeStrId(nId),
89 pWithParent(nullptr),
90 eNodeType(SbxNEW),
91 eType(SbxOBJECT),
92 eTok(NIL),
93 bError(false)
97 SbiExprNode::SbiExprNode() :
98 pWithParent(nullptr),
99 eNodeType(SbxDUMMY),
100 eType(SbxVARIANT),
101 eTok(NIL),
102 bError(false)
106 SbiExprNode::~SbiExprNode()
108 if( IsVariable() )
110 delete aVar.pPar;
111 delete aVar.pNext;
112 delete aVar.pvMorePar;
116 SbiSymDef* SbiExprNode::GetVar()
118 if( eNodeType == SbxVARVAL )
119 return aVar.pDef;
120 else
121 return nullptr;
124 SbiSymDef* SbiExprNode::GetRealVar()
126 SbiExprNode* p = GetRealNode();
127 if( p )
128 return p->GetVar();
129 else
130 return nullptr;
133 // From 1995-12-18
134 SbiExprNode* SbiExprNode::GetRealNode()
136 if( eNodeType == SbxVARVAL )
138 SbiExprNode* p = this;
139 while( p->aVar.pNext )
140 p = p->aVar.pNext;
141 return p;
143 else
144 return nullptr;
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 )
157 eType = SbxINTEGER;
163 bool SbiExprNode::IsNumber() const
165 return eNodeType == SbxNUMVAL;
168 bool SbiExprNode::IsVariable() const
170 return eNodeType == SbxVARVAL;
173 bool SbiExprNode::IsLvalue() const
175 return IsVariable();
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);
187 CollectBits();
190 // Lifting of the error-bits
192 void SbiExprNode::CollectBits()
194 if( pLeft )
196 pLeft->CollectBits();
197 bError = bError || pLeft->bError;
199 if( pRight )
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()) ) )
224 eType = SbxLONG;
226 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
227 eType = SbxINTEGER;
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 )
238 CollectBits();
239 if( eTok == CAT )
240 // CAT affiliate also two numbers!
241 eType = SbxSTRING;
242 if( pLeft->eType == SbxSTRING )
243 // No Type Mismatch!
244 eType = SbxSTRING;
245 if( eType == SbxSTRING )
247 OUString rl( pLeft->GetString() );
248 OUString rr( pRight->GetString() );
249 pLeft.reset();
250 pRight.reset();
251 if( eTok == PLUS || eTok == CAT )
253 eTok = CAT;
254 // Linking:
255 aStrVal = rl;
256 aStrVal += rr;
257 eType = SbxSTRING;
258 eNodeType = SbxSTRVAL;
260 else
262 eType = SbxDOUBLE;
263 eNodeType = SbxNUMVAL;
264 int eRes = rr.compareTo( rl );
265 switch( eTok )
267 case EQ:
268 nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
269 break;
270 case NE:
271 nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
272 break;
273 case LT:
274 nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
275 break;
276 case GT:
277 nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
278 break;
279 case LE:
280 nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
281 break;
282 case GE:
283 nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
284 break;
285 default:
286 pParser->Error( ERRCODE_BASIC_CONVERSION );
287 bError = true;
288 break;
292 else
294 double nl = pLeft->nVal;
295 double nr = pRight->nVal;
296 long ll = 0, lr = 0;
297 long llMod = 0, lrMod = 0;
298 if( ( eTok >= AND && eTok <= IMP )
299 || eTok == IDIV || eTok == MOD )
301 // Integer operations
302 bool bErr = false;
303 if( nl > SbxMAXLNG )
305 bErr = true;
306 nl = SbxMAXLNG;
308 else if( nl < SbxMINLNG )
310 bErr = true;
311 nl = SbxMINLNG;
313 if( nr > SbxMAXLNG )
315 bErr = true;
316 nr = SbxMAXLNG;
318 else if( nr < SbxMINLNG )
320 bErr = true;
321 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);
326 if( bErr )
328 pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
329 bError = true;
332 bool bBothInt = ( pLeft->eType < SbxSINGLE
333 && pRight->eType < SbxSINGLE );
334 pLeft.reset();
335 pRight.reset();
336 nVal = 0;
337 eType = SbxDOUBLE;
338 eNodeType = SbxNUMVAL;
339 bool bCheckType = false;
340 switch( eTok )
342 case EXPON:
343 nVal = pow( nl, nr ); break;
344 case MUL:
345 bCheckType = true;
346 nVal = nl * nr; break;
347 case DIV:
348 if( !nr )
350 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
351 bError = true;
352 } else nVal = nl / nr;
353 break;
354 case PLUS:
355 bCheckType = true;
356 nVal = nl + nr; break;
357 case MINUS:
358 bCheckType = true;
359 nVal = nl - nr; break;
360 case EQ:
361 nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
362 eType = SbxINTEGER; break;
363 case NE:
364 nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
365 eType = SbxINTEGER; break;
366 case LT:
367 nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE;
368 eType = SbxINTEGER; break;
369 case GT:
370 nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE;
371 eType = SbxINTEGER; break;
372 case LE:
373 nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
374 eType = SbxINTEGER; break;
375 case GE:
376 nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
377 eType = SbxINTEGER; break;
378 case IDIV:
379 if( !lr )
381 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
382 bError = true;
383 } else nVal = ll / lr;
384 eType = SbxLONG; break;
385 case MOD:
386 if( !lr )
388 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
389 bError = true;
390 } else nVal = llMod - lrMod * (llMod/lrMod);
391 eType = SbxLONG; break;
392 case AND:
393 nVal = static_cast<double>( ll & lr ); eType = SbxLONG; break;
394 case OR:
395 nVal = static_cast<double>( ll | lr ); eType = SbxLONG; break;
396 case XOR:
397 nVal = static_cast<double>( ll ^ lr ); eType = SbxLONG; break;
398 case EQV:
399 nVal = static_cast<double>( ~ll ^ lr ); eType = SbxLONG; break;
400 case IMP:
401 nVal = static_cast<double>( ~ll | lr ); eType = SbxLONG; break;
402 default: 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);
414 nVal = n;
415 eType = ( n >= SbxMININT && n <= SbxMAXINT )
416 ? SbxINTEGER : SbxLONG;
422 void SbiExprNode::FoldConstantsUnaryNode(SbiParser* pParser)
424 pLeft->FoldConstants(pParser);
425 if (pLeft->IsNumber())
427 nVal = pLeft->nVal;
428 pLeft.reset();
429 eType = SbxDOUBLE;
430 eNodeType = SbxNUMVAL;
431 switch( eTok )
433 case NEG:
434 nVal = -nVal; break;
435 case NOT: {
436 // Integer operation!
437 bool bErr = false;
438 if( nVal > SbxMAXLNG )
440 bErr = true;
441 nVal = SbxMAXLNG;
443 else if( nVal < SbxMINLNG )
445 bErr = true;
446 nVal = SbxMINLNG;
448 if( bErr )
450 pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
451 bError = true;
453 nVal = static_cast<double>(~static_cast<long>(nVal));
454 eType = SbxLONG;
455 } break;
456 default: break;
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()) ) )
466 eType = SbxLONG;
468 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
469 eType = SbxINTEGER;
474 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */