/* * $Id$ */ /* * Harbour Project source code: * Compiler Expression Optimizer - reducing expressions * * Copyright 1999 Ryszard Glab * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version, with one exception: * * The exception is that if you link the Harbour Runtime Library (HRL) * and/or the Harbour Virtual Machine (HVM) with other files to produce * an executable, this does not by itself cause the resulting executable * to be covered by the GNU General Public License. Your use of that * executable is in no way restricted on account of linking the HRL * and/or HVM code into it. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit * their web site at http://www.gnu.org/). * */ /* TOFIX: Split the code, since MSC8 can't compile it, even in Huge model. */ /* TODO: * - Correct post- and pre- operations to correctly handle the following code * a[ i++ ]++ * Notice: in current implementation (an in Clipper too) 'i++' is evaluated * two times! This causes that the new value (after incrementation) is * stored in next element of the array. */ /* NOTE: This must be the first definition * This is a common code shared by macro and standalone compiler */ #define HB_MACRO_SUPPORT #include #include "hbmacro.h" #include "hbcomp.h" HB_EXPR_PTR hb_compExprReduceMod( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) { if( pLeft->value.asNum.NumType == HB_ET_LONG && pRight->value.asNum.NumType == HB_ET_LONG ) { if( pRight->value.asNum.lVal ) { double dVal = pLeft->value.asNum.lVal % pRight->value.asNum.lVal; if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) { pSelf->value.asNum.lVal = ( long ) dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_LONG; } else { pSelf->value.asNum.dVal = dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_DOUBLE; } pSelf->ExprType = HB_ET_NUMERIC; pSelf->ValType = HB_EV_NUMERIC; hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); } } } else { /* TODO: Check for incompatible types e.g. 3 % "txt" */ } return pSelf; } HB_EXPR_PTR hb_compExprReduceDiv( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) { BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); switch( bType ) { case HB_ET_LONG: if( pRight->value.asNum.lVal ) { double dVal = ( double ) pLeft->value.asNum.lVal / ( double ) pRight->value.asNum.lVal; if( fmod( dVal, 1.0 ) == 0.0 ) { /* Return integer results as long */ pSelf->value.asNum.lVal = ( long ) dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_LONG; } else { /* Return non-integer results as double */ pSelf->value.asNum.dVal = dVal; pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; pSelf->value.asNum.NumType = HB_ET_DOUBLE; } pSelf->ExprType = HB_ET_NUMERIC; } break; case HB_ET_DOUBLE: if( pRight->value.asNum.dVal != 0.0 ) { pSelf->value.asNum.dVal = pLeft->value.asNum.dVal / pRight->value.asNum.dVal; pSelf->value.asNum.NumType = HB_ET_DOUBLE; pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; pSelf->ExprType = HB_ET_NUMERIC; } break; default: if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) { if( pRight->value.asNum.lVal ) { pSelf->value.asNum.dVal = pLeft->value.asNum.dVal / ( double ) pRight->value.asNum.lVal; pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; } } else { if( pRight->value.asNum.dVal != 0.0 ) { pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal / pRight->value.asNum.dVal; pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; } } pSelf->value.asNum.NumType = HB_ET_DOUBLE; pSelf->ExprType = HB_ET_NUMERIC; } /* switch bType */ if( pSelf->ExprType == HB_ET_NUMERIC ) { /* The expression was reduced - delete old components */ pSelf->ValType = HB_EV_NUMERIC; hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); } } else { /* TODO: Check for incompatible types e.g. 3 / "txt" */ } return pSelf; } HB_EXPR_PTR hb_compExprReduceMult( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) { BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); switch( bType ) { case HB_ET_LONG: { double dVal = ( double ) pLeft->value.asNum.lVal * ( double ) pRight->value.asNum.lVal; if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) { pSelf->value.asNum.lVal = ( long ) dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_LONG; } else { pSelf->value.asNum.dVal = dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_DOUBLE; } break; } case HB_ET_DOUBLE: { pSelf->value.asNum.dVal = pLeft->value.asNum.dVal * pRight->value.asNum.dVal; pSelf->value.asNum.NumType = HB_ET_DOUBLE; pSelf->value.asNum.bDec = pLeft->value.asNum.bDec + pRight->value.asNum.bDec; break; } default: { if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) { pSelf->value.asNum.dVal = pLeft->value.asNum.dVal * ( double ) pRight->value.asNum.lVal; pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; } else { pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal * pRight->value.asNum.dVal; pSelf->value.asNum.bDec = pRight->value.asNum.bDec; } pSelf->value.asNum.NumType = HB_ET_DOUBLE; } } pSelf->ExprType = HB_ET_NUMERIC; pSelf->ValType = HB_EV_NUMERIC; hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); } else { /* TODO: Check for incompatible types e.g. 3 * "txt" */ } return pSelf; } HB_EXPR_PTR hb_compExprReduceMinus( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) { BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); switch( bType ) { case HB_ET_LONG: { double dVal = ( double ) pLeft->value.asNum.lVal - ( double ) pRight->value.asNum.lVal; if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) { pSelf->value.asNum.lVal = ( long ) dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_LONG; } else { pSelf->value.asNum.dVal = dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_DOUBLE; } break; } case HB_ET_DOUBLE: { pSelf->value.asNum.dVal = pLeft->value.asNum.dVal - pRight->value.asNum.dVal; pSelf->value.asNum.NumType = HB_ET_DOUBLE; if( pLeft->value.asNum.bDec < pRight->value.asNum.bDec ) pSelf->value.asNum.bDec = pRight->value.asNum.bDec; else pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; break; } default: { if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) { pSelf->value.asNum.dVal = pLeft->value.asNum.dVal - ( double ) pRight->value.asNum.lVal; pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; } else { pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal - pRight->value.asNum.dVal; pSelf->value.asNum.bDec = pRight->value.asNum.bDec; } pSelf->value.asNum.NumType = HB_ET_DOUBLE; } } pSelf->ExprType = HB_ET_NUMERIC; pSelf->ValType = HB_EV_NUMERIC; hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); } else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING ) { /* TODO: */ } else { /* TODO: Check for incompatible types e.g. "txt" - 3 */ } return pSelf; } HB_EXPR_PTR hb_compExprReducePlus( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) { BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); switch( bType ) { case HB_ET_LONG: { double dVal = ( double ) pLeft->value.asNum.lVal + ( double ) pRight->value.asNum.lVal; if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) { pSelf->value.asNum.lVal = ( long ) dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_LONG; } else { pSelf->value.asNum.dVal = dVal; pSelf->value.asNum.bDec = 0; pSelf->value.asNum.NumType = HB_ET_DOUBLE; } break; } case HB_ET_DOUBLE: { pSelf->value.asNum.dVal = pLeft->value.asNum.dVal + pRight->value.asNum.dVal; pSelf->value.asNum.NumType = HB_ET_DOUBLE; if( pLeft->value.asNum.bDec < pRight->value.asNum.bDec ) pSelf->value.asNum.bDec = pRight->value.asNum.bDec; else pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; break; } default: { if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) { pSelf->value.asNum.dVal = pLeft->value.asNum.dVal + ( double ) pRight->value.asNum.lVal; pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; } else { pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal + pRight->value.asNum.dVal; pSelf->value.asNum.bDec = pRight->value.asNum.bDec; } pSelf->value.asNum.NumType = HB_ET_DOUBLE; } } pSelf->ExprType = HB_ET_NUMERIC; pSelf->ValType = HB_EV_NUMERIC; hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); } else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING ) { pSelf->ExprType = HB_ET_NONE; /* suppress deletion of operator components */ hb_compExprFree( pSelf, HB_MACRO_PARAM ); if( pRight->ulLength == 0 ) { pSelf = pLeft; hb_compExprFree( pRight, HB_MACRO_PARAM ); } else if( pLeft->ulLength == 0 ) { pSelf = pRight; hb_compExprFree( pLeft, HB_MACRO_PARAM ); } else { pLeft->value.asString = (char *) hb_xrealloc( pLeft->value.asString, pLeft->ulLength + pRight->ulLength + 1 ); memcpy( pLeft->value.asString + pLeft->ulLength, pRight->value.asString, pRight->ulLength ); pLeft->ulLength += pRight->ulLength; pLeft->value.asString[ pLeft->ulLength ] = '\0'; pSelf = pLeft; hb_compExprFree( pRight, HB_MACRO_PARAM ); } } else { /* TODO: Check for incompatible types e.g. "txt" + 3 */ } return pSelf; } HB_EXPR_PTR hb_compExprReduceIN( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { if( ( pSelf->value.asOperator.pLeft->ExprType == pSelf->value.asOperator.pRight->ExprType ) && pSelf->value.asOperator.pLeft->ExprType == HB_ET_STRING ) { /* Both arguments are literal strings */ BOOL bResult; /* NOTE: CA-Cl*pper has a bug where the $ operator returns .T. when an empty string is searched [vszakats] */ if( pSelf->value.asOperator.pLeft->ulLength == 0 ) bResult = TRUE; else bResult = ( hb_strAt( pSelf->value.asOperator.pLeft->value.asString, pSelf->value.asOperator.pLeft->ulLength, pSelf->value.asOperator.pRight->value.asString, pSelf->value.asOperator.pRight->ulLength ) != 0 ); /* NOTE: * "" $ "XXX" = .T. * "" $ "" = .T. */ hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } /* TODO: add checking for incompatible types */ return pSelf; } HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == pRight->ExprType ) switch( pLeft->ExprType ) { case HB_ET_LOGICAL: { /* .F. != .T. = .T. * .T. != .T. = .F. * .F. != .F. = .F. * .T. != .F. = .T. */ BOOL bResult = ( pLeft->value.asLogical != pRight->value.asLogical ); hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; case HB_ET_STRING: /* NOTE: the result depends on SET EXACT setting then it * cannot be optimized except the case when NULL string are * compared - "" != "" is always FALSE regardless of EXACT * setting */ if( (pLeft->ulLength | pRight->ulLength) == 0 ) { hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = FALSE; /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ } break; case HB_ET_NUMERIC: { BOOL bResult; switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) { case HB_ET_LONG: bResult = ( pLeft->value.asNum.lVal != pRight->value.asNum.lVal ); break; case HB_ET_DOUBLE: bResult = ( pLeft->value.asNum.dVal != pRight->value.asNum.dVal ); break; default: { if( pLeft->value.asNum.NumType == HB_ET_LONG ) bResult = ( pLeft->value.asNum.lVal != pRight->value.asNum.dVal ); else bResult = ( pLeft->value.asNum.dVal != pRight->value.asNum.lVal ); } break; } hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; } /* TODO: add checking of incompatible types else { } */ return pSelf; } HB_EXPR_PTR hb_compExprReduceGE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == pRight->ExprType ) switch( pLeft->ExprType ) { case HB_ET_LOGICAL: { /* .T. >= .F. = .T. * .T. >= .T. = .T. * .F. >= .F. = .T. * .F. >= .T. = .f. */ BOOL bResult = ! ( ! pLeft->value.asLogical && pRight->value.asLogical ); hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; case HB_ET_NUMERIC: { BOOL bResult; switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) { case HB_ET_LONG: bResult = ( pLeft->value.asNum.lVal >= pRight->value.asNum.lVal ); break; case HB_ET_DOUBLE: bResult = ( pLeft->value.asNum.dVal >= pRight->value.asNum.dVal ); break; default: { if( pLeft->value.asNum.NumType == HB_ET_LONG ) bResult = ( pLeft->value.asNum.lVal >= pRight->value.asNum.dVal ); else bResult = ( pLeft->value.asNum.dVal >= pRight->value.asNum.lVal ); } break; } hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; } /* TODO: add checking of incompatible types else { } */ return pSelf; } HB_EXPR_PTR hb_compExprReduceLE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == pRight->ExprType ) switch( pLeft->ExprType ) { case HB_ET_LOGICAL: { /* .T. <= .F. = .F. * .T. <= .T. = .T. * .F. <= .F. = .T. * .F. <= .T. = .T. */ BOOL bResult = ! ( pLeft->value.asLogical && ! pRight->value.asLogical ); hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; case HB_ET_NUMERIC: { BOOL bResult; switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) { case HB_ET_LONG: bResult = ( pLeft->value.asNum.lVal <= pRight->value.asNum.lVal ); break; case HB_ET_DOUBLE: bResult = ( pLeft->value.asNum.dVal <= pRight->value.asNum.dVal ); break; default: { if( pLeft->value.asNum.NumType == HB_ET_LONG ) bResult = ( pLeft->value.asNum.lVal <= pRight->value.asNum.dVal ); else bResult = ( pLeft->value.asNum.dVal <= pRight->value.asNum.lVal ); } break; } hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; } /* TODO: add checking of incompatible types else { } */ return pSelf; } HB_EXPR_PTR hb_compExprReduceGT( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == pRight->ExprType ) switch( pLeft->ExprType ) { case HB_ET_LOGICAL: { /* .T. > .F. = .T. * .T. > .T. = .F. * .F. > .F. = .F. * .F. > .T. = .F. */ BOOL bResult = ( pLeft->value.asLogical && ! pRight->value.asLogical ); hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; case HB_ET_NUMERIC: { BOOL bResult; switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) { case HB_ET_LONG: bResult = ( pLeft->value.asNum.lVal > pRight->value.asNum.lVal ); break; case HB_ET_DOUBLE: bResult = ( pLeft->value.asNum.dVal > pRight->value.asNum.dVal ); break; default: { if( pLeft->value.asNum.NumType == HB_ET_LONG ) bResult = ( pLeft->value.asNum.lVal > pRight->value.asNum.dVal ); else bResult = ( pLeft->value.asNum.dVal > pRight->value.asNum.lVal ); } break; } hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; } /* TODO: add checking of incompatible types else { } */ return pSelf; } HB_EXPR_PTR hb_compExprReduceLT( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == pRight->ExprType ) switch( pLeft->ExprType ) { case HB_ET_LOGICAL: { /* .F. < .T. = .T. * .T. < .T. = .F. * .F. < .F. = .F. * .T. < .F. = .F. */ BOOL bResult = ( ! pLeft->value.asLogical && pRight->value.asLogical ); hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; case HB_ET_NUMERIC: { BOOL bResult; switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) { case HB_ET_LONG: bResult = ( pLeft->value.asNum.lVal < pRight->value.asNum.lVal ); break; case HB_ET_DOUBLE: bResult = ( pLeft->value.asNum.dVal < pRight->value.asNum.dVal ); break; default: { if( pLeft->value.asNum.NumType == HB_ET_LONG ) bResult = ( pLeft->value.asNum.lVal < pRight->value.asNum.dVal ); else bResult = ( pLeft->value.asNum.dVal < pRight->value.asNum.lVal ); } break; } hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; default: break; } /* TODO: add checking of incompatible types else { } */ return pSelf; } HB_EXPR_PTR hb_compExprReduceEQ( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == pRight->ExprType ) { switch( pLeft->ExprType ) { case HB_ET_LOGICAL: { BOOL bResult = ( pLeft->value.asLogical == pRight->value.asLogical ); hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; case HB_ET_STRING: { BOOL bResult = FALSE; if( pLeft->ulLength == pRight->ulLength ) bResult = ( strcmp( pLeft->value.asString, pRight->value.asString ) == 0 ); hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; case HB_ET_NUMERIC: { BOOL bResult; switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) { case HB_ET_LONG: bResult = ( pLeft->value.asNum.lVal == pRight->value.asNum.lVal ); break; case HB_ET_DOUBLE: bResult = ( pLeft->value.asNum.dVal == pRight->value.asNum.dVal ); break; default: { if( pLeft->value.asNum.NumType == HB_ET_LONG ) bResult = ( pLeft->value.asNum.lVal == pRight->value.asNum.dVal ); else bResult = ( pLeft->value.asNum.dVal == pRight->value.asNum.lVal ); } break; } hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; } } /* TODO: add checking of incompatible types else { } */ return pSelf; } HB_EXPR_PTR hb_compExprReduceAnd( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == HB_ET_LOGICAL && pRight->ExprType == HB_ET_LOGICAL ) { BOOL bResult; bResult = pLeft->value.asLogical && pRight->value.asLogical; hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } else if( pLeft->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) { if( pLeft->value.asLogical ) { /* .T. .AND. expr => expr */ hb_compExprFree( pLeft, HB_MACRO_PARAM); pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ hb_compExprFree( pSelf, HB_MACRO_PARAM ); pSelf = pRight; } else { /* .F. .AND. expr => .F. */ hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); /* discard expression */ pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = FALSE; } } else if( pRight->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) { if( pRight->value.asLogical ) { /* expr .AND. .T. => expr */ hb_compExprFree( pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ hb_compExprFree( pSelf, HB_MACRO_PARAM ); pSelf = pLeft; } else { /* expr .AND. .F. => .F. */ hb_compExprFree( pLeft, HB_MACRO_PARAM ); /* discard expression */ hb_compExprFree( pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = FALSE; } } return pSelf; } HB_EXPR_PTR hb_compExprReduceOr( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pLeft, pRight; pLeft = pSelf->value.asOperator.pLeft; pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == HB_ET_LOGICAL && pRight->ExprType == HB_ET_LOGICAL ) { BOOL bResult; bResult = pLeft->value.asLogical || pRight->value.asLogical; hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } else if( pLeft->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) { if( pLeft->value.asLogical ) { /* .T. .OR. expr => .T. */ hb_compExprFree( pLeft, HB_MACRO_PARAM ); hb_compExprFree( pRight, HB_MACRO_PARAM ); /* discard expression */ pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = TRUE; } else { /* .F. .OR. expr => expr */ hb_compExprFree( pLeft, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ hb_compExprFree( pSelf, HB_MACRO_PARAM ); pSelf = pRight; } } else if( pRight->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) { if( pRight->value.asLogical ) { /* expr .OR. .T. => .T. */ hb_compExprFree( pLeft, HB_MACRO_PARAM ); /* discard expression */ hb_compExprFree( pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = TRUE; } else { /* expr .OR. .F. => expr */ hb_compExprFree( pRight, HB_MACRO_PARAM ); pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ hb_compExprFree( pSelf, HB_MACRO_PARAM ); pSelf = pLeft; } } return pSelf; } HB_EXPR_PTR hb_compExprReduceIIF( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { HB_EXPR_PTR pExpr; pExpr =pSelf->value.asList.pExprList; /* get conditional expression */ if( pExpr->ExprType == HB_ET_LOGICAL ) { /* the condition was reduced to a logical value: .T. or .F. */ if( pExpr->value.asLogical ) { /* .T. was specified */ pExpr = pExpr->pNext; /* skip to TRUE expression */ /* delete condition - it is no longer needed */ hb_compExprFree( pSelf->value.asList.pExprList, HB_MACRO_PARAM ); /* assign NULL to a start of expressions list to suppress * deletion of expression's components - we are deleting them * here */ pSelf->value.asList.pExprList = NULL; hb_compExprFree( pSelf, HB_MACRO_PARAM ); /* store the TRUE expression as a result of reduction */ pSelf = pExpr; pExpr = pExpr->pNext; /* skip to FALSE expression */ hb_compExprFree( pExpr, HB_MACRO_PARAM ); /* delete FALSE expr */ pSelf->pNext = NULL; } else { /* .F. was specified */ pExpr = pExpr->pNext; /* skip to TRUE expression */ /* delete condition - it is no longer needed */ hb_compExprFree( pSelf->value.asList.pExprList, HB_MACRO_PARAM ); /* assign NULL to a start of expressions list to suppress * deletion of expression's components - we are deleting them * here */ pSelf->value.asList.pExprList = NULL; hb_compExprFree( pSelf, HB_MACRO_PARAM ); /* store the FALSE expression as a result of reduction */ pSelf = pExpr->pNext; hb_compExprFree( pExpr, HB_MACRO_PARAM ); /* delete TRUE expr */ pSelf->pNext = NULL; } } /* check if valid expression is passed */ else if( ( pExpr->ExprType == HB_ET_DOUBLE ) || ( pExpr->ExprType == HB_ET_LONG ) || ( pExpr->ExprType == HB_ET_NIL ) || ( pExpr->ExprType == HB_ET_STRING ) || ( pExpr->ExprType == HB_ET_CODEBLOCK ) || ( pExpr->ExprType == HB_ET_SELF ) || ( pExpr->ExprType == HB_ET_ARRAY ) ) { hb_compExprErrorType( pExpr, HB_MACRO_PARAM ); } return pSelf; } /* replace the list containing a single expression with a simple expression * - strips parenthesis * ( EXPR ) -> EXPR */ HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) { if( pSelf->ExprType == HB_ET_LIST ) { ULONG ulCount = hb_compExprListLen( pSelf ); if( ulCount == 1 && pSelf->value.asList.pExprList->ExprType <= HB_ET_VARIABLE ) { /* replace the list with a simple expression * ( EXPR ) -> EXPR */ HB_EXPR_PTR pExpr = pSelf; pSelf = pSelf->value.asList.pExprList; pExpr->value.asList.pExprList = NULL; hb_compExprFree( pExpr, HB_MACRO_PARAM ); } } return pSelf; }