Branch data Line data Source code
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 <math.h>
22 : :
23 : : #include <rtl/math.hxx>
24 : : #include "sbcomp.hxx"
25 : : #include "expr.hxx"
26 : :
27 : :
28 : 0 : SbiExprNode::SbiExprNode( void )
29 : : {
30 : 0 : pLeft = NULL;
31 : 0 : pRight = NULL;
32 : 0 : eNodeType = SbxDUMMY;
33 : 0 : }
34 : :
35 : 959 : SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
36 : : {
37 : 959 : BaseInit( p );
38 : :
39 : 959 : pLeft = l;
40 : 959 : pRight = r;
41 : 959 : eTok = t;
42 : 959 : nVal = 0;
43 : 959 : eType = SbxVARIANT; // Nodes are always Variant
44 : 959 : eNodeType = SbxNODE;
45 : 959 : }
46 : :
47 : 752 : SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
48 : : {
49 : 752 : BaseInit( p );
50 : :
51 : 752 : eType = t;
52 : 752 : eNodeType = SbxNUMVAL;
53 : 752 : nVal = n;
54 : 752 : }
55 : :
56 : 1534 : SbiExprNode::SbiExprNode( SbiParser* p, const String& rVal )
57 : : {
58 : 1534 : BaseInit( p );
59 : :
60 : 1534 : eType = SbxSTRING;
61 : 1534 : eNodeType = SbxSTRVAL;
62 [ + - ]: 1534 : aStrVal = rVal;
63 : 1534 : }
64 : :
65 : 5784 : SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
66 : : {
67 : 5784 : BaseInit( p );
68 : :
69 [ + + ]: 5784 : eType = ( t == SbxVARIANT ) ? r.GetType() : t;
70 : 5784 : eNodeType = SbxVARVAL;
71 : 5784 : aVar.pDef = (SbiSymDef*) &r;
72 : 5784 : aVar.pPar = l;
73 : 5784 : aVar.pvMorePar = NULL;
74 : 5784 : aVar.pNext= NULL;
75 : 5784 : }
76 : :
77 : : // #120061 TypeOf
78 : 0 : SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId )
79 : : {
80 : 0 : BaseInit( p );
81 : :
82 : 0 : pLeft = l;
83 : 0 : eType = SbxBOOL;
84 : 0 : eNodeType = SbxTYPEOF;
85 : 0 : nTypeStrId = nId;
86 : 0 : }
87 : :
88 : : // new <type>
89 : 0 : SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId )
90 : : {
91 : 0 : BaseInit( p );
92 : :
93 : 0 : eType = SbxOBJECT;
94 : 0 : eNodeType = SbxNEW;
95 : 0 : nTypeStrId = nId;
96 : 0 : }
97 : :
98 : : // From 1995-12-17, auxiliary function for Ctor for the uniform initialisation
99 : 9029 : void SbiExprNode::BaseInit( SbiParser* p )
100 : : {
101 : 9029 : pGen = &p->aGen;
102 : 9029 : eTok = NIL;
103 : 9029 : pLeft = NULL;
104 : 9029 : pRight = NULL;
105 : 9029 : pWithParent = NULL;
106 : 9029 : bError = false;
107 : 9029 : }
108 : :
109 : 9029 : SbiExprNode::~SbiExprNode()
110 : : {
111 [ + + ][ + - ]: 9029 : delete pLeft;
112 [ + + ][ + - ]: 9029 : delete pRight;
113 [ + + ]: 9029 : if( IsVariable() )
114 : : {
115 [ + + ][ + - ]: 5784 : delete aVar.pPar;
116 [ + + ][ + - ]: 5784 : delete aVar.pNext;
117 : 5784 : SbiExprListVector* pvMorePar = aVar.pvMorePar;
118 [ - + ]: 5784 : if( pvMorePar )
119 : : {
120 : 0 : SbiExprListVector::iterator it;
121 [ # # ][ # # ]: 0 : for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
122 [ # # ][ # # ]: 0 : delete *it;
123 [ # # ]: 0 : delete pvMorePar;
124 : : }
125 : : }
126 [ - + ]: 18058 : }
127 : :
128 : 1668 : SbiSymDef* SbiExprNode::GetVar()
129 : : {
130 [ + - ]: 1668 : if( eNodeType == SbxVARVAL )
131 : 1668 : return aVar.pDef;
132 : : else
133 : 1668 : return NULL;
134 : : }
135 : :
136 : 1668 : SbiSymDef* SbiExprNode::GetRealVar()
137 : : {
138 : 1668 : SbiExprNode* p = GetRealNode();
139 [ + - ]: 1668 : if( p )
140 : 1668 : return p->GetVar();
141 : : else
142 : 1668 : return NULL;
143 : : }
144 : :
145 : : // From 1995-12-18
146 : 1668 : SbiExprNode* SbiExprNode::GetRealNode()
147 : : {
148 [ + - ]: 1668 : if( eNodeType == SbxVARVAL )
149 : : {
150 : 1668 : SbiExprNode* p = this;
151 [ + + ]: 2026 : while( p->aVar.pNext )
152 : 358 : p = p->aVar.pNext;
153 : 1668 : return p;
154 : : }
155 : : else
156 : 1668 : return NULL;
157 : : }
158 : :
159 : : // This method transform the type, if it fits into the Integer range
160 : :
161 : 42 : bool SbiExprNode::IsIntConst()
162 : : {
163 [ + - ]: 42 : if( eNodeType == SbxNUMVAL )
164 : : {
165 [ + - ][ + - ]: 42 : if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
166 : : {
167 : : double n;
168 [ + - ][ + - ]: 42 : if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
[ + - ][ + - ]
169 : : {
170 : 42 : nVal = (double) (short) nVal;
171 : 42 : eType = SbxINTEGER;
172 : 42 : return true;
173 : : }
174 : : }
175 : : }
176 : 42 : return false;
177 : : }
178 : :
179 : 375 : bool SbiExprNode::IsNumber()
180 : : {
181 : 375 : return eNodeType == SbxNUMVAL;
182 : : }
183 : :
184 : 10296 : bool SbiExprNode::IsVariable()
185 : : {
186 : 10296 : return eNodeType == SbxVARVAL;
187 : : }
188 : :
189 : 1201 : bool SbiExprNode::IsLvalue()
190 : : {
191 : 1201 : return IsVariable();
192 : : }
193 : :
194 : : // Identify of the depth of a tree
195 : :
196 : 0 : short SbiExprNode::GetDepth()
197 : : {
198 [ # # ]: 0 : if( IsOperand() ) return 0;
199 : : else
200 : : {
201 : 0 : short d1 = pLeft->GetDepth();
202 : 0 : short d2 = pRight->GetDepth();
203 : 0 : return( (d1 < d2 ) ? d2 : d1 ) + 1;
204 : : }
205 : : }
206 : :
207 : :
208 : : // Adjustment of a tree:
209 : : // 1. Constant Folding
210 : : // 2. Type-Adjustment
211 : : // 3. Conversion of the operans into Strings
212 : : // 4. Lifting of the composite- and error-bits
213 : :
214 : 4398 : void SbiExprNode::Optimize()
215 : : {
216 : 4398 : FoldConstants();
217 : 4398 : CollectBits();
218 : 4398 : }
219 : :
220 : : // Lifting of the error-bits
221 : :
222 : 6253 : void SbiExprNode::CollectBits()
223 : : {
224 [ + + ]: 6253 : if( pLeft )
225 : : {
226 : 953 : pLeft->CollectBits();
227 [ - + ][ + - ]: 953 : bError = bError || pLeft->bError;
228 : : }
229 [ + + ]: 6253 : if( pRight )
230 : : {
231 : 842 : pRight->CollectBits();
232 [ - + ][ + - ]: 842 : bError = bError || pRight->bError;
233 : : }
234 : 6253 : }
235 : :
236 : : // If a twig can be converted, True will be returned. In this case
237 : : // the result is in the left twig.
238 : :
239 : 6199 : void SbiExprNode::FoldConstants()
240 : : {
241 [ + + ][ - + ]: 7158 : if( IsOperand() || eTok == LIKE ) return;
[ + + ]
242 [ + - ]: 959 : if( pLeft )
243 : 959 : pLeft->FoldConstants();
244 [ + + ]: 959 : if( pRight )
245 : : {
246 : 842 : pRight->FoldConstants();
247 [ + + ][ + - ]: 842 : if( pLeft->IsConstant() && pRight->IsConstant()
[ + + ][ + + ]
248 : : && pLeft->eNodeType == pRight->eNodeType )
249 : : {
250 : 60 : CollectBits();
251 [ - + ]: 60 : if( eTok == CAT )
252 : : // CAT affiliate also two numbers!
253 : 0 : eType = SbxSTRING;
254 [ + - ]: 60 : if( pLeft->eType == SbxSTRING )
255 : : // No Type Mismatch!
256 : 60 : eType = SbxSTRING;
257 [ + - ]: 60 : if( eType == SbxSTRING )
258 : : {
259 [ + - ]: 60 : String rl( pLeft->GetString() );
260 [ + - ]: 60 : String rr( pRight->GetString() );
261 [ + - ][ + - ]: 60 : delete pLeft; pLeft = NULL;
262 [ + - ][ + - ]: 60 : delete pRight; pRight = NULL;
263 [ - + ][ # # ]: 60 : if( eTok == PLUS || eTok == CAT )
264 : : {
265 : 60 : eTok = CAT;
266 : : // Linking:
267 [ + - ]: 60 : aStrVal = rl;
268 [ + - ]: 60 : aStrVal += rr;
269 : 60 : eType = SbxSTRING;
270 : 60 : eNodeType = SbxSTRVAL;
271 : : }
272 : : else
273 : : {
274 : 0 : eType = SbxDOUBLE;
275 : 0 : eNodeType = SbxNUMVAL;
276 [ # # ]: 0 : StringCompare eRes = rr.CompareTo( rl );
277 [ # # # # : 0 : switch( eTok )
# # # ]
278 : : {
279 : : case EQ:
280 [ # # ]: 0 : nVal = ( eRes == COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE;
281 : 0 : break;
282 : : case NE:
283 [ # # ]: 0 : nVal = ( eRes != COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE;
284 : 0 : break;
285 : : case LT:
286 [ # # ]: 0 : nVal = ( eRes == COMPARE_LESS ) ? SbxTRUE : SbxFALSE;
287 : 0 : break;
288 : : case GT:
289 [ # # ]: 0 : nVal = ( eRes == COMPARE_GREATER ) ? SbxTRUE : SbxFALSE;
290 : 0 : break;
291 : : case LE:
292 [ # # ]: 0 : nVal = ( eRes != COMPARE_GREATER ) ? SbxTRUE : SbxFALSE;
293 : 0 : break;
294 : : case GE:
295 [ # # ]: 0 : nVal = ( eRes != COMPARE_LESS ) ? SbxTRUE : SbxFALSE;
296 : 0 : break;
297 : : default:
298 [ # # ]: 0 : pGen->GetParser()->Error( SbERR_CONVERSION );
299 : 0 : bError = true;
300 : : }
301 [ + - ][ + - ]: 60 : }
302 : : }
303 : : else
304 : : {
305 : 0 : double nl = pLeft->nVal;
306 : 0 : double nr = pRight->nVal;
307 : 0 : long ll = 0, lr = 0;
308 : 0 : long llMod = 0, lrMod = 0;
309 [ # # ][ # # ]: 0 : if( ( eTok >= AND && eTok <= IMP )
[ # # ][ # # ]
310 : : || eTok == IDIV || eTok == MOD )
311 : : {
312 : : // Integer operations
313 : 0 : sal_Bool err = sal_False;
314 [ # # ]: 0 : if( nl > SbxMAXLNG ) err = sal_True, nl = SbxMAXLNG;
315 : : else
316 [ # # ]: 0 : if( nl < SbxMINLNG ) err = sal_True, nl = SbxMINLNG;
317 [ # # ]: 0 : if( nr > SbxMAXLNG ) err = sal_True, nr = SbxMAXLNG;
318 : : else
319 [ # # ]: 0 : if( nr < SbxMINLNG ) err = sal_True, nr = SbxMINLNG;
320 : 0 : ll = (long) nl; lr = (long) nr;
321 [ # # ]: 0 : llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
322 [ # # ]: 0 : lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
323 [ # # ]: 0 : if( err )
324 : : {
325 : 0 : pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
326 : 0 : bError = true;
327 : : }
328 : : }
329 : : sal_Bool bBothInt = sal_Bool( pLeft->eType < SbxSINGLE
330 [ # # ][ # # ]: 0 : && pRight->eType < SbxSINGLE );
331 [ # # ]: 0 : delete pLeft; pLeft = NULL;
332 [ # # ]: 0 : delete pRight; pRight = NULL;
333 : 0 : nVal = 0;
334 : 0 : eType = SbxDOUBLE;
335 : 0 : eNodeType = SbxNUMVAL;
336 : 0 : sal_Bool bCheckType = sal_False;
337 [ # # # # : 0 : switch( eTok )
# # # # #
# # # # #
# # # #
# ]
338 : : {
339 : : case EXPON:
340 : 0 : nVal = pow( nl, nr ); break;
341 : : case MUL:
342 : 0 : bCheckType = sal_True;
343 : 0 : nVal = nl * nr; break;
344 : : case DIV:
345 [ # # ]: 0 : if( !nr )
346 : : {
347 : 0 : pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
348 : 0 : bError = true;
349 : 0 : } else nVal = nl / nr;
350 : 0 : break;
351 : : case PLUS:
352 : 0 : bCheckType = sal_True;
353 : 0 : nVal = nl + nr; break;
354 : : case MINUS:
355 : 0 : bCheckType = sal_True;
356 : 0 : nVal = nl - nr; break;
357 : : case EQ:
358 [ # # ]: 0 : nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
359 : 0 : eType = SbxINTEGER; break;
360 : : case NE:
361 [ # # ]: 0 : nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
362 : 0 : eType = SbxINTEGER; break;
363 : : case LT:
364 [ # # ]: 0 : nVal = ( nl < nr ) ? SbxTRUE : SbxFALSE;
365 : 0 : eType = SbxINTEGER; break;
366 : : case GT:
367 [ # # ]: 0 : nVal = ( nl > nr ) ? SbxTRUE : SbxFALSE;
368 : 0 : eType = SbxINTEGER; break;
369 : : case LE:
370 [ # # ]: 0 : nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
371 : 0 : eType = SbxINTEGER; break;
372 : : case GE:
373 [ # # ]: 0 : nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
374 : 0 : eType = SbxINTEGER; break;
375 : : case IDIV:
376 [ # # ]: 0 : if( !lr )
377 : : {
378 : 0 : pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
379 : 0 : bError = true;
380 : 0 : } else nVal = ll / lr;
381 : 0 : eType = SbxLONG; break;
382 : : case MOD:
383 [ # # ]: 0 : if( !lr )
384 : : {
385 : 0 : pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
386 : 0 : bError = true;
387 : 0 : } else nVal = llMod % lrMod;
388 : 0 : eType = SbxLONG; break;
389 : : case AND:
390 : 0 : nVal = (double) ( ll & lr ); eType = SbxLONG; break;
391 : : case OR:
392 : 0 : nVal = (double) ( ll | lr ); eType = SbxLONG; break;
393 : : case XOR:
394 : 0 : nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
395 : : case EQV:
396 : 0 : nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
397 : : case IMP:
398 : 0 : nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
399 : 0 : default: break;
400 : : }
401 : :
402 [ # # ]: 0 : if( !::rtl::math::isFinite( nVal ) )
403 : 0 : pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
404 : :
405 : : // Recover the data type to kill rounding error
406 [ # # ][ # # ]: 0 : if( bCheckType && bBothInt
[ # # ][ # # ]
407 : : && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
408 : : {
409 : : // Decimal place away
410 : 0 : long n = (long) nVal;
411 : 0 : nVal = n;
412 : : eType = ( n >= SbxMININT && n <= SbxMAXINT )
413 [ # # ][ # # ]: 0 : ? SbxINTEGER : SbxLONG;
414 : : }
415 : : }
416 : : }
417 : : }
418 [ + - ][ + + ]: 117 : else if( pLeft && pLeft->IsNumber() )
[ + + ]
419 : : {
420 : 6 : nVal = pLeft->nVal;
421 [ + - ]: 6 : delete pLeft;
422 : 6 : pLeft = NULL;
423 : 6 : eType = SbxDOUBLE;
424 : 6 : eNodeType = SbxNUMVAL;
425 [ + - - ]: 6 : switch( eTok )
426 : : {
427 : : case NEG:
428 : 6 : nVal = -nVal; break;
429 : : case NOT: {
430 : : // Integer operation!
431 : 0 : sal_Bool err = sal_False;
432 [ # # ]: 0 : if( nVal > SbxMAXLNG ) err = sal_True, nVal = SbxMAXLNG;
433 : : else
434 [ # # ]: 0 : if( nVal < SbxMINLNG ) err = sal_True, nVal = SbxMINLNG;
435 [ # # ]: 0 : if( err )
436 : : {
437 : 0 : pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
438 : 0 : bError = true;
439 : : }
440 : 0 : nVal = (double) ~((long) nVal);
441 : 0 : eType = SbxLONG;
442 : 0 : } break;
443 : 6 : default: break;
444 : : }
445 : : }
446 [ + + ]: 959 : if( eNodeType == SbxNUMVAL )
447 : : {
448 : : // Potentially convolve in INTEGER (because of better opcode)?
449 [ + - ][ + - ]: 6 : if( eType == SbxSINGLE || eType == SbxDOUBLE )
450 : : {
451 : : double x;
452 [ + - ][ + - ]: 6 : if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
[ + - ][ + - ]
453 : 6 : && !modf( nVal, &x ) )
454 : 6 : eType = SbxLONG;
455 : : }
456 [ + - ][ + - ]: 6 : if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
[ + - ]
457 : 6 : eType = SbxINTEGER;
458 : : }
459 : : }
460 : :
461 : :
462 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|