xref: /aoo41x/main/basic/source/comp/exprnode.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 
31 #include <math.h>
32 
33 #include <rtl/math.hxx>
34 #include "sbcomp.hxx"
35 #include "expr.hxx"
36 
37 //////////////////////////////////////////////////////////////////////////
38 
39 SbiExprNode::SbiExprNode( void )
40 {
41 	pLeft = NULL;
42 	pRight = NULL;
43 	eNodeType = SbxDUMMY;
44 }
45 
46 SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, SbiToken t, SbiExprNode* r )
47 {
48 	BaseInit( p );
49 
50 	pLeft     = l;
51 	pRight    = r;
52 	eTok      = t;
53 	nVal	  = 0;
54 	eType     = SbxVARIANT;		// Nodes sind immer Variant
55 	eNodeType = SbxNODE;
56 	bComposite= sal_True;
57 }
58 
59 SbiExprNode::SbiExprNode( SbiParser* p, double n, SbxDataType t )
60 {
61 	BaseInit( p );
62 
63 	eType     = t;
64 	eNodeType = SbxNUMVAL;
65 	nVal      = n;
66 }
67 
68 SbiExprNode::SbiExprNode( SbiParser* p, const String& rVal )
69 {
70 	BaseInit( p );
71 
72 	eType     = SbxSTRING;
73 	eNodeType = SbxSTRVAL;
74 	aStrVal   = rVal;
75 }
76 
77 SbiExprNode::SbiExprNode( SbiParser* p, const SbiSymDef& r, SbxDataType t, SbiExprList* l )
78 {
79 	BaseInit( p );
80 
81 	eType     = ( t == SbxVARIANT ) ? r.GetType() : t;
82 	eNodeType = SbxVARVAL;
83 	aVar.pDef = (SbiSymDef*) &r;
84 	aVar.pPar = l;
85 	aVar.pvMorePar = NULL;
86 	aVar.pNext= NULL;
87 
88 	// Funktionsergebnisse sind nie starr
89 	bComposite= sal_Bool( aVar.pDef->GetProcDef() != NULL );
90 }
91 
92 // #120061 TypeOf
93 SbiExprNode::SbiExprNode( SbiParser* p, SbiExprNode* l, sal_uInt16 nId )
94 {
95 	BaseInit( p );
96 
97 	pLeft      = l;
98 	eType      = SbxBOOL;
99 	eNodeType  = SbxTYPEOF;
100 	nTypeStrId = nId;
101 }
102 
103 // new <type>
104 SbiExprNode::SbiExprNode( SbiParser* p, sal_uInt16 nId )
105 {
106 	BaseInit( p );
107 
108 	eType     = SbxOBJECT;
109 	eNodeType = SbxNEW;
110 	nTypeStrId = nId;
111 }
112 
113 // AB: 17.12.95, Hilfsfunktion fuer Ctor fuer einheitliche Initialisierung
114 void SbiExprNode::BaseInit( SbiParser* p )
115 {
116 	pGen = &p->aGen;
117 	eTok = NIL;
118 	pLeft 		= NULL;
119 	pRight		= NULL;
120 	pWithParent = NULL;
121 	bComposite	= sal_False;
122 	bError	    = sal_False;
123 }
124 
125 SbiExprNode::~SbiExprNode()
126 {
127 	delete pLeft;
128 	delete pRight;
129 	if( IsVariable() )
130 	{
131 		delete aVar.pPar;
132 		delete aVar.pNext;
133 		SbiExprListVector* pvMorePar = aVar.pvMorePar;
134 		if( pvMorePar )
135 		{
136 			SbiExprListVector::iterator it;
137 			for( it = pvMorePar->begin() ; it != pvMorePar->end() ; ++it )
138 				delete *it;
139 			delete pvMorePar;
140 		}
141 	}
142 }
143 
144 SbiSymDef* SbiExprNode::GetVar()
145 {
146 	if( eNodeType == SbxVARVAL )
147 		return aVar.pDef;
148 	else
149 		return NULL;
150 }
151 
152 SbiSymDef* SbiExprNode::GetRealVar()
153 {
154 	SbiExprNode* p = GetRealNode();
155 	if( p )
156 		return p->GetVar();
157 	else
158 		return NULL;
159 }
160 
161 // AB: 18.12.95
162 SbiExprNode* SbiExprNode::GetRealNode()
163 {
164 	if( eNodeType == SbxVARVAL )
165 	{
166 		SbiExprNode* p = this;
167 		while( p->aVar.pNext )
168 			p = p->aVar.pNext;
169 		return p;
170 	}
171 	else
172 		return NULL;
173 }
174 
175 // Diese Methode setzt den Typ um, falls er in den Integer-Bereich hineinpasst
176 
177 sal_Bool SbiExprNode::IsIntConst()
178 {
179 	if( eNodeType == SbxNUMVAL )
180 	{
181 		if( eType >= SbxINTEGER && eType <= SbxDOUBLE )
182 		{
183 			double n;
184 			if( nVal >= SbxMININT && nVal <= SbxMAXINT && modf( nVal, &n ) == 0 )
185 			{
186 				nVal = (double) (short) nVal;
187 				eType = SbxINTEGER;
188 				return sal_True;
189 			}
190 		}
191 	}
192 	return sal_False;
193 }
194 
195 sal_Bool SbiExprNode::IsNumber()
196 {
197 	return sal_Bool( eNodeType == SbxNUMVAL );
198 }
199 
200 sal_Bool SbiExprNode::IsString()
201 {
202 	return sal_Bool( eNodeType == SbxSTRVAL );
203 }
204 
205 sal_Bool SbiExprNode::IsVariable()
206 {
207 	return sal_Bool( eNodeType == SbxVARVAL );
208 }
209 
210 sal_Bool SbiExprNode::IsLvalue()
211 {
212 	return IsVariable();
213 }
214 
215 // Ermitteln der Tiefe eines Baumes
216 
217 short SbiExprNode::GetDepth()
218 {
219 	if( IsOperand() ) return 0;
220 	else
221 	{
222 		short d1 = pLeft->GetDepth();
223 		short d2 = pRight->GetDepth();
224 		return( (d1 < d2 ) ? d2 : d1 ) + 1;
225 	}
226 }
227 
228 
229 // Abgleich eines Baumes:
230 // 1. Constant Folding
231 // 2. Typabgleich
232 // 3. Umwandlung der Operanden in Strings
233 // 4. Hochziehen der Composite- und Error-Bits
234 
235 void SbiExprNode::Optimize()
236 {
237 	FoldConstants();
238 	CollectBits();
239 }
240 
241 // Hochziehen der Composite- und Fehlerbits
242 
243 void SbiExprNode::CollectBits()
244 {
245 	if( pLeft )
246 	{
247 		pLeft->CollectBits();
248 		bError |= pLeft->bError;
249 		bComposite |= pLeft->bComposite;
250 	}
251 	if( pRight )
252 	{
253 		pRight->CollectBits();
254 		bError |= pRight->bError;
255 		bComposite |= pRight->bComposite;
256 	}
257 }
258 
259 // Kann ein Zweig umgeformt werden, wird sal_True zurueckgeliefert. In diesem
260 // Fall ist das Ergebnis im linken Zweig.
261 
262 void SbiExprNode::FoldConstants()
263 {
264 	if( IsOperand() || eTok == LIKE ) return;
265 	if( pLeft )
266 		pLeft->FoldConstants();
267 	if( pRight )
268 	{
269 		pRight->FoldConstants();
270 		if( pLeft->IsConstant() && pRight->IsConstant()
271 			&& pLeft->eNodeType == pRight->eNodeType )
272 		{
273 			CollectBits();
274 			if( eTok == CAT )
275 				// CAT verbindet auch zwei Zahlen miteinander!
276 				eType = SbxSTRING;
277 			if( pLeft->eType == SbxSTRING )
278 				// Kein Type Mismatch!
279 				eType = SbxSTRING;
280 			if( eType == SbxSTRING )
281 			{
282 				String rl( pLeft->GetString() );
283 				String rr( pRight->GetString() );
284 				delete pLeft; pLeft = NULL;
285 				delete pRight; pRight = NULL;
286 				bComposite = sal_False;
287 				if( eTok == PLUS || eTok == CAT )
288 				{
289 					eTok = CAT;
290 					// Verkettung:
291 					aStrVal = rl;
292 					aStrVal += rr;
293 					eType = SbxSTRING;
294 					eNodeType = SbxSTRVAL;
295 				}
296 				else
297 				{
298 					eType = SbxDOUBLE;
299 					eNodeType = SbxNUMVAL;
300 					StringCompare eRes = rr.CompareTo( rl );
301 					switch( eTok )
302 					{
303 						case EQ:
304 							nVal = ( eRes == COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE;
305 							break;
306 						case NE:
307 							nVal = ( eRes != COMPARE_EQUAL ) ? SbxTRUE : SbxFALSE;
308 							break;
309 						case LT:
310 							nVal = ( eRes == COMPARE_LESS ) ? SbxTRUE : SbxFALSE;
311 							break;
312 						case GT:
313 							nVal = ( eRes == COMPARE_GREATER ) ? SbxTRUE : SbxFALSE;
314 							break;
315 						case LE:
316 							nVal = ( eRes != COMPARE_GREATER ) ? SbxTRUE : SbxFALSE;
317 							break;
318 						case GE:
319 							nVal = ( eRes != COMPARE_LESS ) ? SbxTRUE : SbxFALSE;
320 							break;
321 						default:
322 							pGen->GetParser()->Error( SbERR_CONVERSION );
323 							bError = sal_True;
324 					}
325 				}
326 			}
327 			else
328 			{
329 				double nl = pLeft->nVal;
330 				double nr = pRight->nVal;
331 				long ll = 0, lr = 0;
332 				long llMod = 0, lrMod = 0;
333 				if( ( eTok >= AND && eTok <= IMP )
334 				   || eTok == IDIV || eTok == MOD )
335 				{
336 					// Integer-Operationen
337 					sal_Bool err = sal_False;
338 					if( nl > SbxMAXLNG ) err = sal_True, nl = SbxMAXLNG;
339 					else
340 					if( nl < SbxMINLNG ) err = sal_True, nl = SbxMINLNG;
341 					if( nr > SbxMAXLNG ) err = sal_True, nr = SbxMAXLNG;
342 					else
343 					if( nr < SbxMINLNG ) err = sal_True, nr = SbxMINLNG;
344 					ll = (long) nl; lr = (long) nr;
345                     llMod = (long) (nl < 0 ? nl - 0.5 : nl + 0.5);
346                     lrMod = (long) (nr < 0 ? nr - 0.5 : nr + 0.5);
347 					if( err )
348 					{
349 						pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
350 						bError = sal_True;
351 					}
352 				}
353 				sal_Bool bBothInt = sal_Bool( pLeft->eType < SbxSINGLE
354 								   && pRight->eType < SbxSINGLE );
355 				delete pLeft; pLeft = NULL;
356 				delete pRight; pRight = NULL;
357 				nVal = 0;
358 				eType = SbxDOUBLE;
359 				eNodeType = SbxNUMVAL;
360 				bComposite = sal_False;
361 				sal_Bool bCheckType = sal_False;
362 				switch( eTok )
363 				{
364 					case EXPON:
365 						nVal = pow( nl, nr ); break;
366 					case MUL:
367 						bCheckType = sal_True;
368 						nVal = nl * nr; break;
369 					case DIV:
370 						if( !nr )
371 						{
372 							pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
373 							bError = sal_True;
374 						} else nVal = nl / nr;
375 						break;
376 					case PLUS:
377 						bCheckType = sal_True;
378 						nVal = nl + nr; break;
379 					case MINUS:
380 						bCheckType = sal_True;
381 						nVal = nl - nr; break;
382 					case EQ:
383 						nVal = ( nl == nr ) ? SbxTRUE : SbxFALSE;
384 						eType = SbxINTEGER; break;
385 					case NE:
386 						nVal = ( nl != nr ) ? SbxTRUE : SbxFALSE;
387 						eType = SbxINTEGER; break;
388 					case LT:
389 						nVal = ( nl <  nr ) ? SbxTRUE : SbxFALSE;
390 						eType = SbxINTEGER; break;
391 					case GT:
392 						nVal = ( nl >  nr ) ? SbxTRUE : SbxFALSE;
393 						eType = SbxINTEGER; break;
394 					case LE:
395 						nVal = ( nl <= nr ) ? SbxTRUE : SbxFALSE;
396 						eType = SbxINTEGER; break;
397 					case GE:
398 						nVal = ( nl >= nr ) ? SbxTRUE : SbxFALSE;
399 						eType = SbxINTEGER; break;
400 					case IDIV:
401 						if( !lr )
402 						{
403 							pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
404 							bError = sal_True;
405 						} else nVal = ll / lr;
406 						eType = SbxLONG; break;
407 					case MOD:
408 						if( !lr )
409 						{
410 							pGen->GetParser()->Error( SbERR_ZERODIV ); nVal = HUGE_VAL;
411 							bError = sal_True;
412 						} else nVal = llMod % lrMod;
413 						eType = SbxLONG; break;
414 					case AND:
415 						nVal = (double) ( ll & lr ); eType = SbxLONG; break;
416 					case OR:
417 						nVal = (double) ( ll | lr ); eType = SbxLONG; break;
418 					case XOR:
419 						nVal = (double) ( ll ^ lr ); eType = SbxLONG; break;
420 					case EQV:
421 						nVal = (double) ( ~ll ^ lr ); eType = SbxLONG; break;
422 					case IMP:
423 						nVal = (double) ( ~ll | lr ); eType = SbxLONG; break;
424 					default: break;
425 				}
426 
427                 if( !::rtl::math::isFinite( nVal ) )
428 					pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
429 
430 				// Den Datentyp wiederherstellen, um Rundungsfehler
431 				// zu killen
432 				if( bCheckType && bBothInt
433 				 && nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
434 				{
435 					// NK-Stellen weg
436 					long n = (long) nVal;
437 					nVal = n;
438 					eType = ( n >= SbxMININT && n <= SbxMAXINT )
439 						  ? SbxINTEGER : SbxLONG;
440 				}
441 			}
442 		}
443 	}
444 	else if( pLeft && pLeft->IsNumber() )
445 	{
446 		nVal = pLeft->nVal;
447 		delete pLeft;
448 		pLeft = NULL;
449 		eType = SbxDOUBLE;
450 		eNodeType = SbxNUMVAL;
451 		bComposite = sal_False;
452 		switch( eTok )
453 		{
454 			case NEG:
455 				nVal = -nVal; break;
456 			case NOT: {
457 				// Integer-Operation!
458 				sal_Bool err = sal_False;
459 				if( nVal > SbxMAXLNG ) err = sal_True, nVal = SbxMAXLNG;
460 				else
461 				if( nVal < SbxMINLNG ) err = sal_True, nVal = SbxMINLNG;
462 				if( err )
463 				{
464 					pGen->GetParser()->Error( SbERR_MATH_OVERFLOW );
465 					bError = sal_True;
466 				}
467 				nVal = (double) ~((long) nVal);
468 				eType = SbxLONG;
469 				} break;
470 			default: break;
471 		}
472 	}
473 	if( eNodeType == SbxNUMVAL )
474 	{
475 		// Evtl auf INTEGER falten (wg. besserem Opcode)?
476 		if( eType == SbxSINGLE || eType == SbxDOUBLE )
477 		{
478 			double x;
479 			if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG
480 			&& !modf( nVal, &x ) )
481 				eType = SbxLONG;
482 		}
483 		if( eType == SbxLONG && nVal >= SbxMININT && nVal <= SbxMAXINT )
484 			eType = SbxINTEGER;
485 	}
486 }
487 
488 
489