tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / basic / source / comp / exprnode.cxx
blobd6733e96d1ee1762afa09ff4e1af6822041a679c
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>
31 #include <utility>
33 SbiExprNode::SbiExprNode( std::unique_ptr<SbiExprNode> l, SbiToken t, std::unique_ptr<SbiExprNode> r ) :
34 pLeft(std::move(l)),
35 pRight(std::move(r)),
36 pWithParent(nullptr),
37 eNodeType(SbxNODE),
38 eType(SbxVARIANT), // Nodes are always Variant
39 eTok(t),
40 bError(false)
44 SbiExprNode::SbiExprNode( double n, SbxDataType t ):
45 nVal(n),
46 pWithParent(nullptr),
47 eNodeType(SbxNUMVAL),
48 eType(t),
49 eTok(NIL),
50 bError(false)
54 SbiExprNode::SbiExprNode( OUString aVal ):
55 aStrVal(std::move(aVal)),
56 pWithParent(nullptr),
57 eNodeType(SbxSTRVAL),
58 eType(SbxSTRING),
59 eTok(NIL),
60 bError(false)
64 SbiExprNode::SbiExprNode( const SbiSymDef& r, SbxDataType t, SbiExprListPtr l ) :
65 pWithParent(nullptr),
66 eNodeType(SbxVARVAL),
67 eTok(NIL),
68 bError(false)
70 eType = ( t == SbxVARIANT ) ? r.GetType() : t;
71 aVar.pDef = const_cast<SbiSymDef*>(&r);
72 aVar.pPar = l.release();
73 aVar.pvMorePar = nullptr;
74 aVar.pNext= nullptr;
77 // #120061 TypeOf
78 SbiExprNode::SbiExprNode( std::unique_ptr<SbiExprNode> l, sal_uInt16 nId ) :
79 nTypeStrId(nId),
80 pLeft(std::move(l)),
81 pWithParent(nullptr),
82 eNodeType(SbxTYPEOF),
83 eType(SbxBOOL),
84 eTok(NIL),
85 bError(false)
89 // new <type>
90 SbiExprNode::SbiExprNode( sal_uInt16 nId ) :
91 nTypeStrId(nId),
92 pWithParent(nullptr),
93 eNodeType(SbxNEW),
94 eType(SbxOBJECT),
95 eTok(NIL),
96 bError(false)
100 SbiExprNode::SbiExprNode() :
101 pWithParent(nullptr),
102 eNodeType(SbxDUMMY),
103 eType(SbxVARIANT),
104 eTok(NIL),
105 bError(false)
109 SbiExprNode::~SbiExprNode()
111 if( IsVariable() )
113 delete aVar.pPar;
114 delete aVar.pNext;
115 delete aVar.pvMorePar;
119 SbiSymDef* SbiExprNode::GetVar()
121 if (IsVariable())
122 return aVar.pDef;
123 else
124 return nullptr;
127 SbiSymDef* SbiExprNode::GetRealVar()
129 SbiExprNode* p = GetRealNode();
130 if( p )
131 return p->GetVar();
132 else
133 return nullptr;
136 // From 1995-12-18
137 SbiExprNode* SbiExprNode::GetRealNode()
139 if (IsVariable())
141 SbiExprNode* p = this;
142 while( p->aVar.pNext )
143 p = p->aVar.pNext;
144 return p;
146 else
147 return nullptr;
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 )
160 eType = SbxINTEGER;
166 bool SbiExprNode::IsNumber() const
168 return eNodeType == SbxNUMVAL;
171 bool SbiExprNode::IsVariable() const
173 return eNodeType == SbxVARVAL;
176 bool SbiExprNode::IsLvalue() const
178 return IsVariable();
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);
190 CollectBits();
193 // Lifting of the error-bits
195 void SbiExprNode::CollectBits()
197 if( pLeft )
199 pLeft->CollectBits();
200 bError = bError || pLeft->bError;
202 if( pRight )
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()) ) )
227 eType = SbxLONG;
229 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
230 eType = SbxINTEGER;
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) )
240 return;
242 CollectBits();
243 if( eTok == CAT )
244 // CAT affiliate also two numbers!
245 eType = SbxSTRING;
246 if( pLeft->eType == SbxSTRING )
247 // No Type Mismatch!
248 eType = SbxSTRING;
249 if( eType == SbxSTRING )
251 OUString rl( pLeft->GetString() );
252 OUString rr( pRight->GetString() );
253 pLeft.reset();
254 pRight.reset();
255 if( eTok == PLUS || eTok == CAT )
257 eTok = CAT;
258 // Linking:
259 aStrVal = rl;
260 aStrVal += rr;
261 eType = SbxSTRING;
262 eNodeType = SbxSTRVAL;
264 else
266 eType = SbxBOOL;
267 eNodeType = SbxNUMVAL;
268 int eRes = rr.compareTo( rl );
269 switch( eTok )
271 case EQ:
272 nVal = ( eRes == 0 ) ? SbxTRUE : SbxFALSE;
273 break;
274 case NE:
275 nVal = ( eRes != 0 ) ? SbxTRUE : SbxFALSE;
276 break;
277 case LT:
278 nVal = ( eRes > 0 ) ? SbxTRUE : SbxFALSE;
279 break;
280 case GT:
281 nVal = ( eRes < 0 ) ? SbxTRUE : SbxFALSE;
282 break;
283 case LE:
284 nVal = ( eRes >= 0 ) ? SbxTRUE : SbxFALSE;
285 break;
286 case GE:
287 nVal = ( eRes <= 0 ) ? SbxTRUE : SbxFALSE;
288 break;
289 default:
290 pParser->Error( ERRCODE_BASIC_CONVERSION );
291 bError = true;
292 break;
296 else
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
311 bool bErr = false;
312 if( nl > SbxMAXLNG )
314 bErr = true;
315 nl = SbxMAXLNG;
317 else if( nl < SbxMINLNG )
319 bErr = true;
320 nl = SbxMINLNG;
322 if( nr > SbxMAXLNG )
324 bErr = true;
325 nr = SbxMAXLNG;
327 else if( nr < SbxMINLNG )
329 bErr = true;
330 nr = SbxMINLNG;
332 ll = static_cast<tools::Long>(nl); lr = static_cast<tools::Long>(nr);
333 if( bErr )
335 pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
336 bError = true;
339 bool bBothInt = ( pLeft->eType < SbxSINGLE
340 && pRight->eType < SbxSINGLE );
341 pLeft.reset();
342 pRight.reset();
343 nVal = 0;
344 eType = SbxDOUBLE;
345 eNodeType = SbxNUMVAL;
346 bool bCheckType = false;
347 switch( eTok )
349 case EXPON:
350 nVal = pow( nl, nr ); break;
351 case MUL:
352 bCheckType = true;
353 nVal = nl * nr; break;
354 case DIV:
355 if( !nr )
357 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
358 bError = true;
359 } else nVal = nl / nr;
360 break;
361 case PLUS:
362 bCheckType = true;
363 nVal = nl + nr; break;
364 case MINUS:
365 bCheckType = true;
366 nVal = nl - nr; break;
367 case EQ:
368 nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
369 eType = SbxBOOL; break;
370 case NE:
371 nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
372 eType = SbxBOOL; break;
373 case LT:
374 nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE;
375 eType = SbxBOOL; break;
376 case GT:
377 nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE;
378 eType = SbxBOOL; break;
379 case LE:
380 nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
381 eType = SbxBOOL; break;
382 case GE:
383 nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
384 eType = SbxBOOL; break;
385 case IDIV:
386 if( !lr )
388 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
389 bError = true;
390 } else nVal = ll / lr;
391 eType = SbxLONG; break;
392 case MOD:
393 if( !lr )
395 pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
396 bError = true;
397 } else nVal = ll - lr * (ll/lr);
398 eType = SbxLONG; break;
399 case AND:
400 nVal = static_cast<double>( ll & lr ); eType = SbxLONG; break;
401 case OR:
402 nVal = static_cast<double>( ll | lr ); eType = SbxLONG; break;
403 case XOR:
404 nVal = static_cast<double>( ll ^ lr ); eType = SbxLONG; break;
405 case EQV:
406 nVal = static_cast<double>( ~ll ^ lr ); eType = SbxLONG; break;
407 case IMP:
408 nVal = static_cast<double>( ~ll | lr ); eType = SbxLONG; break;
409 default: 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);
421 nVal = n;
422 eType = ( n >= SbxMININT && n <= SbxMAXINT )
423 ? SbxINTEGER : SbxLONG;
428 void SbiExprNode::FoldConstantsUnaryNode(SbiParser* pParser)
430 pLeft->FoldConstants(pParser);
431 if (pLeft->IsNumber())
433 nVal = pLeft->nVal;
434 pLeft.reset();
435 eType = SbxDOUBLE;
436 eNodeType = SbxNUMVAL;
437 switch( eTok )
439 case NEG:
440 nVal = -nVal; break;
441 case NOT: {
442 // Integer operation!
443 bool bErr = false;
444 if( nVal > SbxMAXLNG )
446 bErr = true;
447 nVal = SbxMAXLNG;
449 else if( nVal < SbxMINLNG )
451 bErr = true;
452 nVal = SbxMINLNG;
454 if( bErr )
456 pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
457 bError = true;
459 nVal = static_cast<double>(~static_cast<tools::Long>(nVal));
460 eType = SbxLONG;
461 } break;
462 default: break;
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()) ) )
472 eType = SbxLONG;
474 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
475 eType = SbxINTEGER;
480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */