Files
harbour-core/harbour/include/hbexprb.c
Viktor Szakats 003fd7c41e 2010-01-14 18:01 UTC+0100 Viktor Szakats (harbour.01 syenar.hu)
* src/rtl/strclear.c
    + HB_STRCLEAR() return value will now precisely inform about
      successful clear operation. Thanks to Mindaugas.

  * src/vm/hashfunc.c
  * src/vm/macro.c
  * src/vm/strapi.c
  * src/vm/runner.c
  * src/vm/estack.c
  * src/vm/codebloc.c
  * src/vm/hashes.c
  * src/vm/maindll.c
  * src/vm/dynsym.c
  * src/vm/debug.c
  * src/vm/itemapi.c
  * src/vm/garbage.c
  * src/vm/asort.c
  * src/vm/hvm.c
  * src/vm/cmdarg.c
  * src/vm/mainstd.c
  * src/vm/maindllp.c
  * src/vm/arrays.c
  * src/vm/task.c
  * src/vm/fm.c
  * src/vm/proc.c
  * src/vm/thread.c
  * src/vm/memvars.c
  * src/vm/arrayshb.c
  * src/vm/eval.c
  * src/vm/extend.c
  * src/vm/dynlibhb.c
  * src/vm/set.c
  * src/vm/classes.c
  * src/debug/dbgentry.c
  * src/common/hbgete.c
  * src/common/hbffind.c
  * src/common/hbver.c
  * src/common/hbprintf.c
  * src/common/hbfsapi.c
  * src/common/hbstr.c
  * src/common/expropt1.c
  * src/common/expropt2.c
  * src/common/hbdate.c
  * src/common/strwild.c
  * src/common/hbhash.c
  * src/rtl/gtdos/gtdos.c
  * src/rtl/fscopy.c
  * src/rtl/run.c
  * src/rtl/gtwin/gtwin.c
  * src/rtl/gtxwc/gtxwc.h
  * src/rtl/gtxwc/gtxwc.c
  * src/rtl/math.c
  * src/rtl/empty.c
  * src/rtl/gtcrs/gtcrs.c
  * src/rtl/trim.c
  * src/rtl/filehb.c
  * src/rtl/hbtoken.c
  * src/rtl/fstemp.c
  * src/rtl/gtchrmap.c
  * src/rtl/strmatch.c
  * src/rtl/gtstd/gtstd.c
  * src/rtl/gttrm/gttrm.c
  * src/rtl/padr.c
  * src/rtl/hbstrfmt.c
  * src/rtl/transfrm.c
  * src/rtl/fserr.c
  * src/rtl/minmax.c
  * src/rtl/hbfeof.c
  * src/rtl/dates.c
  * src/rtl/padc.c
  * src/rtl/gtcgi/gtcgi.c
  * src/rtl/errapi.c
  * src/rtl/version.c
  * src/rtl/hbregexc.c
  * src/rtl/hbrandom.c
  * src/rtl/strtran.c
  * src/rtl/hbprocfn.c
  * src/rtl/hbsocket.c
  * src/rtl/hbinet.c
  * src/rtl/copyfile.c
  * src/rtl/errintlo.c
  * src/rtl/gtapi.c
  * src/rtl/filesys.c
  * src/rtl/padl.c
  * src/rtl/hbregex.c
  * src/rtl/hbbit.c
  * src/rtl/isprint.c
  * src/rtl/saverest.c
  * src/rtl/diskspac.c
  * src/rtl/console.c
  * src/rtl/spfiles.c
  * src/rtl/gtos2/gtos2.c
  * src/rtl/philes.c
  * src/rtl/hbbffnc.c
  * src/rtl/hbgtcore.c
  * src/rtl/cdpapi.c
  * src/rtl/dirdrive.c
  * src/rtl/hbi18n1.c
  * src/rtl/gtclip.c
  * src/rtl/mlcfunc.c
  * src/rtl/gtapiu.c
  * src/rtl/accept.c
  * src/rtl/idle.c
  * src/rtl/itemseri.c
  * src/rtl/hbrunfun.c
  * src/rtl/setcolor.c
  * src/rtl/setkey.c
  * src/rtl/gtsln/mousesln.c
  * src/rtl/gtsln/gtsln.c
  * src/rtl/gtsln/kbsln.c
  * src/rtl/gtsln/gtsln.h
  * src/rtl/disksphb.c
  * src/rtl/strc.c
  * src/rtl/gtpca/gtpca.c
  * src/rtl/gtgui/gtgui.c
  * src/rtl/hbhex.c
  * src/rtl/trace.c
  * src/rtl/gt_tpl/gt_tpl.c
  * src/rtl/inkeyapi.c
  * src/rtl/filebuf.c
  * src/rtl/gete.c
  * src/rtl/setcurs.c
  * src/rtl/hbproces.c
  * src/rtl/langapi.c
  * src/rtl/gtwvt/gtwvt.h
  * src/rtl/gtwvt/gtwvt.c
  * src/rtl/mouse53.c
  * src/rtl/fssize.c
  * src/rtl/hbbyte.c
  * src/rtl/mouseapi.c
  * src/rtl/memofile.c
  * src/rtl/valtostr.c
  * src/rtl/file.c
  * src/rtl/val.c
  * src/rtl/rat.c
  * src/rdd/hbsix/sxcompr.c
  * include/hbvmpub.h
  * include/hbset.h
  * include/hbapicdp.h
  * include/hbstack.h
  * include/hbapilng.h
  * include/hbgtcore.h
  * include/hbapifs.h
  * include/hbthread.h
  * include/hbxvm.h
  * include/hbmacro.h
  * include/hbtypes.h
  * include/hbapi.h
  * include/hbapiitm.h
  * include/hbznet.h
  * include/hbvm.h
  * include/hbapidbg.h
  * include/hbcomp.h
  * include/hbsxfunc.h
  * include/hbcompdf.h
  * include/hbmather.h
  * include/hbapistr.h
  * include/hbwmain.c
  * include/hbexpra.c
  * include/hbexprop.h
  * include/hbsocket.h
  * include/hbapigt.h
  * include/hbapicls.h
  * include/hbhash.h
  * include/hbregex.h
  * include/hbexprb.c
  * include/hbdate.h
  * contrib/gtalleg/gtalleg.c
  * contrib/xhb/hboutdbg.c
  * contrib/xhb/hbserv.h
  * contrib/xhb/bkgtsks.c
  * contrib/xhb/dbf2txt.c
  * contrib/xhb/xhbis.c
  * contrib/xhb/fparse.c
  * contrib/xhb/xhb.h
  * contrib/xhb/xhbsave.c
  * contrib/xhb/xhbmsgs.c
  * contrib/xhb/freadlin.c
  * contrib/xhb/txtline.c
  * contrib/xhb/dbgfxc.c
  * contrib/xhb/xhberrc.c
  * contrib/xhb/filestat.c
  * contrib/xhb/xhbcopyf.c
  * contrib/xhb/hbnxs.h
  * contrib/xhb/hbserv.c
  * contrib/xhb/cstructc.c
  * contrib/xhb/xhbfunc.c
  * contrib/hbmzip/hbmzip.c
  * contrib/gtqtc/gtqtc.cpp
  * contrib/gtwvg/gtwvg.c
  * contrib/gtwvg/gtwvg.h
  * contrib/gtwvg/wvggui.c
  * contrib/gtwvg/wvgcuig.c
  * contrib/gtwvg/wvggui.h
  * contrib/gtwvg/wvgwin.c
  * contrib/gtwvg/wvgutils.c
  * contrib/gtwvg/wvgcore.c
  * contrib/gtwvg/wvgwing.c
  * contrib/hbmisc/hb_f.c
  * contrib/hbmisc/dates2.c
  * contrib/hbwin/hbwapi.h
  * contrib/hbbtree/tests/ctest.c
    * BOOL  -> HB_BOOL
    * TRUE  -> HB_TRUE
    * FALSE -> HB_FALSE
    ; If possible please try to verify me, at least your own are of interest
      or expertise. Look for HB_BOOL/HB_TRUE/HB_FALSE usage in WINAPI calls,
      if you see such thing, it's wrong. Also some, HB_BOOL WINAPI BOOL
      implicit conversions may need to be cleaned.
    ; I didn't touch PP, RDD, SDD and compiler parts yet.
    ; In few places it's possible that some in-line comments are disaligned
      after this operation.
2010-01-14 17:59:30 +00:00

5351 lines
172 KiB
C

/*
* $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, or (at your option)
* any later version.
*
* 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 software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries 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 Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#include "hbcomp.h"
#include "hbmacro.ch"
#if !defined( HB_HASH_USES_ARRAY_INDEXES )
# define HB_HASH_USES_ARRAY_INDEXES
#endif
#define HB_USE_ARRAYAT_REF
/* Temporary disabled optimization with references to object variables
until we will not have extended reference items in our HVM [druzus] */
/* #define HB_USE_OBJMSG_REF */
/* Forward declarations
*/
/* forward declaration of callback functions
*/
static HB_EXPR_FUNC( hb_compExprUseDummy );
static HB_EXPR_FUNC( hb_compExprUseNil );
static HB_EXPR_FUNC( hb_compExprUseNumeric );
static HB_EXPR_FUNC( hb_compExprUseDate );
static HB_EXPR_FUNC( hb_compExprUseTimeStamp );
static HB_EXPR_FUNC( hb_compExprUseString );
static HB_EXPR_FUNC( hb_compExprUseCodeblock );
static HB_EXPR_FUNC( hb_compExprUseLogical );
static HB_EXPR_FUNC( hb_compExprUseSelf );
static HB_EXPR_FUNC( hb_compExprUseArray );
static HB_EXPR_FUNC( hb_compExprUseHash );
static HB_EXPR_FUNC( hb_compExprUseVarRef );
static HB_EXPR_FUNC( hb_compExprUseRef );
static HB_EXPR_FUNC( hb_compExprUseFunRef );
static HB_EXPR_FUNC( hb_compExprUseIIF );
static HB_EXPR_FUNC( hb_compExprUseList );
static HB_EXPR_FUNC( hb_compExprUseArgList );
static HB_EXPR_FUNC( hb_compExprUseMacroArgList );
static HB_EXPR_FUNC( hb_compExprUseArrayAt );
static HB_EXPR_FUNC( hb_compExprUseMacro );
static HB_EXPR_FUNC( hb_compExprUseFunCall );
static HB_EXPR_FUNC( hb_compExprUseAliasVar );
static HB_EXPR_FUNC( hb_compExprUseAliasExpr );
static HB_EXPR_FUNC( hb_compExprUseSend );
static HB_EXPR_FUNC( hb_compExprUseFunName );
static HB_EXPR_FUNC( hb_compExprUseAlias );
static HB_EXPR_FUNC( hb_compExprUseRTVariable );
static HB_EXPR_FUNC( hb_compExprUseVariable );
static HB_EXPR_FUNC( hb_compExprUseAssign );
static HB_EXPR_FUNC( hb_compExprUseEqual );
static HB_EXPR_FUNC( hb_compExprUsePlus );
static HB_EXPR_FUNC( hb_compExprUseMinus );
static HB_EXPR_FUNC( hb_compExprUseMult );
static HB_EXPR_FUNC( hb_compExprUseDiv );
static HB_EXPR_FUNC( hb_compExprUseMod );
static HB_EXPR_FUNC( hb_compExprUsePower );
static HB_EXPR_FUNC( hb_compExprUsePostInc );
static HB_EXPR_FUNC( hb_compExprUsePostDec );
static HB_EXPR_FUNC( hb_compExprUsePreInc );
static HB_EXPR_FUNC( hb_compExprUsePreDec );
static HB_EXPR_FUNC( hb_compExprUsePlusEq );
static HB_EXPR_FUNC( hb_compExprUseMinusEq );
static HB_EXPR_FUNC( hb_compExprUseMultEq );
static HB_EXPR_FUNC( hb_compExprUseDivEq );
static HB_EXPR_FUNC( hb_compExprUseModEq );
static HB_EXPR_FUNC( hb_compExprUseExpEq );
static HB_EXPR_FUNC( hb_compExprUseAnd );
static HB_EXPR_FUNC( hb_compExprUseOr );
static HB_EXPR_FUNC( hb_compExprUseNot );
static HB_EXPR_FUNC( hb_compExprUseEQ );
static HB_EXPR_FUNC( hb_compExprUseLT );
static HB_EXPR_FUNC( hb_compExprUseGT );
static HB_EXPR_FUNC( hb_compExprUseLE );
static HB_EXPR_FUNC( hb_compExprUseGE );
static HB_EXPR_FUNC( hb_compExprUseNE );
static HB_EXPR_FUNC( hb_compExprUseIN );
static HB_EXPR_FUNC( hb_compExprUseNegate );
/* other helper functions
*/
#if defined( HB_MACRO_SUPPORT )
static void hb_compExprCodeblockPush( HB_EXPR_PTR, HB_COMP_DECL );
#else
static void hb_compExprCodeblockPush( HB_EXPR_PTR, HB_BOOL, HB_COMP_DECL );
static void hb_compExprCodeblockEarly( HB_EXPR_PTR, HB_COMP_DECL );
static void hb_compExprCodeblockExtPush( HB_EXPR_PTR pSelf, HB_COMP_DECL );
#endif
static void hb_compExprPushSendPop( HB_EXPR_PTR pSelf, HB_COMP_DECL );
static void hb_compExprPushSendPush( HB_EXPR_PTR pSelf, HB_COMP_DECL );
static void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_COMP_DECL );
static void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_COMP_DECL );
static void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_COMP_DECL );
static void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_COMP_DECL );
static void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_COMP_DECL );
static void hb_compExprUseAliasMacro( HB_EXPR_PTR pAliasedVar, BYTE bAction, HB_COMP_DECL );
static HB_EXPR_PTR hb_compExprReduceList( HB_EXPR_PTR pExpr, HB_COMP_DECL );
static HB_EXPR_PTR hb_compExprReduceAliasString( HB_EXPR_PTR pExpr, HB_EXPR_PTR pAlias, HB_COMP_DECL );
static HB_BOOL hb_compExprIsMemvarAlias( const char *szAlias );
const HB_EXPR_FUNC_PTR hb_comp_ExprTable[ HB_EXPR_COUNT ] = {
hb_compExprUseDummy,
hb_compExprUseNil,
hb_compExprUseNumeric,
hb_compExprUseDate,
hb_compExprUseTimeStamp,
hb_compExprUseString,
hb_compExprUseCodeblock,
hb_compExprUseLogical,
hb_compExprUseSelf,
hb_compExprUseArray,
hb_compExprUseHash,
hb_compExprUseFunRef,
hb_compExprUseVarRef,
hb_compExprUseRef,
hb_compExprUseIIF,
hb_compExprUseList,
hb_compExprUseArgList,
hb_compExprUseMacroArgList,
hb_compExprUseArrayAt,
hb_compExprUseMacro,
hb_compExprUseFunCall,
hb_compExprUseAliasVar,
hb_compExprUseAliasExpr,
hb_compExprUseSend,
hb_compExprUseFunName,
hb_compExprUseAlias,
hb_compExprUseRTVariable,
hb_compExprUseVariable,
hb_compExprUsePostInc, /* post-operators -> lowest precedence */
hb_compExprUsePostDec,
hb_compExprUseAssign, /* assigments */
hb_compExprUsePlusEq,
hb_compExprUseMinusEq,
hb_compExprUseMultEq,
hb_compExprUseDivEq,
hb_compExprUseModEq,
hb_compExprUseExpEq,
hb_compExprUseOr, /* logical operators */
hb_compExprUseAnd,
hb_compExprUseNot,
hb_compExprUseEqual, /* relational operators */
hb_compExprUseEQ,
hb_compExprUseNE,
hb_compExprUseIN,
hb_compExprUseLT,
hb_compExprUseGT,
hb_compExprUseLE,
hb_compExprUseGE,
hb_compExprUsePlus, /* addition */
hb_compExprUseMinus,
hb_compExprUseMult, /* multiple */
hb_compExprUseDiv,
hb_compExprUseMod,
hb_compExprUsePower,
hb_compExprUseNegate, /* sign operator */
hb_compExprUsePreInc,
hb_compExprUsePreDec /* highest precedence */
};
/* ************************************************************************* */
static HB_EXPR_FUNC( hb_compExprUseDummy )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC1( PCode1, HB_P_PUSHNIL );
break;
case HB_EA_POP_PCODE:
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_NIL expression
*/
static HB_EXPR_FUNC( hb_compExprUseNil )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* NIL cannot be used as index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC1( PCode1, HB_P_PUSHNIL );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_NUMERIC expression
*/
static HB_EXPR_FUNC( hb_compExprUseNumeric )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
if( pSelf->value.asNum.NumType == HB_ET_DOUBLE )
HB_GEN_FUNC3( PushDouble, pSelf->value.asNum.val.d, pSelf->value.asNum.bWidth, pSelf->value.asNum.bDec );
else
HB_GEN_FUNC1( PushLong, pSelf->value.asNum.val.l );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_DATE expression
*/
static HB_EXPR_FUNC( hb_compExprUseDate )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
#ifdef HB_HASH_USES_ARRAY_INDEXES
if( !HB_SUPPORT_HARBOUR )
#endif
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* Date cannot be used as index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC1( PushDate, pSelf->value.asDate.lDate );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_TIMESTAMP expression
*/
static HB_EXPR_FUNC( hb_compExprUseTimeStamp )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
#ifdef HB_HASH_USES_ARRAY_INDEXES
if( !HB_SUPPORT_HARBOUR )
#endif
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* timestamp cannot be used as index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC2( PushTimeStamp, pSelf->value.asDate.lDate,
pSelf->value.asDate.lTime );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_STRING expression
*/
static HB_EXPR_FUNC( hb_compExprUseString )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
#ifdef HB_HASH_USES_ARRAY_INDEXES
if( !HB_SUPPORT_HARBOUR )
#endif
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* string cannot be used as index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
{
HB_GEN_FUNC2( PushString, pSelf->value.asString.string,
pSelf->ulLength + 1 );
#if ! defined( HB_MACRO_SUPPORT )
if( HB_SUPPORT_MACROTEXT &&
hb_compIsValidMacroText( HB_COMP_PARAM,
pSelf->value.asString.string,
pSelf->ulLength ) )
#else
if( hb_macroIsValidMacroText( pSelf->value.asString.string,
pSelf->ulLength ) )
#endif
{
HB_GEN_FUNC1( PCode1, HB_P_MACROTEXT );
}
break;
}
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
break;
case HB_EA_DELETE:
if( pSelf->value.asString.dealloc )
hb_xfree( pSelf->value.asString.string );
break;
}
return pSelf;
}
/* actions for HB_ET_CODEBLOCK expression
*/
static HB_EXPR_FUNC( hb_compExprUseCodeblock )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* codeblock cannot be used as index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
{
#if defined( HB_MACRO_SUPPORT )
HB_EXPR_PCODE1( hb_compExprCodeblockPush, pSelf );
#else
if( pSelf->value.asCodeblock.flags & HB_BLOCK_EXT )
hb_compExprCodeblockExtPush( pSelf, HB_COMP_PARAM );
else if( ( pSelf->value.asCodeblock.flags & HB_BLOCK_MACRO ) &&
!( pSelf->value.asCodeblock.flags &
( HB_BLOCK_LATEEVAL | HB_BLOCK_VPARAMS ) ) )
/* early evaluation of a macro */
hb_compExprCodeblockEarly( pSelf, HB_COMP_PARAM );
else
hb_compExprCodeblockPush( pSelf, TRUE, HB_COMP_PARAM );
#endif
break;
}
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
break;
case HB_EA_DELETE:
{
HB_EXPR_PTR pExp = pSelf->value.asCodeblock.pExprList;
HB_EXPR_PTR pNext;
hb_compExprCBVarDel( pSelf->value.asCodeblock.pLocals );
if( pSelf->value.asCodeblock.string )
hb_xfree( pSelf->value.asCodeblock.string );
/* Delete all expressions of the block. */
while( pExp )
{
pNext = pExp->pNext;
HB_COMP_EXPR_DELETE( pExp );
pExp = pNext;
}
break;
}
}
return pSelf;
}
/* actions for HB_ET_LOGICAL expression
*/
static HB_EXPR_FUNC( hb_compExprUseLogical )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* logical cannot be used as array index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC1( PushLogical, pSelf->value.asLogical );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_SELF expression
*/
static HB_EXPR_FUNC( hb_compExprUseSelf )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
/* Clipper allows such operation and because some valid Clipper
* code needs it then I disabled error message, [druzus]
*/
/* HB_COMP_ERROR_TYPE( pSelf ); */
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* SELF cannot be used as array index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC1( PCode1, HB_P_PUSHSELF );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for a literal array { , , , ... }
*/
static HB_EXPR_FUNC( hb_compExprUseArray )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf = hb_compExprReduceList( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* array cannot be used as index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
{
USHORT usItems = ( USHORT ) hb_compExprParamListCheck( HB_COMP_PARAM, pSelf );
if( usItems == 0 )
{
HB_GEN_FUNC3( PCode3, HB_P_ARRAYGEN, 0, 0 );
}
else
{
HB_BOOL fArgsList = pSelf->ExprType == HB_ET_MACROARGLIST;
if( !fArgsList )
{
/* Note: direct type change */
pSelf->ExprType = HB_ET_ARGLIST;
}
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
/* restore original expression type */
pSelf->ExprType = HB_ET_ARRAY;
if( fArgsList )
{
HB_GEN_FUNC3( PCode3, HB_P_MACROARRAYGEN,
HB_LOBYTE( usItems ), HB_HIBYTE( usItems ) );
}
else
{
HB_GEN_FUNC3( PCode3, HB_P_ARRAYGEN,
HB_LOBYTE( usItems ), HB_HIBYTE( usItems ) );
}
}
break;
}
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
{
HB_EXPR_PTR pElem = pSelf->value.asList.pExprList;
/* Push non-constant values only
*/
while( pElem )
{
HB_EXPR_USE( pElem, HB_EA_PUSH_POP );
pElem = pElem->pNext;
}
}
break;
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
break;
case HB_EA_DELETE:
{
HB_EXPR_PTR pElem = pSelf->value.asList.pExprList;
/* Delete all elements of the array
*/
HB_EXPR_PTR pNext;
while( pElem )
{
pNext = pElem->pNext;
HB_COMP_EXPR_DELETE( pElem );
pElem = pNext;
}
}
break;
}
return pSelf;
}
/* actions for HB_ET_HASH literal hash
* { key1=>val1, key2=>val2, ... keyN=>valN }
*/
static HB_EXPR_FUNC( hb_compExprUseHash )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf = hb_compExprReduceList( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf ); /* array cannot be used as index element */
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
{
USHORT usItems = ( USHORT ) ( pSelf->ulLength >> 1 );
/* Note: direct type change */
pSelf->ExprType = HB_ET_ARGLIST;
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
/* restore original expression type */
pSelf->ExprType = HB_ET_HASH;
HB_GEN_FUNC3( PCode3, HB_P_HASHGEN, HB_LOBYTE( usItems ), HB_HIBYTE( usItems ) );
break;
}
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
{
HB_EXPR_PTR pElem = pSelf->value.asList.pExprList;
/* Push non-constant values only */
while( pElem )
{
HB_EXPR_USE( pElem, HB_EA_PUSH_POP );
pElem = pElem->pNext;
}
}
break;
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
break;
case HB_EA_DELETE:
{
HB_EXPR_PTR pElem = pSelf->value.asList.pExprList;
/* Delete all elements of the array
*/
HB_EXPR_PTR pNext;
while( pElem )
{
pNext = pElem->pNext;
HB_COMP_EXPR_DELETE( pElem );
pElem = pNext;
}
}
break;
}
return pSelf;
}
/* actions for HB_ET_VARREF expression
*/
static HB_EXPR_FUNC( hb_compExprUseVarRef )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC1( PushVarRef, pSelf->value.asSymbol );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_FUNREF expression
*/
static HB_EXPR_FUNC( hb_compExprUseFunRef )
{
switch( iMessage )
{
case HB_EA_REDUCE:
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC1( PushFunRef, pSelf->value.asSymbol );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
break;
}
return pSelf;
}
/* actions for HB_ET_REFERENCE expression
*/
static HB_EXPR_FUNC( hb_compExprUseRef )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asReference = HB_EXPR_USE( pSelf->value.asReference, HB_EA_REDUCE );
if( pSelf->value.asReference->ExprType == HB_ET_IIF )
{
HB_EXPR_PTR pCond, pIIF, pFalse;
pIIF = pSelf->value.asReference;
pCond = pIIF->value.asList.pExprList;
pFalse = hb_compExprNewRef( pCond->pNext->pNext, HB_COMP_PARAM );
pCond->pNext = hb_compExprNewRef( pCond->pNext, HB_COMP_PARAM );
pCond->pNext->pNext = pFalse;
memcpy( pSelf, pIIF, sizeof( HB_EXPR ) );
HB_COMP_EXPR_CLEAR( pIIF );
}
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
{
HB_EXPR_PTR pExp = pSelf->value.asReference;
if( pExp->ExprType == HB_ET_MACRO )
{
pExp->value.asMacro.SubType = HB_ET_MACRO_REFER;
HB_EXPR_USE( pExp, HB_EA_PUSH_PCODE );
break;
}
else if( pExp->ExprType == HB_ET_ARRAYAT )
{
pExp->value.asList.reference = TRUE;
HB_EXPR_USE( pExp, HB_EA_PUSH_PCODE );
break;
}
else if( pExp->ExprType == HB_ET_SEND )
{
/* HB_EXPR_PTR pSend = pExp->value.asMessage.pObject;
if( !pSend || pSend->ExprType == HB_ET_VARIABLE ) */
{
hb_compExprPushSendPop( pExp, HB_COMP_PARAM );
HB_GEN_FUNC1( PCode1, HB_P_PUSHOVARREF );
break;
}
}
else if( pExp->ExprType == HB_ET_VARIABLE )
{
pExp->ExprType = HB_ET_VARREF;
HB_EXPR_USE( pExp, HB_EA_PUSH_PCODE );
pExp->ExprType = HB_ET_VARIABLE;
break;
}
else if( pExp->ExprType == HB_ET_ALIASVAR )
{
if( pExp->value.asAlias.pVar->ExprType == HB_ET_VARIABLE &&
hb_compExprIsMemvarAlias( pExp->value.asAlias.pAlias->value.asSymbol ) )
{ /* @M-> @MEMVAR-> or @MEMVA-> or @MEMV-> */
HB_GEN_FUNC1( PushMemvarRef, pExp->value.asAlias.pVar->value.asSymbol );
break;
}
}
else if( pExp->ExprType == HB_ET_VARREF ||
pExp->ExprType == HB_ET_REFERENCE )
{
HB_EXPR_USE( pExp, HB_EA_PUSH_PCODE );
break;
}
hb_compErrorRefer( HB_COMP_PARAM, NULL, hb_compExprDescription( pExp ) );
break;
}
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
case HB_EA_DELETE:
HB_COMP_EXPR_DELETE( pSelf->value.asReference );
break;
}
return pSelf;
}
/* actions for HB_ET_IIF expression
*/
static HB_EXPR_FUNC( hb_compExprUseIIF )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf = hb_compExprReduceIIF( hb_compExprReduceList( pSelf, HB_COMP_PARAM ), HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
if( HB_SUPPORT_HARBOUR )
{
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList->pNext;
HB_EXPR_USE( pExpr, HB_EA_LVALUE );
HB_EXPR_USE( pExpr->pNext, HB_EA_LVALUE );
}
else
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
{
/* this is called if all three parts of IIF expression should be generated
*/
LONG lPosFalse, lPosEnd;
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList;
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
lPosFalse = HB_GEN_FUNC1( JumpFalse, 0 );
pExpr =pExpr->pNext;
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
lPosEnd = HB_GEN_FUNC1( Jump, 0 );
pExpr =pExpr->pNext;
HB_GEN_FUNC1( JumpHere, lPosFalse );
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( JumpHere, lPosEnd );
break;
}
case HB_EA_POP_PCODE:
{
/* this is called if all three parts of IIF expression should be generated
*/
LONG lPosFalse, lPosEnd;
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList;
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
lPosFalse = HB_GEN_FUNC1( JumpFalse, 0 );
pExpr =pExpr->pNext;
HB_EXPR_USE( pExpr, HB_EA_POP_PCODE );
lPosEnd = HB_GEN_FUNC1( Jump, 0 );
pExpr =pExpr->pNext;
HB_GEN_FUNC1( JumpHere, lPosFalse );
HB_EXPR_USE( pExpr, HB_EA_POP_PCODE );
HB_GEN_FUNC1( JumpHere, lPosEnd );
break;
}
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
{
#ifdef HB_CLP_STRICT
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP ); /* remove a value if used in statement */
#else
ULONG ulPosFalse, ulPosEnd;
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList;
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
ulPosFalse = HB_GEN_FUNC1( JumpFalse, 0 );
pExpr =pExpr->pNext;
/* do not generate warning about meaningless use of expression NIL */
if( pExpr->ExprType != HB_ET_NIL )
HB_EXPR_USE( pExpr, HB_EA_PUSH_POP );
pExpr =pExpr->pNext;
#if defined( HB_MACRO_SUPPORT )
if( HB_PCODE_DATA->lPCodePos == ulPosFalse + 3 )
{
HB_PCODE_DATA->pCode[ ulPosFalse - 1 ] = HB_P_JUMPTRUEFAR;
ulPosEnd = ulPosFalse;
}
#else
if( HB_COMP_PARAM->functions.pLast->lPCodePos == ulPosFalse + 3 )
{
HB_COMP_PARAM->functions.pLast->pCode[ ulPosFalse - 1 ] = HB_P_JUMPTRUEFAR;
ulPosEnd = ulPosFalse;
}
#endif
else
{
ulPosEnd = HB_GEN_FUNC1( Jump, 0 );
HB_GEN_FUNC1( JumpHere, ulPosFalse );
}
/* do not generate warning about meaningless use of expression NIL */
if( pExpr->ExprType != HB_ET_NIL )
HB_EXPR_USE( pExpr, HB_EA_PUSH_POP );
HB_GEN_FUNC1( JumpHere, ulPosEnd );
#endif
break;
}
case HB_EA_DELETE:
if( pSelf->value.asList.pExprList )
{
HB_EXPR_PTR pTmp, pExpr = pSelf->value.asList.pExprList;
while( pExpr )
{
pTmp = pExpr->pNext; /* store next expression */
HB_COMP_EXPR_DELETE( pExpr );
pExpr =pTmp;
}
pSelf->value.asList.pExprList = NULL;
}
break;
}
return pSelf; /* return self */
}
/* NOTE: In PUSH operation it leaves on the eval stack the last expression only
*/
static HB_EXPR_FUNC( hb_compExprUseList )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf = hb_compExprReduceList( pSelf, HB_COMP_PARAM );
if( HB_SUPPORT_HARBOUR )
pSelf = hb_compExprListStrip( pSelf, HB_COMP_PARAM );
if( HB_SUPPORT_XBASE && pSelf->ExprType == HB_ET_LIST )
{
if( hb_compExprListLen( pSelf ) == 1 )
{
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList;
if( pExpr->ExprType == HB_ET_MACRO &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_SYMBOL &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_REFER &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_ALIASED )
{
pExpr->value.asMacro.SubType |= HB_ET_MACRO_PARE;
}
}
}
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
if( hb_compExprListLen( pSelf ) == 1 )
{
/* For example:
* ( a ) := 4
*/
hb_compErrorLValue( HB_COMP_PARAM, pSelf->value.asList.pExprList );
}
else
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
{
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList;
if( pExpr->ExprType == HB_ET_NONE && pExpr->pNext == NULL )
{
/* Empty list was used ()
*/
HB_COMP_ERROR_SYNTAX( pExpr );
}
else
{
while( pExpr )
{
if( HB_SUPPORT_XBASE )
{
if( pExpr->ExprType == HB_ET_MACRO &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_SYMBOL &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_REFER &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_ALIASED )
{
pExpr->value.asMacro.SubType |= HB_ET_MACRO_PARE;
}
}
if( pExpr->pNext )
HB_EXPR_USE( pExpr, HB_EA_PUSH_POP );
else
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); /* the last expression */
pExpr = pExpr->pNext;
}
}
}
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
{
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList;
while( pExpr )
{
if( HB_SUPPORT_XBASE )
{
if( pExpr->ExprType == HB_ET_MACRO &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_SYMBOL &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_REFER &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_ALIASED )
{
pExpr->value.asMacro.SubType |= HB_ET_MACRO_PARE;
}
}
HB_EXPR_USE( pExpr, HB_EA_PUSH_POP );
pExpr = pExpr->pNext;
}
}
break;
case HB_EA_DELETE:
if( pSelf->value.asList.pExprList )
{
HB_EXPR_PTR pTmp, pExpr = pSelf->value.asList.pExprList;
while( pExpr )
{
pTmp = pExpr->pNext; /* store next expression */
HB_COMP_EXPR_DELETE( pExpr );
pExpr =pTmp;
}
pSelf->value.asList.pExprList = NULL;
}
break;
}
return pSelf;
}
/* NOTE: In PUSH operation it leaves all expressions on the eval stack
*/
static HB_EXPR_FUNC( hb_compExprUseArgList )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf = hb_compExprReduceList( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
if( pSelf->value.asList.reference )
{
#if defined( HB_MACRO_SUPPORT )
if( !HB_PCODE_DATA->fVParams )
#else
if( !HB_COMP_PARAM->functions.pLast->fVParams )
#endif
{
hb_compErrorVParams( HB_COMP_PARAM,
HB_COMP_PARAM->functions.pLast->szName ?
"Function" : "Codeblock" );
}
HB_GEN_FUNC1( PCode1, HB_P_PUSHVPARAMS );
}
else
{
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList;
while( pExpr )
{
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
pExpr = pExpr->pNext;
}
}
break;
case HB_EA_POP_PCODE:
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
break;
case HB_EA_DELETE:
if( pSelf->value.asList.pExprList )
{
HB_EXPR_PTR pTmp, pExpr = pSelf->value.asList.pExprList;
while( pExpr )
{
pTmp = pExpr->pNext; /* store next expression */
HB_COMP_EXPR_DELETE( pExpr );
pExpr =pTmp;
}
pSelf->value.asList.pExprList = NULL;
}
break;
}
return pSelf;
}
/* NOTE: In PUSH operation it leaves all expressions on the eval stack,
* the expresions are divided into macro compiled blocks
*/
static HB_EXPR_FUNC( hb_compExprUseMacroArgList )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf = hb_compExprReduceList( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
{
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList;
USHORT usItems = 0;
while( pExpr )
{
if( ( pExpr->ExprType == HB_ET_MACRO &&
( pExpr->value.asMacro.SubType & HB_ET_MACRO_LIST ) ) ||
( pExpr->ExprType == HB_ET_ARGLIST &&
pExpr->value.asList.reference ) )
{
if( usItems )
{
HB_GEN_FUNC1( PushLong, usItems );
usItems = 0;
}
}
else
++usItems;
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
pExpr = pExpr->pNext;
}
if( usItems )
{
HB_GEN_FUNC1( PushLong, usItems );
}
}
break;
case HB_EA_POP_PCODE:
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
break;
case HB_EA_DELETE:
if( pSelf->value.asList.pExprList )
{
HB_EXPR_PTR pTmp, pExpr = pSelf->value.asList.pExprList;
while( pExpr )
{
pTmp = pExpr->pNext; /* store next expression */
HB_COMP_EXPR_DELETE( pExpr );
pExpr =pTmp;
}
pSelf->value.asList.pExprList = NULL;
}
break;
}
return pSelf;
}
/* handler for ( ( array[ idx ] )[ idx ] )[ idx ]
*/
static HB_EXPR_FUNC( hb_compExprUseArrayAt )
{
switch( iMessage )
{
case HB_EA_REDUCE:
{
HB_EXPR_PTR pIdx;
/* Clipper forces memvar context for undeclared variables used with
* array index, f.e.: var[ n ]
* but not for code like: ( var )[ n ]
*/
if( pSelf->value.asList.pExprList->ExprType == HB_ET_VARIABLE )
{
#if !defined( HB_MACRO_SUPPORT )
int iScope;
hb_compVariableFind( HB_COMP_PARAM, pSelf->value.asList.pExprList->value.asSymbol, NULL, &iScope );
if( iScope == HB_VS_UNDECLARED )
{
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_MEMVAR_ASSUMED,
pSelf->value.asList.pExprList->value.asSymbol, NULL );
#else
if( hb_macroLocalVarGetPos( pSelf->value.asList.pExprList->value.asSymbol, HB_COMP_PARAM ) == 0 )
{
#endif
pSelf->value.asList.pExprList = hb_compExprNewAliasVar(
hb_compExprNewAlias( "MEMVAR", HB_COMP_PARAM ),
pSelf->value.asList.pExprList, HB_COMP_PARAM );
}
}
pSelf->value.asList.pExprList = HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_REDUCE );
pSelf->value.asList.pIndex = HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_REDUCE );
pIdx = pSelf->value.asList.pIndex;
if( pIdx->ExprType == HB_ET_NUMERIC )
{
HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList; /* the expression that holds an array */
LONG lIndex;
if( pIdx->value.asNum.NumType == HB_ET_LONG )
lIndex = ( LONG ) pIdx->value.asNum.val.l;
else
lIndex = ( LONG ) pIdx->value.asNum.val.d;
if( pExpr->ExprType == HB_ET_ARRAY ) /* is it a literal array */
{
ULONG ulSize = hb_compExprParamListCheck( HB_COMP_PARAM, pExpr );
if( pExpr->ExprType == HB_ET_MACROARGLIST )
/* restore original expression type */
pExpr->ExprType = HB_ET_ARRAY;
else if( !HB_IS_VALID_INDEX( lIndex, ulSize ) )
{
if( !HB_SUPPORT_ARRSTR )
hb_compErrorBound( HB_COMP_PARAM, pIdx );
}
else
{
pExpr = pExpr->value.asList.pExprList; /* the first element in the array */
while( --lIndex && pExpr )
pExpr = pExpr->pNext;
if( pExpr ) /* found ? */
{
/* extract a single expression from the array
*/
HB_EXPR_PTR pNew = HB_COMP_EXPR_NEW( HB_ET_NONE );
memcpy( pNew, pExpr, sizeof( HB_EXPR ) );
/* This will suppres releasing of memory occupied by components of
* the expression - we have just copied them into the new expression.
* This method is simpler then traversing the list and releasing all
* but this choosen one.
*/
pExpr->ExprType = HB_ET_NONE;
/* Here comes the magic */
HB_COMP_EXPR_DELETE( pSelf );
pSelf = pNew;
}
else if( !HB_SUPPORT_ARRSTR )
hb_compErrorBound( HB_COMP_PARAM, pIdx );
}
}
#if 0
else if( pExpr->ExprType == HB_ET_STRING && HB_SUPPORT_ARRSTR ) /* is it a literal string */
{
if( HB_IS_VALID_INDEX( lIndex, pExpr->ulLength ) )
{
UCHAR ucValue = ( UCHAR ) pExpr->value.asString.string[ lIndex - 1 ];
HB_COMP_EXPR_DELETE( pSelf );
pSelf = hb_compExprNewLong( ucValue, HB_COMP_PARAM );
}
else
hb_compErrorBound( HB_COMP_PARAM, pIdx );
}
#endif
else if( !HB_SUPPORT_ARRSTR )
{
HB_EXPR_USE( pExpr, HB_EA_ARRAY_AT );
}
}
break;
}
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
{
HB_BOOL fMacroIndex = FALSE;
if( pSelf->value.asList.pIndex->ExprType == HB_ET_MACRO )
{
if( HB_SUPPORT_XBASE )
{
if( pSelf->value.asMacro.SubType != HB_ET_MACRO_SYMBOL &&
pSelf->value.asMacro.SubType != HB_ET_MACRO_REFER &&
pSelf->value.asMacro.SubType != HB_ET_MACRO_ALIASED )
{
pSelf->value.asList.pIndex->value.asMacro.SubType |= HB_ET_MACRO_LIST;
fMacroIndex = TRUE;
}
}
}
else if( pSelf->value.asList.pIndex->ExprType == HB_ET_ARGLIST )
{
fMacroIndex = pSelf->value.asList.pIndex->value.asList.reference;
}
if( pSelf->value.asList.reference && HB_SUPPORT_ARRSTR )
{
HB_EXPR_PTR pList = pSelf->value.asList.pExprList;
if( pList->ExprType == HB_ET_VARIABLE )
{
pList->ExprType = HB_ET_VARREF;
HB_EXPR_USE( pList, HB_EA_PUSH_PCODE );
pList->ExprType = HB_ET_VARIABLE;
}
else if( pList->ExprType == HB_ET_ALIASVAR &&
pList->value.asAlias.pVar->ExprType == HB_ET_VARIABLE &&
hb_compExprIsMemvarAlias( pList->value.asAlias.pAlias->value.asSymbol ) )
{
HB_GEN_FUNC1( PushMemvarRef, pList->value.asAlias.pVar->value.asSymbol );
}
else if( pList->ExprType == HB_ET_SEND )
{
hb_compExprPushSendPop( pList, HB_COMP_PARAM );
HB_GEN_FUNC1( PCode1, HB_P_PUSHOVARREF );
}
else if( pList->ExprType == HB_ET_ARRAYAT &&
!pList->value.asList.reference )
{
pList->value.asList.reference = TRUE;
HB_EXPR_USE( pList, HB_EA_PUSH_PCODE );
pList->value.asList.reference = FALSE;
}
else if( pList->ExprType == HB_ET_MACRO &&
pList->value.asMacro.SubType == HB_ET_MACRO_VAR )
{
pList->value.asMacro.SubType = HB_ET_MACRO_REFER;
HB_EXPR_USE( pList, HB_EA_PUSH_PCODE );
pList->value.asMacro.SubType = HB_ET_MACRO_VAR;
}
else
HB_EXPR_USE( pList, HB_EA_PUSH_PCODE );
}
else
HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_PCODE );
if( fMacroIndex )
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSHINDEX );
if( pSelf->value.asList.reference )
HB_GEN_FUNC1( PCode1, HB_P_ARRAYPUSHREF );
else
HB_GEN_FUNC1( PCode1, HB_P_ARRAYPUSH );
break;
}
case HB_EA_POP_PCODE:
{
HB_BOOL fMacroIndex = FALSE;
if( pSelf->value.asList.pIndex->ExprType == HB_ET_MACRO )
{
if( HB_SUPPORT_XBASE )
{
if( pSelf->value.asMacro.SubType != HB_ET_MACRO_SYMBOL &&
pSelf->value.asMacro.SubType != HB_ET_MACRO_REFER &&
pSelf->value.asMacro.SubType != HB_ET_MACRO_ALIASED )
{
pSelf->value.asList.pIndex->value.asMacro.SubType |= HB_ET_MACRO_LIST;
fMacroIndex = TRUE;
}
}
}
else if( pSelf->value.asList.pIndex->ExprType == HB_ET_ARGLIST )
{
fMacroIndex = pSelf->value.asList.pIndex->value.asList.reference;
}
/* to manage strings as bytes arrays, they must be pushed by reference */
/* arrays also are passed by reference */
if( HB_SUPPORT_ARRSTR )
{
HB_EXPR_PTR pList = pSelf->value.asList.pExprList;
if( pList->ExprType == HB_ET_VARIABLE )
{
pList->ExprType = HB_ET_VARREF;
HB_EXPR_USE( pList, HB_EA_PUSH_PCODE );
pList->ExprType = HB_ET_VARIABLE;
}
else if( pList->ExprType == HB_ET_ALIASVAR &&
pList->value.asAlias.pVar->ExprType == HB_ET_VARIABLE &&
hb_compExprIsMemvarAlias( pList->value.asAlias.pAlias->value.asSymbol ) )
{
HB_GEN_FUNC1( PushMemvarRef, pList->value.asAlias.pVar->value.asSymbol );
}
else if( pList->ExprType == HB_ET_SEND )
{
hb_compExprPushSendPop( pList, HB_COMP_PARAM );
HB_GEN_FUNC1( PCode1, HB_P_PUSHOVARREF );
}
else if( pList->ExprType == HB_ET_ARRAYAT &&
!pList->value.asList.reference )
{
pList->value.asList.reference = TRUE;
HB_EXPR_USE( pList, HB_EA_PUSH_PCODE );
pList->value.asList.reference = FALSE;
}
else if( pList->ExprType == HB_ET_MACRO &&
pList->value.asMacro.SubType == HB_ET_MACRO_VAR )
{
pList->value.asMacro.SubType = HB_ET_MACRO_REFER;
HB_EXPR_USE( pList, HB_EA_PUSH_PCODE );
pList->value.asMacro.SubType = HB_ET_MACRO_VAR;
}
else
HB_EXPR_USE( pList, HB_EA_PUSH_PCODE );
}
else
HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_PCODE );
if( fMacroIndex )
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSHINDEX );
HB_GEN_FUNC1( PCode1, HB_P_ARRAYPOP );
break;
}
case HB_EA_PUSH_POP:
/* NOTE: This is highly optimized code - this will work even
* if accessed value isn't an array. It will work also if
* the index is invalid
*/
HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_POP );
/* no break */
case HB_EA_STATEMENT:
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
break;
case HB_EA_DELETE:
HB_COMP_EXPR_DELETE( pSelf->value.asList.pExprList );
HB_COMP_EXPR_DELETE( pSelf->value.asList.pIndex );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseMacro )
{
switch( iMessage )
{
case HB_EA_REDUCE:
if( pSelf->value.asMacro.pExprList )
pSelf->value.asMacro.pExprList = HB_EXPR_USE( pSelf->value.asMacro.pExprList, HB_EA_REDUCE );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
if( pSelf->value.asMacro.SubType & HB_ET_MACRO_ASSIGN )
HB_GEN_FUNC2( PushString, "_", 2 );
if( pSelf->value.asMacro.pExprList )
{
/* macro expression: &( expressions_list )
* NOTE: only the last expression will be macro-compiled
*/
HB_EXPR_USE( pSelf->value.asMacro.pExprList, HB_EA_PUSH_PCODE );
}
else
{
if( pSelf->value.asMacro.cMacroOp )
{
/* simple macro variable expansion: &variable
* 'szMacro' is a variable name
*/
HB_GEN_FUNC2( PushVar, pSelf->value.asMacro.szMacro, TRUE );
}
else
{
/* complex macro expression: prefix&var.suffix
* all components should be placed as a string that will
* be compiled after text susbstitution
*/
/* Check if macrotext variable does not refer to
* local, static or field.
*/
#if ! defined( HB_MACRO_SUPPORT )
hb_compIsValidMacroText( HB_COMP_PARAM,
pSelf->value.asMacro.szMacro,
strlen( pSelf->value.asMacro.szMacro ) );
#endif
HB_GEN_FUNC2( PushString, pSelf->value.asMacro.szMacro, strlen( pSelf->value.asMacro.szMacro ) + 1 );
}
}
if( pSelf->value.asMacro.SubType & HB_ET_MACRO_ASSIGN )
{
HB_GEN_FUNC1( PCode1, HB_P_PLUS );
pSelf->value.asMacro.SubType &= ~HB_ET_MACRO_ASSIGN;
}
/* compile & run - leave a result on the eval stack
*/
if( pSelf->value.asMacro.SubType == HB_ET_MACRO_SYMBOL )
HB_GEN_FUNC1( PCode1, HB_P_MACROSYMBOL );
else if( pSelf->value.asMacro.SubType == HB_ET_MACRO_REFER )
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSHREF );
else if( pSelf->value.asMacro.SubType != HB_ET_MACRO_ALIASED )
{
if( HB_SUPPORT_XBASE )
{
if( pSelf->value.asMacro.SubType & HB_ET_MACRO_LIST )
{
/* { &macro }, funCall( &macro ) or var[ &macro ] */
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSHLIST );
}
else if( pSelf->value.asMacro.SubType & HB_ET_MACRO_PARE )
{
/* var := (somevalue, &macro) - in Xbase++ compatibility mode
* EVAL( {|| &macro} ) - in all cases
*/
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSHPARE );
}
else
{
/* usual &macro */
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSH );
}
}
else
/* usual &macro */
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSH );
/* Always add byte to pcode indicating requested macro compiler flag. */
HB_GEN_FUNC1( PCode1, ( BYTE ) HB_MACRO_GENFLAGS );
}
/* NOTE: pcode for alias context is generated in
* hb_compExprUseAliasVar()
*/
break;
case HB_EA_POP_PCODE:
if( pSelf->value.asMacro.pExprList )
{
/* macro expression: &( expressions_list )
* NOTE: only the last expression will be macro-compiled
*/
HB_EXPR_USE( pSelf->value.asMacro.pExprList, HB_EA_PUSH_PCODE );
}
else
{
if( pSelf->value.asMacro.cMacroOp )
{
/* simple macro variable expansion: &variable
* 'szMacro' is a variable name
*/
HB_GEN_FUNC2( PushVar, pSelf->value.asMacro.szMacro, TRUE );
}
else
{
/* complex macro expression: prefix&var.suffix
* all components should be placed as a string that will
* be compiled after text susbstitution
*/
/* Check if macrotext variable does not refer to
* local, static or field.
*/
#if ! defined( HB_MACRO_SUPPORT )
hb_compIsValidMacroText( HB_COMP_PARAM,
pSelf->value.asMacro.szMacro,
strlen( pSelf->value.asMacro.szMacro ) );
#endif
HB_GEN_FUNC2( PushString, pSelf->value.asMacro.szMacro, strlen( pSelf->value.asMacro.szMacro ) + 1 );
}
}
/* compile & run - macro compiler will generate pcode to pop a value
* from the eval stack
*/
if( pSelf->value.asMacro.SubType != HB_ET_MACRO_ALIASED )
{
HB_GEN_FUNC1( PCode1, HB_P_MACROPOP );
/* Always add byte to pcode indicating requested macro compiler flag. */
HB_GEN_FUNC1( PCode1, ( BYTE ) HB_MACRO_GENFLAGS );
}
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
break;
case HB_EA_DELETE:
if( pSelf->value.asMacro.pExprList )
HB_COMP_EXPR_DELETE( pSelf->value.asMacro.pExprList );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseFunCall )
{
switch( iMessage )
{
case HB_EA_REDUCE:
/* Reduce the expressions on the list of arguments
*/
if( pSelf->value.asFunCall.pParms )
pSelf->value.asFunCall.pParms = HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_REDUCE );
if( pSelf->value.asFunCall.pFunName->ExprType == HB_ET_FUNNAME )
{
HB_EXPR_PTR pName = pSelf->value.asFunCall.pFunName;
HB_EXPR_PTR pParms = pSelf->value.asFunCall.pParms;
USHORT usCount = ( USHORT ) hb_compExprParamListLen( pParms );
#ifndef HB_MACRO_SUPPORT
if( hb_compFunCallCheck( HB_COMP_PARAM, pName->value.asSymbol, usCount ) )
#endif
{
if( strcmp( "AT", pName->value.asSymbol ) == 0 )
{
if( usCount == 2 )
hb_compExprReduceAT( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "ASC", pName->value.asSymbol ) == 0 )
{
if( usCount )
hb_compExprReduceASC( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "CHR", pName->value.asSymbol ) == 0 )
{
if( usCount )
hb_compExprReduceCHR( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "LEN", pName->value.asSymbol ) == 0 )
{
if( usCount )
hb_compExprReduceLEN( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "UPPER", pName->value.asSymbol ) == 0 )
{
if( usCount )
hb_compExprReduceUPPER( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "EMPTY", pName->value.asSymbol ) == 0 )
{
if( usCount && HB_SUPPORT_HARBOUR )
hb_compExprReduceEMPTY( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "INT", pName->value.asSymbol ) == 0 )
{
if( usCount == 1 && HB_SUPPORT_HARBOUR )
hb_compExprReduceINT( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "MIN", pName->value.asSymbol ) == 0 )
{
if( usCount == 2 && HB_SUPPORT_HARBOUR )
hb_compExprReduceMIN( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "MAX", pName->value.asSymbol ) == 0 )
{
if( usCount == 2 && HB_SUPPORT_HARBOUR )
hb_compExprReduceMAX( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "STOD", pName->value.asSymbol ) == 0 ||
strcmp( "HB_STOD", pName->value.asSymbol ) == 0 )
{
if( usCount < 2 && HB_SUPPORT_HARBOUR )
hb_compExprReduceSTOD( pSelf, usCount, HB_COMP_PARAM );
}
else if( strcmp( "HB_STOT", pName->value.asSymbol ) == 0 )
{
hb_compExprReduceSTOT( pSelf, usCount, HB_COMP_PARAM );
}
else if( strcmp( "DTOS", pName->value.asSymbol ) == 0 )
{
if( usCount == 1 )
hb_compExprReduceDTOS( pSelf, HB_COMP_PARAM );
}
else if( strcmp( "CTOD", pName->value.asSymbol ) == 0 )
{
if( usCount && HB_SUPPORT_HARBOUR )
hb_compExprReduceCTOD( pSelf, HB_COMP_PARAM );
}
else if( strncmp( "HB_BIT", pName->value.asSymbol, 6 ) == 0 &&
usCount && pParms->value.asList.pExprList->ExprType == HB_ET_NUMERIC )
{
HB_EXPR_PTR pArg = pParms->value.asList.pExprList;
HB_LONG lResult = 0;
HB_BOOL fOptimize = FALSE, fBool = FALSE;
if( usCount >= 2 )
{
if( pArg->pNext->ExprType == HB_ET_NUMERIC )
{
if( strcmp( "AND", pName->value.asSymbol + 6 ) == 0 )
{
fOptimize = TRUE;
lResult = hb_compExprAsLongNum( pArg );
while( --usCount )
{
pArg = pArg->pNext;
if( pArg->ExprType != HB_ET_NUMERIC )
{
fOptimize = FALSE;
break;
}
lResult &= hb_compExprAsLongNum( pArg );
}
}
else if( strcmp( "OR", pName->value.asSymbol + 6 ) == 0 )
{
fOptimize = TRUE;
lResult = hb_compExprAsLongNum( pArg );
while( --usCount )
{
pArg = pArg->pNext;
if( pArg->ExprType != HB_ET_NUMERIC )
{
fOptimize = FALSE;
break;
}
lResult |= hb_compExprAsLongNum( pArg );
}
}
else if( strcmp( "XOR", pName->value.asSymbol + 6 ) == 0 )
{
fOptimize = TRUE;
lResult = hb_compExprAsLongNum( pArg );
while( --usCount )
{
pArg = pArg->pNext;
if( pArg->ExprType != HB_ET_NUMERIC )
{
fOptimize = FALSE;
break;
}
lResult ^= hb_compExprAsLongNum( pArg );
}
}
else if( strcmp( "TEST", pName->value.asSymbol + 6 ) == 0 )
{
HB_LONG lBit = hb_compExprAsLongNum( pArg->pNext );
lResult = ( hb_compExprAsLongNum( pArg ) &
( ( HB_LONG ) 1 << lBit ) ) != 0;
fOptimize = fBool = TRUE;
}
else if( strcmp( "SET", pName->value.asSymbol + 6 ) == 0 )
{
HB_LONG lBit = hb_compExprAsLongNum( pArg->pNext );
lResult = hb_compExprAsLongNum( pArg ) |
( ( HB_LONG ) 1 << lBit );
fOptimize = TRUE;
}
else if( strcmp( "RESET", pName->value.asSymbol + 6 ) == 0 )
{
HB_LONG lBit = hb_compExprAsLongNum( pArg->pNext );
lResult = hb_compExprAsLongNum( pArg ) &
( ~ ( ( HB_LONG ) 1 << lBit ) );
fOptimize = TRUE;
}
else if( strcmp( "SHIFT", pName->value.asSymbol + 6 ) == 0 )
{
HB_LONG lBits = hb_compExprAsLongNum( pArg->pNext );
lResult = hb_compExprAsLongNum( pArg );
if( lBits < 0 )
lResult >>= -lBits;
else
lResult <<= lBits;
fOptimize = TRUE;
}
}
}
else if( strcmp( "NOT", pName->value.asSymbol + 6 ) == 0 )
{
lResult = ~hb_compExprAsLongNum( pArg );
fOptimize = TRUE;
}
if( fOptimize )
hb_compExprReduceBitFunc( pSelf, lResult, fBool, HB_COMP_PARAM );
}
#ifndef HB_MACRO_SUPPORT
else if( strncmp( "HB_I18N_", pName->value.asSymbol, 8 ) == 0 )
{
HB_EXPR_PTR pArg = pParms->value.asList.pExprList, pCount = NULL;
HB_BOOL fStrict, fNoop, fPlural, fI18nFunc;
ULONG ulPos = 8;
fStrict = fNoop = fPlural = fI18nFunc = FALSE;
if( pName->value.asSymbol[ ulPos ] == 'N' )
{
fPlural = TRUE;
ulPos++;
}
if( strncmp( "GETTEXT", &pName->value.asSymbol[ ulPos ], 7 ) == 0 )
{
ulPos += 7;
if( strncmp( "_STRICT", &pName->value.asSymbol[ ulPos ], 7 ) == 0 )
{
ulPos += 7;
fStrict = TRUE;
}
else if( strncmp( "_NOOP", &pName->value.asSymbol[ ulPos ], 5 ) == 0 )
{
ulPos += 5;
fNoop = TRUE;
}
if( !pName->value.asSymbol[ ulPos ] || pName->value.asSymbol[ ulPos ] == '_' )
fI18nFunc = TRUE;
}
if( fI18nFunc )
{
int iWarning = 0;
HB_EXPR_PTR pBadParam = NULL;
const char * szExpect = NULL;
const char * szContext = NULL;
if( fPlural && usCount )
{
pCount = pArg;
pArg = pArg->pNext;
--usCount;
if( pCount->ExprType <= HB_ET_FUNREF &&
pCount->ExprType != HB_ET_NUMERIC )
{
iWarning = HB_COMP_WARN_PARAM_TYPE;
pBadParam = pCount;
szExpect = "Numeric expression";
}
}
if( usCount == 2 )
{
if( pArg->pNext->ExprType == HB_ET_STRING && pArg->pNext->ulLength > 0 )
{
szContext = pArg->pNext->value.asString.string;
--usCount;
}
else
{
iWarning = HB_COMP_WARN_PARAM_TYPE;
pBadParam = pArg->pNext;
szExpect = "String";
}
}
if( iWarning == 0 )
{
const char * szPlurals[ HB_I18N_PLURAL_MAX ];
if( usCount == 1 )
{
if( pArg->ExprType == HB_ET_STRING )
{
if( HB_COMP_PARAM->fI18n && pArg->ulLength > 0 )
{
if( pCount )
{
szPlurals[ 0 ] = pArg->value.asString.string;
hb_compI18nAddPlural( HB_COMP_PARAM, szPlurals, 1, szContext,
HB_COMP_PARAM->currModule, HB_COMP_PARAM->currLine );
}
else
hb_compI18nAdd( HB_COMP_PARAM, pArg->value.asString.string, szContext,
HB_COMP_PARAM->currModule, HB_COMP_PARAM->currLine );
}
}
else if( pCount && pArg->ExprType == HB_ET_ARRAY &&
hb_compExprListTypeCheck( pArg, HB_ET_STRING ) )
{
if( HB_COMP_PARAM->fI18n )
{
ULONG ulLen = hb_compExprListLen( pArg ), ul;
HB_EXPR_PTR pArgExp = pArg->value.asList.pExprList;
if( ulLen > HB_I18N_PLURAL_MAX )
ulLen = HB_I18N_PLURAL_MAX;
for( ul = 0; ul < ulLen; ++ul )
{
szPlurals[ ul ] = pArgExp->value.asString.string;
pArgExp = pArgExp->pNext;
}
hb_compI18nAddPlural( HB_COMP_PARAM, szPlurals, ulLen, szContext,
HB_COMP_PARAM->currModule, HB_COMP_PARAM->currLine );
}
}
else if( fStrict || fNoop || pArg->ExprType <= HB_ET_FUNREF )
{
iWarning = HB_COMP_WARN_PARAM_TYPE;
pBadParam = pArg;
szExpect = fPlural ? "String or Array of Strings" : "String";
}
}
else
iWarning = HB_COMP_WARN_PARAM_COUNT;
}
if( iWarning != 0 )
{
/* TODO: warning message does not fit very well, because it requires
* type of used parameter. Let's print "unknown", to avoid deeper
* analysis of parameter.
*/
if( iWarning == HB_COMP_WARN_PARAM_TYPE )
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_PARAM_TYPE,
pBadParam && pBadParam->ExprType > HB_ET_NONE &&
pBadParam->ExprType <= HB_ET_FUNREF ?
hb_compExprDescription( pBadParam ) : "Unknown", szExpect );
else
{
char buf[ 16 ];
hb_snprintf( buf, sizeof( buf ), "%d", ( int ) usCount + ( pCount ? 1 : 0 ) + ( szContext ? 1 : 0 ) );
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_PARAM_COUNT, buf, fPlural ? "2 or 3" : "1 or 2" );
}
}
/* hb_i18n_gettext_noop() is not a real function. It is used to
force writing of string to .pot file. So, we should try to
replace function call by first argument regardless fI18n flag
and warnings.
*/
else if( fNoop && usCount )
{
pParms->value.asList.pExprList = pArg->pNext; /* skip first parameter */
pArg->pNext = NULL;
HB_COMP_EXPR_FREE( pParms );
HB_COMP_EXPR_FREE( pSelf->value.asFunCall.pFunName );
if( pCount )
{
if( pArg->ExprType == HB_ET_ARRAY )
{
if( hb_compExprListLen( pArg ) == 1 )
{
HB_COMP_EXPR_FREE( pCount );
pCount = pArg;
pArg = pArg->value.asList.pExprList;
pCount->value.asList.pExprList = NULL;
}
else
{
/* build expression: pArray[ iif( pCount == 1, 1, 2 ) ] */
HB_EXPR_PTR pIndex;
/* create pCount == 1 */
pIndex = hb_compExprSetOperand( hb_compExprNewEQ( pCount, HB_COMP_PARAM ),
hb_compExprNewLong( 1, HB_COMP_PARAM ), HB_COMP_PARAM );
/* create: ( pCount == 1, */
pIndex = hb_compExprNewList( pIndex, HB_COMP_PARAM );
/* create: ( pCount == 1, 1, */
pIndex = hb_compExprAddListExpr( pIndex, hb_compExprNewLong( 1, HB_COMP_PARAM ) );
/* create: ( pCount == 1, 1, 2 )*/
pIndex = hb_compExprAddListExpr( pIndex, hb_compExprNewLong( 2, HB_COMP_PARAM ) );
/* create: IIF() expression */
pIndex = hb_compExprNewIIF( pIndex );
/* create: pArray[ iif( pCount == 1, 1, 2 ) ] */
pArg = hb_compExprNewArrayAt( pArg, pIndex, HB_COMP_PARAM );
/* reduce the final expression */
pArg = HB_EXPR_USE( pArg, HB_EA_REDUCE );
pCount = NULL;
}
}
if( pCount )
HB_COMP_EXPR_FREE( pCount );
}
memcpy( pSelf, pArg, sizeof( HB_EXPR ) );
/* free pArg expression body but without freeing its subexpressions */
HB_COMP_EXPR_CLEAR( pArg );
}
}
}
#endif
}
}
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
{
HB_BOOL fArgsList = FALSE;
USHORT usCount = 0;
if( pSelf->value.asFunCall.pFunName->ExprType == HB_ET_FUNNAME )
{
HB_GEN_FUNC1( PushFunCall, pSelf->value.asFunCall.pFunName->value.asSymbol );
}
else
{
HB_EXPR_USE( pSelf->value.asFunCall.pFunName, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_PUSHNIL );
}
/* NOTE: pParms will be NULL in 'DO procname' (if there is
* no WITH keyword)
*/
if( pSelf->value.asFunCall.pParms )
{
usCount = ( USHORT ) hb_compExprParamListCheck( HB_COMP_PARAM, pSelf->value.asFunCall.pParms );
fArgsList = pSelf->value.asFunCall.pParms->ExprType == HB_ET_MACROARGLIST;
if( usCount )
HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_PUSH_PCODE );
}
if( fArgsList )
{
HB_GEN_FUNC3( PCode3, HB_P_MACROFUNC, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) );
/* restore original expression type */
pSelf->value.asFunCall.pParms->ExprType = HB_ET_ARGLIST;
}
else if( usCount > 255 )
HB_GEN_FUNC3( PCode3, HB_P_FUNCTION, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) );
else
HB_GEN_FUNC2( PCode2, HB_P_FUNCTIONSHORT, ( BYTE ) usCount );
break;
}
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
{
HB_BOOL fArgsList = FALSE;
USHORT usCount = 0;
if( pSelf->value.asFunCall.pFunName->ExprType == HB_ET_FUNNAME )
{
HB_GEN_FUNC1( PushFunCall, pSelf->value.asFunCall.pFunName->value.asSymbol );
}
else
{
HB_EXPR_USE( pSelf->value.asFunCall.pFunName, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_PUSHNIL );
}
if( pSelf->value.asFunCall.pParms )
{
usCount = ( USHORT ) hb_compExprParamListCheck( HB_COMP_PARAM, pSelf->value.asFunCall.pParms );
fArgsList = pSelf->value.asFunCall.pParms->ExprType == HB_ET_MACROARGLIST;
if( usCount )
HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_PUSH_PCODE );
}
if( fArgsList )
{
HB_GEN_FUNC3( PCode3, HB_P_MACRODO, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) );
/* restore original expression type */
pSelf->value.asFunCall.pParms->ExprType = HB_ET_ARGLIST;
}
else if( usCount > 255 )
HB_GEN_FUNC3( PCode3, HB_P_DO, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) );
else
HB_GEN_FUNC2( PCode2, HB_P_DOSHORT, ( BYTE ) usCount );
break;
}
case HB_EA_DELETE:
if( pSelf->value.asFunCall.pParms )
HB_COMP_EXPR_DELETE( pSelf->value.asFunCall.pParms );
HB_COMP_EXPR_DELETE( pSelf->value.asFunCall.pFunName );
break;
}
return pSelf;
}
/* handler for expression->identifier syntax
*/
static HB_EXPR_FUNC( hb_compExprUseAliasVar )
{
HB_TRACE(HB_TR_DEBUG, ("hb_compExprUseAliasVar()"));
switch( iMessage )
{
case HB_EA_REDUCE:
/* NOTE: direct reduction not used for HB_ET_LIST to avoid
* list stripping before PUSH/POP operations
*/
if( pSelf->value.asAlias.pAlias->ExprType == HB_ET_LIST )
{
pSelf->value.asAlias.pAlias = hb_compExprReduceList(
pSelf->value.asAlias.pAlias, HB_COMP_PARAM );
if( HB_SUPPORT_EXTOPT &&
pSelf->value.asAlias.pAlias->value.asList.pExprList->ExprType == HB_ET_STRING &&
pSelf->value.asAlias.pAlias->value.asList.pExprList->pNext == NULL )
{
pSelf->value.asAlias.pAlias = hb_compExprReduceAliasString(
pSelf->value.asAlias.pAlias,
pSelf->value.asAlias.pAlias->value.asList.pExprList,
HB_COMP_PARAM );
}
}
else
pSelf->value.asAlias.pAlias = HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_REDUCE );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
{
HB_EXPR_PTR pAlias = pSelf->value.asAlias.pAlias;
if( pAlias->ExprType == HB_ET_MACRO ||
pSelf->value.asAlias.pVar->ExprType == HB_ET_MACRO )
{
/* Macro operator is used on the left or right side of an alias
* operator - handle it with a special care
*/
HB_EXPR_PCODE2( hb_compExprUseAliasMacro, pSelf, HB_EA_PUSH_PCODE );
}
else if( pAlias->ExprType == HB_ET_ALIAS )
{
/*
* myalias->var
* FIELD->var
* MEMVAR->var
*
* NOTE: TRUE = push also alias
*/
HB_GEN_FUNC4( PushAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, TRUE, pAlias->value.asSymbol, 0 );
}
else if( pAlias->ExprType == HB_ET_NUMERIC )
{
/* numeric alias
* 2->var
*
* NOTE: only integer (long) values are allowed
*/
if( pAlias->value.asNum.NumType == HB_ET_LONG )
HB_GEN_FUNC4( PushAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, TRUE, NULL, pAlias->value.asNum.val.l );
else
hb_compErrorAlias( HB_COMP_PARAM, pAlias );
}
else if( pAlias->ExprType == HB_ET_LIST )
{
/*
* ( expression )->var
*
* NOTE: FALSE = don't push alias value
*/
HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE );
HB_GEN_FUNC4( PushAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, FALSE, NULL, 0 );
}
else
hb_compErrorAlias( HB_COMP_PARAM, pAlias );
break;
}
case HB_EA_POP_PCODE:
{
HB_EXPR_PTR pAlias = pSelf->value.asAlias.pAlias;
if( pAlias->ExprType == HB_ET_MACRO || pSelf->value.asAlias.pVar->ExprType == HB_ET_MACRO )
{
/* Macro operator is used on the left or right side of an alias
* operator - handle it with a special care
* (we need convert to a string the whole expression)
*/
HB_EXPR_PCODE2( hb_compExprUseAliasMacro, pSelf, HB_EA_POP_PCODE );
}
else if( pAlias->ExprType == HB_ET_ALIAS )
{
/*
* myalias->var
* FIELD->var
* MEMVAR->var
*/
HB_GEN_FUNC4( PopAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, TRUE, pAlias->value.asSymbol, 0 );
}
else if( pAlias->ExprType == HB_ET_NUMERIC )
{
/* numeric alias
* 2->var
*
* NOTE: only integer (long) values are allowed
*/
if( pAlias->value.asNum.NumType == HB_ET_LONG )
HB_GEN_FUNC4( PopAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, TRUE, NULL, pAlias->value.asNum.val.l );
else
hb_compErrorAlias( HB_COMP_PARAM, pAlias );
}
else if( pAlias->ExprType == HB_ET_LIST )
{
/*
* ( expression )->var
*
* NOTE: FALSE = don't push alias value
*/
HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE );
HB_GEN_FUNC4( PopAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, FALSE, NULL, 0 );
}
else
hb_compErrorAlias( HB_COMP_PARAM, pAlias );
break;
}
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
break;
case HB_EA_DELETE:
HB_COMP_EXPR_DELETE( pSelf->value.asAlias.pAlias );
if( pSelf->value.asAlias.pVar )
HB_COMP_EXPR_DELETE( pSelf->value.asAlias.pVar );
break;
}
return pSelf;
}
/* handler for expression->( exression, ... ) syntax
*/
static HB_EXPR_FUNC( hb_compExprUseAliasExpr )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asAlias.pAlias = HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_REDUCE );
pSelf->value.asAlias.pExpList = HB_EXPR_USE( pSelf->value.asAlias.pExpList, HB_EA_REDUCE );
if( HB_SUPPORT_EXTOPT && pSelf->value.asAlias.pAlias->ExprType == HB_ET_STRING )
pSelf->value.asAlias.pAlias = hb_compExprReduceAliasString(
pSelf->value.asAlias.pAlias,
pSelf->value.asAlias.pAlias, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
/* save currently selected workarea
*/
HB_GEN_FUNC1( PCode1, HB_P_PUSHALIAS );
/* push the expression that will return a new workarea
*/
HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_PUSH_PCODE );
/* pop the value from the stack and select it as current workarea
*/
HB_GEN_FUNC1( PCode1, HB_P_POPALIAS );
/* evaluate any expression
*/
HB_EXPR_USE( pSelf->value.asAlias.pExpList, HB_EA_PUSH_PCODE );
/* swap the two last items on the eval stack: one item is a
* value returned by evaluated expression and the second item
* is previously selected workarea. After swaping select again
* the restored workarea.
*/
HB_GEN_FUNC1( PCode1, HB_P_SWAPALIAS );
break;
case HB_EA_POP_PCODE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
/* save currently selected workarea
*/
HB_GEN_FUNC1( PCode1, HB_P_PUSHALIAS );
/* push the expression that will return a new workarea
*/
HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_PUSH_PCODE );
/* pop the value from the stack and select it as current workarea
*/
HB_GEN_FUNC1( PCode1, HB_P_POPALIAS );
/* evaluate any expression - it will not leave any return
* value on the eval stack
*/
HB_EXPR_USE( pSelf->value.asAlias.pExpList, HB_EA_PUSH_POP );
/* Pop and select again the restored workarea.
*/
HB_GEN_FUNC1( PCode1, HB_P_POPALIAS );
break;
case HB_EA_DELETE:
HB_COMP_EXPR_DELETE( pSelf->value.asAlias.pAlias );
HB_COMP_EXPR_DELETE( pSelf->value.asAlias.pExpList );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseAlias )
{
switch( iMessage )
{
case HB_EA_REDUCE:
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC2( PushSymbol, pSelf->value.asSymbol, HB_SYM_ALIAS );
break;
case HB_EA_POP_PCODE:
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
break;
case HB_EA_DELETE:
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseFunName )
{
switch( iMessage )
{
case HB_EA_REDUCE:
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
HB_GEN_FUNC1( PushFunSym, pSelf->value.asSymbol );
break;
case HB_EA_POP_PCODE:
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
case HB_EA_DELETE:
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseRTVariable )
{
switch( iMessage )
{
case HB_EA_REDUCE:
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
if( pSelf->value.asRTVar.szName )
HB_GEN_FUNC2( PushSymbol, pSelf->value.asRTVar.szName, HB_SYM_MEMVAR ); /* this is not a function */
else
HB_EXPR_USE( pSelf->value.asRTVar.pMacro, HB_EA_PUSH_PCODE );
break;
case HB_EA_POP_PCODE:
if( pSelf->value.asRTVar.szName )
HB_GEN_FUNC1( PopMemvar, pSelf->value.asRTVar.szName );
else
HB_EXPR_USE( pSelf->value.asRTVar.pMacro, HB_EA_POP_PCODE );
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
break;
case HB_EA_DELETE:
#if ! defined( HB_MACRO_SUPPORT )
if( ! pSelf->value.asRTVar.szName )
HB_COMP_EXPR_DELETE( pSelf->value.asRTVar.pMacro );
#endif
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseVariable )
{
switch( iMessage )
{
case HB_EA_REDUCE:
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
#if defined( HB_MACRO_SUPPORT )
{
/* NOTE: When the following syntax is used:
* ( any_expr )->&var2
* then macro compiler is compiling the right side of alias
* operator only (if 'any_expr' is not a string) - an alias value
* is placed on the eval stack before macro compilation.
* The HB_MACRO_GEN_ALIASED flag is used to signal that we have to
* genearate alias aware pcode even if we known a variable part only.
*/
if( HB_MACRO_DATA->Flags & HB_MACRO_GEN_ALIASED )
HB_GEN_FUNC4( PushAliasedVar, pSelf->value.asSymbol, FALSE, NULL, 0 );
else
HB_GEN_FUNC2( PushVar, pSelf->value.asSymbol, FALSE );
}
#else
HB_GEN_FUNC2( PushVar, pSelf->value.asSymbol, FALSE );
#endif
break;
case HB_EA_POP_PCODE:
#if defined( HB_MACRO_SUPPORT )
{
if( HB_MACRO_DATA->Flags & HB_MACRO_GEN_ALIASED )
HB_GEN_FUNC4( PopAliasedVar, pSelf->value.asSymbol, FALSE, NULL, 0 );
else
HB_GEN_FUNC1( PopVar, pSelf->value.asSymbol );
}
#else
HB_GEN_FUNC1( PopVar, pSelf->value.asSymbol );
#endif
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_GEN_FUNC2( PushVar, pSelf->value.asSymbol, FALSE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
break;
case HB_EA_DELETE:
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseSend )
{
switch( iMessage )
{
case HB_EA_REDUCE:
/* Clipper does not reduce object expressions */
if( HB_SUPPORT_HARBOUR && pSelf->value.asMessage.pObject )
pSelf->value.asMessage.pObject = HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_REDUCE );
if( pSelf->value.asMessage.pParms ) /* Is it a method call ? */
pSelf->value.asMessage.pParms = HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_REDUCE );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
if( pSelf->value.asMessage.pParms )
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
if( pSelf->value.asMessage.pParms ) /* Is it a method call ? */
{
HB_BOOL fArgsList = FALSE;
int iParms = ( int ) hb_compExprParamListCheck( HB_COMP_PARAM, pSelf->value.asMessage.pParms );
hb_compExprPushSendPush( pSelf, HB_COMP_PARAM );
if( iParms )
{
HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE );
fArgsList = pSelf->value.asMessage.pParms->ExprType == HB_ET_MACROARGLIST;
}
if( fArgsList )
{
HB_GEN_FUNC3( PCode3, HB_P_MACROSEND, HB_LOBYTE( iParms ), HB_HIBYTE( iParms ) );
/* restore original expression type */
pSelf->value.asMessage.pParms->ExprType = HB_ET_ARGLIST;
}
else if( iParms > 255 )
HB_GEN_FUNC3( PCode3, HB_P_SEND, HB_LOBYTE( iParms ), HB_HIBYTE( iParms ) );
else
HB_GEN_FUNC2( PCode2, HB_P_SENDSHORT, ( BYTE ) iParms );
}
else
{
/* acces to instance variable */
hb_compExprPushSendPush( pSelf, HB_COMP_PARAM );
HB_GEN_FUNC2( PCode2, HB_P_SENDSHORT, 0 );
}
break;
case HB_EA_POP_PCODE:
hb_compExprPushSendPop( pSelf, HB_COMP_PARAM );
if( pSelf->value.asMessage.pParms )
{
HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE );
}
else
{
/* executed from macro compiler */
HB_GEN_FUNC2( PCode2, HB_P_SWAP, 1 );
HB_GEN_FUNC2( PCode2, HB_P_SWAP, 1 );
}
HB_GEN_FUNC2( PCode2, HB_P_SENDSHORT, 1 );
if( !pSelf->value.asMessage.pParms )
HB_GEN_FUNC1( PCode1, HB_P_POP );
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
if( ! pSelf->value.asMessage.pParms ) /* Is it a method call ? */
{
/* instance variable */
/* QUESTION: This warning can be misleading if nested messages
* are used, e.g. a:b():c - should we generate it ?
*/
hb_compWarnMeaningless( HB_COMP_PARAM, pSelf );
}
break;
case HB_EA_DELETE:
{
if( pSelf->value.asMessage.pObject )
{
HB_COMP_EXPR_DELETE( pSelf->value.asMessage.pObject );
}
if( pSelf->value.asMessage.pParms )
{
HB_COMP_EXPR_DELETE( pSelf->value.asMessage.pParms );
}
if( pSelf->value.asMessage.pMessage )
{
HB_COMP_EXPR_DELETE( pSelf->value.asMessage.pMessage );
}
}
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUsePostInc )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushPostOp, pSelf, HB_P_INC );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
/* a++ used standalone as a statement is the same as ++a
*/
HB_EXPR_PCODE2( hb_compExprUsePreOp, pSelf, HB_P_INC );
break;
case HB_EA_DELETE:
if( pSelf->value.asOperator.pLeft )
HB_COMP_EXPR_DELETE( pSelf->value.asOperator.pLeft );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUsePostDec )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushPostOp, pSelf, HB_P_DEC );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUsePreOp, pSelf, HB_P_DEC );
break;
case HB_EA_DELETE:
if( pSelf->value.asOperator.pLeft )
HB_COMP_EXPR_DELETE( pSelf->value.asOperator.pLeft );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseAssign )
{
switch( iMessage )
{
case HB_EA_REDUCE:
{
HB_EXPR_PTR pExpr;
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
/* optimize:
* var := var <op> <exp>
* to:
* var <op>= <exp>
*/
pExpr = pSelf->value.asOperator.pRight;
if( HB_SUPPORT_HARBOUR &&
pSelf->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE &&
( pExpr->ExprType == HB_EO_PLUS || pExpr->ExprType == HB_EO_MINUS ||
pExpr->ExprType == HB_EO_MULT || pExpr->ExprType == HB_EO_DIV ||
pExpr->ExprType == HB_EO_MOD || pExpr->ExprType == HB_EO_POWER ) &&
pExpr->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE &&
strcmp( pSelf->value.asOperator.pLeft->value.asSymbol,
pExpr->value.asOperator.pLeft->value.asSymbol ) == 0 )
{
/* NOTE: direct type change */
switch( pExpr->ExprType )
{
case HB_EO_PLUS:
pSelf->ExprType = HB_EO_PLUSEQ;
break;
case HB_EO_MINUS:
pSelf->ExprType = HB_EO_MINUSEQ;
break;
case HB_EO_MULT:
pSelf->ExprType = HB_EO_MULTEQ;
break;
case HB_EO_DIV:
pSelf->ExprType = HB_EO_DIVEQ;
break;
case HB_EO_MOD:
pSelf->ExprType = HB_EO_MODEQ;
break;
case HB_EO_POWER:
pSelf->ExprType = HB_EO_EXPEQ;
break;
}
pSelf->value.asOperator.pRight = pExpr->value.asOperator.pRight;
pExpr->value.asOperator.pRight = NULL;
HB_COMP_EXPR_FREE( pExpr );
}
break;
}
case HB_EA_ARRAY_AT:
case HB_EA_ARRAY_INDEX:
case HB_EA_LVALUE:
break;
case HB_EA_PUSH_PCODE:
/* NOTE: assigment to an object instance variable needs special handling
*/
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
{
HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft;
pObj->value.asMessage.pParms = pSelf->value.asOperator.pRight;
HB_EXPR_USE( pObj, HB_EA_POP_PCODE );
pObj->value.asMessage.pParms = NULL; /* to suppress duplicated releasing */
}
else
{
/* it assigns a value and leaves it on the stack */
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
/* QUESTION: Can we replace DUPLICATE+POP with a single PUT opcode
*/
HB_GEN_FUNC1( PCode1, HB_P_PUSHUNREF );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE );
}
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
/* NOTE: assigment to an object instance variable needs special handling
*/
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
{
HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft;
pObj->value.asMessage.pParms = pSelf->value.asOperator.pRight;
HB_EXPR_USE( pObj, HB_EA_POP_PCODE );
pObj->value.asMessage.pParms = NULL; /* to suppress duplicated releasing */
/* Remove the return value */
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
else
{
/* it assigns a value and removes it from the stack */
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE );
}
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUsePlusEq )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushOperEq, pSelf, HB_P_PLUS );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUseOperEq, pSelf, HB_P_PLUS );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseMinusEq )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushOperEq, pSelf, HB_P_MINUS );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUseOperEq, pSelf, HB_P_MINUS );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseMultEq )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushOperEq, pSelf, HB_P_MULT );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUseOperEq, pSelf, HB_P_MULT );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseDivEq )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushOperEq, pSelf, HB_P_DIVIDE );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUseOperEq, pSelf, HB_P_DIVIDE );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseModEq )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushOperEq, pSelf, HB_P_MODULUS );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUseOperEq, pSelf, HB_P_MODULUS );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseExpEq )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushOperEq, pSelf, HB_P_POWER );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUseOperEq, pSelf, HB_P_POWER );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseOr )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceOr( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf );
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_SHORTCUTS ) )
{
LONG lEndPos;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_DUPLICATE );
lEndPos = HB_GEN_FUNC1( JumpTrue, 0 );
HB_GEN_FUNC1( PCode1, HB_P_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( JumpHere, lEndPos );
}
else
{
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_OR );
}
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_SHORTCUTS ) )
{
LONG lEndPos;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
lEndPos = HB_GEN_FUNC1( JumpTrue, 0 );
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
#if defined( HB_MACRO_SUPPORT )
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
#else
{
HB_BOOL fMeaningful = HB_COMP_PARAM->fMeaningful;
/* do not generate warning about meaningless expression usage */
HB_COMP_PARAM->fMeaningful = TRUE;
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
HB_COMP_PARAM->fMeaningful = fMeaningful;
}
#endif
HB_GEN_FUNC1( JumpHere, lEndPos );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseAnd )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceAnd( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf );
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_SHORTCUTS ) )
{
LONG lEndPos;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_DUPLICATE );
lEndPos = HB_GEN_FUNC1( JumpFalse, 0 );
HB_GEN_FUNC1( PCode1, HB_P_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( JumpHere, lEndPos );
}
else
{
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_AND );
}
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_SHORTCUTS ) )
{
LONG lEndPos;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
lEndPos = HB_GEN_FUNC1( JumpFalse, 0 );
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
#if defined( HB_MACRO_SUPPORT )
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
#else
{
HB_BOOL fMeaningful = HB_COMP_PARAM->fMeaningful;
/* do not generate warning about meaningless expression usage */
HB_COMP_PARAM->fMeaningful = TRUE;
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
HB_COMP_PARAM->fMeaningful = fMeaningful;
}
#endif
HB_GEN_FUNC1( JumpHere, lEndPos );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseNot )
{
switch( iMessage )
{
case HB_EA_REDUCE:
{
HB_EXPR_PTR pExpr;
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pExpr = pSelf->value.asOperator.pLeft;
if( pExpr->ExprType == HB_ET_LOGICAL )
{
pExpr->value.asLogical = ! pExpr->value.asLogical;
pSelf->ExprType = HB_ET_NONE; /* do not delete operator parameter - we are still using it */
HB_COMP_EXPR_DELETE( pSelf );
pSelf = pExpr;
}
else if( pExpr->ExprType == HB_EO_NOT && HB_SUPPORT_EXTOPT )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
pExpr->ExprType = HB_ET_NONE; /* do not delete operator parameter - we are still using it */
pExpr = pExpr->value.asOperator.pLeft;
HB_COMP_EXPR_DELETE( pSelf );
pSelf = pExpr;
}
break;
}
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
hb_compErrorIndex( HB_COMP_PARAM, pSelf );
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_NOT );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_COMP_EXPR_DELETE( pSelf->value.asOperator.pLeft );
break;
}
return pSelf;
}
/* handler for = operator
*/
static HB_EXPR_FUNC( hb_compExprUseEqual )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceEQ( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_EQUAL );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
/* handler for == operator
*/
static HB_EXPR_FUNC( hb_compExprUseEQ )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceEQ( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_EXACTLYEQUAL );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseLT )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceLT( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_LESS );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseGT )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceGT( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_GREATER );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseLE )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceLE( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_LESSEQUAL );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseGE )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceGE( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_GREATEREQUAL );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseNE )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceNE( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_NOTEQUAL );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseIN )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceIN( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_INSTRING );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUsePlus )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReducePlus( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
if( HB_SUPPORT_EXTOPT )
{
HB_EXPR_PTR pLeft, pRight;
pLeft = pSelf->value.asOperator.pLeft;
pRight = pSelf->value.asOperator.pRight;
if( pLeft->ExprType == HB_ET_NUMERIC )
{
if( pLeft->value.asNum.NumType == HB_ET_LONG ?
pLeft->value.asNum.val.l == 1 :
pLeft->value.asNum.val.d == 1 )
{
HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_INC );
break;
}
else if( pLeft->value.asNum.NumType == HB_ET_LONG ?
pLeft->value.asNum.val.l == -1 :
pLeft->value.asNum.val.d == -1 )
{
HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_DEC );
break;
}
}
else if( pRight->ExprType == HB_ET_NUMERIC )
{
if( pRight->value.asNum.NumType == HB_ET_LONG ?
pRight->value.asNum.val.l == 1 :
pRight->value.asNum.val.d == 1 )
{
HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_INC );
break;
}
else if( pRight->value.asNum.NumType == HB_ET_LONG ?
pRight->value.asNum.val.l == -1 :
pRight->value.asNum.val.d == -1 )
{
HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_DEC );
break;
}
}
}
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_PLUS );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseMinus )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceMinus( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
if( HB_SUPPORT_EXTOPT )
{
HB_EXPR_PTR pRight = pSelf->value.asOperator.pRight;
if( pRight->ExprType == HB_ET_NUMERIC )
{
if( pRight->value.asNum.NumType == HB_ET_LONG ?
pRight->value.asNum.val.l == 1 :
pRight->value.asNum.val.d == 1 )
{
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_DEC );
break;
}
else if( pRight->value.asNum.NumType == HB_ET_LONG ?
pRight->value.asNum.val.l == -1 :
pRight->value.asNum.val.d == -1 )
{
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_INC );
break;
}
}
}
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_MINUS );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseMult )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceMult( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_MULT );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseDiv )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf = hb_compExprReduceDiv( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_DIVIDE );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseMod )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
pSelf =hb_compExprReduceMod( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_MODULUS );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUsePower )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE );
if( HB_SUPPORT_HARBOUR ) /* Clipper doesn't optimize it */
pSelf =hb_compExprReducePower( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POWER );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
HB_EXPR_PCODE1( hb_compExprDelOperator, pSelf );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUseNegate )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
pSelf = hb_compExprReduceNegate( pSelf, HB_COMP_PARAM );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_NEGATE );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
if( HB_SUPPORT_HARBOUR )
{
/* NOTE: This will not generate a runtime error if incompatible
* data type is used
*/
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP );
}
else
{
HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
break;
case HB_EA_STATEMENT:
HB_COMP_ERROR_SYNTAX( pSelf );
break;
case HB_EA_DELETE:
if( pSelf->value.asOperator.pLeft )
HB_COMP_EXPR_DELETE( pSelf->value.asOperator.pLeft );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUsePreInc )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushPreOp, pSelf, HB_P_INC );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUsePreOp, pSelf, HB_P_INC );
break;
case HB_EA_DELETE:
if( pSelf->value.asOperator.pLeft )
HB_COMP_EXPR_DELETE( pSelf->value.asOperator.pLeft );
break;
}
return pSelf;
}
static HB_EXPR_FUNC( hb_compExprUsePreDec )
{
switch( iMessage )
{
case HB_EA_REDUCE:
pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE );
break;
case HB_EA_ARRAY_AT:
HB_COMP_ERROR_TYPE( pSelf );
break;
case HB_EA_ARRAY_INDEX:
break;
case HB_EA_LVALUE:
hb_compErrorLValue( HB_COMP_PARAM, pSelf );
break;
case HB_EA_PUSH_PCODE:
HB_EXPR_PCODE2( hb_compExprPushPreOp, pSelf, HB_P_DEC );
break;
case HB_EA_POP_PCODE:
break;
case HB_EA_PUSH_POP:
case HB_EA_STATEMENT:
HB_EXPR_PCODE2( hb_compExprUsePreOp, pSelf, HB_P_DEC );
break;
case HB_EA_DELETE:
if( pSelf->value.asOperator.pLeft )
HB_COMP_EXPR_DELETE( pSelf->value.asOperator.pLeft );
break;
}
return pSelf;
}
/* ************************************************************************* */
/* This generates a push pcode for a codeblock (with no macro expression or
with late evaluation of a macro)
*/
#if defined( HB_MACRO_SUPPORT )
static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_COMP_DECL )
#else
static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_COMP_DECL )
#endif
{
HB_EXPR_PTR pExpr, pNext;
HB_EXPR_PTR * pPrev;
/* Define requested local variables
*/
#if defined( HB_MACRO_SUPPORT )
hb_macroCodeBlockStart( HB_COMP_PARAM );
HB_PCODE_DATA->pLocals = pSelf->value.asCodeblock.pLocals;
HB_PCODE_DATA->fVParams =
( pSelf->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
#else
hb_compCodeBlockStart( HB_COMP_PARAM, bLateEval );
HB_COMP_PARAM->functions.pLast->fVParams =
( pSelf->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
{
HB_CBVAR_PTR pVar;
HB_COMP_PARAM->iVarScope = VS_PARAMETER;
pVar = pSelf->value.asCodeblock.pLocals;
while( pVar )
{
hb_compVariableAdd( HB_COMP_PARAM, pVar->szName, hb_compVarTypeNew( HB_COMP_PARAM, pVar->bType, NULL ) );
pVar =pVar->pNext;
}
}
HB_EXPR_PCODE0( hb_compLinePushIfDebugger );
#endif
pExpr = pSelf->value.asCodeblock.pExprList;
pPrev = &pSelf->value.asCodeblock.pExprList;
while( pExpr )
{
if( pExpr->ExprType == HB_ET_MACRO &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_SYMBOL &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_REFER &&
pExpr->value.asMacro.SubType != HB_ET_MACRO_ALIASED )
{
/* Clipper allows for list expressions in a codeblock
* macro := "1,2"
* EVAL( {|| &macro} )
*/
pExpr->value.asMacro.SubType |= HB_ET_MACRO_PARE;
}
/* store next expression in case the current will be reduced
* NOTE: During reduction the expression can be replaced by the
* new one - this will break the linked list of expressions.
*/
pNext = pExpr->pNext; /* store next expression in case the current will be reduced */
pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE );
/* Generate push/pop pcodes for all expresions except the last one
* The value of the last expression is used as a return value
* of a codeblock evaluation
*/
/* NOTE: This will genereate warnings if constant value is
* used as an expression - some operators will generate it too
* e.g.
* EVAL( {|| 3+5, func()} )
*/
*pPrev = pExpr; /* store a new expression into the previous one */
pExpr->pNext = pNext; /* restore the link to next expression */
#if defined( HB_MACRO_SUPPORT )
if( pNext )
HB_EXPR_USE( pExpr, HB_EA_PUSH_POP );
else
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
#else
if( pNext && bLateEval )
HB_EXPR_USE( pExpr, HB_EA_PUSH_POP );
else
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
#endif
pPrev = &pExpr->pNext;
pExpr = pNext;
}
#if defined( HB_MACRO_SUPPORT )
hb_macroCodeBlockEnd( HB_COMP_PARAM );
#else
if( bLateEval )
hb_compCodeBlockEnd( HB_COMP_PARAM );
else
hb_compCodeBlockRewind( HB_COMP_PARAM );
#endif
}
/* This generates a push pcode for early evaluation of a macro
*/
#if !defined( HB_MACRO_SUPPORT )
static void hb_compExprCodeblockExtPush( HB_EXPR_PTR pSelf, HB_COMP_DECL )
{
hb_compGenPCodeN( ( BYTE * ) pSelf->value.asCodeblock.string,
pSelf->ulLength, HB_COMP_PARAM );
}
static void hb_compExprCodeblockEarly( HB_EXPR_PTR pSelf, HB_COMP_DECL )
{
HB_EXPR_PTR pExpr;
/* check first expression */
pExpr = pSelf->value.asCodeblock.pExprList;
if( pExpr->ExprType == HB_ET_MACRO && pExpr->value.asMacro.cMacroOp )
{
/* simple macro variable expansion: &variable
* 'szMacro' is a variable name
* {|| &variable} => &( '{||' + variable +'}' )
*/
HB_EXPR_PTR pVar, pNew;
pVar = hb_compExprNewVar( pExpr->value.asMacro.szMacro, HB_COMP_PARAM );
pNew = hb_compExprNewString( "{||", 3, FALSE, HB_COMP_PARAM );
pNew = hb_compExprSetOperand( hb_compExprNewPlus( pNew, HB_COMP_PARAM ), pVar, HB_COMP_PARAM );
pNew = hb_compExprSetOperand( hb_compExprNewPlus( pNew, HB_COMP_PARAM ), hb_compExprNewString( "}", 1, FALSE, HB_COMP_PARAM ), HB_COMP_PARAM );
pNew = hb_compExprNewMacro( pNew, 0, NULL, HB_COMP_PARAM );
HB_EXPR_USE( pNew, HB_EA_PUSH_PCODE );
HB_COMP_EXPR_DELETE( pNew );
}
else
{
/* everything else is macro compiled at runtime
* {|| &variable+1} => &( '{|| &variable+1}' )
*/
HB_EXPR_PTR pNew;
hb_compExprCodeblockPush( pSelf, FALSE, HB_COMP_PARAM );
pNew = hb_compExprNewMacro( hb_compExprNewString( pSelf->value.asCodeblock.string, pSelf->ulLength, FALSE, HB_COMP_PARAM ), 0, NULL, HB_COMP_PARAM );
HB_EXPR_USE( pNew, HB_EA_PUSH_PCODE );
HB_COMP_EXPR_DELETE( pNew );
hb_compCodeBlockStop( HB_COMP_PARAM );
}
}
#endif /*HB_MACRO_SUPPORT*/
static void hb_compExprPushSendPop( HB_EXPR_PTR pSelf, HB_COMP_DECL )
{
if( pSelf->value.asMessage.pObject )
{
/* Push _message */
if( pSelf->value.asMessage.szMessage )
{
HB_GEN_FUNC2( MessageData, pSelf->value.asMessage.szMessage, TRUE );
}
else
{
if( pSelf->value.asMessage.pMessage->ExprType == HB_ET_MACRO )
/* o:&macro := value
* set ASSIGN flag in macro expression
* it's cleared just after use
*/
pSelf->value.asMessage.pMessage->value.asMacro.SubType |= HB_ET_MACRO_ASSIGN;
HB_EXPR_USE( pSelf->value.asMessage.pMessage, HB_EA_PUSH_PCODE );
}
/* Push object */
HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE );
}
else /* WITH OBJECT */
{
/* Push _message and object */
if( pSelf->value.asMessage.szMessage )
{
HB_GEN_FUNC2( MessageData, pSelf->value.asMessage.szMessage, FALSE );
}
else
{
if( pSelf->value.asMessage.pMessage->ExprType == HB_ET_MACRO )
/* o:&macro := value
* set ASSIGN flag in macro expression
* it's cleared just after use
*/
pSelf->value.asMessage.pMessage->value.asMacro.SubType |= HB_ET_MACRO_ASSIGN;
HB_EXPR_USE( pSelf->value.asMessage.pMessage, HB_EA_PUSH_PCODE );
/* Push object using WITHOBJECTMESSAGE pcode */
HB_GEN_FUNC2( Message, NULL, FALSE );
}
}
}
static void hb_compExprPushSendPush( HB_EXPR_PTR pSelf, HB_COMP_DECL )
{
if( pSelf->value.asMessage.pObject )
{
/* Push message */
if( pSelf->value.asMessage.szMessage )
{
HB_GEN_FUNC2( Message, pSelf->value.asMessage.szMessage, TRUE );
}
else
{
HB_EXPR_USE( pSelf->value.asMessage.pMessage, HB_EA_PUSH_PCODE );
}
/* Push object */
HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE );
}
else /* WITH OBJECT */
{
if( pSelf->value.asMessage.szMessage )
{
/* Push message and object */
HB_GEN_FUNC2( Message, pSelf->value.asMessage.szMessage, FALSE );
}
else
{
/* Push message */
HB_EXPR_USE( pSelf->value.asMessage.pMessage, HB_EA_PUSH_PCODE );
/* Push object using WITHOBJECTMESSAGE pcode */
HB_GEN_FUNC2( Message, NULL, FALSE );
}
}
}
static void hb_compExprPushSendPopPush( HB_EXPR_PTR pObj, HB_EXPR_PTR pValue,
HB_BOOL fPreOp, BYTE bOper, HB_COMP_DECL )
{
if( HB_SUPPORT_HARBOUR )
{
hb_compExprPushSendPop( pObj, HB_COMP_PARAM );
/* duplicate object variable */
HB_GEN_FUNC1( PCode1, HB_P_DUPLICATE );
/* Push message */
if( pObj->value.asMessage.szMessage )
{
/* TRUE used intnetionally to not push object variable in WITH OBJECT */
HB_GEN_FUNC2( Message, pObj->value.asMessage.szMessage, TRUE );
}
else
{
HB_EXPR_USE( pObj->value.asMessage.pMessage, HB_EA_PUSH_PCODE );
}
HB_GEN_FUNC2( PCode2, HB_P_SWAP, 0 );
HB_GEN_FUNC2( PCode2, HB_P_SENDSHORT, 0 );
if( fPreOp )
{
/* push the result on the stack */
HB_GEN_FUNC1( PCode1, HB_P_DUPLICATE );
HB_GEN_FUNC2( PCode2, HB_P_SWAP, 2 );
}
}
else
{
if( fPreOp )
{
/* push current value - it will be a result of whole expression */
HB_EXPR_USE( pObj, HB_EA_PUSH_PCODE );
}
hb_compExprPushSendPop( pObj, HB_COMP_PARAM );
hb_compExprPushSendPush( pObj, HB_COMP_PARAM );
HB_GEN_FUNC2( PCode2, HB_P_SENDSHORT, 0 );
}
/* push increment value */
if( pValue )
{
HB_EXPR_USE( pValue, HB_EA_PUSH_PCODE );
}
/* do operation */
HB_GEN_FUNC1( PCode1, bOper );
/* Now do the assignment - call pop message with one argument */
HB_GEN_FUNC2( PCode2, HB_P_SENDSHORT, 1 );
if( fPreOp )
{
/* pop the unneeded value left by assignment message from the stack */
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
}
/* Generates pcodes for compound operators += -= *= /= %= ^=
*
* pExpr is an expression created by hb_compExprNew<operator>Eq functions
*/
/* NOTE: COMPATIBILITY ISSUE:
* The HB_SUPPORT_HARBOUR in code below 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
* (HB_SUPPORT_HARBOUR is not set: -kc compiler switch ) and
*
* temp := a:b( COUNT() ), temp:c += 1
*
* in non-strict mode (-kh).
* 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
*/
static void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_COMP_DECL )
{
BYTE bNewOp;
if( HB_SUPPORT_HARBOUR )
{
switch( bOpEq )
{
case HB_P_PLUS:
bNewOp = HB_P_PLUSEQ;
break;
case HB_P_MINUS:
bNewOp = HB_P_MINUSEQ;
break;
case HB_P_MULT:
bNewOp = HB_P_MULTEQ;
break;
case HB_P_DIVIDE:
bNewOp = HB_P_DIVEQ;
break;
case HB_P_MODULUS:
bNewOp = HB_P_MODEQ;
break;
case HB_P_POWER:
bNewOp = HB_P_EXPEQ;
break;
default:
bNewOp = bOpEq;
break;
}
}
else
bNewOp = bOpEq;
/* NOTE: an object instance variable needs special handling
*/
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
{
#ifdef HB_USE_OBJMSG_REF
if( bOpEq != bNewOp )
{
hb_compExprPushSendPop( pSelf->value.asOperator.pLeft, HB_COMP_PARAM );
HB_GEN_FUNC1( PCode1, HB_P_PUSHOVARREF );
/* push increment value */
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, bNewOp );
}
else
#endif
{
hb_compExprPushSendPopPush( pSelf->value.asOperator.pLeft,
pSelf->value.asOperator.pRight,
FALSE, bOpEq, HB_COMP_PARAM );
}
return;
}
else if( bOpEq != bNewOp )
{
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_MACRO )
{
USHORT usType = pSelf->value.asOperator.pLeft->value.asMacro.SubType;
if( usType == HB_ET_MACRO_VAR )
{
/* NOTE: direct type change */
pSelf->value.asOperator.pLeft->value.asMacro.SubType = HB_ET_MACRO_REFER;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, bNewOp );
pSelf->value.asOperator.pLeft->value.asMacro.SubType = usType;
return;
}
}
#ifdef HB_USE_ARRAYAT_REF
/* NOTE: code for arrays is differ to correctly handle a[ i++ ]++ */
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_ARRAYAT )
{
/* Note: change type to array reference */
pSelf->value.asOperator.pLeft->value.asList.reference = TRUE;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
pSelf->value.asOperator.pLeft->value.asList.reference = FALSE;
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, bNewOp );
return;
}
#endif
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE )
{
#if defined( HB_MACRO_SUPPORT )
{
#else
int iVar, iScope;
hb_compVariableFind( HB_COMP_PARAM, pSelf->value.asOperator.pLeft->value.asSymbol, &iVar, &iScope );
if( iScope != HB_VS_LOCAL_FIELD && iScope != HB_VS_GLOBAL_FIELD &&
iScope != HB_VS_UNDECLARED )
{
if( iScope == HB_VS_LOCAL_VAR &&
pSelf->value.asOperator.pRight->ExprType == HB_ET_NUMERIC &&
( bOpEq == HB_P_PLUS || bOpEq == HB_P_MINUS ) )
{
if( hb_compExprIsInteger( pSelf->value.asOperator.pRight ) )
{
short iIncrement = ( short ) pSelf->value.asOperator.pRight->value.asNum.val.l;
if( bOpEq != HB_P_MINUS || iIncrement >= -INT16_MAX )
{
BYTE buffer[ 5 ];
if( bOpEq == HB_P_MINUS )
iIncrement = -iIncrement;
buffer[ 0 ] = HB_P_LOCALADDINT;
buffer[ 1 ] = HB_LOBYTE( iVar );
buffer[ 2 ] = HB_HIBYTE( iVar );
buffer[ 3 ] = HB_LOBYTE( iIncrement );
buffer[ 4 ] = HB_HIBYTE( iIncrement );
HB_GEN_FUNC2( PCodeN, buffer, 5 );
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
return;
}
}
}
#endif
/* NOTE: direct type change */
pSelf->value.asOperator.pLeft->ExprType = HB_ET_VARREF;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, bNewOp );
return;
}
}
}
/* 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_GEN_FUNC1( PCode1, bOpEq );
HB_GEN_FUNC1( PCode1, 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)
*/
static void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_COMP_DECL )
{
BYTE bNewOp;
if( HB_SUPPORT_HARBOUR )
{
switch( bOpEq )
{
case HB_P_PLUS:
bNewOp = HB_P_PLUSEQPOP;
break;
case HB_P_MINUS:
bNewOp = HB_P_MINUSEQPOP;
break;
case HB_P_MULT:
bNewOp = HB_P_MULTEQPOP;
break;
case HB_P_DIVIDE:
bNewOp = HB_P_DIVEQPOP;
break;
case HB_P_MODULUS:
bNewOp = HB_P_MODEQPOP;
break;
case HB_P_POWER:
bNewOp = HB_P_EXPEQPOP;
break;
default:
bNewOp = bOpEq;
break;
}
}
else
bNewOp = bOpEq;
/* NOTE: an object instance variable needs special handling
*/
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
{
#ifdef HB_USE_OBJMSG_REF
if( bOpEq != bNewOp )
{
hb_compExprPushSendPop( pSelf->value.asOperator.pLeft, HB_COMP_PARAM );
HB_GEN_FUNC1( PCode1, HB_P_PUSHOVARREF );
/* push increment value */
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, bNewOp );
}
else
#endif
{
hb_compExprPushSendPopPush( pSelf->value.asOperator.pLeft,
pSelf->value.asOperator.pRight,
FALSE, bOpEq, HB_COMP_PARAM );
/* pop the unneeded value from the stack */
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
return;
}
else if( bOpEq != bNewOp )
{
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_MACRO )
{
USHORT usType = pSelf->value.asOperator.pLeft->value.asMacro.SubType;
if( usType == HB_ET_MACRO_VAR )
{
/* NOTE: direct type change */
pSelf->value.asOperator.pLeft->value.asMacro.SubType = HB_ET_MACRO_REFER;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, bNewOp );
pSelf->value.asOperator.pLeft->value.asMacro.SubType = usType;
return;
}
}
#ifdef HB_USE_ARRAYAT_REF
/* NOTE: code for arrays is differ to correctly handle a[ i++ ]++ */
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_ARRAYAT )
{
/* Note: change type to array reference */
pSelf->value.asOperator.pLeft->value.asList.reference = TRUE;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
pSelf->value.asOperator.pLeft->value.asList.reference = FALSE;
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, bNewOp );
return;
}
#endif
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE )
{
HB_EXPRTYPE iOldType;
#if defined( HB_MACRO_SUPPORT )
{
#else
int iVar, iScope;
hb_compVariableFind( HB_COMP_PARAM, pSelf->value.asOperator.pLeft->value.asSymbol, &iVar, &iScope );
if( iScope != HB_VS_LOCAL_FIELD && iScope != HB_VS_GLOBAL_FIELD &&
iScope != HB_VS_UNDECLARED )
{
if( iScope == HB_VS_LOCAL_VAR &&
pSelf->value.asOperator.pRight->ExprType == HB_ET_NUMERIC &&
( bOpEq == HB_P_PLUS || bOpEq == HB_P_MINUS ) )
{
if( hb_compExprIsInteger( pSelf->value.asOperator.pRight ) )
{
short iIncrement = ( short ) pSelf->value.asOperator.pRight->value.asNum.val.l;
if( bOpEq != HB_P_MINUS || iIncrement >= -INT16_MAX )
{
BYTE buffer[ 5 ];
if( bOpEq == HB_P_MINUS )
iIncrement = -iIncrement;
buffer[ 0 ] = HB_P_LOCALADDINT;
buffer[ 1 ] = HB_LOBYTE( iVar );
buffer[ 2 ] = HB_HIBYTE( iVar );
buffer[ 3 ] = HB_LOBYTE( iIncrement );
buffer[ 4 ] = HB_HIBYTE( iIncrement );
HB_GEN_FUNC2( PCodeN, buffer, 5 );
return;
}
}
}
#endif
/* NOTE: direct type change */
iOldType = pSelf->value.asOperator.pLeft->ExprType;
pSelf->value.asOperator.pLeft->ExprType = HB_ET_VARREF;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, bNewOp );
pSelf->value.asOperator.pLeft->ExprType = iOldType;
return;
}
}
}
/* 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_GEN_FUNC1( PCode1, 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
*/
static void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_COMP_DECL )
{
/* NOTE: an object instance variable needs special handling
*/
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
{
#ifdef HB_USE_OBJMSG_REF
if( HB_SUPPORT_HARBOUR )
{
hb_compExprPushSendPop( pSelf->value.asOperator.pLeft, HB_COMP_PARAM );
HB_GEN_FUNC1( PCode1, HB_P_PUSHOVARREF );
/* increase/decrease operation, leave unreferenced value on stack */
HB_GEN_FUNC1( PCode1, ( bOper == HB_P_INC ) ? HB_P_INCEQ : HB_P_DECEQ );
}
else
#endif
{
hb_compExprPushSendPopPush( pSelf->value.asOperator.pLeft, NULL,
FALSE, bOper, HB_COMP_PARAM );
}
return;
}
else if( HB_SUPPORT_HARBOUR )
{
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_MACRO &&
pSelf->value.asOperator.pLeft->value.asMacro.SubType == HB_ET_MACRO_VAR )
{
USHORT usType = pSelf->value.asOperator.pLeft->value.asMacro.SubType;
/* NOTE: direct type change */
pSelf->value.asOperator.pLeft->value.asMacro.SubType = HB_ET_MACRO_REFER;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
pSelf->value.asOperator.pLeft->value.asMacro.SubType = usType;
/* increase/decrease operation, leave unreferenced value on stack */
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQ : HB_P_DECEQ ) );
return;
}
#ifdef HB_USE_ARRAYAT_REF
/* NOTE: code for arrays is differ to correctly handle a[ i++ ]++ */
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_ARRAYAT )
{
/* push reference to current value */
/* Note: change type to array reference */
pSelf->value.asOperator.pLeft->value.asList.reference = TRUE;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
pSelf->value.asOperator.pLeft->value.asList.reference = FALSE;
/* increase/decrease operation, leave unreferenced value on stack */
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQ : HB_P_DECEQ ) );
return;
}
#endif
#if !defined( HB_MACRO_SUPPORT )
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE )
{
int iVar, iScope;
hb_compVariableFind( HB_COMP_PARAM, pSelf->value.asOperator.pLeft->value.asSymbol, &iVar, &iScope );
if( iScope != HB_VS_LOCAL_FIELD && iScope != HB_VS_GLOBAL_FIELD &&
iScope != HB_VS_UNDECLARED )
{
if( iScope == HB_VS_LOCAL_VAR )
{
if( bOper == HB_P_INC )
{
HB_GEN_FUNC3( PCode3, HB_P_LOCALINCPUSH, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) );
}
else
{
HB_GEN_FUNC3( PCode3, HB_P_LOCALDEC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) );
/* Push current value */
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
}
}
else
{
/* NOTE: direct type change */
HB_EXPRTYPE iOldType = pSelf->value.asOperator.pLeft->ExprType;
pSelf->value.asOperator.pLeft->ExprType = HB_ET_VARREF;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQ : HB_P_DECEQ ) );
pSelf->value.asOperator.pLeft->ExprType = iOldType;
}
return;
}
}
#endif
}
/* Push current value */
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
/* Increment */
HB_GEN_FUNC1( PCode1, bOper );
/* duplicate a value */
HB_GEN_FUNC1( PCode1, 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
*/
static void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_COMP_DECL )
{
/* NOTE: an object instance variable needs special handling
*/
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
{
#ifdef HB_USE_OBJMSG_REF
if( HB_SUPPORT_HARBOUR )
{
/* push reference to current value */
hb_compExprPushSendPop( pSelf->value.asOperator.pLeft, HB_COMP_PARAM );
HB_GEN_FUNC1( PCode1, HB_P_PUSHOVARREF );
/* Duplicate the reference and unref the original one -
* it will be the result of whole expression
*/
HB_GEN_FUNC1( PCode1, HB_P_DUPLUNREF );
/* increment/decrement the value */
HB_GEN_FUNC1( PCode1, ( bOper == HB_P_INC ) ? HB_P_INCEQPOP : HB_P_DECEQPOP );
}
else
#endif
{
hb_compExprPushSendPopPush( pSelf->value.asOperator.pLeft, NULL,
TRUE, bOper, HB_COMP_PARAM );
}
return;
}
else if( HB_SUPPORT_HARBOUR )
{
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_MACRO &&
pSelf->value.asOperator.pLeft->value.asMacro.SubType == HB_ET_MACRO_VAR )
{
USHORT usType = pSelf->value.asOperator.pLeft->value.asMacro.SubType;
/* NOTE: direct type change */
pSelf->value.asOperator.pLeft->value.asMacro.SubType = HB_ET_MACRO_REFER;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
pSelf->value.asOperator.pLeft->value.asMacro.SubType = usType;
/* Duplicate the reference and unref the original one -
* it will be the result of whole expression
*/
HB_GEN_FUNC1( PCode1, HB_P_DUPLUNREF );
/* increase/decrease operation */
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQPOP : HB_P_DECEQPOP ) );
return;
}
#ifdef HB_USE_ARRAYAT_REF
/* NOTE: code for arrays is differ to correctly handle a[ i++ ]++ */
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_ARRAYAT )
{
/* push reference to current value */
/* Note: change type to array reference */
pSelf->value.asOperator.pLeft->value.asList.reference = TRUE;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
pSelf->value.asOperator.pLeft->value.asList.reference = FALSE;
/* Duplicate the reference and unref the original one -
* it will be the result of whole expression
*/
HB_GEN_FUNC1( PCode1, HB_P_DUPLUNREF );
/* increase/decrease operation */
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQPOP : HB_P_DECEQPOP ) );
return;
}
#endif
#if !defined( HB_MACRO_SUPPORT )
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE )
{
int iVar, iScope;
hb_compVariableFind( HB_COMP_PARAM, pSelf->value.asOperator.pLeft->value.asSymbol, &iVar, &iScope );
if( iScope != HB_VS_LOCAL_FIELD && iScope != HB_VS_GLOBAL_FIELD &&
iScope != HB_VS_UNDECLARED )
{
if( iScope == HB_VS_LOCAL_VAR )
{
/* Push current value */
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC3( PCode3, ( BYTE ) ( bOper == HB_P_INC ? HB_P_LOCALINC : HB_P_LOCALDEC ),
HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) );
}
else
{
/* NOTE: direct type change */
HB_EXPRTYPE iOldType = pSelf->value.asOperator.pLeft->ExprType;
pSelf->value.asOperator.pLeft->ExprType = HB_ET_VARREF;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, HB_P_DUPLUNREF );
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQPOP : HB_P_DECEQPOP ) );
pSelf->value.asOperator.pLeft->ExprType = iOldType;
}
return;
}
}
#endif
}
/* Push current value */
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
/* Duplicate value */
HB_GEN_FUNC1( PCode1, HB_P_DUPLICATE );
/* Increment */
HB_GEN_FUNC1( PCode1, 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
*/
static void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_COMP_DECL )
{
/* NOTE: an object instance variable needs special handling
*/
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND )
{
#ifdef HB_USE_OBJMSG_REF
if( HB_SUPPORT_HARBOUR )
{
/* push reference to current value */
hb_compExprPushSendPop( pSelf->value.asOperator.pLeft, HB_COMP_PARAM );
HB_GEN_FUNC1( PCode1, HB_P_PUSHOVARREF );
/* increment/decrement the value */
HB_GEN_FUNC1( PCode1, ( bOper == HB_P_INC ) ? HB_P_INCEQPOP : HB_P_DECEQPOP );
}
else
#endif
{
hb_compExprPushSendPopPush( pSelf->value.asOperator.pLeft, NULL,
FALSE, bOper, HB_COMP_PARAM );
/* pop the value from the stack */
HB_GEN_FUNC1( PCode1, HB_P_POP );
}
return;
}
else if( HB_SUPPORT_HARBOUR )
{
if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_MACRO &&
pSelf->value.asOperator.pLeft->value.asMacro.SubType == HB_ET_MACRO_VAR )
{
USHORT usType = pSelf->value.asOperator.pLeft->value.asMacro.SubType;
/* NOTE: direct type change */
pSelf->value.asOperator.pLeft->value.asMacro.SubType = HB_ET_MACRO_REFER;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
pSelf->value.asOperator.pLeft->value.asMacro.SubType = usType;
/* increase/decrease operation */
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQPOP : HB_P_DECEQPOP ) );
return;
}
#ifdef HB_USE_ARRAYAT_REF
/* NOTE: code for arrays is differ to correctly handle a[ i++ ]++ */
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_ARRAYAT )
{
/* push reference to current value */
/* Note: change type to array reference */
pSelf->value.asOperator.pLeft->value.asList.reference = TRUE;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
pSelf->value.asOperator.pLeft->value.asList.reference = FALSE;
/* increase/decrease operation */
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQPOP : HB_P_DECEQPOP ) );
return;
}
#endif
#if !defined( HB_MACRO_SUPPORT )
else if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE )
{
int iVar, iScope;
hb_compVariableFind( HB_COMP_PARAM, pSelf->value.asOperator.pLeft->value.asSymbol, &iVar, &iScope );
if( iScope != HB_VS_LOCAL_FIELD && iScope != HB_VS_GLOBAL_FIELD &&
iScope != HB_VS_UNDECLARED )
{
if( iScope == HB_VS_LOCAL_VAR )
{
HB_GEN_FUNC3( PCode3, ( BYTE ) ( bOper == HB_P_INC ? HB_P_LOCALINC : HB_P_LOCALDEC ),
HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) );
}
else
{
/* NOTE: direct type change */
HB_EXPRTYPE iOldType = pSelf->value.asOperator.pLeft->ExprType;
pSelf->value.asOperator.pLeft->ExprType = HB_ET_VARREF;
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
HB_GEN_FUNC1( PCode1, ( BYTE ) ( bOper == HB_P_INC ? HB_P_INCEQPOP : HB_P_DECEQPOP ) );
pSelf->value.asOperator.pLeft->ExprType = iOldType;
}
return;
}
}
#endif
}
/* Push current value */
HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE );
/* Increment */
HB_GEN_FUNC1( PCode1, 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->&macro or &macro->expression or &macro->&macro
*/
static void hb_compExprUseAliasMacro( HB_EXPR_PTR pAliasedVar, BYTE bAction, HB_COMP_DECL )
{
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_GEN_FUNC2( PushString, pAlias->value.asSymbol, strlen( pAlias->value.asSymbol ) + 1 );
HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE );
if( bAction == HB_EA_PUSH_PCODE )
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSHALIASED );
else
HB_GEN_FUNC1( PCode1, HB_P_MACROPOPALIASED );
}
else if( pVar->ExprType == HB_ET_VARIABLE )
{
/* NOTE:
* &macro->var is the same as: &( macro + "->var" )
*/
HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE );
HB_GEN_FUNC2( PushString, pVar->value.asSymbol, strlen( pVar->value.asSymbol ) + 1 );
if( bAction == HB_EA_PUSH_PCODE )
HB_GEN_FUNC1( PCode1, HB_P_MACROPUSHALIASED );
else
HB_GEN_FUNC1( PCode1, 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_GEN_FUNC1( PCode1, HB_P_MACROPUSHALIASED );
else
HB_GEN_FUNC1( PCode1, HB_P_MACROPOPALIASED );
}
/* Always add byte to pcode indicating requested macro compiler flag. */
HB_GEN_FUNC1( PCode1, ( BYTE ) HB_MACRO_GENFLAGS );
}
/* Reduces the list of expressions
*
* pExpr is the first expression on the list
*/
static HB_EXPR_PTR hb_compExprReduceList( HB_EXPR_PTR pList, HB_COMP_DECL )
{
HB_EXPR_PTR pNext, pExpr;
HB_EXPR_PTR * pPrev;
/* NOTE: During optimalization an expression on the list can be
* replaced by the new one
*/
pPrev = &pList->value.asList.pExprList;
pExpr = pList->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 );
if( HB_SUPPORT_HARBOUR )
pExpr = hb_compExprListStrip( pExpr, HB_COMP_PARAM );
*pPrev = pExpr; /* store a new expression into the previous one */
pExpr->pNext = pNext; /* restore the link to next expression */
pPrev = &pExpr->pNext;
pExpr = pNext;
}
return pList;
}
/* reduce ( "alias" )-> to ALIAS->
*/
static HB_EXPR_PTR hb_compExprReduceAliasString( HB_EXPR_PTR pExpr, HB_EXPR_PTR pAlias, HB_COMP_DECL )
{
const char * szAlias = pAlias->value.asString.string;
if( HB_ISFIRSTIDCHAR( *szAlias ) )
{
ULONG ulLen = pAlias->ulLength;
if( ulLen <= HB_SYMBOL_NAME_LEN )
{
HB_BOOL fLower = FALSE;
while( ulLen )
{
char c = szAlias[ ulLen - 1 ];
if( !HB_ISNEXTIDCHAR( c ) )
break;
if( HB_ISLOWER( c ) )
fLower = TRUE;
--ulLen;
}
if( ulLen == 0 )
{
#if defined( HB_MACRO_SUPPORT )
if( fLower )
szAlias = hb_macroIdentNew( HB_COMP_PARAM, hb_strupr( hb_strdup( szAlias ) ) );
else if( pAlias->value.asString.dealloc )
szAlias = hb_macroIdentNew( HB_COMP_PARAM, hb_strdup( szAlias ) );
#else
if( fLower )
szAlias = hb_compIdentifierNew( HB_COMP_PARAM, hb_strupr( hb_strdup( szAlias ) ), HB_IDENT_FREE );
else if( pAlias->value.asString.dealloc )
szAlias = hb_compIdentifierNew( HB_COMP_PARAM, szAlias, HB_IDENT_COPY );
#endif
HB_COMP_EXPR_DELETE( pExpr );
pExpr = hb_compExprNewAlias( szAlias, HB_COMP_PARAM );
}
}
}
return pExpr;
}
static HB_BOOL hb_compExprIsMemvarAlias( const char *szAlias )
{
int iLen = strlen( szAlias );
/* @M-> @MEMVAR-> or @MEMVA-> or @MEMV-> */
return ( iLen == 1 || ( iLen >= 4 && iLen <= 6 ) ) &&
memcmp( szAlias, "MEMVAR", iLen ) == 0;
}