ChangeLog 20000318-21:30 GMT+1
This commit is contained in:
@@ -1,3 +1,62 @@
|
||||
20000318-21:30 GMT+1 Ryszard Glab <rglab@imid.med.pl>
|
||||
|
||||
*include/hbexpr.c
|
||||
-removed
|
||||
*include/hbexpra.c
|
||||
*include/hbexprb.c
|
||||
*include/hbexprc.c
|
||||
+new files with expression optimizer shared by the standalone
|
||||
and the macro compilers - these files produces different code
|
||||
for the compilers
|
||||
|
||||
*source/compiler/expropt.c
|
||||
-removed
|
||||
*source/compiler/expropta.c
|
||||
*source/compiler/exproptb.c
|
||||
*source/compiler/exproptc.c
|
||||
+new files with expression optimizer used by the standalone compiler
|
||||
|
||||
*source/macro/macroa.c
|
||||
*source/macro/macrob.c
|
||||
*source/macro/macroc.c
|
||||
+new files with expression optimizer shared by the macro compiler
|
||||
|
||||
*source/common/expropt1.c
|
||||
*source/common/expropt2.c
|
||||
+new files with expression optimizer shared by the standalone
|
||||
and the macro compilers - the common part of expression optimizer
|
||||
|
||||
*source/macro/macro.l
|
||||
+added HB_MACRO_SUPPORT definition
|
||||
|
||||
*source/macro/macro.c
|
||||
*removed including of hbexprop.h
|
||||
|
||||
*include/hbexprop.h
|
||||
*include/hbcomp.h
|
||||
*corrected to support new design of expression optimizer
|
||||
|
||||
*source/common/Makefile
|
||||
*source/compiler/Makefile
|
||||
*source/macro/Makefile
|
||||
*makefile.bc
|
||||
*makefile.vc
|
||||
+added the depenencies for the new files (BC & VC not tested !)
|
||||
|
||||
*source/rtl/console.c
|
||||
*source/rtl/filesys.c
|
||||
*source/rtl/fssize.c
|
||||
*source/rtl/gtapi.c
|
||||
*"io.h" is not included if OS_UNIX_COMPATIBLE is defined
|
||||
(in some places #include hbsetup.h" was added to get a chance to
|
||||
define OS_xxx_COMPATIBLE before it is checked)
|
||||
|
||||
*source/rtl/gt/gtcrs.c
|
||||
*a very basic support for colors was added
|
||||
*a very basic support for inkey was added
|
||||
(these two changes are for testing and checking rather than a real
|
||||
solution)
|
||||
|
||||
20000318-12:45 EST Paul Tucker <ptucker@sympatico.ca>
|
||||
* contrib/rdd_ads/ads1.c
|
||||
* added cast in strlen()
|
||||
|
||||
@@ -203,7 +203,7 @@ extern void hb_compGenPushLogical( int, HB_MACRO_DECL ); /* pushes a logical
|
||||
extern void hb_compGenPushLong( long, HB_MACRO_DECL ); /* Pushes a long number on the virtual machine stack */
|
||||
extern void hb_compGenPushNil( HB_MACRO_DECL ); /* Pushes nil on the virtual machine stack */
|
||||
extern void hb_compGenPushString( char *, ULONG, HB_MACRO_DECL ); /* Pushes a string on the virtual machine stack */
|
||||
extern void hb_compGenPushSymbol( char *, HB_MACRO_DECL ); /* Pushes a symbol on to the Virtual machine stack */
|
||||
extern void hb_compGenPushSymbol( char *, int, HB_MACRO_DECL ); /* Pushes a symbol on to the Virtual machine stack */
|
||||
extern void hb_compGenPushAliasedVar( char *, BOOL, char *, long, HB_MACRO_DECL );
|
||||
extern void hb_compGenPopAliasedVar( char *, BOOL, char *, long, HB_MACRO_DECL );
|
||||
extern void hb_compGenPushFunRef( char *, HB_MACRO_DECL );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
585
harbour/include/hbexpra.c
Normal file
585
harbour/include/hbexpra.c
Normal file
@@ -0,0 +1,585 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Harbour Project source code:
|
||||
* Compiler Expression Optimizer
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "hbcomp.h"
|
||||
|
||||
/* memory allocation
|
||||
*/
|
||||
#define HB_XGRAB( size ) hb_xgrab( (size) )
|
||||
#define HB_XFREE( pPtr ) hb_xfree( (void *)(pPtr) )
|
||||
|
||||
|
||||
/* Table with operators precedence
|
||||
* NOTE:
|
||||
* HB_ET_NIL is used for an ordinary values and post- operators
|
||||
* HB_ET_NONE is used for invalid syntax, e.g. var := var1 += 2
|
||||
*/
|
||||
static BYTE s_PrecedTable[] = {
|
||||
HB_ET_NIL, /* HB_ET_NONE = 0, */
|
||||
HB_ET_NIL, /* HB_ET_NIL, */
|
||||
HB_ET_NIL, /* HB_ET_NUMERIC, */
|
||||
HB_ET_NIL, /* HB_ET_STRING, */
|
||||
HB_ET_NIL, /* HB_ET_CODEBLOCK, */
|
||||
HB_ET_NIL, /* HB_ET_LOGICAL, */
|
||||
HB_ET_NIL, /* HB_ET_SELF, */
|
||||
HB_ET_NIL, /* HB_ET_ARRAY, */
|
||||
HB_ET_NIL, /* HB_ET_VARREF, */
|
||||
HB_ET_NIL, /* HB_ET_FUNREF, */
|
||||
HB_ET_NIL, /* HB_ET_IIF, */
|
||||
HB_ET_NIL, /* HB_ET_LIST, */
|
||||
HB_ET_NIL, /* HB_ET_ARGLIST, */
|
||||
HB_ET_NIL, /* HB_ET_ARRAYAT, */
|
||||
HB_ET_NIL, /* HB_ET_MACRO, */
|
||||
HB_ET_NIL, /* HB_ET_FUNCALL, */
|
||||
HB_ET_NIL, /* HB_ET_ALIASVAR, */
|
||||
HB_ET_NIL, /* HB_ET_ALIASEXPR, */
|
||||
HB_ET_NIL, /* HB_ET_SEND, */
|
||||
HB_ET_NIL, /* HB_ET_FUNNAME, */
|
||||
HB_ET_NIL, /* HB_ET_ALIAS, */
|
||||
HB_ET_NIL, /* HB_ET_RTVARIABLE, */
|
||||
HB_ET_NIL, /* HB_ET_VARIABLE, */
|
||||
HB_ET_NIL, /* HB_EO_POSTINC, post-operators */
|
||||
HB_ET_NIL, /* HB_EO_POSTDEC, */
|
||||
HB_ET_NONE, /* HB_EO_ASSIGN, assigments */
|
||||
HB_ET_NONE, /* HB_EO_PLUSEQ, Invalid syntax */
|
||||
HB_ET_NONE, /* HB_EO_MINUSEQ, */
|
||||
HB_ET_NONE, /* HB_EO_MULTEQ, */
|
||||
HB_ET_NONE, /* HB_EO_DIVEQ, */
|
||||
HB_ET_NONE, /* HB_EO_MODEQ, */
|
||||
HB_ET_NONE, /* HB_EO_EXPEQ, */
|
||||
HB_EO_OR, /* HB_EO_OR, logical operators */
|
||||
HB_EO_AND, /* HB_EO_AND, */
|
||||
HB_ET_NIL, /* HB_EO_NOT, */
|
||||
HB_EO_EQUAL, /* HB_EO_EQUAL, relational operators */
|
||||
HB_EO_EQUAL, /* HB_EO_EQ, */
|
||||
HB_EO_EQUAL, /* HB_EO_LT, */
|
||||
HB_EO_EQUAL, /* HB_EO_GT, */
|
||||
HB_EO_EQUAL, /* HB_EO_LE, */
|
||||
HB_EO_EQUAL, /* HB_EO_GE, */
|
||||
HB_EO_EQUAL, /* HB_EO_NE, */
|
||||
HB_EO_EQUAL, /* HB_EO_IN, */
|
||||
HB_EO_PLUS, /* HB_EO_PLUS, addition */
|
||||
HB_EO_PLUS, /* HB_EO_MINUS, */
|
||||
HB_EO_MULT, /* HB_EO_MULT, multiple */
|
||||
HB_EO_MULT, /* HB_EO_DIV, */
|
||||
HB_EO_MULT, /* HB_EO_MOD, */
|
||||
HB_EO_POWER, /* HB_EO_POWER, */
|
||||
HB_ET_NIL, /* HB_EO_NEGATE, sign operator */
|
||||
HB_ET_NIL, /* HB_EO_PREINC, */
|
||||
HB_ET_NIL /* HB_EO_PREDEC, pre-operators */
|
||||
};
|
||||
|
||||
|
||||
static HB_CBVAR_PTR hb_compExprCBVarNew( char *, BYTE );
|
||||
|
||||
/* ************************************************************************ */
|
||||
|
||||
/* Delete all components and delete self
|
||||
*/
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
void hb_compExprDelete( HB_EXPR_PTR pExpr, HB_MACRO_DECL )
|
||||
#else
|
||||
void hb_compExprDelete( HB_EXPR_PTR pExpr )
|
||||
#endif
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprDelete()"));
|
||||
HB_EXPR_USE( pExpr, HB_EA_DELETE );
|
||||
HB_XFREE( pExpr );
|
||||
}
|
||||
|
||||
/* Delete all components and delete self
|
||||
*/
|
||||
void hb_compExprFree( HB_EXPR_PTR pExpr, HB_MACRO_DECL )
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprFree()"));
|
||||
HB_EXPR_USE( pExpr, HB_EA_DELETE );
|
||||
HB_XFREE( pExpr );
|
||||
HB_SYMBOL_UNUSED( HB_MACRO_VARNAME );
|
||||
}
|
||||
|
||||
void hb_compExprErrorType( HB_EXPR_PTR pExpr, HB_MACRO_DECL )
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprErrorType()"));
|
||||
hb_compErrorType( pExpr );
|
||||
HB_SYMBOL_UNUSED( HB_MACRO_VARNAME );
|
||||
}
|
||||
|
||||
/* Add a new local variable declaration
|
||||
*/
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, HB_MACRO_DECL )
|
||||
#else
|
||||
HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, BYTE bType )
|
||||
#endif
|
||||
{
|
||||
HB_CBVAR_PTR pVar;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprCBVarAdd(%s)", szVarName));
|
||||
|
||||
if( pCB->value.asList.pIndex )
|
||||
{
|
||||
/* add it to the end of the list
|
||||
*/
|
||||
pVar = ( HB_CBVAR_PTR ) pCB->value.asList.pIndex;
|
||||
while( pVar )
|
||||
{
|
||||
if( strcmp( szVarName, pVar->szName ) == 0 )
|
||||
hb_compErrorDuplVar( szVarName );
|
||||
|
||||
if( pVar->pNext )
|
||||
pVar = pVar->pNext;
|
||||
else
|
||||
{
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
pVar->pNext = hb_compExprCBVarNew( szVarName, ' ' );
|
||||
#else
|
||||
pVar->pNext = hb_compExprCBVarNew( szVarName, bType );
|
||||
#endif
|
||||
pVar = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, ' ' );
|
||||
#else
|
||||
pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, bType );
|
||||
#endif
|
||||
|
||||
return pCB;
|
||||
}
|
||||
|
||||
/* Create a new IIF() expression or set arguments
|
||||
*
|
||||
* pIIF is a list of three expressions
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewIIF( HB_EXPR_PTR pExpr )
|
||||
{
|
||||
#ifndef HB_MACRO_SUPPORT
|
||||
HB_EXPR_PTR pTmp;
|
||||
|
||||
pExpr->ExprType = HB_ET_IIF;
|
||||
|
||||
pTmp = pExpr->value.asList.pExprList; /* get first expression */
|
||||
if( pTmp->ExprType == HB_ET_NONE )
|
||||
{
|
||||
/* there is no conditional expression e.g. IIF( , true, false )
|
||||
*/
|
||||
hb_compErrorSyntax( pExpr );
|
||||
}
|
||||
#else
|
||||
pExpr->ExprType = HB_ET_IIF;
|
||||
#endif
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Create function call
|
||||
*/
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms, HB_MACRO_DECL )
|
||||
#else
|
||||
HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms )
|
||||
#endif
|
||||
{
|
||||
HB_EXPR_PTR pExpr = NULL;
|
||||
|
||||
if( pName->ExprType == HB_ET_FUNNAME )
|
||||
{
|
||||
/* The name of a function is specified at compile time
|
||||
* e.g. MyFunc()
|
||||
*
|
||||
* NOTE: 'pName' can be a macro expression that will be resolved
|
||||
* at runtime - in this case pName is an expression of HB_ET_MACRO type
|
||||
* e.g. &MyVar()
|
||||
*/
|
||||
int iCount;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunCall(%s)", pName->value.asSymbol));
|
||||
|
||||
if( pParms )
|
||||
{
|
||||
iCount = hb_compExprListLen( pParms );
|
||||
/* Check the special case when no parameters are passed - in this case
|
||||
* pParms is an expression of type HB_ET_NONE and we shouldn't
|
||||
* replace it with NIL value
|
||||
*/
|
||||
if( iCount == 1 && pParms->value.asList.pExprList->ExprType == HB_ET_NONE )
|
||||
--iCount;
|
||||
}
|
||||
else
|
||||
iCount = 0;
|
||||
|
||||
#ifndef HB_MACRO_SUPPORT
|
||||
hb_compFunCallCheck( pName->value.asSymbol, iCount );
|
||||
#endif
|
||||
|
||||
/* TODO: AT() (also done by Clipper, already mentioned)
|
||||
LEN() (also done by Clipper)
|
||||
ASC() (not done by Clipper)
|
||||
EMPTY() (not done by Clipper) */
|
||||
|
||||
if( ( strcmp( "CHR", pName->value.asSymbol ) == 0 ) && iCount )
|
||||
{
|
||||
/* try to change it into a string */
|
||||
HB_EXPR_PTR pArg = pParms->value.asList.pExprList;
|
||||
|
||||
if( pArg->ExprType == HB_ET_NUMERIC )
|
||||
{
|
||||
/* NOTE: CA-Cl*pper's compiler optimizer will be wrong for those
|
||||
CHR() cases where the passed parameter is a constant which
|
||||
can be divided by 256 but it's not zero, in this case it
|
||||
will return an empty string instead of a Chr(0). [vszakats] */
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_STRING );
|
||||
pExpr->ValType = HB_EV_STRING;
|
||||
if( pArg->value.asNum.NumType == HB_ET_LONG )
|
||||
{
|
||||
if( ( pArg->value.asNum.lVal % 256 ) == 0 && pArg->value.asNum.lVal != 0 )
|
||||
{
|
||||
pExpr->value.asString = ( char * ) HB_XGRAB( 1 );
|
||||
pExpr->value.asString[ 0 ] = '\0';
|
||||
pExpr->ulLength = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pExpr->value.asString = ( char * ) HB_XGRAB( 2 );
|
||||
pExpr->value.asString[ 0 ] = ( pArg->value.asNum.lVal % 256 );
|
||||
pExpr->value.asString[ 1 ] = '\0';
|
||||
pExpr->ulLength = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pExpr->value.asString = ( char * ) HB_XGRAB( 2 );
|
||||
pExpr->value.asString[ 0 ] = ( ( long ) pArg->value.asNum.dVal % 256 );
|
||||
pExpr->value.asString[ 1 ] = '\0';
|
||||
pExpr->ulLength = 1;
|
||||
}
|
||||
HB_EXPR_PCODE1( hb_compExprDelete, pParms );
|
||||
HB_EXPR_PCODE1( hb_compExprDelete, pName );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( pName->ExprType == HB_ET_MACRO )
|
||||
{
|
||||
/* Signal that macro compiler have to generate a pcode that will
|
||||
* return function name as symbol instead of usual value
|
||||
*/
|
||||
pName->value.asMacro.SubType = HB_ET_MACRO_SYMBOL;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunCall(&)"));
|
||||
}
|
||||
|
||||
if( pExpr == NULL )
|
||||
{
|
||||
pExpr = hb_compExprNew( HB_ET_FUNCALL );
|
||||
pExpr->value.asFunCall.pParms = pParms;
|
||||
pExpr->value.asFunCall.pFunName = pName;
|
||||
}
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Creates new array access expression
|
||||
* pArray[ pIndex ]
|
||||
* NOTE: In case of multiple indexes it is called recursively
|
||||
* array[ idx1, idx2 ] => ( array[ idx1 ] )[ idx2 ]
|
||||
*/
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex, HB_MACRO_DECL )
|
||||
#else
|
||||
HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex )
|
||||
#endif
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArrayAt()"));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_ARRAYAT );
|
||||
|
||||
/* Check if this expression can be indexed */
|
||||
HB_EXPR_USE( pArray, HB_EA_ARRAY_AT );
|
||||
/* Check if this expression can be an index */
|
||||
HB_EXPR_USE( pIndex, HB_EA_ARRAY_INDEX );
|
||||
pExpr->value.asList.pExprList = pArray;
|
||||
pExpr->value.asList.pIndex = pIndex;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
#ifndef HB_MACRO_SUPPORT
|
||||
static void hb_compExprCheckStaticInitializers( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr )
|
||||
{
|
||||
HB_EXPR_PTR pElem = pRightExpr->value.asList.pExprList;
|
||||
HB_EXPR_PTR pNext;
|
||||
HB_EXPR_PTR * pPrev;
|
||||
|
||||
pPrev = &pRightExpr->value.asList.pExprList;
|
||||
while( pElem )
|
||||
{
|
||||
/* NOTE: During reduction the expression can be replaced by the
|
||||
* new one - this will break the linked list of expressions.
|
||||
* (classical case of replacing an item in a linked list)
|
||||
*/
|
||||
pNext = pElem->pNext; /* store next expression in case the current will be reduced */
|
||||
pElem = hb_compExprListStrip( HB_EXPR_USE( pElem, HB_EA_REDUCE ), HB_MACRO_PARAM );
|
||||
if( pElem->ExprType > HB_ET_FUNREF )
|
||||
hb_compErrorStatic( pLeftExpr->value.asSymbol, pElem );
|
||||
*pPrev = pElem; /* store a new expression into the previous one */
|
||||
pElem->pNext = pNext; /* restore the link to next expression */
|
||||
pPrev = &pElem->pNext;
|
||||
pElem = pNext;
|
||||
}
|
||||
}
|
||||
|
||||
/* It initializes static variable.
|
||||
* It is called in the following context:
|
||||
* STATIC sVar := expression
|
||||
*
|
||||
* pLeftExpr - is a variable name
|
||||
* pRightExpr - can be an expression of any type
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprAssignStatic( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprAssignStatic()"));
|
||||
|
||||
pExpr = hb_compExprNew( HB_EO_ASSIGN );
|
||||
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
/* Try to reduce the assigned value */
|
||||
pRightExpr = hb_compExprListStrip( HB_EXPR_USE( pRightExpr, HB_EA_REDUCE ), HB_MACRO_PARAM );
|
||||
pExpr->value.asOperator.pRight = pRightExpr;
|
||||
|
||||
if( pRightExpr->ExprType == HB_ET_ARGLIST )
|
||||
{
|
||||
/* HB_ET_ARGLIST is used in case of STATIC var[dim1, dim2, dimN]
|
||||
* was used - we have to check if all array dimensions are
|
||||
* constant values
|
||||
*/
|
||||
hb_compExprCheckStaticInitializers( pLeftExpr, pRightExpr );
|
||||
}
|
||||
else if( pRightExpr->ExprType > HB_ET_FUNREF )
|
||||
{
|
||||
/* Illegal initializer for static variable (not a constant value)
|
||||
*/
|
||||
hb_compErrorStatic( pLeftExpr->value.asSymbol, pRightExpr );
|
||||
}
|
||||
else if( pRightExpr->ExprType == HB_ET_ARRAY )
|
||||
{
|
||||
/* { elem1, elem2, elemN } was used as initializer
|
||||
* Scan an array for illegal initializers.
|
||||
* An array item have to be a const value too.
|
||||
*/
|
||||
hb_compExprCheckStaticInitializers( pLeftExpr, pRightExpr );
|
||||
}
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Sets the argument of an operation found previously
|
||||
*/
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem, HB_MACRO_DECL )
|
||||
#else
|
||||
HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem )
|
||||
#endif
|
||||
{
|
||||
BYTE ucRight;
|
||||
|
||||
ucRight = s_PrecedTable[ pItem->ExprType ];
|
||||
if( ucRight == HB_ET_NIL )
|
||||
{
|
||||
/* the right side of an operator is an ordinary value
|
||||
* e.g. a := 1
|
||||
*/
|
||||
pExpr->value.asOperator.pRight = pItem;
|
||||
}
|
||||
else if( ucRight == HB_ET_NONE )
|
||||
{
|
||||
/* the right side of an operator is an invalid expression
|
||||
* e.g.
|
||||
* a := 1 + b:=2
|
||||
* a := 1 + b += 2
|
||||
*/
|
||||
hb_compErrorSyntax( pItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the right side of an operator is an expression with other operator
|
||||
* e.g. a := 2 + b * 3
|
||||
* We have to set the proper order of evaluation using
|
||||
* precedence rules
|
||||
*/
|
||||
BYTE ucLeft = s_PrecedTable[ pExpr->ExprType ];
|
||||
if( ucLeft >= ucRight )
|
||||
{
|
||||
/* Left operator has the same or lower precedence then the right one
|
||||
* e.g. a * b + c
|
||||
* pItem -> b + c -> L=b R=c O=+
|
||||
* pExpr -> a * -> l=a r= o=*
|
||||
*
|
||||
* -> (a * b) + c -> Lelf=(a * b) Right=c Oper=+
|
||||
* Left := l (o) L
|
||||
* Right := R
|
||||
* Oper := O
|
||||
*/
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft, HB_MACRO_PARAM );
|
||||
#else
|
||||
pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft );
|
||||
#endif
|
||||
pExpr = pItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Left operator has a lower precedence then the right one
|
||||
* e.g. a + b * c
|
||||
* pItem -> b * c -> L=b R=c O=*
|
||||
* pExpr -> a + -> l=a r= o=+
|
||||
*
|
||||
* -> a + (b * c) -> Left=a Right=(b * c) Oper=+
|
||||
* Left := l
|
||||
* Right := L (O) R := pItem
|
||||
* Oper := o
|
||||
*/
|
||||
pExpr->value.asOperator.pRight = pItem;
|
||||
}
|
||||
}
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
/* Generates pcode for inline expression used as a statement
|
||||
* NOTE: It doesn't not leave any value on the eval stack
|
||||
*/
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr, HB_MACRO_DECL )
|
||||
#else
|
||||
HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr )
|
||||
#endif
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenStatement(%i)", pExpr->ExprType));
|
||||
|
||||
pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE );
|
||||
HB_EXPR_USE( pExpr, HB_EA_STATEMENT );
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Generates pcode to push an expressions
|
||||
* NOTE: It pushes a value on the stack and leaves this value on the stack
|
||||
*/
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr, HB_MACRO_DECL )
|
||||
#else
|
||||
HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr )
|
||||
#endif
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenPush(%i)", pExpr->ExprType));
|
||||
|
||||
pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE );
|
||||
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Generates pcode to pop an expressions
|
||||
*/
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr, HB_MACRO_DECL )
|
||||
#else
|
||||
HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr )
|
||||
#endif
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenPop(%i)", pExpr->ExprType));
|
||||
|
||||
return HB_EXPR_USE( pExpr, HB_EA_POP_PCODE );
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
/* Create a new declaration for codeblock local variable
|
||||
*/
|
||||
static HB_CBVAR_PTR hb_compExprCBVarNew( char * szVarName, BYTE bType )
|
||||
{
|
||||
HB_CBVAR_PTR pVar;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprCBVarNew(%s)", szVarName));
|
||||
|
||||
pVar = ( HB_CBVAR_PTR ) HB_XGRAB( sizeof( HB_CBVAR ) );
|
||||
|
||||
pVar->szName = szVarName;
|
||||
pVar->bType = bType;
|
||||
pVar->pNext = NULL;
|
||||
|
||||
return pVar;
|
||||
}
|
||||
|
||||
/* NOTE: This deletes all linked variables
|
||||
*/
|
||||
void hb_compExprCBVarDel( HB_CBVAR_PTR pVars )
|
||||
{
|
||||
HB_CBVAR_PTR pDel;
|
||||
|
||||
while( pVars )
|
||||
{
|
||||
pDel = pVars;
|
||||
pVars = pVars->pNext;
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
HB_XFREE( pDel->szName );
|
||||
#endif
|
||||
HB_XFREE( pDel );
|
||||
}
|
||||
}
|
||||
|
||||
3178
harbour/include/hbexprb.c
Normal file
3178
harbour/include/hbexprb.c
Normal file
File diff suppressed because it is too large
Load Diff
450
harbour/include/hbexprc.c
Normal file
450
harbour/include/hbexprc.c
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Harbour Project source code:
|
||||
* Compiler Expression Optimizer - utilities
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "hbcomp.h"
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
void hb_compExprDelOperator( HB_EXPR_PTR pExpr, HB_MACRO_DECL )
|
||||
#else
|
||||
void hb_compExprDelOperator( HB_EXPR_PTR pExpr )
|
||||
#endif
|
||||
{
|
||||
if( pExpr->value.asOperator.pLeft )
|
||||
HB_EXPR_PCODE1( hb_compExprDelete, pExpr->value.asOperator.pLeft );
|
||||
if( pExpr->value.asOperator.pRight )
|
||||
HB_EXPR_PCODE1( hb_compExprDelete, pExpr->value.asOperator.pRight );
|
||||
}
|
||||
|
||||
|
||||
/* Generates pcodes for compound operators += -= *= /= %= ^=
|
||||
*
|
||||
* pExpr is an expression created by hb_compExprNew<operator>Eq functions
|
||||
*/
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL )
|
||||
#else
|
||||
void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq )
|
||||
#endif
|
||||
{
|
||||
/* NOTE: an object instance variable needs special handling
|
||||
*/
|
||||
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
|
||||
{
|
||||
HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft;
|
||||
|
||||
/* Push object */
|
||||
HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE );
|
||||
/* Push _message for later use */
|
||||
HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage );
|
||||
|
||||
/* Now push current value of variable */
|
||||
#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY
|
||||
/* push object */
|
||||
HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE );
|
||||
#else
|
||||
/* NOTE: this duplicate optimization requires that HB_P_MESSAGE
|
||||
* reverts items on the stack !
|
||||
* duplicate object on the stack
|
||||
*/
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE );
|
||||
#endif
|
||||
/* now send the message */
|
||||
HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage );
|
||||
HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 0, 0 );
|
||||
|
||||
/* NOTE: COMPATIBILITY ISSUE:
|
||||
* The above HARBOUR_STRICT_CLIPPER_COMPATIBILITY setting determines
|
||||
* the way the chained send messages are handled.
|
||||
* For example, the following code:
|
||||
*
|
||||
* a:b( COUNT() ):c += 1
|
||||
*
|
||||
* will be handled as:
|
||||
*
|
||||
* a:b( COUNT() ):c := a:b( COUNT() ):c + 1
|
||||
*
|
||||
* in strict Clipper compatibility mode and
|
||||
*
|
||||
* temp := a:b( COUNT() ), temp:c += 1
|
||||
*
|
||||
* in non-strict mode.
|
||||
* In practice in Clipper it will call COUNT() function two times: the
|
||||
* first time before addition and the second one after addition - in Harbour,
|
||||
* COUNT() function will be called only once, before addition.
|
||||
* The Harbour (non-strict) method is:
|
||||
* 1) faster
|
||||
* 2) it guarantees that the same instance variable of the same object will
|
||||
* be changed
|
||||
*/
|
||||
|
||||
/* push increment value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
|
||||
/* increase operation */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, bOpEq );
|
||||
|
||||
/* call pop message with one argument */
|
||||
HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 1, 0 );
|
||||
}
|
||||
/* TODO: add a special code for arrays to correctly handle a[ i++ ]++
|
||||
*/
|
||||
else
|
||||
{
|
||||
/* push old value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
|
||||
/* push increment value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
|
||||
/* perform operation and duplicate the new value */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, bOpEq );
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE );
|
||||
/* pop the new value into variable and leave the copy on the stack */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates pcodes for <operator>= syntax
|
||||
* used standalone as a statement (it cannot leave the value on the stack)
|
||||
*/
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL )
|
||||
#else
|
||||
void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq )
|
||||
#endif
|
||||
{
|
||||
/* NOTE: an object instance variable needs special handling
|
||||
*/
|
||||
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
|
||||
{
|
||||
HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft;
|
||||
|
||||
/* Push object */
|
||||
HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE );
|
||||
/* Push _message for later use */
|
||||
HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage );
|
||||
|
||||
/* Now push current value of variable */
|
||||
#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY
|
||||
/* push object */
|
||||
HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE );
|
||||
#else
|
||||
/* duplicate object on the stack */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE );
|
||||
#endif
|
||||
/* now send the message */
|
||||
HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage );
|
||||
HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 0, 0 );
|
||||
|
||||
/* push increment value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
|
||||
/* increase operation */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, bOpEq );
|
||||
|
||||
/* call pop message with one argument */
|
||||
HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 1, 0 );
|
||||
/* pop the value from the stack */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* push old value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
|
||||
/* push increment value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
|
||||
/* add */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, bOpEq );
|
||||
/* pop the new value into variable and remove it from the stack */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates the pcodes for pre- increment/decrement expressions
|
||||
*/
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL )
|
||||
#else
|
||||
void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper )
|
||||
#endif
|
||||
{
|
||||
/* NOTE: an object instance variable needs special handling
|
||||
*/
|
||||
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
|
||||
{
|
||||
HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft;
|
||||
|
||||
/* Push object */
|
||||
HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE );
|
||||
/* Push _message for later use */
|
||||
HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage );
|
||||
|
||||
/* Now push current value of variable */
|
||||
#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY
|
||||
/* push object */
|
||||
HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE );
|
||||
#else
|
||||
/* duplicate object on the stack */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE );
|
||||
#endif
|
||||
/* now send the message */
|
||||
HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage );
|
||||
HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 0, 0 );
|
||||
|
||||
/* increase/decrease operation */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, bOper );
|
||||
|
||||
/* call pop message with one argument - it leaves the value on the stack */
|
||||
HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 1, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Push current value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
|
||||
/* Increment */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, bOper );
|
||||
/* duplicate a value */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE );
|
||||
/* pop new value and leave the duplicated copy of it on the stack */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates the pcodes for post- increment/decrement expressions
|
||||
*/
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL )
|
||||
#else
|
||||
void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper )
|
||||
#endif
|
||||
{
|
||||
/* NOTE: an object instance variable needs special handling
|
||||
*/
|
||||
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
|
||||
{
|
||||
/* push current value - it will be a result of whole expression */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
|
||||
/* now increment the value */
|
||||
HB_EXPR_PCODE2( hb_compExprPushPreOp, pSelf, bOper );
|
||||
/* pop the value from the stack */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Push current value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
|
||||
/* Duplicate value */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE );
|
||||
/* Increment */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, bOper );
|
||||
/* pop new value from the stack */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Generates the pcodes for increment/decrement operations
|
||||
* used standalone as a statement
|
||||
*/
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL )
|
||||
#else
|
||||
void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper )
|
||||
#endif
|
||||
{
|
||||
/* NOTE: an object instance variable needs special handling
|
||||
*/
|
||||
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
|
||||
{
|
||||
HB_EXPR_PCODE2( hb_compExprPushPreOp, pSelf, bOper );
|
||||
/* pop the value from the stack */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Push current value */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
|
||||
/* Increment */
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, bOper );
|
||||
/* pop new value from the stack */
|
||||
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate pcode for aliased expression which contains macro operator on
|
||||
* the left or right side of the alias operator
|
||||
* expression->¯o or ¯o->expression or ¯o->¯o
|
||||
*/
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
void hb_compExprUseAliasMacro( HB_EXPR_PTR pAliasedVar, BYTE bAction, HB_MACRO_DECL )
|
||||
#else
|
||||
void hb_compExprUseAliasMacro( HB_EXPR_PTR pAliasedVar, BYTE bAction )
|
||||
#endif
|
||||
{
|
||||
HB_EXPR_PTR pAlias, pVar;
|
||||
|
||||
/* Alias->Var
|
||||
*/
|
||||
pAlias = pAliasedVar->value.asAlias.pAlias;
|
||||
pVar = pAliasedVar->value.asAlias.pVar;
|
||||
if( pAlias->ExprType == HB_ET_ALIAS )
|
||||
{
|
||||
/* database alias */
|
||||
/* Push alias identifier as string so it can be joined with
|
||||
* variable at runtime
|
||||
* NOTE:
|
||||
* ALIAS->&var is the same as &( "ALIAS->" + var )
|
||||
*
|
||||
*/
|
||||
HB_EXPR_PCODE2( hb_compGenPushString, pAlias->value.asSymbol, strlen(pAlias->value.asSymbol) );
|
||||
HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE );
|
||||
if( bAction == HB_EA_PUSH_PCODE )
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPUSHALIASED );
|
||||
else
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPOPALIASED );
|
||||
}
|
||||
else if( pVar->ExprType == HB_ET_VARIABLE )
|
||||
{
|
||||
/* NOTE:
|
||||
* ¯o->var is the same as: &( macro + "->var" )
|
||||
*/
|
||||
HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE );
|
||||
HB_EXPR_PCODE2( hb_compGenPushString, pVar->value.asSymbol, strlen(pVar->value.asSymbol) );
|
||||
if( bAction == HB_EA_PUSH_PCODE )
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPUSHALIASED );
|
||||
else
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPOPALIASED );
|
||||
}
|
||||
else
|
||||
{
|
||||
HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE );
|
||||
HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE );
|
||||
if( bAction == HB_EA_PUSH_PCODE )
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPUSHALIASED );
|
||||
else
|
||||
HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPOPALIASED );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Reduces the list of expressions
|
||||
*
|
||||
* pExpr is the first expression on the list
|
||||
*/
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
ULONG hb_compExprReduceList( HB_EXPR_PTR pExpr, HB_MACRO_DECL )
|
||||
#else
|
||||
ULONG hb_compExprReduceList( HB_EXPR_PTR pExpr )
|
||||
#endif
|
||||
{
|
||||
HB_EXPR_PTR pNext;
|
||||
HB_EXPR_PTR * pPrev;
|
||||
ULONG ulCnt = 0;
|
||||
|
||||
/* NOTE: During optimalization an expression on the list can be
|
||||
* replaced by the new one
|
||||
*/
|
||||
|
||||
pPrev = &pExpr->value.asList.pExprList;
|
||||
pExpr = pExpr->value.asList.pExprList;
|
||||
while( pExpr )
|
||||
{
|
||||
pNext = pExpr->pNext; /* store next expression in case the current will be reduced */
|
||||
pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE );
|
||||
*pPrev = pExpr; /* store a new expression into the previous one */
|
||||
pExpr->pNext = pNext; /* restore the link to next expression */
|
||||
pPrev = &pExpr->pNext;
|
||||
pExpr = pNext;
|
||||
++ulCnt;
|
||||
}
|
||||
return ulCnt;
|
||||
}
|
||||
|
||||
BOOL hb_compExprCheckMacroVar( char * szText )
|
||||
{
|
||||
char * pTmp = szText;
|
||||
BOOL bTextSubst = FALSE;
|
||||
|
||||
while( ( pTmp = strchr( pTmp, '&' ) ) != NULL )
|
||||
{
|
||||
/* Check if macro operator is used inside a string
|
||||
* Macro operator is ignored if it is the last char or
|
||||
* next char is '(' e.g. "this is &(ignored)"
|
||||
*
|
||||
* NOTE: This uses _a-zA-Z pattern to check for
|
||||
* variable name beginning
|
||||
*/
|
||||
|
||||
++pTmp;
|
||||
bTextSubst = ( *pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') );
|
||||
/* NOTE: All variables are assumed memvars in macro compiler -
|
||||
* there is no need to check for a valid name
|
||||
*/
|
||||
#if !defined( HB_MACRO_SUPPORT )
|
||||
if( bTextSubst )
|
||||
{
|
||||
/* There is a valid character after '&' that can be used in
|
||||
* variable name - check if the whole variable name is valid
|
||||
* (local, static and field variable names are invalid because
|
||||
* they are not visible at runtime)
|
||||
*/
|
||||
char * pStart = pTmp;
|
||||
char cSave;
|
||||
|
||||
/* NOTE: This uses _a-zA-Z0-9 pattern to check for
|
||||
* variable name
|
||||
*/
|
||||
while( *pTmp && (*pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') || (*pTmp >= '0' && *pTmp <= '9')) )
|
||||
++pTmp;
|
||||
|
||||
cSave = *pTmp;
|
||||
*pTmp = '\0';
|
||||
hb_compVariableMacroCheck( pStart );
|
||||
*pTmp = cSave;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return bTextSubst;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,110 @@
|
||||
|
||||
#include "hbapi.h"
|
||||
|
||||
/* value types seen at language level
|
||||
*/
|
||||
#define HB_EV_UNKNOWN 0
|
||||
#define HB_EV_NIL 1
|
||||
#define HB_EV_NUMERIC 2
|
||||
#define HB_EV_STRING 4
|
||||
#define HB_EV_CODEBLOCK 8
|
||||
#define HB_EV_LOGICAL 16
|
||||
#define HB_EV_OBJECT 32
|
||||
#define HB_EV_ARRAY 64
|
||||
#define HB_EV_SYMBOL 128
|
||||
#define HB_EV_VARREF 256
|
||||
#define HB_EV_FUNREF 512
|
||||
|
||||
/* messages sent to expressions
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HB_EA_REDUCE = 0, /* reduce the expression into optimized one */
|
||||
HB_EA_ARRAY_AT, /* check if the expession can be used as array */
|
||||
HB_EA_ARRAY_INDEX, /* check if the expession can be used as index */
|
||||
HB_EA_LVALUE, /* check if the expression can be used as lvalue (left side of an assigment) */
|
||||
HB_EA_PUSH_PCODE, /* generate the pcodes to push the value of expression */
|
||||
HB_EA_POP_PCODE, /* generate the pcodes to pop the value of expression */
|
||||
HB_EA_PUSH_POP, /* generate the pcodes to push and pop the expression */
|
||||
HB_EA_STATEMENT, /* generate the pcodes for a statement */
|
||||
HB_EA_DELETE /* delete components of the expression */
|
||||
} HB_EXPR_MESSAGE;
|
||||
|
||||
/* additional definitions used to distinguish numeric expressions
|
||||
*/
|
||||
#define HB_ET_LONG 1
|
||||
#define HB_ET_DOUBLE 2
|
||||
|
||||
/* additional definitions used to distinguish macro expressions
|
||||
*/
|
||||
#define HB_ET_MACRO_VAR 0 /* &variable */
|
||||
#define HB_ET_MACRO_SYMBOL 1 /* &fimcall() */
|
||||
#define HB_ET_MACRO_ALIASED 2 /* &alias->&variable */
|
||||
#define HB_ET_MACRO_EXPR 4 /* &( expr ) */
|
||||
|
||||
/* types of expressions
|
||||
* NOTE: the order of these definition is important - change it carefully
|
||||
* All types <= HB_ET_FUNREF are constant values
|
||||
* All types <= HB_ET_VARIABLE are a simple values
|
||||
* All types > HB_ET_VARIABLE are operators
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HB_ET_NONE = 0,
|
||||
HB_ET_NIL,
|
||||
HB_ET_NUMERIC,
|
||||
HB_ET_STRING,
|
||||
HB_ET_CODEBLOCK,
|
||||
HB_ET_LOGICAL,
|
||||
HB_ET_SELF,
|
||||
HB_ET_ARRAY,
|
||||
HB_ET_VARREF,
|
||||
HB_ET_FUNREF,
|
||||
HB_ET_IIF,
|
||||
HB_ET_LIST,
|
||||
HB_ET_ARGLIST,
|
||||
HB_ET_ARRAYAT,
|
||||
HB_ET_MACRO,
|
||||
HB_ET_FUNCALL,
|
||||
HB_ET_ALIASVAR,
|
||||
HB_ET_ALIASEXPR,
|
||||
HB_ET_SEND,
|
||||
HB_ET_FUNNAME,
|
||||
HB_ET_ALIAS,
|
||||
HB_ET_RTVAR, /* PRIVATE or PUBLIC declaration of variable */
|
||||
HB_ET_VARIABLE,
|
||||
HB_EO_POSTINC, /* post-operators -> lowest precedence */
|
||||
HB_EO_POSTDEC,
|
||||
HB_EO_ASSIGN, /* assigments */
|
||||
HB_EO_PLUSEQ,
|
||||
HB_EO_MINUSEQ,
|
||||
HB_EO_MULTEQ,
|
||||
HB_EO_DIVEQ,
|
||||
HB_EO_MODEQ,
|
||||
HB_EO_EXPEQ,
|
||||
HB_EO_OR, /* logical operators */
|
||||
HB_EO_AND,
|
||||
HB_EO_NOT,
|
||||
HB_EO_EQUAL, /* relational operators */
|
||||
HB_EO_EQ,
|
||||
HB_EO_LT,
|
||||
HB_EO_GT,
|
||||
HB_EO_LE,
|
||||
HB_EO_GE,
|
||||
HB_EO_NE,
|
||||
HB_EO_IN,
|
||||
HB_EO_PLUS, /* addition */
|
||||
HB_EO_MINUS,
|
||||
HB_EO_MULT, /* multiple */
|
||||
HB_EO_DIV,
|
||||
HB_EO_MOD,
|
||||
HB_EO_POWER,
|
||||
HB_EO_NEGATE, /* sign operator */
|
||||
HB_EO_PREINC,
|
||||
HB_EO_PREDEC /* pre-operators -> the highest precedence */
|
||||
} HB_EXPR_OPERATOR;
|
||||
|
||||
|
||||
typedef struct HB_EXPR_
|
||||
{
|
||||
union
|
||||
@@ -101,31 +205,55 @@ typedef struct HB_EXPR_
|
||||
/* Definitions of function templates used in expression's message
|
||||
* handling
|
||||
*/
|
||||
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
/* Compilation for macro compiler
|
||||
*/
|
||||
#define HB_EXPR_FUNC( proc ) HB_EXPR_PTR proc( HB_EXPR_PTR pSelf, int iMessage, void * pMacro )
|
||||
typedef HB_EXPR_FUNC( HB_EXPR_FUNC_ );
|
||||
typedef HB_EXPR_FUNC_ *HB_EXPR_FUNC_PTR;
|
||||
|
||||
extern HB_EXPR_FUNC_PTR hb_comp_ExprTable[];
|
||||
|
||||
#define HB_EXPR_USE( pSelf, iMessage ) \
|
||||
s_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage), pMacro )
|
||||
hb_comp_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage), pMacro )
|
||||
|
||||
typedef HB_EXPR_PTR HB_EXPR_ACTION( HB_EXPR_PTR pSelf, int iMessage, void * pMacro );
|
||||
|
||||
#define HB_EXPR_PCODE0( action ) action( pMacro )
|
||||
#define HB_EXPR_PCODE1( action, p1 ) action( (p1), pMacro )
|
||||
#define HB_EXPR_PCODE2( action, p1, p2 ) action( (p1), (p2), pMacro )
|
||||
#define HB_EXPR_PCODE3( action, p1, p2, p3 ) action( (p1), (p2), (p3), pMacro )
|
||||
#define HB_EXPR_PCODE4( action, p1, p2, p3, p4 ) action( (p1), (p2), (p3), (p4), pMacro )
|
||||
|
||||
#define HB_MACRO_VARNAME pMacro
|
||||
|
||||
#else
|
||||
|
||||
#define HB_EXPR_FUNC( proc ) HB_EXPR_PTR proc( HB_EXPR_PTR pSelf, int iMessage )
|
||||
typedef HB_EXPR_FUNC( HB_EXPR_FUNC_ );
|
||||
typedef HB_EXPR_FUNC_ *HB_EXPR_FUNC_PTR;
|
||||
|
||||
extern HB_EXPR_FUNC_PTR hb_comp_ExprTable[];
|
||||
|
||||
#define HB_EXPR_USE( pSelf, iMessage ) \
|
||||
s_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage) )
|
||||
hb_comp_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage) )
|
||||
|
||||
typedef HB_EXPR_PTR HB_EXPR_ACTION( HB_EXPR_PTR pSelf, int iMessage );
|
||||
|
||||
#define HB_EXPR_PCODE0( action ) action( )
|
||||
#define HB_EXPR_PCODE1( action, p1 ) action( (p1) )
|
||||
#define HB_EXPR_PCODE2( action, p1, p2 ) action( (p1), (p2) )
|
||||
#define HB_EXPR_PCODE3( action, p1, p2, p3 ) action( (p1), (p2), (p3) )
|
||||
#define HB_EXPR_PCODE4( action, p1, p2, p3, p4 ) action( (p1), (p2), (p3), (p4) )
|
||||
|
||||
/* pass NULL instead of macro structure pointer */
|
||||
#define HB_MACRO_DECL void *pMacro
|
||||
#define HB_MACRO_PARAM NULL
|
||||
#define HB_MACRO_VARNAME pMacro
|
||||
#endif
|
||||
|
||||
|
||||
HB_EXPR_PTR hb_compExprNew( int );
|
||||
HB_EXPR_PTR hb_compExprNewEmpty( void );
|
||||
HB_EXPR_PTR hb_compExprNewNil( void );
|
||||
HB_EXPR_PTR hb_compExprNewDouble( double, BYTE );
|
||||
@@ -189,6 +317,12 @@ ULONG hb_compExprListLen( HB_EXPR_PTR );
|
||||
void hb_compExprClear( HB_EXPR_PTR );
|
||||
char * hb_compExprDescription( HB_EXPR_PTR );
|
||||
|
||||
void hb_compExprFree( HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
void hb_compExprErrorType( HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
BOOL hb_compExprCheckMacroVar( char * );
|
||||
void hb_compExprCBVarDel( HB_CBVAR_PTR );
|
||||
|
||||
#ifdef HB_MACRO_SUPPORT
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR, HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
@@ -197,8 +331,8 @@ HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR, HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
void hb_compExprDelete( HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR, char *, HB_MACRO_DECL );
|
||||
void hb_compExprDelete( HB_EXPR_PTR, HB_MACRO_DECL );
|
||||
|
||||
#else
|
||||
|
||||
@@ -208,8 +342,8 @@ HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR );
|
||||
HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR );
|
||||
HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR );
|
||||
HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR, HB_EXPR_PTR );
|
||||
void hb_compExprDelete( HB_EXPR_PTR );
|
||||
HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR, char *, BYTE );
|
||||
void hb_compExprDelete( HB_EXPR_PTR );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -337,6 +337,8 @@ COMMON_LIB_OBJS = \
|
||||
$(OBJ_DIR)\hbfsapi.obj \
|
||||
$(OBJ_DIR)\hbstr.obj \
|
||||
$(OBJ_DIR)\hbtrace.obj \
|
||||
$(OBJ_DIR)\expropt1.obj \
|
||||
$(OBJ_DIR)\expropt2.obj \
|
||||
$(OBJ_DIR)\reserved.obj
|
||||
|
||||
#
|
||||
@@ -389,6 +391,9 @@ HARBOUR_EXE_OBJS = \
|
||||
$(OBJ_DIR)\genrc.obj \
|
||||
$(OBJ_DIR)\genhrb.obj \
|
||||
$(OBJ_DIR)\expropt.obj \
|
||||
$(OBJ_DIR)\expropta.obj \
|
||||
$(OBJ_DIR)\exproptb.obj \
|
||||
$(OBJ_DIR)\exproptc.obj \
|
||||
$(OBJ_DIR)\hbfunchk.obj
|
||||
|
||||
#
|
||||
@@ -480,6 +485,14 @@ $(OBJ_DIR)\hbtrace.obj : $(COMMON_DIR)\hbtrace.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
tlib $(COMMON_LIB) -+$@,,
|
||||
|
||||
$(OBJ_DIR)\expropt1.obj : $(COMMON_DIR)\expropt1.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
tlib $(COMMON_LIB) -+$@,,
|
||||
|
||||
$(OBJ_DIR)\expropt2.obj : $(COMMON_DIR)\expropt2.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
tlib $(COMMON_LIB) -+$@,,
|
||||
|
||||
#
|
||||
# PP.LIB dependencies
|
||||
#
|
||||
@@ -521,7 +534,9 @@ $(HARBOUR_EXE) : $(HARBOUR_EXE_OBJS)
|
||||
echo. $(OBJ_DIR)\genpas.obj >> make.tmp
|
||||
echo. $(OBJ_DIR)\genrc.obj >> make.tmp
|
||||
echo. $(OBJ_DIR)\genhrb.obj >> make.tmp
|
||||
echo. $(OBJ_DIR)\expropt.obj >> make.tmp
|
||||
echo. $(OBJ_DIR)\expropta.obj >> make.tmp
|
||||
echo. $(OBJ_DIR)\exproptb.obj >> make.tmp
|
||||
echo. $(OBJ_DIR)\exproptc.obj >> make.tmp
|
||||
echo. $(OBJ_DIR)\hbfunchk.obj >> make.tmp
|
||||
echo. $(COMMON_LIB) $(PP_LIB) >> make.tmp
|
||||
$(CC) @make.tmp
|
||||
@@ -572,7 +587,13 @@ $(OBJ_DIR)\genrc.obj : $(COMPILER_DIR)\genrc.c
|
||||
$(OBJ_DIR)\genhrb.obj : $(COMPILER_DIR)\genhrb.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
|
||||
$(OBJ_DIR)\expropt.obj : $(COMPILER_DIR)\expropt.c
|
||||
$(OBJ_DIR)\expropta.obj : $(COMPILER_DIR)\expropta.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
|
||||
$(OBJ_DIR)\exproptb.obj : $(COMPILER_DIR)\exproptb.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
|
||||
$(OBJ_DIR)\exproptc.obj : $(COMPILER_DIR)\exproptc.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
|
||||
$(OBJ_DIR)\hbfunchk.obj : $(COMPILER_DIR)\hbfunchk.c
|
||||
@@ -1531,6 +1552,18 @@ $(OBJ_DIR)\macro.obj : $(MACRO_DIR)\macro.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
tlib $(MACRO_LIB) -+$@,,
|
||||
|
||||
$(OBJ_DIR)\macroa.obj : $(MACRO_DIR)\macroa.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
tlib $(MACRO_LIB) -+$@,,
|
||||
|
||||
$(OBJ_DIR)\macrob.obj : $(MACRO_DIR)\macrob.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
tlib $(MACRO_LIB) -+$@,,
|
||||
|
||||
$(OBJ_DIR)\macroc.obj : $(MACRO_DIR)\macroc.c
|
||||
$(CC) $(CLIBFLAGS) -o$@ $**
|
||||
tlib $(MACRO_LIB) -+$@,,
|
||||
|
||||
#
|
||||
# NULSYS.LIB dependencies
|
||||
#
|
||||
|
||||
@@ -344,6 +344,9 @@ TOOLS_LIB_OBJS = \
|
||||
MACRO_LIB_OBJS = \
|
||||
$(OBJ_DIR)\macrol.obj \
|
||||
$(OBJ_DIR)\macroy.obj \
|
||||
$(OBJ_DIR)\macroa.obj \
|
||||
$(OBJ_DIR)\macrob.obj \
|
||||
$(OBJ_DIR)\macroc.obj \
|
||||
$(OBJ_DIR)\macro.obj
|
||||
|
||||
#
|
||||
@@ -472,6 +475,8 @@ DEBUG_LIB_OBJS = \
|
||||
COMMON_LIB_OBJS = \
|
||||
$(OBJ_DIR)\hbfsapi.obj \
|
||||
$(OBJ_DIR)\hbstr.obj \
|
||||
$(OBJ_DIR)\expropt1.obj \
|
||||
$(OBJ_DIR)\expropt2.obj \
|
||||
$(OBJ_DIR)\hbtrace.obj \
|
||||
$(OBJ_DIR)\reserved.obj
|
||||
|
||||
@@ -655,7 +660,9 @@ $(HARBOUR_EXE) : \
|
||||
$(COMPILER_DIR)\genrc.c \
|
||||
$(COMPILER_DIR)\genjava.c \
|
||||
$(COMPILER_DIR)\genpas.c \
|
||||
$(COMPILER_DIR)\expropt.c
|
||||
$(COMPILER_DIR)\expropta.c \
|
||||
$(COMPILER_DIR)\exproptb.c \
|
||||
$(COMPILER_DIR)\exproptc.c \
|
||||
-echo. > $(INCLUDE_DIR)\unistd.h
|
||||
$(CC) $(CFLAGS) -Fo$(OBJ_DIR)\ -w $** -o $(HARBOUR_EXE) /link $(PP_LIB) $(COMMON_LIB)
|
||||
-del $(INCLUDE_DIR)\unistd.h
|
||||
|
||||
@@ -9,6 +9,8 @@ C_SOURCES=\
|
||||
hbstr.c \
|
||||
hbtrace.c \
|
||||
reserved.c \
|
||||
expropt1.c \
|
||||
expropt2.c \
|
||||
|
||||
PRG_SOURCES=\
|
||||
|
||||
|
||||
836
harbour/source/common/expropt1.c
Normal file
836
harbour/source/common/expropt1.c
Normal file
@@ -0,0 +1,836 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Harbour Project source code:
|
||||
* Compiler Expression Optimizer - common 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 <math.h>
|
||||
#include "hbmacro.h"
|
||||
#include "hbcomp.h"
|
||||
|
||||
/* memory allocation
|
||||
*/
|
||||
#define HB_XGRAB( size ) hb_xgrab( (size) )
|
||||
#define HB_XFREE( pPtr ) hb_xfree( (void *)(pPtr) )
|
||||
|
||||
static char * s_OperTable[] = {
|
||||
"",
|
||||
"NIL",
|
||||
"Numeric",
|
||||
"String",
|
||||
"Codeblock",
|
||||
"Logical",
|
||||
"SELF",
|
||||
"Array",
|
||||
"@",
|
||||
"@",
|
||||
"IIF",
|
||||
",",
|
||||
",",
|
||||
"[",
|
||||
"&",
|
||||
"()",
|
||||
"->",
|
||||
"->",
|
||||
":",
|
||||
"", /* symbol */
|
||||
"", /* alias */
|
||||
"", /* RunTime variable */
|
||||
"", /* variable */
|
||||
"++", /* post-operators -> lowest precedence */
|
||||
"--",
|
||||
":=", /* assigments */
|
||||
"+=",
|
||||
"-=",
|
||||
"*=",
|
||||
"/=",
|
||||
"%=",
|
||||
"^=",
|
||||
".OR.", /* logical operators */
|
||||
".AND.",
|
||||
".NOT.",
|
||||
"=", /* relational operators */
|
||||
"==",
|
||||
"<",
|
||||
">",
|
||||
"<=",
|
||||
">=",
|
||||
"!=",
|
||||
"$",
|
||||
"+", /* addition */
|
||||
"-",
|
||||
"*", /* multiple */
|
||||
"/",
|
||||
"%",
|
||||
"^",
|
||||
"-", /* sign operator */
|
||||
"++",
|
||||
"--"
|
||||
};
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
HB_EXPR_PTR hb_compExprNew( int iType )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNew(%i)", iType));
|
||||
|
||||
pExpr = ( HB_EXPR_PTR ) HB_XGRAB( sizeof( HB_EXPR ) );
|
||||
|
||||
pExpr->ExprType = iType;
|
||||
pExpr->pNext = NULL;
|
||||
pExpr->ValType = HB_EV_UNKNOWN;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Delete self - all components will be deleted somewhere else
|
||||
*/
|
||||
void hb_compExprClear( HB_EXPR_PTR pExpr )
|
||||
{
|
||||
HB_XFREE( pExpr );
|
||||
}
|
||||
|
||||
char * hb_compExprDescription( HB_EXPR_PTR pExpr )
|
||||
{
|
||||
if( pExpr )
|
||||
return s_OperTable[ pExpr->ExprType ];
|
||||
else
|
||||
return s_OperTable[ 0 ];
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewEmpty( void )
|
||||
{
|
||||
return hb_compExprNew( HB_ET_NONE );
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewDouble( double dValue, BYTE ucDec )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewDouble(%f, %i)", dValue, ucDec));
|
||||
|
||||
pExpr =hb_compExprNew( HB_ET_NUMERIC );
|
||||
|
||||
pExpr->value.asNum.dVal = dValue;
|
||||
pExpr->value.asNum.bDec = ucDec;
|
||||
pExpr->value.asNum.NumType = HB_ET_DOUBLE;
|
||||
pExpr->ValType = HB_EV_NUMERIC;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewLong( long lValue )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewLong(%li)", lValue));
|
||||
|
||||
pExpr =hb_compExprNew( HB_ET_NUMERIC );
|
||||
|
||||
pExpr->value.asNum.lVal = lValue;
|
||||
pExpr->value.asNum.bDec = 0;
|
||||
pExpr->value.asNum.NumType = HB_ET_LONG;
|
||||
pExpr->ValType = HB_EV_NUMERIC;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewString( char *szValue )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewString(%s)", szValue));
|
||||
|
||||
pExpr =hb_compExprNew( HB_ET_STRING );
|
||||
|
||||
pExpr->value.asString = szValue;
|
||||
pExpr->ulLength = strlen( szValue );
|
||||
pExpr->ValType = HB_EV_STRING;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewCodeBlock( void )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewCodeBlock()"));
|
||||
|
||||
pExpr =hb_compExprNew( HB_ET_CODEBLOCK );
|
||||
|
||||
pExpr->value.asList.pExprList = NULL;
|
||||
pExpr->value.asList.pIndex = NULL; /* this will hold local variables declarations */
|
||||
pExpr->ValType = HB_EV_CODEBLOCK;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewLogical( int iValue )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewLogical(%i)", iValue));
|
||||
|
||||
pExpr =hb_compExprNew( HB_ET_LOGICAL );
|
||||
|
||||
pExpr->value.asLogical = iValue;
|
||||
pExpr->ValType = HB_EV_LOGICAL;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewNil( void )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewNil()"));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_NIL );
|
||||
|
||||
pExpr->ValType = HB_EV_NIL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewSelf( void )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewSelf()"));
|
||||
|
||||
pExpr =hb_compExprNew( HB_ET_SELF );
|
||||
|
||||
pExpr->ValType = HB_EV_OBJECT;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewVarRef( char * szVarName )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewVarRef(%s)", szVarName));
|
||||
|
||||
pExpr =hb_compExprNew( HB_ET_VARREF );
|
||||
|
||||
pExpr->value.asSymbol = szVarName;
|
||||
pExpr->ValType = HB_EV_VARREF;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewFunRef( char * szFunName )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunRef(%s)", szFunName));
|
||||
|
||||
pExpr =hb_compExprNew( HB_ET_FUNREF );
|
||||
|
||||
pExpr->value.asSymbol = szFunName;
|
||||
pExpr->ValType = HB_EV_FUNREF;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Creates a new literal array { item1, item2, ... itemN }
|
||||
* 'pArrList' is a list of array elements
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArray()"));
|
||||
|
||||
pArrList->ExprType = HB_ET_ARRAY; /* change type from ET_LIST */
|
||||
pArrList->ValType = HB_EV_ARRAY;
|
||||
pArrList->ulLength = 0;
|
||||
|
||||
pExpr = pArrList->value.asList.pExprList; /* get first element on the list */
|
||||
/* Now we need to replace all EO_NONE expressions with ET_NIL expressions
|
||||
* If EO_NONE is the first expression and there is no more expressions
|
||||
* then it is an empty array {} and ET_NIL cannot be used
|
||||
*/
|
||||
if( pExpr->ExprType == HB_ET_NONE && pExpr->pNext == NULL )
|
||||
{
|
||||
pArrList->value.asList.pExprList = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* there are at least one non-empty element specified
|
||||
*/
|
||||
while( pExpr )
|
||||
{
|
||||
/* if empty element was specified replace it with NIL value */
|
||||
if( pExpr->ExprType == HB_ET_NONE )
|
||||
pExpr->ExprType = HB_ET_NIL;
|
||||
pExpr = pExpr->pNext;
|
||||
++pArrList->ulLength;
|
||||
}
|
||||
}
|
||||
pArrList->value.asList.pIndex = NULL;
|
||||
return pArrList;
|
||||
}
|
||||
|
||||
/* Creates new macro expression
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewMacro( HB_EXPR_PTR pMacroExpr, unsigned char cMacroOp, char * szName )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
if( szName )
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewMacro(%s)", szName));
|
||||
|
||||
/* Macro variable is used: &identifier
|
||||
* or macro text: [text]&variable[more_macro_text]
|
||||
*/
|
||||
/*
|
||||
* NOTE: Clipper assumes that all variables used in macro expressions
|
||||
* are memvar variables
|
||||
* NOTE: Clipper pushes the complete macro expression converted
|
||||
* to string in case complex expression is used, e.g.
|
||||
* My&var.1
|
||||
* is pushed as:
|
||||
* "MY&VAR.1"
|
||||
*/
|
||||
pExpr = hb_compExprNew( HB_ET_MACRO );
|
||||
pExpr->value.asMacro.cMacroOp = cMacroOp; /* '&' if variable or 0 if text */
|
||||
pExpr->value.asMacro.szMacro = szName; /* variable name or macro text */
|
||||
pExpr->value.asMacro.pExprList = NULL; /* this is not a parenthesized expressions */
|
||||
pExpr->value.asMacro.SubType = HB_ET_MACRO_VAR;
|
||||
|
||||
if( cMacroOp == 0 )
|
||||
{
|
||||
/* check if variable with valid scope is used in macro text
|
||||
* (local, static and field variables are not allowed)
|
||||
* e.g.
|
||||
* LOCAL var
|
||||
* ? &var // this is OK
|
||||
* ? &var.ext // this is invalid
|
||||
*/
|
||||
hb_compExprCheckMacroVar( szName );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewMacro(&)"));
|
||||
|
||||
/* Macro expression: &( expression_list )
|
||||
*/
|
||||
pExpr = hb_compExprNew( HB_ET_MACRO );
|
||||
pExpr->value.asMacro.pExprList = pMacroExpr;
|
||||
pExpr->value.asMacro.szMacro = NULL; /* this is used to distinguish &(...) from &ident */
|
||||
pExpr->value.asMacro.SubType = HB_ET_MACRO_EXPR;
|
||||
}
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Creates new aliased variable
|
||||
* aliasexpr -> identifier
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewAliasVar( HB_EXPR_PTR pAlias, HB_EXPR_PTR pVariable )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAliasVar()"));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_ALIASVAR );
|
||||
|
||||
pExpr->value.asAlias.pAlias = pAlias;
|
||||
pExpr->value.asAlias.pVar = pVariable;
|
||||
pExpr->value.asAlias.pExpList = NULL;
|
||||
|
||||
/* macro expressions in alias context require a special handling
|
||||
*/
|
||||
if( pAlias->ExprType == HB_ET_MACRO )
|
||||
pAlias->value.asMacro.SubType = HB_ET_MACRO_ALIASED;
|
||||
if( pVariable->ExprType == HB_ET_MACRO )
|
||||
pVariable->value.asMacro.SubType = HB_ET_MACRO_ALIASED;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Creates new aliased expression
|
||||
* alias_expr -> ( expression )
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewAliasExpr( HB_EXPR_PTR pAlias, HB_EXPR_PTR pExpList )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAliasExpr()"));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_ALIASEXPR );
|
||||
|
||||
pExpr->value.asAlias.pAlias = pAlias;
|
||||
pExpr->value.asAlias.pExpList = pExpList;
|
||||
pExpr->value.asAlias.pVar = NULL;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Creates new send expression
|
||||
* pObject : szMessage
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR pObject, char * szMessage )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewSend(%p, %s)", pObject, szMessage));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_SEND );
|
||||
pExpr->value.asMessage.szMessage = szMessage;
|
||||
pExpr->value.asMessage.pObject = pObject;
|
||||
pExpr->value.asMessage.pParms = NULL;
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Creates new method call
|
||||
* pObject : identifier ( pArgList )
|
||||
*
|
||||
* pObject = is an expression returned by hb_compExprNewSend
|
||||
* pArgList = list of passed arguments - it will be HB_ET_NONE if no arguments
|
||||
* are passed
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewMethodCall( HB_EXPR_PTR pObject, HB_EXPR_PTR pArgList )
|
||||
{
|
||||
pObject->value.asMessage.pParms = pArgList;
|
||||
|
||||
return pObject;
|
||||
}
|
||||
|
||||
/* Creates a list - all elements will be used
|
||||
* This list can be used to create an array or function's call arguments
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewList( HB_EXPR_PTR pFirstItem )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewList()"));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_LIST );
|
||||
pExpr->value.asList.pExprList = pFirstItem;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Creates a list of function call arguments
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewArgList( HB_EXPR_PTR pFirstItem )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArgList()"));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_ARGLIST );
|
||||
pExpr->value.asList.pExprList = pFirstItem;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Adds new element to the list
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprAddListExpr( HB_EXPR_PTR pList, HB_EXPR_PTR pNewItem )
|
||||
{
|
||||
if( pList->value.asList.pExprList )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
/* add new item to the end of the list */
|
||||
pExpr = pList->value.asList.pExprList;
|
||||
while( pExpr->pNext )
|
||||
pExpr = pExpr->pNext;
|
||||
pExpr->pNext = pNewItem;
|
||||
}
|
||||
else
|
||||
pList->value.asList.pExprList = pNewItem;
|
||||
|
||||
return pList;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewVar( char * szName )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewVar(%s)", szName));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_VARIABLE );
|
||||
pExpr->value.asSymbol = szName;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Create a new declaration of PUBLIC or PRIVATE variable.
|
||||
*
|
||||
* szName is a string with variable name if 'PUBLIC varname' context
|
||||
* pMacroVar is a macro expression if 'PUBLIC &varname' context
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewRTVar( char * szName, HB_EXPR_PTR pMacroVar )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewRTVar(%s, %p)", szName, pMacroVar));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_RTVAR );
|
||||
pExpr->value.asRTVar.szName = szName;
|
||||
pExpr->value.asRTVar.pMacro = pMacroVar;
|
||||
if( pMacroVar )
|
||||
pMacroVar->value.asMacro.SubType = HB_ET_MACRO_SYMBOL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Create a new symbol used in function calls
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewFunName( char * szName )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunName(%s)", szName));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_FUNNAME );
|
||||
pExpr->value.asSymbol = szName;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Create a new symbol used in an alias expressions
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewAlias( char * szName )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAlias(%s)", szName));
|
||||
|
||||
pExpr = hb_compExprNew( HB_ET_ALIAS );
|
||||
pExpr->value.asSymbol = szName;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewEqual( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EQUAL );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewPlus( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PLUS );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewMinus( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MINUS );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewMult( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MULT );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewDiv( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_DIV );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewMod( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MOD );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewPower( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POWER );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewPostInc( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POSTINC );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewPostDec( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POSTDEC );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewPreInc( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PREINC );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewPreDec( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PREDEC );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewPlusEq( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PLUSEQ );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewMinusEq( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MINUSEQ );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewMultEq( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MULTEQ );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewDivEq( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_DIVEQ );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewModEq( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MODEQ );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewExpEq( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EXPEQ );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewAnd( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_AND );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewOr( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_OR );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewNot( HB_EXPR_PTR pNotExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
if( pNotExpr->ExprType == HB_ET_LOGICAL )
|
||||
{
|
||||
pNotExpr->value.asLogical = ! pNotExpr->value.asLogical;
|
||||
pExpr = pNotExpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
pExpr = hb_compExprNew( HB_EO_NOT );
|
||||
pExpr->value.asOperator.pLeft = pNotExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
}
|
||||
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewEQ( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EQ );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewLT( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_LT );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewGT( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_GT );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewLE( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_LE );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewGE( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_GE );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewNE( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_NE );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
HB_EXPR_PTR hb_compExprNewIN( HB_EXPR_PTR pLeftExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_IN );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* NOTE: all invalid cases are handled by yacc rules
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprNewNegate( HB_EXPR_PTR pNegExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
if( pNegExpr->ExprType == HB_ET_NUMERIC )
|
||||
{
|
||||
if( pNegExpr->value.asNum.NumType == HB_ET_DOUBLE )
|
||||
pNegExpr->value.asNum.dVal = - pNegExpr->value.asNum.dVal;
|
||||
else
|
||||
pNegExpr->value.asNum.lVal = - pNegExpr->value.asNum.lVal;
|
||||
pExpr = pNegExpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
pExpr = hb_compExprNew( HB_EO_NEGATE );
|
||||
pExpr->value.asOperator.pLeft = pNegExpr;
|
||||
pExpr->value.asOperator.pRight = NULL;
|
||||
}
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
/* Handles (expression := expression) syntax
|
||||
*/
|
||||
HB_EXPR_PTR hb_compExprAssign( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr )
|
||||
{
|
||||
HB_EXPR_PTR pExpr;
|
||||
|
||||
HB_TRACE(HB_TR_DEBUG, ("hb_compExprAssign()"));
|
||||
|
||||
pExpr = hb_compExprNew( HB_EO_ASSIGN );
|
||||
pExpr->value.asOperator.pLeft = pLeftExpr;
|
||||
pExpr->value.asOperator.pRight = pRightExpr;
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
/* Return a number of elements on the linked list
|
||||
*/
|
||||
ULONG hb_compExprListLen( HB_EXPR_PTR pExpr )
|
||||
{
|
||||
ULONG ulLen = 0;
|
||||
|
||||
pExpr = pExpr->value.asList.pExprList;
|
||||
while( pExpr )
|
||||
{
|
||||
pExpr = pExpr->pNext;
|
||||
++ulLen;
|
||||
}
|
||||
|
||||
return ulLen;
|
||||
}
|
||||
|
||||
1099
harbour/source/common/expropt2.c
Normal file
1099
harbour/source/common/expropt2.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -33,7 +33,9 @@ C_SOURCES=\
|
||||
hbgenerr.c \
|
||||
hbpcode.c \
|
||||
hbusage.c \
|
||||
expropt.c \
|
||||
expropta.c \
|
||||
exproptb.c \
|
||||
exproptc.c \
|
||||
|
||||
C_MAIN=harbour.c
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* hbexpr.c is also included from ../macro/macro.c
|
||||
* However it produces a slighty different code if used in
|
||||
* macro compiler
|
||||
* 3 - ignore this magic number - this is used to force compilation
|
||||
*/
|
||||
#include "hbexpr.c"
|
||||
10
harbour/source/compiler/expropta.c
Normal file
10
harbour/source/compiler/expropta.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* hbexpra.c is also included from ../macro/macro.c
|
||||
* However it produces a slighty different code if used in
|
||||
* macro compiler (there is an additional parameter passed to some functions)
|
||||
* 0 - ignore this magic number - this is used to force compilation
|
||||
*/
|
||||
#include "hbexpra.c"
|
||||
10
harbour/source/compiler/exproptb.c
Normal file
10
harbour/source/compiler/exproptb.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* hbexprb.c is also included from ../macro/macro.c
|
||||
* However it produces a slighty different code if used in
|
||||
* macro compiler (there is an additional parameter passed to some functions)
|
||||
* 0 - ignore this magic number - this is used to force compilation
|
||||
*/
|
||||
#include "hbexprb.c"
|
||||
10
harbour/source/compiler/exproptc.c
Normal file
10
harbour/source/compiler/exproptc.c
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* hbexprc.c is also included from ../macro/macro.c
|
||||
* However it produces a slighty different code if used in
|
||||
* macro compiler (there is an additional parameter passed to some functions)
|
||||
* 0 - ignore this magic number - this is used to force compilation
|
||||
*/
|
||||
#include "hbexprc.c"
|
||||
Reference in New Issue
Block a user