LibreOffice Module basic (master) 1
exprnode.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include <cmath>
22
23#include <o3tl/temporary.hxx>
24#include <parser.hxx>
25#include <expr.hxx>
26#include <tools/long.hxx>
27
28#include <basic/sberrors.hxx>
29
30#include <rtl/math.hxx>
31#include <utility>
32
33SbiExprNode::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)
41{
42}
43
45 nVal(n),
46 pWithParent(nullptr),
47 eNodeType(SbxNUMVAL),
48 eType(t),
49 eTok(NIL),
50 bError(false)
51{
52}
53
54SbiExprNode::SbiExprNode( OUString aVal ):
55 aStrVal(std::move(aVal)),
56 pWithParent(nullptr),
57 eNodeType(SbxSTRVAL),
59 eTok(NIL),
60 bError(false)
61{
62}
63
65 pWithParent(nullptr),
66 eNodeType(SbxVARVAL),
67 eTok(NIL),
68 bError(false)
69{
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;
75}
76
77// #120061 TypeOf
78SbiExprNode::SbiExprNode( std::unique_ptr<SbiExprNode> l, sal_uInt16 nId ) :
79 nTypeStrId(nId),
80 pLeft(std::move(l)),
81 pWithParent(nullptr),
82 eNodeType(SbxTYPEOF),
84 eTok(NIL),
85 bError(false)
86{
87}
88
89// new <type>
90SbiExprNode::SbiExprNode( sal_uInt16 nId ) :
91 nTypeStrId(nId),
92 pWithParent(nullptr),
93 eNodeType(SbxNEW),
95 eTok(NIL),
96 bError(false)
97{
98}
99
101 pWithParent(nullptr),
102 eNodeType(SbxDUMMY),
104 eTok(NIL),
105 bError(false)
106{
107}
108
110{
111 if( IsVariable() )
112 {
113 delete aVar.pPar;
114 delete aVar.pNext;
115 delete aVar.pvMorePar;
116 }
117}
118
120{
121 if( eNodeType == SbxVARVAL )
122 return aVar.pDef;
123 else
124 return nullptr;
125}
126
128{
130 if( p )
131 return p->GetVar();
132 else
133 return nullptr;
134}
135
136// From 1995-12-18
138{
139 if( eNodeType == SbxVARVAL )
140 {
141 SbiExprNode* p = this;
142 while( p->aVar.pNext )
143 p = p->aVar.pNext;
144 return p;
145 }
146 else
147 return nullptr;
148}
149
150// This method transform the type, if it fits into the Integer range
151
153{
154 if( eNodeType == SbxNUMVAL )
155 {
156 if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
157 {
158 if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &o3tl::temporary(double()) ) == 0 )
159 {
161 }
162 }
163 }
164}
165
167{
168 return eNodeType == SbxNUMVAL;
169}
170
172{
173 return eNodeType == SbxVARVAL;
174}
175
177{
178 return IsVariable();
179}
180
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
186
188{
189 FoldConstants(pParser);
190 CollectBits();
191}
192
193// Lifting of the error-bits
194
196{
197 if( pLeft )
198 {
199 pLeft->CollectBits();
200 bError = bError || pLeft->bError;
201 }
202 if( pRight )
203 {
204 pRight->CollectBits();
205 bError = bError || pRight->bError;
206 }
207}
208
209// If a twig can be converted, True will be returned. In this case
210// the result is in the left twig.
212{
213 if( IsOperand() || eTok == LIKE ) return;
214
215 if (pLeft && !pRight)
216 FoldConstantsUnaryNode(pParser);
217 else if (pLeft && pRight)
219
220 if( eNodeType == SbxNUMVAL )
221 {
222 // Potentially convolve in INTEGER (because of better opcode)?
223 if( eType == SbxSINGLE || eType == SbxDOUBLE )
224 {
225 if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
226 && !modf( nVal, &o3tl::temporary(double()) ) )
227 eType = SbxLONG;
228 }
229 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
231 }
232}
233
235{
236 pLeft->FoldConstants(pParser);
237 pRight->FoldConstants(pParser);
238 if( !(pLeft->IsConstant() && pRight->IsConstant()
239 && pLeft->eNodeType == pRight->eNodeType) )
240 return;
241
242 CollectBits();
243 if( eTok == CAT )
244 // CAT affiliate also two numbers!
246 if( pLeft->eType == SbxSTRING )
247 // No Type Mismatch!
249 if( eType == SbxSTRING )
250 {
251 OUString rl( pLeft->GetString() );
252 OUString rr( pRight->GetString() );
253 pLeft.reset();
254 pRight.reset();
255 if( eTok == PLUS || eTok == CAT )
256 {
257 eTok = CAT;
258 // Linking:
259 aStrVal = rl;
260 aStrVal += rr;
263 }
264 else
265 {
266 eType = SbxBOOL;
268 int eRes = rr.compareTo( rl );
269 switch( eTok )
270 {
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:
291 bError = true;
292 break;
293 }
294 }
295 }
296 else
297 {
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)
302 {
303 nl = rtl::math::round(nl);
304 nr = rtl::math::round(nr);
305 }
306 tools::Long ll = 0, lr = 0;
307 if( ( eTok >= AND && eTok <= IMP )
308 || eTok == IDIV || eTok == MOD )
309 {
310 // Integer operations
311 bool bErr = false;
312 if( nl > SbxMAXLNG )
313 {
314 bErr = true;
315 nl = SbxMAXLNG;
316 }
317 else if( nl < SbxMINLNG )
318 {
319 bErr = true;
320 nl = SbxMINLNG;
321 }
322 if( nr > SbxMAXLNG )
323 {
324 bErr = true;
325 nr = SbxMAXLNG;
326 }
327 else if( nr < SbxMINLNG )
328 {
329 bErr = true;
330 nr = SbxMINLNG;
331 }
332 ll = static_cast<tools::Long>(nl); lr = static_cast<tools::Long>(nr);
333 if( bErr )
334 {
336 bError = true;
337 }
338 }
339 bool bBothInt = ( pLeft->eType < SbxSINGLE
340 && pRight->eType < SbxSINGLE );
341 pLeft.reset();
342 pRight.reset();
343 nVal = 0;
346 bool bCheckType = false;
347 switch( eTok )
348 {
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 )
356 {
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 )
387 {
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 )
394 {
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;
410 }
411
412 if( !std::isfinite( nVal ) )
414
415 // Recover the data type to kill rounding error
416 if( bCheckType && bBothInt
417 && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
418 {
419 // Decimal place away
420 tools::Long n = static_cast<tools::Long>(nVal);
421 nVal = n;
422 eType = ( n >= SbxMININT && n <= SbxMAXINT )
424 }
425 }
426
427}
429{
430 pLeft->FoldConstants(pParser);
431 if (pLeft->IsNumber())
432 {
433 nVal = pLeft->nVal;
434 pLeft.reset();
437 switch( eTok )
438 {
439 case NEG:
440 nVal = -nVal; break;
441 case NOT: {
442 // Integer operation!
443 bool bErr = false;
444 if( nVal > SbxMAXLNG )
445 {
446 bErr = true;
447 nVal = SbxMAXLNG;
448 }
449 else if( nVal < SbxMINLNG )
450 {
451 bErr = true;
452 nVal = SbxMINLNG;
453 }
454 if( bErr )
455 {
457 bError = true;
458 }
459 nVal = static_cast<double>(~static_cast<tools::Long>(nVal));
460 eType = SbxLONG;
461 } break;
462 default: break;
463 }
464 }
465 if( eNodeType == SbxNUMVAL )
466 {
467 // Potentially convolve in INTEGER (because of better opcode)?
468 if( eType == SbxSINGLE || eType == SbxDOUBLE )
469 {
470 if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
471 && !modf( nVal, &o3tl::temporary(double()) ) )
472 eType = SbxLONG;
473 }
474 if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
476 }
477}
478
479
480/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
SbiSymDef * GetRealVar()
Definition: exprnode.cxx:127
SbxDataType eType
Definition: expr.hxx:120
bool IsVariable() const
Definition: exprnode.cxx:171
void ConvertToIntConstIfPossible()
Definition: exprnode.cxx:152
void FoldConstantsUnaryNode(SbiParser *)
Definition: exprnode.cxx:428
std::unique_ptr< SbiExprNode > pLeft
Definition: expr.hxx:116
SbiNodeType eNodeType
Definition: expr.hxx:119
SbiToken eTok
Definition: expr.hxx:121
SbiSymDef * GetVar()
Definition: exprnode.cxx:119
std::unique_ptr< SbiExprNode > pRight
Definition: expr.hxx:117
void Optimize(SbiParser *)
Definition: exprnode.cxx:187
void FoldConstants(SbiParser *)
Definition: exprnode.cxx:211
bool bError
Definition: expr.hxx:122
SbiExprNode * GetRealNode()
Definition: exprnode.cxx:137
double nVal
Definition: expr.hxx:112
void FoldConstantsBinaryNode(SbiParser *)
Definition: exprnode.cxx:234
bool IsLvalue() const
Definition: exprnode.cxx:176
void CollectBits()
Definition: exprnode.cxx:195
bool IsOperand() const
Definition: expr.hxx:127
OUString aStrVal
Definition: expr.hxx:115
SbVar aVar
Definition: expr.hxx:113
bool IsNumber() const
Definition: exprnode.cxx:166
SbxDataType GetType() const
Definition: symtbl.hxx:115
void Error(ErrCode c)
Definition: token.hxx:123
std::unique_ptr< SbiExprList > SbiExprListPtr
Definition: expr.hxx:34
@ SbxTYPEOF
Definition: expr.hxx:75
@ SbxSTRVAL
Definition: expr.hxx:73
@ SbxNODE
Definition: expr.hxx:76
@ SbxNEW
Definition: expr.hxx:77
@ SbxDUMMY
Definition: expr.hxx:78
@ SbxVARVAL
Definition: expr.hxx:74
@ SbxNUMVAL
Definition: expr.hxx:72
DocumentType eType
void * p
sal_Int64 n
constexpr T & temporary(T &&x)
long Long
sal_Int16 nId
#define ERRCODE_BASIC_MATH_OVERFLOW
Definition: sberrors.hxx:27
#define ERRCODE_BASIC_CONVERSION
Definition: sberrors.hxx:30
#define ERRCODE_BASIC_ZERODIV
Definition: sberrors.hxx:29
constexpr auto SbxMAXLNG
Definition: sbxdef.hxx:190
constexpr sal_Int32 SbxMINLNG
Definition: sbxdef.hxx:191
SbxBOOL
Definition: sbxdef.hxx:215
@ SbxFALSE
Definition: sbxdef.hxx:215
@ SbxTRUE
Definition: sbxdef.hxx:215
constexpr auto SbxMAXINT
Definition: sbxdef.hxx:187
SbxDataType
Definition: sbxdef.hxx:37
@ SbxOBJECT
Definition: sbxdef.hxx:47
@ SbxLONG
Definition: sbxdef.hxx:41
@ SbxVARIANT
Definition: sbxdef.hxx:51
@ SbxSINGLE
Definition: sbxdef.hxx:42
@ SbxSTRING
Definition: sbxdef.hxx:46
@ SbxINTEGER
Definition: sbxdef.hxx:40
@ SbxDOUBLE
Definition: sbxdef.hxx:43
constexpr auto SbxMININT
Definition: sbxdef.hxx:188
SbiExprListVector * pvMorePar
Definition: expr.hxx:44
SbiExprNode * pNext
Definition: expr.hxx:41
SbiSymDef * pDef
Definition: expr.hxx:42
SbiExprList * pPar
Definition: expr.hxx:43
SbiToken
Definition: token.hxx:30
@ NOT
Definition: token.hxx:74
@ MUL
Definition: token.hxx:71
@ GT
Definition: token.hxx:73
@ MOD
Definition: token.hxx:72
@ CAT
Definition: token.hxx:75
@ LT
Definition: token.hxx:73
@ NE
Definition: token.hxx:73
@ GE
Definition: token.hxx:73
@ LE
Definition: token.hxx:73
@ NIL
Definition: token.hxx:31
@ EQV
Definition: token.hxx:74
@ IMP
Definition: token.hxx:75
@ DIV
Definition: token.hxx:72
@ AND
Definition: token.hxx:74
@ PLUS
Definition: token.hxx:72
@ OR
Definition: token.hxx:74
@ EQ
Definition: token.hxx:73
@ LIKE
Definition: token.hxx:75
@ XOR
Definition: token.hxx:74
@ EXPON
Definition: token.hxx:71
@ MINUS
Definition: token.hxx:72
@ NEG
Definition: token.hxx:71
@ IDIV
Definition: token.hxx:72