diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 81ee64c3d2..7a63164cd7 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,62 @@ +20000318-21:30 GMT+1 Ryszard Glab + + *include/hbexpr.c + -removed + *include/hbexpra.c + *include/hbexprb.c + *include/hbexprc.c + +new files with expression optimizer shared by the standalone + and the macro compilers - these files produces different code + for the compilers + + *source/compiler/expropt.c + -removed + *source/compiler/expropta.c + *source/compiler/exproptb.c + *source/compiler/exproptc.c + +new files with expression optimizer used by the standalone compiler + + *source/macro/macroa.c + *source/macro/macrob.c + *source/macro/macroc.c + +new files with expression optimizer shared by the macro compiler + + *source/common/expropt1.c + *source/common/expropt2.c + +new files with expression optimizer shared by the standalone + and the macro compilers - the common part of expression optimizer + + *source/macro/macro.l + +added HB_MACRO_SUPPORT definition + + *source/macro/macro.c + *removed including of hbexprop.h + + *include/hbexprop.h + *include/hbcomp.h + *corrected to support new design of expression optimizer + + *source/common/Makefile + *source/compiler/Makefile + *source/macro/Makefile + *makefile.bc + *makefile.vc + +added the depenencies for the new files (BC & VC not tested !) + + *source/rtl/console.c + *source/rtl/filesys.c + *source/rtl/fssize.c + *source/rtl/gtapi.c + *"io.h" is not included if OS_UNIX_COMPATIBLE is defined + (in some places #include hbsetup.h" was added to get a chance to + define OS_xxx_COMPATIBLE before it is checked) + + *source/rtl/gt/gtcrs.c + *a very basic support for colors was added + *a very basic support for inkey was added + (these two changes are for testing and checking rather than a real + solution) + 20000318-12:45 EST Paul Tucker * contrib/rdd_ads/ads1.c * added cast in strlen() diff --git a/harbour/include/hbcomp.h b/harbour/include/hbcomp.h index d74ec2b129..df4cb10795 100644 --- a/harbour/include/hbcomp.h +++ b/harbour/include/hbcomp.h @@ -203,7 +203,7 @@ extern void hb_compGenPushLogical( int, HB_MACRO_DECL ); /* pushes a logical extern void hb_compGenPushLong( long, HB_MACRO_DECL ); /* Pushes a long number on the virtual machine stack */ extern void hb_compGenPushNil( HB_MACRO_DECL ); /* Pushes nil on the virtual machine stack */ extern void hb_compGenPushString( char *, ULONG, HB_MACRO_DECL ); /* Pushes a string on the virtual machine stack */ -extern void hb_compGenPushSymbol( char *, HB_MACRO_DECL ); /* Pushes a symbol on to the Virtual machine stack */ +extern void hb_compGenPushSymbol( char *, int, HB_MACRO_DECL ); /* Pushes a symbol on to the Virtual machine stack */ extern void hb_compGenPushAliasedVar( char *, BOOL, char *, long, HB_MACRO_DECL ); extern void hb_compGenPopAliasedVar( char *, BOOL, char *, long, HB_MACRO_DECL ); extern void hb_compGenPushFunRef( char *, HB_MACRO_DECL ); diff --git a/harbour/include/hbexpr.c b/harbour/include/hbexpr.c deleted file mode 100644 index f36846b7ae..0000000000 --- a/harbour/include/hbexpr.c +++ /dev/null @@ -1,5999 +0,0 @@ -/* - * $Id$ - */ - -/* - * Harbour Project source code: - * Compiler Expression Optimizer - * - * Copyright 1999 Ryszard Glab - * www - http://www.harbour-project.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version, with one exception: - * - * The exception is that if you link the Harbour Runtime Library (HRL) - * and/or the Harbour Virtual Machine (HVM) with other files to produce - * an executable, this does not by itself cause the resulting executable - * to be covered by the GNU General Public License. Your use of that - * executable is in no way restricted on account of linking the HRL - * and/or HVM code into it. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit - * their web site at http://www.gnu.org/). - * - */ - -/* TOFIX: Split the code, since MSC8 can't compile it, even in Huge model. */ - -/* TODO: - * - Correct post- and pre- operations to correctly handle the following code - * a[ i++ ]++ - * Notice: in current implementation (an in Clipper too) 'i++' is evaluated - * two times! This causes that the new value (after incrementation) is - * stored in next element of the array. - */ - -#include -#include "hbcomp.h" - -/* memory allocation - */ -#define HB_XGRAB( size ) hb_xgrab( (size) ) -#define HB_XFREE( pPtr ) hb_xfree( (void *)(pPtr) ) - -/* NOTE: We need to pass additional parameter if compilation for macro - * compiler support. This parameter is a pointer to an internal macro - * structure used to store all data needed for re-entrant compilation - */ -#ifdef HB_MACRO_SUPPORT - -#define hb_compGenPCode1( p1 ) hb_compGenPCode1( p1, HB_MACRO_PARAM ) -#define hb_compGenPCode3( p1, p2, p3 ) hb_compGenPCode3( p1, p2, p3, HB_MACRO_PARAM ) -#define hb_compGenPCodeN( p1, p2 ) hb_compGenPCodeN( p1, p2, HB_MACRO_PARAM ) - -#define hb_compCodeBlockStart( ) hb_compCodeBlockStart( HB_MACRO_PARAM ) -#define hb_compCodeBlockEnd( ) hb_compCodeBlockEnd( HB_MACRO_PARAM ) - -#define hb_compGenJump( p1 ) hb_compGenJump( p1, HB_MACRO_PARAM ) -#define hb_compGenJumpFalse( p1 ) hb_compGenJumpFalse( p1, HB_MACRO_PARAM ) -#define hb_compGenJumpTrue( p1 ) hb_compGenJumpTrue( p1, HB_MACRO_PARAM ) -#define hb_compGenJumpHere( p1 ) hb_compGenJumpHere( p1, HB_MACRO_PARAM ) -#define hb_compGenJumpThere( p1, p2 ) hb_compGenJumpThere( p1, p2, HB_MACRO_PARAM ) - -#define hb_compGenMessage( p1 ) hb_compGenMessage( p1, HB_MACRO_PARAM ) -#define hb_compGenMessageData( p1 ) hb_compGenMessageData( p1, HB_MACRO_PARAM ) -#define hb_compGenPopVar( p1 ) hb_compGenPopVar( p1, HB_MACRO_PARAM ) -#define hb_compGenPushDouble( p1, p2 ) hb_compGenPushDouble( p1, p2, HB_MACRO_PARAM ) -#define hb_compGenPushFunCall( p1 ) hb_compGenPushFunCall( p1, HB_MACRO_PARAM ) -#define hb_compGenPushVar( p1 ) hb_compGenPushVar( p1, HB_MACRO_PARAM ) -#define hb_compGenPushVarRef( p1 ) hb_compGenPushVarRef( p1, HB_MACRO_PARAM ) -#define hb_compGenPushLogical( p1 ) hb_compGenPushLogical( p1, HB_MACRO_PARAM ) -#define hb_compGenPushLong( p1 ) hb_compGenPushLong( p1, HB_MACRO_PARAM ) -#define hb_compGenPushNil( ) hb_compGenPushNil( p1, HB_MACRO_PARAM ) -#define hb_compGenPushString( p1, p2 ) hb_compGenPushString( p1, p2, HB_MACRO_PARAM ) -#define hb_compGenPushSymbol( p1 ) hb_compGenPushSymbol( p1, HB_MACRO_PARAM ) -#define hb_compGenPushAliasedVar( p1, p2, p3, p4 ) hb_compGenPushAliasedVar( p1, p2, p3, p4, HB_MACRO_PARAM ) -#define hb_compGenPopAliasedVar( p1, p2 , p3, p4 ) hb_compGenPopAliasedVar( p1, p2, p3, p4, HB_MACRO_PARAM ) -#define hb_compGenPushFunRef( p1 ) hb_compGenPushFunRef( p1, HB_MACRO_PARAM ) - -#endif /* ifdef HB_MACRO_SUPPORT */ - -/* value types seen at language level - */ -#define HB_EV_UNKNOWN 0 -#define HB_EV_NIL 1 -#define HB_EV_NUMERIC 2 -#define HB_EV_STRING 4 -#define HB_EV_CODEBLOCK 8 -#define HB_EV_LOGICAL 16 -#define HB_EV_OBJECT 32 -#define HB_EV_ARRAY 64 -#define HB_EV_SYMBOL 128 -#define HB_EV_VARREF 256 -#define HB_EV_FUNREF 512 - -/* messages sent to expressions - */ -typedef enum -{ - HB_EA_REDUCE = 0, /* reduce the expression into optimized one */ - HB_EA_ARRAY_AT, /* check if the expession can be used as array */ - HB_EA_ARRAY_INDEX, /* check if the expession can be used as index */ - HB_EA_LVALUE, /* check if the expression can be used as lvalue (left side of an assigment) */ - HB_EA_PUSH_PCODE, /* generate the pcodes to push the value of expression */ - HB_EA_POP_PCODE, /* generate the pcodes to pop the value of expression */ - HB_EA_PUSH_POP, /* generate the pcodes to push and pop the expression */ - HB_EA_STATEMENT, /* generate the pcodes for a statement */ - HB_EA_DELETE /* delete components of the expression */ -} HB_EXPR_MESSAGE; - -/* additional definitions used to distinguish numeric expressions - */ -#define HB_ET_LONG 1 -#define HB_ET_DOUBLE 2 - -/* additional definitions used to distinguish macro expressions - */ -#define HB_ET_MACRO_VAR 0 /* &variable */ -#define HB_ET_MACRO_SYMBOL 1 /* &fimcall() */ -#define HB_ET_MACRO_ALIASED 2 /* &alias->&variable */ -#define HB_ET_MACRO_EXPR 4 /* &( expr ) */ - -/* types of expressions - * NOTE: the order of these definition is important - change it carefully - * All types <= HB_ET_FUNREF are constant values - * All types <= HB_ET_VARIABLE are a simple values - * All types > HB_ET_VARIABLE are operators - */ -typedef enum -{ - HB_ET_NONE = 0, - HB_ET_NIL, - HB_ET_NUMERIC, - HB_ET_STRING, - HB_ET_CODEBLOCK, - HB_ET_LOGICAL, - HB_ET_SELF, - HB_ET_ARRAY, - HB_ET_VARREF, - HB_ET_FUNREF, - HB_ET_IIF, - HB_ET_LIST, - HB_ET_ARGLIST, - HB_ET_ARRAYAT, - HB_ET_MACRO, - HB_ET_FUNCALL, - HB_ET_ALIASVAR, - HB_ET_ALIASEXPR, - HB_ET_SEND, - HB_ET_FUNNAME, - HB_ET_ALIAS, - HB_ET_RTVAR, /* PRIVATE or PUBLIC declaration of variable */ - HB_ET_VARIABLE, - HB_EO_POSTINC, /* post-operators -> lowest precedence */ - HB_EO_POSTDEC, - HB_EO_ASSIGN, /* assigments */ - HB_EO_PLUSEQ, - HB_EO_MINUSEQ, - HB_EO_MULTEQ, - HB_EO_DIVEQ, - HB_EO_MODEQ, - HB_EO_EXPEQ, - HB_EO_OR, /* logical operators */ - HB_EO_AND, - HB_EO_NOT, - HB_EO_EQUAL, /* relational operators */ - HB_EO_EQ, - HB_EO_LT, - HB_EO_GT, - HB_EO_LE, - HB_EO_GE, - HB_EO_NE, - HB_EO_IN, - HB_EO_PLUS, /* addition */ - HB_EO_MINUS, - HB_EO_MULT, /* multiple */ - HB_EO_DIV, - HB_EO_MOD, - HB_EO_POWER, - HB_EO_NEGATE, /* sign operator */ - HB_EO_PREINC, - HB_EO_PREDEC /* pre-operators -> the highest precedence */ -} HB_EXPR_OPERATOR; - -/* 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_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_compExprUseVarRef ); -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_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 ); - -static HB_EXPR_FUNC_PTR s_ExprTable[] = { - hb_compExprUseDummy, - hb_compExprUseNil, - hb_compExprUseNumeric, - hb_compExprUseString, - hb_compExprUseCodeblock, - hb_compExprUseLogical, - hb_compExprUseSelf, - hb_compExprUseArray, - hb_compExprUseVarRef, - hb_compExprUseFunRef, - hb_compExprUseIIF, - hb_compExprUseList, - hb_compExprUseArgList, - 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_compExprUseLT, - hb_compExprUseGT, - hb_compExprUseLE, - hb_compExprUseGE, - hb_compExprUseNE, - hb_compExprUseIN, - hb_compExprUsePlus, /* addition */ - hb_compExprUseMinus, - hb_compExprUseMult, /* multiple */ - hb_compExprUseDiv, - hb_compExprUseMod, - hb_compExprUsePower, - hb_compExprUseNegate, /* sign operator */ - hb_compExprUsePreInc, - hb_compExprUsePreDec /* highest precedence */ -}; - -/* Table with operators precedence - * NOTE: - * HB_ET_NIL is used for an ordinary values and post- operators - * HB_ET_NONE is used for invalid syntax, e.g. var := var1 += 2 - */ -static BYTE s_PrecedTable[] = { - HB_ET_NIL, /* HB_ET_NONE = 0, */ - HB_ET_NIL, /* HB_ET_NIL, */ - HB_ET_NIL, /* HB_ET_NUMERIC, */ - HB_ET_NIL, /* HB_ET_STRING, */ - HB_ET_NIL, /* HB_ET_CODEBLOCK, */ - HB_ET_NIL, /* HB_ET_LOGICAL, */ - HB_ET_NIL, /* HB_ET_SELF, */ - HB_ET_NIL, /* HB_ET_ARRAY, */ - HB_ET_NIL, /* HB_ET_VARREF, */ - HB_ET_NIL, /* HB_ET_FUNREF, */ - HB_ET_NIL, /* HB_ET_IIF, */ - HB_ET_NIL, /* HB_ET_LIST, */ - HB_ET_NIL, /* HB_ET_ARGLIST, */ - HB_ET_NIL, /* HB_ET_ARRAYAT, */ - HB_ET_NIL, /* HB_ET_MACRO, */ - HB_ET_NIL, /* HB_ET_FUNCALL, */ - HB_ET_NIL, /* HB_ET_ALIASVAR, */ - HB_ET_NIL, /* HB_ET_ALIASEXPR, */ - HB_ET_NIL, /* HB_ET_SEND, */ - HB_ET_NIL, /* HB_ET_FUNNAME, */ - HB_ET_NIL, /* HB_ET_ALIAS, */ - HB_ET_NIL, /* HB_ET_RTVARIABLE, */ - HB_ET_NIL, /* HB_ET_VARIABLE, */ - HB_ET_NIL, /* HB_EO_POSTINC, post-operators */ - HB_ET_NIL, /* HB_EO_POSTDEC, */ - HB_ET_NONE, /* HB_EO_ASSIGN, assigments */ - HB_ET_NONE, /* HB_EO_PLUSEQ, Invalid syntax */ - HB_ET_NONE, /* HB_EO_MINUSEQ, */ - HB_ET_NONE, /* HB_EO_MULTEQ, */ - HB_ET_NONE, /* HB_EO_DIVEQ, */ - HB_ET_NONE, /* HB_EO_MODEQ, */ - HB_ET_NONE, /* HB_EO_EXPEQ, */ - HB_EO_OR, /* HB_EO_OR, logical operators */ - HB_EO_AND, /* HB_EO_AND, */ - HB_ET_NIL, /* HB_EO_NOT, */ - HB_EO_EQUAL, /* HB_EO_EQUAL, relational operators */ - HB_EO_EQUAL, /* HB_EO_EQ, */ - HB_EO_EQUAL, /* HB_EO_LT, */ - HB_EO_EQUAL, /* HB_EO_GT, */ - HB_EO_EQUAL, /* HB_EO_LE, */ - HB_EO_EQUAL, /* HB_EO_GE, */ - HB_EO_EQUAL, /* HB_EO_NE, */ - HB_EO_EQUAL, /* HB_EO_IN, */ - HB_EO_PLUS, /* HB_EO_PLUS, addition */ - HB_EO_PLUS, /* HB_EO_MINUS, */ - HB_EO_MULT, /* HB_EO_MULT, multiple */ - HB_EO_MULT, /* HB_EO_DIV, */ - HB_EO_MULT, /* HB_EO_MOD, */ - HB_EO_POWER, /* HB_EO_POWER, */ - HB_ET_NIL, /* HB_EO_NEGATE, sign operator */ - HB_ET_NIL, /* HB_EO_PREINC, */ - HB_ET_NIL /* HB_EO_PREDEC, pre-operators */ -}; - -static char * s_OperTable[] = { - "", - "NIL", - "Numeric", - "String", - "Codeblock", - "Logical", - "SELF", - "Array", - "@", - "@", - "IIF", - ",", - ",", - "[", - "&", - "()", - "->", - "->", - ":", - "", /* symbol */ - "", /* alias */ - "", /* RunTime variable */ - "", /* variable */ - "++", /* post-operators -> lowest precedence */ - "--", - ":=", /* assigments */ - "+=", - "-=", - "*=", - "/=", - "%=", - "^=", - ".OR.", /* logical operators */ - ".AND.", - ".NOT.", - "=", /* relational operators */ - "==", - "<", - ">", - "<=", - ">=", - "!=", - "$", - "+", /* addition */ - "-", - "*", /* multiple */ - "/", - "%", - "^", - "-", /* sign operator */ - "++", - "--" -}; - -/* Forward declarations - */ - -#ifdef HB_MACRO_SUPPORT - -static void hb_compExprDelOperatorMC( HB_EXPR_PTR, HB_MACRO_DECL ); -static ULONG hb_compExprListReduceMC( HB_EXPR_PTR, HB_MACRO_DECL ); -static HB_EXPR_PTR hb_compExprListStripMC( HB_EXPR_PTR, HB_MACRO_DECL ); -static void hb_compExprPushOperEqMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); -static void hb_compExprUseOperEqMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); -static void hb_compExprPushPreOpMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); -static void hb_compExprPushPostOpMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); -static void hb_compExprUsePreOpMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); -static void hb_compExprUseAliasMacroMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); - -#define hb_compExprDelOperator( p ) hb_compExprDelOperatorMC( p, HB_MACRO_PARAM ) -#define hb_compExprListReduce( pSelf ) hb_compExprListReduceMC( pSelf, HB_MACRO_PARAM ) -#define hb_compExprListStrip( p ) hb_compExprListStripMC( p, HB_MACRO_PARAM ) -#define hb_compExprPushOperEq( p, b ) hb_compExprPushOperEqMC( p, b, HB_MACRO_PARAM ) -#define hb_compExprUseOperEq( p, b ) hb_compExprUseOperEqMC( p, b, HB_MACRO_PARAM ) -#define hb_compExprPushPreOp( p, b ) hb_compExprPushPreOpMC( p, b, HB_MACRO_PARAM ) -#define hb_compExprPushPostOp( p, b ) hb_compExprPushPostOpMC( p, b, HB_MACRO_PARAM ) -#define hb_compExprUsePreOp( p, b ) hb_compExprUsePreOpMC( p, b, HB_MACRO_PARAM ) -#define hb_compExprUseAliasMacro( p, b ) hb_compExprUseAliasMacroMC( p, b, HB_MACRO_PARAM ) - -#define hb_comp_bShortCuts ( HB_MACRO_DATA->bShortCuts ) - -#else - -static void hb_compExprDelOperator( HB_EXPR_PTR ); -static ULONG hb_compExprListReduce( HB_EXPR_PTR ); -static HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR ); -static void hb_compExprPushOperEq( HB_EXPR_PTR, BYTE ); -static void hb_compExprUseOperEq( HB_EXPR_PTR, BYTE ); -static void hb_compExprPushPreOp( HB_EXPR_PTR, BYTE ); -static void hb_compExprPushPostOp( HB_EXPR_PTR, BYTE ); -static void hb_compExprUsePreOp( HB_EXPR_PTR, BYTE ); -static void hb_compExprUseAliasMacro( HB_EXPR_PTR, BYTE ); -static void hb_compExprCheckStaticInitializers( HB_EXPR_PTR, HB_EXPR_PTR ); -#endif - -static BOOL hb_compExprCheckMacroVar( char * ); -static HB_CBVAR_PTR hb_compExprCBVarNew( char *, BYTE ); -static void hb_compExprCBVarDel( HB_CBVAR_PTR ); - -/* ************************************************************************ */ - -HB_EXPR_PTR hb_compExprNew( int iType ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNew(%i)", iType)); - - pExpr = ( HB_EXPR_PTR ) HB_XGRAB( sizeof( HB_EXPR ) ); - - pExpr->ExprType = iType; - pExpr->pNext = NULL; - pExpr->ValType = HB_EV_UNKNOWN; - - return pExpr; -} - -/* Delete all components and delete self - */ -#ifdef HB_MACRO_SUPPORT -void hb_compExprDelete( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_compExprDelete()")); - HB_EXPR_USE( pExpr, HB_EA_DELETE ); - HB_XFREE( pExpr ); -} - -#define hb_compExprDelete( pParms ) hb_compExprDelete( pParms, HB_MACRO_PARAM ) - -#else -void hb_compExprDelete( HB_EXPR_PTR pExpr ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_compExprDelete()")); - HB_EXPR_USE( pExpr, HB_EA_DELETE ); - HB_XFREE( pExpr ); -} -#endif - -/* Delete self - all components will be deleted somewhere else - */ -void hb_compExprClear( HB_EXPR_PTR pExpr ) -{ - HB_XFREE( pExpr ); -} - -char * hb_compExprDescription( HB_EXPR_PTR pExpr ) -{ - if( pExpr ) - return s_OperTable[ pExpr->ExprType ]; - else - return s_OperTable[ 0 ]; -} - -HB_EXPR_PTR hb_compExprNewEmpty( void ) -{ - return hb_compExprNew( HB_ET_NONE ); -} - -HB_EXPR_PTR hb_compExprNewDouble( double dValue, BYTE ucDec ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewDouble(%f, %i)", dValue, ucDec)); - - pExpr =hb_compExprNew( HB_ET_NUMERIC ); - - pExpr->value.asNum.dVal = dValue; - pExpr->value.asNum.bDec = ucDec; - pExpr->value.asNum.NumType = HB_ET_DOUBLE; - pExpr->ValType = HB_EV_NUMERIC; - - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewLong( long lValue ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewLong(%li)", lValue)); - - pExpr =hb_compExprNew( HB_ET_NUMERIC ); - - pExpr->value.asNum.lVal = lValue; - pExpr->value.asNum.bDec = 0; - pExpr->value.asNum.NumType = HB_ET_LONG; - pExpr->ValType = HB_EV_NUMERIC; - - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewString( char *szValue ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewString(%s)", szValue)); - - pExpr =hb_compExprNew( HB_ET_STRING ); - - pExpr->value.asString = szValue; - pExpr->ulLength = strlen( szValue ); - pExpr->ValType = HB_EV_STRING; - - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewCodeBlock( void ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewCodeBlock()")); - - pExpr =hb_compExprNew( HB_ET_CODEBLOCK ); - - pExpr->value.asList.pExprList = NULL; - pExpr->value.asList.pIndex = NULL; /* this will hold local variables declarations */ - pExpr->ValType = HB_EV_CODEBLOCK; - - return pExpr; -} - -/* Add a new local variable declaration - */ -#ifdef HB_MACRO_SUPPORT -HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, HB_MACRO_DECL ) -#else -HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, BYTE bType ) -#endif -{ - HB_CBVAR_PTR pVar; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprCBVarAdd(%s)", szVarName)); - - if( pCB->value.asList.pIndex ) - { - /* add it to the end of the list - */ - pVar = ( HB_CBVAR_PTR ) pCB->value.asList.pIndex; - while( pVar ) - { - if( strcmp( szVarName, pVar->szName ) == 0 ) - hb_compErrorDuplVar( szVarName ); - - if( pVar->pNext ) - pVar = pVar->pNext; - else - { -#ifdef HB_MACRO_SUPPORT - pVar->pNext = hb_compExprCBVarNew( szVarName, ' ' ); -#else - pVar->pNext = hb_compExprCBVarNew( szVarName, bType ); -#endif - pVar = NULL; - } - } - } - else -#ifdef HB_MACRO_SUPPORT - pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, ' ' ); -#else - pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, bType ); -#endif - - return pCB; -} - -HB_EXPR_PTR hb_compExprNewLogical( int iValue ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewLogical(%i)", iValue)); - - pExpr =hb_compExprNew( HB_ET_LOGICAL ); - - pExpr->value.asLogical = iValue; - pExpr->ValType = HB_EV_LOGICAL; - - return pExpr; -} - - -HB_EXPR_PTR hb_compExprNewNil( void ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewNil()")); - - pExpr = hb_compExprNew( HB_ET_NIL ); - - pExpr->ValType = HB_EV_NIL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewSelf( void ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewSelf()")); - - pExpr =hb_compExprNew( HB_ET_SELF ); - - pExpr->ValType = HB_EV_OBJECT; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewVarRef( char * szVarName ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewVarRef(%s)", szVarName)); - - pExpr =hb_compExprNew( HB_ET_VARREF ); - - pExpr->value.asSymbol = szVarName; - pExpr->ValType = HB_EV_VARREF; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewFunRef( char * szFunName ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunRef(%s)", szFunName)); - - pExpr =hb_compExprNew( HB_ET_FUNREF ); - - pExpr->value.asSymbol = szFunName; - pExpr->ValType = HB_EV_FUNREF; - return pExpr; -} - -/* Create a new IIF() expression or set arguments - * - * pIIF is a list of three expressions - */ -HB_EXPR_PTR hb_compExprNewIIF( HB_EXPR_PTR pExpr ) -{ -#ifndef HB_MACRO_SUPPORT - HB_EXPR_PTR pTmp; - - pExpr->ExprType = HB_ET_IIF; - - pTmp = pExpr->value.asList.pExprList; /* get first expression */ - if( pTmp->ExprType == HB_ET_NONE ) - { - /* there is no conditional expression e.g. IIF( , true, false ) - */ - hb_compErrorSyntax( pExpr ); - } -#else - pExpr->ExprType = HB_ET_IIF; -#endif - - return pExpr; -} - -/* Create function call - */ -#ifdef HB_MACRO_SUPPORT -HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms, HB_MACRO_DECL ) -#else -HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) -#endif -{ - HB_EXPR_PTR pExpr = NULL; - - if( pName->ExprType == HB_ET_FUNNAME ) - { - /* The name of a function is specified at compile time - * e.g. MyFunc() - * - * NOTE: 'pName' can be a macro expression that will be resolved - * at runtime - in this case pName is an expression of HB_ET_MACRO type - * e.g. &MyVar() - */ - int iCount; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunCall(%s)", pName->value.asSymbol)); - - if( pParms ) - { - iCount = hb_compExprListLen( pParms ); - /* Check the special case when no parameters are passed - in this case - * pParms is an expression of type HB_ET_NONE and we shouldn't - * replace it with NIL value - */ - if( iCount == 1 && pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) - --iCount; - } - else - iCount = 0; - -#ifndef HB_MACRO_SUPPORT - hb_compFunCallCheck( pName->value.asSymbol, iCount ); -#endif - - /* TODO: AT() (also done by Clipper, already mentioned) - LEN() (also done by Clipper) - ASC() (not done by Clipper) - EMPTY() (not done by Clipper) */ - - if( ( strcmp( "CHR", pName->value.asSymbol ) == 0 ) && iCount ) - { - /* try to change it into a string */ - HB_EXPR_PTR pArg = pParms->value.asList.pExprList; - - if( pArg->ExprType == HB_ET_NUMERIC ) - { - /* NOTE: CA-Cl*pper's compiler optimizer will be wrong for those - CHR() cases where the passed parameter is a constant which - can be divided by 256 but it's not zero, in this case it - will return an empty string instead of a Chr(0). [vszakats] */ - - pExpr = hb_compExprNew( HB_ET_STRING ); - pExpr->ValType = HB_EV_STRING; - if( pArg->value.asNum.NumType == HB_ET_LONG ) - { - if( ( pArg->value.asNum.lVal % 256 ) == 0 && pArg->value.asNum.lVal != 0 ) - { - pExpr->value.asString = ( char * ) HB_XGRAB( 1 ); - pExpr->value.asString[ 0 ] = '\0'; - pExpr->ulLength = 0; - } - else - { - pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); - pExpr->value.asString[ 0 ] = ( pArg->value.asNum.lVal % 256 ); - pExpr->value.asString[ 1 ] = '\0'; - pExpr->ulLength = 1; - } - } - else - { - pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); - pExpr->value.asString[ 0 ] = ( ( long ) pArg->value.asNum.dVal % 256 ); - pExpr->value.asString[ 1 ] = '\0'; - pExpr->ulLength = 1; - } - hb_compExprDelete( pParms ); - hb_compExprDelete( pName ); - } - } - } - else if( pName->ExprType == HB_ET_MACRO ) - { - /* Signal that macro compiler have to generate a pcode that will - * return function name as symbol instead of usual value - */ - pName->value.asMacro.SubType = HB_ET_MACRO_SYMBOL; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunCall(&)")); - } - - if( pExpr == NULL ) - { - pExpr = hb_compExprNew( HB_ET_FUNCALL ); - pExpr->value.asFunCall.pParms = pParms; - pExpr->value.asFunCall.pFunName = pName; - } - - return pExpr; -} - -/* Creates a new literal array { item1, item2, ... itemN } - * 'pArrList' is a list of array elements - */ -HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArray()")); - - pArrList->ExprType = HB_ET_ARRAY; /* change type from ET_LIST */ - pArrList->ValType = HB_EV_ARRAY; - pArrList->ulLength = 0; - - pExpr = pArrList->value.asList.pExprList; /* get first element on the list */ - /* Now we need to replace all EO_NONE expressions with ET_NIL expressions - * If EO_NONE is the first expression and there is no more expressions - * then it is an empty array {} and ET_NIL cannot be used - */ - if( pExpr->ExprType == HB_ET_NONE && pExpr->pNext == NULL ) - { - pArrList->value.asList.pExprList = NULL; - } - else - { - /* there are at least one non-empty element specified - */ - while( pExpr ) - { - /* if empty element was specified replace it with NIL value */ - if( pExpr->ExprType == HB_ET_NONE ) - pExpr->ExprType = HB_ET_NIL; - pExpr = pExpr->pNext; - ++pArrList->ulLength; - } - } - pArrList->value.asList.pIndex = NULL; - return pArrList; -} - -/* Creates new array access expression - * pArray[ pIndex ] - * NOTE: In case of multiple indexes it is called recursively - * array[ idx1, idx2 ] => ( array[ idx1 ] )[ idx2 ] - */ -#ifdef HB_MACRO_SUPPORT -HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex, HB_MACRO_DECL ) -#else -HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex ) -#endif -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArrayAt()")); - - pExpr = hb_compExprNew( HB_ET_ARRAYAT ); - - /* Check if this expression can be indexed */ - HB_EXPR_USE( pArray, HB_EA_ARRAY_AT ); - /* Check if this expression can be an index */ - HB_EXPR_USE( pIndex, HB_EA_ARRAY_INDEX ); - pExpr->value.asList.pExprList = pArray; - pExpr->value.asList.pIndex = pIndex; - - return pExpr; -} - -/* Creates new macro expression - */ -HB_EXPR_PTR hb_compExprNewMacro( HB_EXPR_PTR pMacroExpr, unsigned char cMacroOp, char * szName ) -{ - HB_EXPR_PTR pExpr; - - if( szName ) - { - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewMacro(%s)", szName)); - - /* Macro variable is used: &identifier - * or macro text: [text]&variable[more_macro_text] - */ - /* - * NOTE: Clipper assumes that all variables used in macro expressions - * are memvar variables - * NOTE: Clipper pushes the complete macro expression converted - * to string in case complex expression is used, e.g. - * My&var.1 - * is pushed as: - * "MY&VAR.1" - */ - pExpr = hb_compExprNew( HB_ET_MACRO ); - pExpr->value.asMacro.cMacroOp = cMacroOp; /* '&' if variable or 0 if text */ - pExpr->value.asMacro.szMacro = szName; /* variable name or macro text */ - pExpr->value.asMacro.pExprList = NULL; /* this is not a parenthesized expressions */ - pExpr->value.asMacro.SubType = HB_ET_MACRO_VAR; - - if( cMacroOp == 0 ) - { - /* check if variable with valid scope is used in macro text - * (local, static and field variables are not allowed) - * e.g. - * LOCAL var - * ? &var // this is OK - * ? &var.ext // this is invalid - */ - hb_compExprCheckMacroVar( szName ); - } - } - else - { - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewMacro(&)")); - - /* Macro expression: &( expression_list ) - */ - pExpr = hb_compExprNew( HB_ET_MACRO ); - pExpr->value.asMacro.pExprList = pMacroExpr; - pExpr->value.asMacro.szMacro = NULL; /* this is used to distinguish &(...) from &ident */ - pExpr->value.asMacro.SubType = HB_ET_MACRO_EXPR; - } - - return pExpr; -} - -/* Creates new aliased variable - * aliasexpr -> identifier - */ -HB_EXPR_PTR hb_compExprNewAliasVar( HB_EXPR_PTR pAlias, HB_EXPR_PTR pVariable ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAliasVar()")); - - pExpr = hb_compExprNew( HB_ET_ALIASVAR ); - - pExpr->value.asAlias.pAlias = pAlias; - pExpr->value.asAlias.pVar = pVariable; - pExpr->value.asAlias.pExpList = NULL; - - /* macro expressions in alias context require a special handling - */ - if( pAlias->ExprType == HB_ET_MACRO ) - pAlias->value.asMacro.SubType = HB_ET_MACRO_ALIASED; - if( pVariable->ExprType == HB_ET_MACRO ) - pVariable->value.asMacro.SubType = HB_ET_MACRO_ALIASED; - - return pExpr; -} - -/* Creates new aliased expression - * alias_expr -> ( expression ) - */ -HB_EXPR_PTR hb_compExprNewAliasExpr( HB_EXPR_PTR pAlias, HB_EXPR_PTR pExpList ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAliasExpr()")); - - pExpr = hb_compExprNew( HB_ET_ALIASEXPR ); - - pExpr->value.asAlias.pAlias = pAlias; - pExpr->value.asAlias.pExpList = pExpList; - pExpr->value.asAlias.pVar = NULL; - - return pExpr; -} - -/* Creates new send expression - * pObject : szMessage - */ -HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR pObject, char * szMessage ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewSend(%p, %s)", pObject, szMessage)); - - pExpr = hb_compExprNew( HB_ET_SEND ); - pExpr->value.asMessage.szMessage = szMessage; - pExpr->value.asMessage.pObject = pObject; - pExpr->value.asMessage.pParms = NULL; - - return pExpr; -} - -/* Creates new method call - * pObject : identifier ( pArgList ) - * - * pObject = is an expression returned by hb_compExprNewSend - * pArgList = list of passed arguments - it will be HB_ET_NONE if no arguments - * are passed - */ -HB_EXPR_PTR hb_compExprNewMethodCall( HB_EXPR_PTR pObject, HB_EXPR_PTR pArgList ) -{ - pObject->value.asMessage.pParms = pArgList; - - return pObject; -} - -/* Creates a list - all elements will be used - * This list can be used to create an array or function's call arguments - */ -HB_EXPR_PTR hb_compExprNewList( HB_EXPR_PTR pFirstItem ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewList()")); - - pExpr = hb_compExprNew( HB_ET_LIST ); - pExpr->value.asList.pExprList = pFirstItem; - return pExpr; -} - -/* Creates a list of function call arguments - */ -HB_EXPR_PTR hb_compExprNewArgList( HB_EXPR_PTR pFirstItem ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArgList()")); - - pExpr = hb_compExprNew( HB_ET_ARGLIST ); - pExpr->value.asList.pExprList = pFirstItem; - return pExpr; -} - -/* Adds new element to the list - */ -HB_EXPR_PTR hb_compExprAddListExpr( HB_EXPR_PTR pList, HB_EXPR_PTR pNewItem ) -{ - if( pList->value.asList.pExprList ) - { - HB_EXPR_PTR pExpr; - - /* add new item to the end of the list */ - pExpr = pList->value.asList.pExprList; - while( pExpr->pNext ) - pExpr = pExpr->pNext; - pExpr->pNext = pNewItem; - } - else - pList->value.asList.pExprList = pNewItem; - - return pList; -} - -HB_EXPR_PTR hb_compExprNewVar( char * szName ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewVar(%s)", szName)); - - pExpr = hb_compExprNew( HB_ET_VARIABLE ); - pExpr->value.asSymbol = szName; - return pExpr; -} - -/* Create a new declaration of PUBLIC or PRIVATE variable. - * - * szName is a string with variable name if 'PUBLIC varname' context - * pMacroVar is a macro expression if 'PUBLIC &varname' context - */ -HB_EXPR_PTR hb_compExprNewRTVar( char * szName, HB_EXPR_PTR pMacroVar ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewRTVar(%s, %p)", szName, pMacroVar)); - - pExpr = hb_compExprNew( HB_ET_RTVAR ); - pExpr->value.asRTVar.szName = szName; - pExpr->value.asRTVar.pMacro = pMacroVar; - if( pMacroVar ) - pMacroVar->value.asMacro.SubType = HB_ET_MACRO_SYMBOL; - return pExpr; -} - -/* Create a new symbol used in function calls - */ -HB_EXPR_PTR hb_compExprNewFunName( char * szName ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunName(%s)", szName)); - - pExpr = hb_compExprNew( HB_ET_FUNNAME ); - pExpr->value.asSymbol = szName; - return pExpr; -} - -/* Create a new symbol used in an alias expressions - */ -HB_EXPR_PTR hb_compExprNewAlias( char * szName ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAlias(%s)", szName)); - - pExpr = hb_compExprNew( HB_ET_ALIAS ); - pExpr->value.asSymbol = szName; - return pExpr; -} - - -/* ************************************************************************* */ - -HB_EXPR_PTR hb_compExprNewEqual( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EQUAL ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewPlus( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PLUS ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewMinus( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MINUS ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewMult( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MULT ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewDiv( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_DIV ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewMod( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MOD ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewPower( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POWER ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewPostInc( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POSTINC ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewPostDec( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POSTDEC ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewPreInc( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PREINC ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewPreDec( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PREDEC ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewPlusEq( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PLUSEQ ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewMinusEq( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MINUSEQ ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewMultEq( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MULTEQ ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewDivEq( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_DIVEQ ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewModEq( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MODEQ ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewExpEq( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EXPEQ ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewAnd( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_AND ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewOr( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_OR ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewNot( HB_EXPR_PTR pNotExpr ) -{ - HB_EXPR_PTR pExpr; - - if( pNotExpr->ExprType == HB_ET_LOGICAL ) - { - pNotExpr->value.asLogical = ! pNotExpr->value.asLogical; - pExpr = pNotExpr; - } - else - { - pExpr = hb_compExprNew( HB_EO_NOT ); - pExpr->value.asOperator.pLeft = pNotExpr; - pExpr->value.asOperator.pRight = NULL; - } - - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewEQ( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EQ ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewLT( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_LT ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewGT( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_GT ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewLE( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_LE ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewGE( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_GE ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewNE( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_NE ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -HB_EXPR_PTR hb_compExprNewIN( HB_EXPR_PTR pLeftExpr ) -{ - HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_IN ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = NULL; - return pExpr; -} - -/* NOTE: all invalid cases are handled by yacc rules - */ -HB_EXPR_PTR hb_compExprNewNegate( HB_EXPR_PTR pNegExpr ) -{ - HB_EXPR_PTR pExpr; - - if( pNegExpr->ExprType == HB_ET_NUMERIC ) - { - if( pNegExpr->value.asNum.NumType == HB_ET_DOUBLE ) - pNegExpr->value.asNum.dVal = - pNegExpr->value.asNum.dVal; - else - pNegExpr->value.asNum.lVal = - pNegExpr->value.asNum.lVal; - pExpr = pNegExpr; - } - else - { - pExpr = hb_compExprNew( HB_EO_NEGATE ); - pExpr->value.asOperator.pLeft = pNegExpr; - pExpr->value.asOperator.pRight = NULL; - } - return pExpr; -} - - -/* ************************************************************************* */ - -/* Handles (expression := expression) syntax - */ -HB_EXPR_PTR hb_compExprAssign( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprAssign()")); - - pExpr = hb_compExprNew( HB_EO_ASSIGN ); - pExpr->value.asOperator.pLeft = pLeftExpr; - pExpr->value.asOperator.pRight = pRightExpr; - return pExpr; -} - -/* It initializes static variable. - * It is called in the following context: - * STATIC sVar := expression - * - * pLeftExpr - is a variable name - * pRightExpr - can be an expression of any type - */ -#ifndef HB_MACRO_SUPPORT -HB_EXPR_PTR hb_compExprAssignStatic( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprAssignStatic()")); - - pExpr = hb_compExprNew( HB_EO_ASSIGN ); - - pExpr->value.asOperator.pLeft = pLeftExpr; - /* Try to reduce the assigned value */ - pRightExpr = hb_compExprListStrip( HB_EXPR_USE( pRightExpr, HB_EA_REDUCE ) ); - pExpr->value.asOperator.pRight = pRightExpr; - - if( pRightExpr->ExprType == HB_ET_ARGLIST ) - { - /* HB_ET_ARGLIST is used in case of STATIC var[dim1, dim2, dimN] - * was used - we have to check if all array dimensions are - * constant values - */ - hb_compExprCheckStaticInitializers( pLeftExpr, pRightExpr ); - } - else if( pRightExpr->ExprType > HB_ET_FUNREF ) - { - /* Illegal initializer for static variable (not a constant value) - */ - hb_compErrorStatic( pLeftExpr->value.asSymbol, pRightExpr ); - } - else if( pRightExpr->ExprType == HB_ET_ARRAY ) - { - /* { elem1, elem2, elemN } was used as initializer - * Scan an array for illegal initializers. - * An array item have to be a const value too. - */ - hb_compExprCheckStaticInitializers( pLeftExpr, pRightExpr ); - } - - return pExpr; -} -#endif - - -/* Sets the argument of an operation found previously - */ -#ifdef HB_MACRO_SUPPORT -HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem, HB_MACRO_DECL ) -#else -HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem ) -#endif -{ - BYTE ucRight; - - ucRight = s_PrecedTable[ pItem->ExprType ]; - if( ucRight == HB_ET_NIL ) - { - /* the right side of an operator is an ordinary value - * e.g. a := 1 - */ - pExpr->value.asOperator.pRight = pItem; - } - else if( ucRight == HB_ET_NONE ) - { - /* the right side of an operator is an invalid expression - * e.g. - * a := 1 + b:=2 - * a := 1 + b += 2 - */ - hb_compErrorSyntax( pItem ); - } - else - { - /* the right side of an operator is an expression with other operator - * e.g. a := 2 + b * 3 - * We have to set the proper order of evaluation using - * precedence rules - */ - BYTE ucLeft = s_PrecedTable[ pExpr->ExprType ]; - if( ucLeft >= ucRight ) - { - /* Left operator has the same or lower precedence then the right one - * e.g. a * b + c - * pItem -> b + c -> L=b R=c O=+ - * pExpr -> a * -> l=a r= o=* - * - * -> (a * b) + c -> Lelf=(a * b) Right=c Oper=+ - * Left := l (o) L - * Right := R - * Oper := O - */ -#ifdef HB_MACRO_SUPPORT - pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft, HB_MACRO_PARAM ); -#else - pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft ); -#endif - pExpr = pItem; - } - else - { - /* Left operator has a lower precedence then the right one - * e.g. a + b * c - * pItem -> b * c -> L=b R=c O=* - * pExpr -> a + -> l=a r= o=+ - * - * -> a + (b * c) -> Left=a Right=(b * c) Oper=+ - * Left := l - * Right := L (O) R := pItem - * Oper := o - */ - pExpr->value.asOperator.pRight = pItem; - } - } - - return pExpr; -} - -/* Return a number of elements on the linked list - */ -ULONG hb_compExprListLen( HB_EXPR_PTR pExpr ) -{ - ULONG ulLen = 0; - - pExpr = pExpr->value.asList.pExprList; - while( pExpr ) - { - pExpr = pExpr->pNext; - ++ulLen; - } - - return ulLen; -} - -/* ************************************************************************* */ - -/* Generates pcode for inline expression used as a statement - * NOTE: It doesn't not leave any value on the eval stack - */ -#ifdef HB_MACRO_SUPPORT -HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) -#else -HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr ) -#endif -{ - HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenStatement(%i)", pExpr->ExprType)); - - pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); - HB_EXPR_USE( pExpr, HB_EA_STATEMENT ); - return pExpr; -} - -/* Generates pcode to push an expressions - * NOTE: It pushes a value on the stack and leaves this value on the stack - */ -#ifdef HB_MACRO_SUPPORT -HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) -#else -HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr ) -#endif -{ - HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenPush(%i)", pExpr->ExprType)); - - pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); - HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); - return pExpr; -} - -/* Generates pcode to pop an expressions - */ -#ifdef HB_MACRO_SUPPORT -HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) -#else -HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr ) -#endif -{ - HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenPop(%i)", pExpr->ExprType)); - - return HB_EXPR_USE( pExpr, HB_EA_POP_PCODE ); -} - - -/* ************************************************************************* */ - -static HB_EXPR_FUNC( hb_compExprUseDummy ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - break; - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf); - case HB_EA_ARRAY_INDEX: - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - hb_compGenPCode1( 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_compErrorType( pSelf ); - break; - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); /* NIL cannot be used as index element */ - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - hb_compGenPCode1( HB_P_PUSHNIL ); - break; - case HB_EA_POP_PCODE: - break; - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compWarnMeaningless( 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_compErrorType( pSelf ); - break; - case HB_EA_ARRAY_INDEX: - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - if( pSelf->value.asNum.NumType == HB_ET_DOUBLE ) - hb_compGenPushDouble( pSelf->value.asNum.dVal, pSelf->value.asNum.bDec ); - else - hb_compGenPushLong( pSelf->value.asNum.lVal ); - break; - case HB_EA_POP_PCODE: - break; - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compWarnMeaningless( 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_compErrorType( pSelf ); - break; - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); /* string cannot be used as index element */ - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - { - hb_compGenPushString( pSelf->value.asString, pSelf->ulLength ); -#ifndef HB_MACRO_SUPPORT -/* only memvar variables are allowed in macro compilation - there is no - * need to check for locals or static variables - */ - if( hb_compExprCheckMacroVar( pSelf->value.asString ) ) - hb_compGenPCode1( HB_P_MACROTEXT ); -#endif - } - break; - case HB_EA_POP_PCODE: - break; - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compWarnMeaningless( pSelf ); - break; - case HB_EA_DELETE: - HB_XFREE( pSelf->value.asString ); - 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_compErrorType( pSelf ); - break; - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); /* codeblock cannot be used as index element */ - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - { - HB_EXPR_PTR pExpr, pNext; - HB_EXPR_PTR * pPrev; -#ifndef HB_MACRO_SUPPORT - HB_CBVAR_PTR pVar; -#endif - - hb_compCodeBlockStart(); - /* Define requested local variables - */ -#ifdef HB_MACRO_SUPPORT - HB_PCODE_DATA->pLocals = ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex; -#else - pVar = ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex; - while( pVar ) - { - hb_compVariableAdd( pVar->szName, pVar->bType ); - pVar =pVar->pNext; - } -#endif - pExpr = pSelf->value.asList.pExprList; - pPrev = &pSelf->value.asList.pExprList; - while( pExpr ) - { - /* 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( pNext ) - HB_EXPR_USE( pExpr, HB_EA_PUSH_POP ); - else - HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); - pPrev = &pExpr->pNext; - pExpr = pNext; - } - hb_compCodeBlockEnd(); - } - break; - case HB_EA_POP_PCODE: - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compWarnMeaningless( pSelf ); - break; - case HB_EA_DELETE: - hb_compExprCBVarDel( ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex ); - hb_compExprDelete( pSelf->value.asList.pExprList ); - 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_compErrorType( pSelf ); - break; - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); /* logical cannot be used as array index element */ - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - hb_compGenPushLogical( pSelf->value.asLogical ); - break; - case HB_EA_POP_PCODE: - break; - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compWarnMeaningless( 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: - hb_compErrorType( pSelf ); /* QUESTION: Is this OK ? */ - break; - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); /* SELF cannot be used as array index element */ - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - hb_compGenPCode1( HB_P_PUSHSELF ); - break; - case HB_EA_POP_PCODE: - break; - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compWarnMeaningless( 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: - hb_compExprListReduce( pSelf ); - break; - - case HB_EA_ARRAY_AT: - break; - - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); /* array cannot be used as index element */ - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - { - HB_EXPR_PTR pElem = pSelf->value.asList.pExprList; - /* Push all elements of the array - */ - if( ( pElem == NULL ) || ( pElem->ExprType == HB_ET_NONE && pElem->pNext == NULL ) ) - hb_compGenPCode3( HB_P_ARRAYGEN, 0, 0 ); - else - { - while( pElem ) - { - HB_EXPR_USE( pElem, HB_EA_PUSH_PCODE ); - pElem = pElem->pNext; - } - hb_compGenPCode3( HB_P_ARRAYGEN, HB_LOBYTE( pSelf->ulLength ), HB_HIBYTE( pSelf->ulLength ) ); - } - } - 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( 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_compExprDelete( 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_compErrorType( pSelf ); - break; - case HB_EA_ARRAY_INDEX: - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - hb_compGenPushVarRef( pSelf->value.asSymbol ); - break; - case HB_EA_POP_PCODE: - break; - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compWarnMeaningless( 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_compErrorType( pSelf ); - break; - case HB_EA_ARRAY_INDEX: - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - hb_compGenPushFunCall( pSelf->value.asSymbol ); - hb_compGenPCode1( HB_P_FUNCPTR ); - break; - case HB_EA_POP_PCODE: - break; - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compWarnMeaningless( pSelf ); - case HB_EA_DELETE: - break; - } - return pSelf; -} - -/* actions for HB_ET_IIF expression - */ -static HB_EXPR_FUNC( hb_compExprUseIIF ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pExpr; - - hb_compExprListReduce( pSelf ); - - pExpr =pSelf->value.asList.pExprList; /* get conditional expression */ - if( pExpr->ExprType == HB_ET_LOGICAL ) - { - /* the condition was reduced to a logical value: .T. or .F. - */ - if( pExpr->value.asLogical ) - { - /* .T. was specified - */ - pExpr = pExpr->pNext; /* skip to TRUE expression */ - /* delete condition - it is no longer needed - */ - hb_compExprDelete( pSelf->value.asList.pExprList ); - /* assign NULL to a start of expressions list to suppress - * deletion of expression's components - we are deleting them - * here - */ - pSelf->value.asList.pExprList = NULL; - hb_compExprDelete( pSelf ); - /* store the TRUE expression as a result of reduction - */ - pSelf = pExpr; - pExpr = pExpr->pNext; /* skip to FALSE expression */ - hb_compExprDelete( pExpr ); /* delete FALSE expr */ - pSelf->pNext = NULL; - } - else - { - /* .F. was specified - */ - pExpr = pExpr->pNext; /* skip to TRUE expression */ - /* delete condition - it is no longer needed - */ - hb_compExprDelete( pSelf->value.asList.pExprList ); - /* assign NULL to a start of expressions list to suppress - * deletion of expression's components - we are deleting them - * here - */ - pSelf->value.asList.pExprList = NULL; - hb_compExprDelete( pSelf ); - /* store the FALSE expression as a result of reduction - */ - pSelf = pExpr->pNext; - hb_compExprDelete( pExpr ); /* delete TRUE expr */ - pSelf->pNext = NULL; - } - } - /* check if valid expression is passed - */ - else if( ( pExpr->ExprType == HB_ET_DOUBLE ) || - ( pExpr->ExprType == HB_ET_LONG ) || - ( pExpr->ExprType == HB_ET_NIL ) || - ( pExpr->ExprType == HB_ET_STRING ) || - ( pExpr->ExprType == HB_ET_CODEBLOCK ) || - ( pExpr->ExprType == HB_ET_SELF ) || - ( pExpr->ExprType == HB_ET_ARRAY ) ) - { - hb_compErrorType( pExpr ); - } - } - break; - - case HB_EA_ARRAY_AT: - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenJumpFalse( 0 ); - pExpr =pExpr->pNext; - - HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); - lPosEnd = hb_compGenJump( 0 ); - pExpr =pExpr->pNext; - - hb_compGenJumpHere( lPosFalse ); - HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); - hb_compGenJumpHere( lPosEnd ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - { - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); /* remove a value if used in 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_compExprDelete( 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: - { - hb_compExprListReduce( pSelf ); - /* NOTE: if the list contains a single expression then the list - * is not reduced to this expression - if you need that reduction - * then call hb_compExprListStrip() additionaly - */ - } - 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( pSelf->value.asList.pExprList ); - } - else - hb_compErrorLValue( 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_compErrorSyntax( pExpr ); - } - else - { - while( pExpr ) - { - 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 ) - { - 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_compExprDelete( 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: - hb_compExprListReduce( pSelf ); - 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; - - 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_compExprDelete( 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; - - 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 */ - - if( pExpr->ExprType == HB_ET_ARRAY ) /* is it a literal array */ - { - LONG lIndex; - - pExpr = pExpr->value.asList.pExprList; /* the first element in the array */ - if( pIdx->value.asNum.NumType == HB_ET_LONG ) - lIndex = pIdx->value.asNum.lVal; - else - lIndex = ( LONG ) pIdx->value.asNum.dVal; - - if( lIndex > 0 ) - { - while( --lIndex && pExpr ) - pExpr = pExpr->pNext; - } - else - pExpr = NULL; /* index is <= 0 - generate bound error */ - - if( pExpr ) /* found ? */ - { - /* extract a single expression from the array - */ - HB_EXPR_PTR pNew = hb_compExprNew( 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_compExprDelete( pSelf ); - pSelf = pNew; - } - else - { - hb_compErrorBound( pIdx ); - } - } - else - { - LONG lIndex; - - if( pIdx->value.asNum.NumType == HB_ET_LONG ) - lIndex = pIdx->value.asNum.lVal; - else - lIndex = ( LONG ) pIdx->value.asNum.dVal; - - if( lIndex > 0 ) - HB_EXPR_USE( pExpr, HB_EA_ARRAY_AT ); - else - hb_compErrorBound( pIdx ); /* index <= 0 - bound error */ - } - } - } - break; - - case HB_EA_ARRAY_AT: - case HB_EA_ARRAY_INDEX: - case HB_EA_LVALUE: - break; - case HB_EA_PUSH_PCODE: - { - HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_ARRAYPUSH ); - } - break; - - case HB_EA_POP_PCODE: - { - HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( 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( pSelf ); - break; - case HB_EA_DELETE: - hb_compExprDelete( pSelf->value.asList.pExprList ); - hb_compExprDelete( pSelf->value.asList.pIndex ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseMacro ) -{ - 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.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_compGenPushVar( pSelf->value.asMacro.szMacro ); - } - else - { - /* complex macro expression: prefix&var.suffix - * all components should be placed as a string that will - * be compiled after text susbstitution - */ - hb_compGenPushString( pSelf->value.asMacro.szMacro, strlen(pSelf->value.asMacro.szMacro) ); - } - } - /* compile & run - leave a result on the eval stack - */ - if( pSelf->value.asMacro.SubType == HB_ET_MACRO_SYMBOL ) - hb_compGenPCode1( HB_P_MACROSYMBOL ); - else if( pSelf->value.asMacro.SubType != HB_ET_MACRO_ALIASED ) - hb_compGenPCode1( HB_P_MACROPUSH ); - /* 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_compGenPushVar( pSelf->value.asMacro.szMacro ); - } - else - { - /* complex macro expression: prefix&var.suffix - * all components should be placed as a string that will - * be compiled after text susbstitution - */ - hb_compGenPushString( pSelf->value.asMacro.szMacro, strlen(pSelf->value.asMacro.szMacro) ); - } - } - /* 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_compGenPCode1( HB_P_MACROPOP ); - } - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); - break; - - case HB_EA_DELETE: - if( pSelf->value.asMacro.pExprList ) - hb_compExprDelete( pSelf->value.asMacro.pExprList ); -/* NOTE: This will be released during releasing of symbols' table - * - * if( pSelf->value.asMacro.szMacro ); - * HB_XFREE( pSelf->value.asMacro.szMacro ); - */ - 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 ); - } - break; - - case HB_EA_ARRAY_AT: - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - { - USHORT usCount; - - HB_EXPR_USE( pSelf->value.asFunCall.pFunName, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_PUSHNIL ); - - if( pSelf->value.asFunCall.pParms ) - { - /* NOTE: pParms will be NULL in 'DO procname' (if there is - * no WITH keyword) - */ - usCount = ( USHORT ) hb_compExprListLen( pSelf->value.asFunCall.pParms ); - if( usCount == 1 && pSelf->value.asFunCall.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) - --usCount; - if( usCount ) - HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_PUSH_PCODE ); - } - else - usCount = 0; - hb_compGenPCode3( HB_P_FUNCTION, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - { - USHORT usCount; - - HB_EXPR_USE( pSelf->value.asFunCall.pFunName, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_PUSHNIL ); - - if( pSelf->value.asFunCall.pParms ) - { - usCount = ( USHORT ) hb_compExprListLen( pSelf->value.asFunCall.pParms ); - if( usCount == 1 && pSelf->value.asFunCall.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) - --usCount; - if( usCount ) - HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_PUSH_PCODE ); - } - else - usCount = 0; - hb_compGenPCode3( HB_P_DO, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) ); - } - break; - - case HB_EA_DELETE: - if( pSelf->value.asFunCall.pParms ) - hb_compExprDelete( pSelf->value.asFunCall.pParms ); - hb_compExprDelete( pSelf->value.asFunCall.pFunName ); - break; - } - return pSelf; -} - -/* handler for expression->identifier syntax - */ -static HB_EXPR_FUNC( hb_compExprUseAliasVar ) -{ - 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_EXPR_PTR pAlias = pSelf->value.asAlias.pAlias; - BOOL bReduced = FALSE; - - if( pAlias->ExprType == HB_ET_LIST ) - { - /* ( expr1, expr2, ... )->variable - */ - pSelf->value.asAlias.pAlias = HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_REDUCE ); - bReduced = TRUE; - } - - 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_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_compGenPushAliasedVar( 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_compGenPushAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, TRUE, NULL, pAlias->value.asNum.lVal ); - else - hb_compErrorAlias( pAlias ); - } - else if( bReduced ) - { - /* - * ( expression )->var - * - * NOTE: FALSE = don't push alias value - */ - HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); - hb_compGenPushAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, FALSE, NULL, 0 ); - } - else - hb_compErrorAlias( pAlias ); - } - break; - - case HB_EA_POP_PCODE: - { - HB_EXPR_PTR pAlias = pSelf->value.asAlias.pAlias; - BOOL bReduced = FALSE; - - if( pAlias->ExprType == HB_ET_LIST ) - { - pSelf->value.asAlias.pAlias = HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_REDUCE ); - bReduced = TRUE; - } - - 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_compExprUseAliasMacro( pSelf, HB_EA_POP_PCODE ); - } - else if( pAlias->ExprType == HB_ET_ALIAS ) - { - /* - * myalias->var - * FIELD->var - * MEMVAR->var - */ - hb_compGenPopAliasedVar( 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_compGenPopAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, TRUE, NULL, pAlias->value.asNum.lVal ); - else - hb_compErrorAlias( pAlias ); - } - else if( bReduced ) - { - /* - * ( expression )->var - * - * NOTE: FALSE = don't push alias value - */ - if( pAlias->ExprType == HB_ET_NONE ) - { - /* empty expression -> ()->var - */ - hb_compErrorAlias( pAlias ); - } - else - { - HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); - hb_compGenPopAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, FALSE, NULL, 0 ); - } - } - else - hb_compErrorAlias( pAlias ); - } - break; - - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); - break; - - case HB_EA_DELETE: - hb_compExprDelete( pSelf->value.asAlias.pAlias ); -#ifdef HB_MACRO_SUPPORT - if( pSelf->value.asAlias.pVar ) - hb_compExprDelete( pSelf->value.asAlias.pVar ); -#else - /* NOTE: variable name is not released now */ -#endif - break; - } - return pSelf; -} - -/* handler for expression->( exression, ... ) syntax - */ -static HB_EXPR_FUNC( hb_compExprUseAliasExpr ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - case HB_EA_ARRAY_AT: - case HB_EA_ARRAY_INDEX: - break; - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - { - /* save currently selected workarea - */ - hb_compGenPCode1( 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_compGenPCode1( 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_compGenPCode1( HB_P_SWAPALIAS ); - } - break; - - case HB_EA_POP_PCODE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - { - /* save currently selected workarea - */ - hb_compGenPCode1( 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_compGenPCode1( 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_compGenPCode1( HB_P_POPALIAS ); - } - break; - case HB_EA_DELETE: - hb_compExprDelete( pSelf->value.asAlias.pAlias ); - hb_compExprDelete( 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: -#ifdef HB_MACRO_SUPPORT - hb_compGenPushSymbol( pSelf->value.asSymbol ); -#else - hb_compGenPushSymbol( pSelf->value.asSymbol, FALSE ); -#endif - break; - case HB_EA_POP_PCODE: - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - break; - case HB_EA_DELETE: -#ifdef HB_MACRO_SUPPORT - hb_xfree( pSelf->value.asSymbol ); -#endif - 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_compGenPushFunCall( pSelf->value.asSymbol ); - break; - case HB_EA_POP_PCODE: - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - case HB_EA_DELETE: -#ifdef HB_MACRO_SUPPORT - HB_XFREE( pSelf->value.asSymbol ); -#endif - 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 ) -#ifndef HB_MACRO_SUPPORT - hb_compGenPushSymbol( pSelf->value.asRTVar.szName, 0 ); /* this is not a function name */ -#else - hb_compGenPushSymbol( pSelf->value.asRTVar.szName ); -#endif - else - HB_EXPR_USE( pSelf->value.asRTVar.pMacro, HB_EA_PUSH_PCODE ); - break; - case HB_EA_POP_PCODE: - if( pSelf->value.asRTVar.szName ) - hb_compGenPopVar( 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: - case HB_EA_DELETE: - 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: - -#ifdef 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_compGenPushAliasedVar( pSelf->value.asSymbol, FALSE, NULL, 0 ); - else - hb_compGenPushVar( pSelf->value.asSymbol ); -#else - hb_compGenPushVar( pSelf->value.asSymbol ); -#endif - break; - - case HB_EA_POP_PCODE: -#ifdef HB_MACRO_SUPPORT - if( HB_MACRO_DATA->Flags & HB_MACRO_GEN_ALIASED ) - hb_compGenPopAliasedVar( pSelf->value.asSymbol, FALSE, NULL, 0 ); - else - hb_compGenPopVar( pSelf->value.asSymbol ); -#else - hb_compGenPopVar( pSelf->value.asSymbol ); -#endif - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compGenPushVar( pSelf->value.asSymbol ); - hb_compGenPCode1( HB_P_POP ); - break; - - case HB_EA_DELETE: -#ifdef HB_MACRO_SUPPORT - HB_XFREE( pSelf->value.asSymbol ); -#else - /* NOTE: variable name will be released after pcode generation */ -#endif - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseSend ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - pSelf->value.asMessage.pObject = hb_compExprListStrip( 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: - case HB_EA_LVALUE: - break; - - case HB_EA_PUSH_PCODE: - { - if( pSelf->value.asMessage.pParms ) /* Is it a method call ? */ - { - int iParms = hb_compExprListLen( pSelf->value.asMessage.pParms ); - HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - hb_compGenMessage( pSelf->value.asMessage.szMessage ); - /* NOTE: if method with no parameters is called then the list - * of parameters contain only one expression of type HB_ET_NONE - * There is no need to push this parameter - */ - if( iParms == 1 && pSelf->value.asMessage.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) - --iParms; - if( iParms ) - HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE ); - hb_compGenPCode3( HB_P_FUNCTION, HB_LOBYTE( iParms ), HB_HIBYTE( iParms ) ); - } - else - { - /* acces to instance variable */ - HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - hb_compGenMessage( pSelf->value.asMessage.szMessage ); - hb_compGenPCode3( HB_P_FUNCTION, 0, 0 ); - } - } - break; - - case HB_EA_POP_PCODE: - { - /* NOTE: This is an exception from the rule - this leaves - * the return value on the stack - */ - HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - hb_compGenMessageData( pSelf->value.asMessage.szMessage ); - HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE ); - hb_compGenPCode3( HB_P_FUNCTION, 1, 0 ); - } - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( 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( pSelf ); - } - - case HB_EA_DELETE: -#ifdef HB_MACRO_SUPPORT - hb_compExprDelete( pSelf->value.asMessage.pObject ); - if( pSelf->value.asMessage.pParms ) - hb_compExprDelete( pSelf->value.asMessage.pParms ); - HB_XFREE( pSelf->value.asMessage.szMessage ); -#endif - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUsePostInc ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( 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( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - 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_compExprUsePreOp( pSelf, HB_P_INC ); - break; - - case HB_EA_DELETE: - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUsePostDec ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( 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( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - hb_compExprPushPostOp( pSelf, HB_P_DEC ); - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUsePreOp( pSelf, HB_P_DEC ); - break; - - case HB_EA_DELETE: - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseAssign ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( 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: - 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_compGenPCode1( HB_P_DUPLICATE ); - 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_compGenPCode1( 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_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUsePlusEq ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( 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_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - { - hb_compExprPushOperEq( pSelf, HB_P_PLUS ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUseOperEq( pSelf, HB_P_PLUS ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseMinusEq ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( 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_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - { - hb_compExprPushOperEq( pSelf, HB_P_MINUS ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUseOperEq( pSelf, HB_P_MINUS ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseMultEq ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( 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_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - { - hb_compExprPushOperEq( pSelf, HB_P_MULT ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUseOperEq( pSelf, HB_P_MULT ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseDivEq ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( 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_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - { - hb_compExprPushOperEq( pSelf, HB_P_DIVIDE ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUseOperEq( pSelf, HB_P_DIVIDE ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseModEq ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( 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_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - { - hb_compExprPushOperEq( pSelf, HB_P_MODULUS ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUseOperEq( pSelf, HB_P_MODULUS ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseExpEq ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( 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_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - { - hb_compExprPushOperEq( pSelf, HB_P_POWER ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUseOperEq( pSelf, HB_P_POWER ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseOr ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == HB_ET_LOGICAL && pRight->ExprType == HB_ET_LOGICAL ) - { - BOOL bResult; - - bResult = pLeft->value.asLogical || pRight->value.asLogical; - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - else if( pLeft->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) - { - if( pLeft->value.asLogical ) - { - /* .T. .OR. expr => .T. - */ - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); /* discard expression */ - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = TRUE; - } - else - { - /* .F. .OR. expr => expr - */ - hb_compExprDelete( pLeft ); - pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ - hb_compExprDelete( pSelf ); - pSelf = pRight; - } - } - else if( pRight->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) - { - if( pRight->value.asLogical ) - { - /* expr .OR. .T. => .T. - */ - hb_compExprDelete( pLeft ); /* discard expression */ - hb_compExprDelete( pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = TRUE; - } - else - { - /* expr .OR. .F. => expr - */ - hb_compExprDelete( pRight ); - pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ - hb_compExprDelete( pSelf ); - pSelf = pLeft; - } - } - - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - if( hb_comp_bShortCuts ) - { - LONG lEndPos; - - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_DUPLICATE ); - lEndPos = hb_compGenJumpTrue( 0 ); - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_OR ); - hb_compGenJumpHere( 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_compGenPCode1( HB_P_OR ); - } - break; - - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseAnd ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == HB_ET_LOGICAL && pRight->ExprType == HB_ET_LOGICAL ) - { - BOOL bResult; - - bResult = pLeft->value.asLogical && pRight->value.asLogical; - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - else if( pLeft->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) - { - if( pLeft->value.asLogical ) - { - /* .T. .AND. expr => expr - */ - hb_compExprDelete( pLeft ); - pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ - hb_compExprDelete( pSelf ); - pSelf = pRight; - } - else - { - /* .F. .AND. expr => .F. - */ - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); /* discard expression */ - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = FALSE; - } - } - else if( pRight->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) - { - if( pRight->value.asLogical ) - { - /* expr .AND. .T. => expr - */ - hb_compExprDelete( pRight ); - pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ - hb_compExprDelete( pSelf ); - pSelf = pLeft; - } - else - { - /* expr .AND. .F. => .F. - */ - hb_compExprDelete( pLeft ); /* discard expression */ - hb_compExprDelete( pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = FALSE; - } - } - - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - if( hb_comp_bShortCuts ) - { - LONG lEndPos; - - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_DUPLICATE ); - lEndPos = hb_compGenJumpFalse( 0 ); - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_AND ); - hb_compGenJumpHere( 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_compGenPCode1( HB_P_AND ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - 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_compExprListStrip( 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_compExprDelete( pSelf ); - pSelf = pExpr; - } - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - hb_compErrorIndex( pSelf ); - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_NOT ); - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseEqual ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - } - break; - - case HB_EA_ARRAY_AT: - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - { - /* '=' used in an expression - compare values - */ - /* Try to optimize expression - we cannot optimize in HB_EA_REDUCE - * because it is not decided yet if it is assigment or comparision - */ - HB_EXPR_PTR pLeft, pRight; - - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == pRight->ExprType ) - switch( pLeft->ExprType ) - { - case HB_ET_LOGICAL: - hb_compGenPushLogical( pLeft->value.asLogical == pRight->value.asLogical ); - break; - - case HB_ET_STRING: - /* NOTE: the result depends on SET EXACT setting then it - * cannot be optimized except the case when NULL string are - * compared - the result is always TRUE regardless of EXACT - * setting - */ - if( (pLeft->ulLength | pRight->ulLength) == 0 ) - hb_compGenPushLogical( TRUE ); /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ - else - { - HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_EQUAL ); - } - break; - - case HB_ET_NIL: - /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ - hb_compGenPushLogical( TRUE ); /* NIL = NIL is always TRUE */ - break; - - case HB_ET_NUMERIC: - switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) - { - case HB_ET_LONG: - hb_compGenPushLogical( pLeft->value.asNum.lVal == pRight->value.asNum.lVal ); - break; - case HB_ET_DOUBLE: - hb_compGenPushLogical( pLeft->value.asNum.dVal == pRight->value.asNum.dVal ); - break; - default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - hb_compGenPushLogical( pLeft->value.asNum.lVal == pRight->value.asNum.dVal ); - else - hb_compGenPushLogical( pLeft->value.asNum.dVal == pRight->value.asNum.lVal ); - } - break; - } - break; - - default: - { - HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_EQUAL ); - } - } - else - { - /* TODO: check for incompatible types - */ - HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_EQUAL ); - } - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - { - /* '=' used standalone in a statement - assign a value - * it assigns a value and removes it from the stack - * */ - if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) - { - /* Send messages are implemented as function calls - */ - 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_compGenPCode1( HB_P_POP ); - } - else - { - 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_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -/* handler for == operator - */ -static HB_EXPR_FUNC( hb_compExprUseEQ ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == pRight->ExprType ) - { - switch( pLeft->ExprType ) - { - case HB_ET_LOGICAL: - { - BOOL bResult = ( pLeft->value.asLogical == pRight->value.asLogical ); - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - case HB_ET_STRING: - { - BOOL bResult = FALSE; - - if( pLeft->ulLength == pRight->ulLength ) - bResult = ( strcmp( pLeft->value.asString, pRight->value.asString ) == 0 ); - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - case HB_ET_NUMERIC: - { - BOOL bResult; - - switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) - { - case HB_ET_LONG: - bResult = ( pLeft->value.asNum.lVal == pRight->value.asNum.lVal ); - break; - case HB_ET_DOUBLE: - bResult = ( pLeft->value.asNum.dVal == pRight->value.asNum.dVal ); - break; - default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - bResult = ( pLeft->value.asNum.lVal == pRight->value.asNum.dVal ); - else - bResult = ( pLeft->value.asNum.dVal == pRight->value.asNum.lVal ); - } - break; - } - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - } - } - /* TODO: add checking of incompatible types - else - { - } - */ - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_EXACTLYEQUAL ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseLT ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == pRight->ExprType ) - switch( pLeft->ExprType ) - { - case HB_ET_LOGICAL: - { - /* .F. < .T. = .T. - * .T. < .T. = .F. - * .F. < .F. = .F. - * .T. < .F. = .F. - */ - BOOL bResult = ( ! pLeft->value.asLogical && pRight->value.asLogical ); - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - case HB_ET_NUMERIC: - { - BOOL bResult; - - switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) - { - case HB_ET_LONG: - bResult = ( pLeft->value.asNum.lVal < pRight->value.asNum.lVal ); - break; - case HB_ET_DOUBLE: - bResult = ( pLeft->value.asNum.dVal < pRight->value.asNum.dVal ); - break; - default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - bResult = ( pLeft->value.asNum.lVal < pRight->value.asNum.dVal ); - else - bResult = ( pLeft->value.asNum.dVal < pRight->value.asNum.lVal ); - } - break; - } - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - default: - break; - } - /* TODO: add checking of incompatible types - else - { - } - */ - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_LESS ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseGT ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == pRight->ExprType ) - switch( pLeft->ExprType ) - { - case HB_ET_LOGICAL: - { - /* .T. > .F. = .T. - * .T. > .T. = .F. - * .F. > .F. = .F. - * .F. > .T. = .F. - */ - BOOL bResult = ( pLeft->value.asLogical && ! pRight->value.asLogical ); - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - case HB_ET_NUMERIC: - { - BOOL bResult; - - switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) - { - case HB_ET_LONG: - bResult = ( pLeft->value.asNum.lVal > pRight->value.asNum.lVal ); - break; - case HB_ET_DOUBLE: - bResult = ( pLeft->value.asNum.dVal > pRight->value.asNum.dVal ); - break; - default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - bResult = ( pLeft->value.asNum.lVal > pRight->value.asNum.dVal ); - else - bResult = ( pLeft->value.asNum.dVal > pRight->value.asNum.lVal ); - } - break; - } - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - } - /* TODO: add checking of incompatible types - else - { - } - */ - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_GREATER ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseLE ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == pRight->ExprType ) - switch( pLeft->ExprType ) - { - case HB_ET_LOGICAL: - { - /* .T. <= .F. = .F. - * .T. <= .T. = .T. - * .F. <= .F. = .T. - * .F. <= .T. = .T. - */ - BOOL bResult = ! ( pLeft->value.asLogical && ! pRight->value.asLogical ); - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - case HB_ET_NUMERIC: - { - BOOL bResult; - - switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) - { - case HB_ET_LONG: - bResult = ( pLeft->value.asNum.lVal <= pRight->value.asNum.lVal ); - break; - case HB_ET_DOUBLE: - bResult = ( pLeft->value.asNum.dVal <= pRight->value.asNum.dVal ); - break; - default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - bResult = ( pLeft->value.asNum.lVal <= pRight->value.asNum.dVal ); - else - bResult = ( pLeft->value.asNum.dVal <= pRight->value.asNum.lVal ); - } - break; - } - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - } - /* TODO: add checking of incompatible types - else - { - } - */ - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_LESSEQUAL ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseGE ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == pRight->ExprType ) - switch( pLeft->ExprType ) - { - case HB_ET_LOGICAL: - { - /* .T. >= .F. = .T. - * .T. >= .T. = .T. - * .F. >= .F. = .T. - * .F. >= .T. = .f. - */ - BOOL bResult = ! ( ! pLeft->value.asLogical && pRight->value.asLogical ); - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - case HB_ET_NUMERIC: - { - BOOL bResult; - - switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) - { - case HB_ET_LONG: - bResult = ( pLeft->value.asNum.lVal >= pRight->value.asNum.lVal ); - break; - case HB_ET_DOUBLE: - bResult = ( pLeft->value.asNum.dVal >= pRight->value.asNum.dVal ); - break; - default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - bResult = ( pLeft->value.asNum.lVal >= pRight->value.asNum.dVal ); - else - bResult = ( pLeft->value.asNum.dVal >= pRight->value.asNum.lVal ); - } - break; - } - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - } - /* TODO: add checking of incompatible types - else - { - } - */ - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_GREATEREQUAL ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseNE ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == pRight->ExprType ) - switch( pLeft->ExprType ) - { - case HB_ET_LOGICAL: - { - /* .F. != .T. = .T. - * .T. != .T. = .F. - * .F. != .F. = .F. - * .T. != .F. = .T. - */ - BOOL bResult = ( pLeft->value.asLogical != pRight->value.asLogical ); - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - case HB_ET_STRING: - /* NOTE: the result depends on SET EXACT setting then it - * cannot be optimized except the case when NULL string are - * compared - "" != "" is always FALSE regardless of EXACT - * setting - */ - if( (pLeft->ulLength | pRight->ulLength) == 0 ) - hb_compGenPushLogical( FALSE ); /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ - break; - - case HB_ET_NUMERIC: - { - BOOL bResult; - - switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) - { - case HB_ET_LONG: - bResult = ( pLeft->value.asNum.lVal != pRight->value.asNum.lVal ); - break; - case HB_ET_DOUBLE: - bResult = ( pLeft->value.asNum.dVal != pRight->value.asNum.dVal ); - break; - default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - bResult = ( pLeft->value.asNum.lVal != pRight->value.asNum.dVal ); - else - bResult = ( pLeft->value.asNum.dVal != pRight->value.asNum.lVal ); - } - break; - } - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - break; - - } - /* TODO: add checking of incompatible types - else - { - } - */ - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_NOTEQUAL ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseIN ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - - if( ( pSelf->value.asOperator.pLeft->ExprType == pSelf->value.asOperator.pRight->ExprType ) && pSelf->value.asOperator.pLeft->ExprType == HB_ET_STRING ) - { - /* Both arguments are literal strings - */ - BOOL bResult; - - /* NOTE: CA-Cl*pper has a bug where the $ operator returns .T. - when an empty string is searched [vszakats] */ - - if( pSelf->value.asOperator.pLeft->ulLength == 0 ) - bResult = TRUE; - else - bResult = ( hb_strAt( pSelf->value.asOperator.pLeft->value.asString, pSelf->value.asOperator.pLeft->ulLength, - pSelf->value.asOperator.pRight->value.asString, pSelf->value.asOperator.pRight->ulLength ) != 0 ); - - /* NOTE: - * "" $ "XXX" = .T. - * "" $ "" = .T. - */ - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - hb_compExprDelete( pSelf->value.asOperator.pRight ); - pSelf->ExprType = HB_ET_LOGICAL; - pSelf->ValType = HB_EV_LOGICAL; - pSelf->value.asLogical = bResult; - } - /* TODO: add checking for incompatible types - */ - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_INSTRING ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUsePlus ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) - { - BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); - - switch( bType ) - { - case HB_ET_LONG: - { - double dVal = ( double ) pLeft->value.asNum.lVal + ( double ) pRight->value.asNum.lVal; - - if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) - { - pSelf->value.asNum.lVal = ( long ) dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_LONG; - } - else - { - pSelf->value.asNum.dVal = dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - } - - break; - } - - case HB_ET_DOUBLE: - { - pSelf->value.asNum.dVal = pLeft->value.asNum.dVal + pRight->value.asNum.dVal; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - if( pLeft->value.asNum.bDec < pRight->value.asNum.bDec ) - pSelf->value.asNum.bDec = pRight->value.asNum.bDec; - else - pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; - - break; - } - - default: - { - if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) - { - pSelf->value.asNum.dVal = pLeft->value.asNum.dVal + ( double ) pRight->value.asNum.lVal; - pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; - } - else - { - pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal + pRight->value.asNum.dVal; - pSelf->value.asNum.bDec = pRight->value.asNum.bDec; - } - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - } - } - pSelf->ExprType = HB_ET_NUMERIC; - pSelf->ValType = HB_EV_NUMERIC; - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); - } - else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING ) - { - pSelf->ExprType = HB_ET_NONE; /* suppress deletion of operator components */ - hb_compExprDelete( pSelf ); - if( pRight->ulLength == 0 ) - { - pSelf = pLeft; - hb_compExprDelete( pRight ); - } - else if( pLeft->ulLength == 0 ) - { - pSelf = pRight; - hb_compExprDelete( pLeft ); - } - else - { - pLeft->value.asString = (char *) hb_xrealloc( pLeft->value.asString, pLeft->ulLength + pRight->ulLength + 1 ); - memcpy( pLeft->value.asString + pLeft->ulLength, - pRight->value.asString, pRight->ulLength ); - pLeft->ulLength += pRight->ulLength; - pLeft->value.asString[ pLeft->ulLength ] = '\0'; - pSelf = pLeft; - hb_compExprDelete( pRight ); - } - } - else - { - /* TODO: Check for incompatible types e.g. "txt" + 3 - */ - } - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_PLUS ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseMinus ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) - { - BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); - - switch( bType ) - { - case HB_ET_LONG: - { - double dVal = ( double ) pLeft->value.asNum.lVal - ( double ) pRight->value.asNum.lVal; - - if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) - { - pSelf->value.asNum.lVal = ( long ) dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_LONG; - } - else - { - pSelf->value.asNum.dVal = dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - } - - break; - } - - case HB_ET_DOUBLE: - { - pSelf->value.asNum.dVal = pLeft->value.asNum.dVal - pRight->value.asNum.dVal; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - if( pLeft->value.asNum.bDec < pRight->value.asNum.bDec ) - pSelf->value.asNum.bDec = pRight->value.asNum.bDec; - else - pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; - - break; - } - - default: - { - if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) - { - pSelf->value.asNum.dVal = pLeft->value.asNum.dVal - ( double ) pRight->value.asNum.lVal; - pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; - } - else - { - pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal - pRight->value.asNum.dVal; - pSelf->value.asNum.bDec = pRight->value.asNum.bDec; - } - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - } - } - pSelf->ExprType = HB_ET_NUMERIC; - pSelf->ValType = HB_EV_NUMERIC; - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); - } - else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING ) - { - /* TODO: - */ - } - else - { - /* TODO: Check for incompatible types e.g. "txt" - 3 - */ - } - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_MINUS ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseMult ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) - { - BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); - - switch( bType ) - { - case HB_ET_LONG: - { - double dVal = ( double ) pLeft->value.asNum.lVal * ( double ) pRight->value.asNum.lVal; - - if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) - { - pSelf->value.asNum.lVal = ( long ) dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_LONG; - } - else - { - pSelf->value.asNum.dVal = dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - } - - break; - } - - case HB_ET_DOUBLE: - { - pSelf->value.asNum.dVal = pLeft->value.asNum.dVal * pRight->value.asNum.dVal; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - pSelf->value.asNum.bDec = pLeft->value.asNum.bDec + pRight->value.asNum.bDec; - - break; - } - - default: - { - if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) - { - pSelf->value.asNum.dVal = pLeft->value.asNum.dVal * ( double ) pRight->value.asNum.lVal; - pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; - } - else - { - pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal * pRight->value.asNum.dVal; - pSelf->value.asNum.bDec = pRight->value.asNum.bDec; - } - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - } - } - pSelf->ExprType = HB_ET_NUMERIC; - pSelf->ValType = HB_EV_NUMERIC; - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); - } - else - { - /* TODO: Check for incompatible types e.g. 3 * "txt" - */ - } - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_MULT ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseDiv ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) - { - BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); - - switch( bType ) - { - case HB_ET_LONG: - - if( pRight->value.asNum.lVal ) - { - double dVal = ( double ) pLeft->value.asNum.lVal / ( double ) pRight->value.asNum.lVal; - - if( fmod( dVal, 1.0 ) == 0.0 ) - { - /* Return integer results as long */ - pSelf->value.asNum.lVal = ( long ) dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_LONG; - } - else - { - /* Return non-integer results as double */ - pSelf->value.asNum.dVal = dVal; - pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - } - pSelf->ExprType = HB_ET_NUMERIC; - } - break; - - case HB_ET_DOUBLE: - - if( pRight->value.asNum.dVal != 0.0 ) - { - pSelf->value.asNum.dVal = pLeft->value.asNum.dVal / pRight->value.asNum.dVal; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; - pSelf->ExprType = HB_ET_NUMERIC; - } - break; - - default: - - if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) - { - if( pRight->value.asNum.lVal ) - { - pSelf->value.asNum.dVal = pLeft->value.asNum.dVal / ( double ) pRight->value.asNum.lVal; - pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; - } - } - else - { - if( pRight->value.asNum.dVal != 0.0 ) - { - pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal / pRight->value.asNum.dVal; - pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; - } - } - - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - pSelf->ExprType = HB_ET_NUMERIC; - - } /* switch bType */ - - if( pSelf->ExprType == HB_ET_NUMERIC ) - { - /* The expression was reduced - delete old components */ - pSelf->ValType = HB_EV_NUMERIC; - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); - } - } - else - { - /* TODO: Check for incompatible types e.g. 3 / "txt" - */ - } - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_DIVIDE ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseMod ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pLeft, pRight; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ) ); - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) - { - if( pLeft->value.asNum.NumType == HB_ET_LONG && pRight->value.asNum.NumType == HB_ET_LONG ) - { - if( pRight->value.asNum.lVal ) - { - double dVal = pLeft->value.asNum.lVal % pRight->value.asNum.lVal; - - if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) - { - pSelf->value.asNum.lVal = ( long ) dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_LONG; - } - else - { - pSelf->value.asNum.dVal = dVal; - pSelf->value.asNum.bDec = 0; - pSelf->value.asNum.NumType = HB_ET_DOUBLE; - } - - pSelf->ExprType = HB_ET_NUMERIC; - pSelf->ValType = HB_EV_NUMERIC; - hb_compExprDelete( pLeft ); - hb_compExprDelete( pRight ); - } - } - } - else - { - /* TODO: Check for incompatible types e.g. 3 % "txt" - */ - } - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_MODULUS ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUsePower ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: /* Clipper doesn't optimize it */ - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( 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_compGenPCode1( HB_P_POWER ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - case HB_EA_DELETE: - hb_compExprDelOperator( pSelf ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUseNegate ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - { - HB_EXPR_PTR pExpr; - - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ) ); - pExpr = pSelf->value.asOperator.pLeft; - - if( pExpr->ExprType == HB_ET_NUMERIC ) - { - if( pExpr->value.asNum.NumType == HB_ET_DOUBLE ) - pExpr->value.asNum.dVal = - pExpr->value.asNum.dVal; - else - pExpr->value.asNum.lVal = - pExpr->value.asNum.lVal; - pSelf->ExprType = HB_ET_NONE; /* do not delete operator parameter - we are still using it */ - hb_compExprDelete( pSelf ); - pSelf = pExpr; - } - } - break; - - case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - case HB_EA_PUSH_PCODE: - { - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_NEGATE ); - } - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); - hb_compGenPCode1( HB_P_POP ); -#else - /* 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 ); -#endif - break; - - case HB_EA_STATEMENT: - hb_compErrorSyntax( pSelf ); - break; - - case HB_EA_DELETE: - if( pSelf->value.asOperator.pLeft ) - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUsePreInc ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( 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_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - hb_compExprPushPreOp( pSelf, HB_P_INC ); - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUsePreOp( pSelf, HB_P_INC ); - break; - - case HB_EA_DELETE: - if( pSelf->value.asOperator.pLeft ) - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - break; - } - return pSelf; -} - -static HB_EXPR_FUNC( hb_compExprUsePreDec ) -{ - switch( iMessage ) - { - case HB_EA_REDUCE: - pSelf->value.asOperator.pLeft = hb_compExprListStrip( 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_compErrorType( pSelf ); - break; - - case HB_EA_ARRAY_INDEX: - break; - - case HB_EA_LVALUE: - hb_compErrorLValue( pSelf ); - break; - - case HB_EA_PUSH_PCODE: - hb_compExprPushPreOp( pSelf, HB_P_DEC ); - break; - - case HB_EA_POP_PCODE: - break; - - case HB_EA_PUSH_POP: - case HB_EA_STATEMENT: - hb_compExprUsePreOp( pSelf, HB_P_DEC ); - break; - - case HB_EA_DELETE: - if( pSelf->value.asOperator.pLeft ) - hb_compExprDelete( pSelf->value.asOperator.pLeft ); - break; - } - return pSelf; -} - -/* ************************************************************************* */ - -#ifdef HB_MACRO_SUPPORT -static void hb_compExprDelOperatorMC( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) -#else -static void hb_compExprDelOperator( HB_EXPR_PTR pExpr ) -#endif -{ - if( pExpr->value.asOperator.pLeft ) - hb_compExprDelete( pExpr->value.asOperator.pLeft ); - if( pExpr->value.asOperator.pRight ) - hb_compExprDelete( pExpr->value.asOperator.pRight ); -} - -/* Reduces the list of expressions - * - * pExpr is the first expression on the list - */ -#ifdef HB_MACRO_SUPPORT -static ULONG hb_compExprListReduceMC( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) -#else -static ULONG hb_compExprListReduce( HB_EXPR_PTR pExpr ) -#endif -{ - HB_EXPR_PTR pNext; - HB_EXPR_PTR * pPrev; - ULONG ulCnt = 0; - - /* NOTE: During optimalization an expression on the list can be - * replaced by the new one - */ - - pPrev = &pExpr->value.asList.pExprList; - pExpr = pExpr->value.asList.pExprList; - while( pExpr ) - { - pNext = pExpr->pNext; /* store next expression in case the current will be reduced */ - pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); - *pPrev = pExpr; /* store a new expression into the previous one */ - pExpr->pNext = pNext; /* restore the link to next expression */ - pPrev = &pExpr->pNext; - pExpr = pNext; - ++ulCnt; - } - return ulCnt; -} - -/* replace the list containing a single expression with a simple expression - * - strips parenthesis - * ( EXPR ) -> EXPR - */ -#ifdef HB_MACRO_SUPPORT -static HB_EXPR_PTR hb_compExprListStripMC( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) -#else -static HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR pSelf ) -#endif -{ - - if( pSelf->ExprType == HB_ET_LIST ) - { - ULONG ulCount = hb_compExprListLen( pSelf ); - - if( ulCount == 1 && pSelf->value.asList.pExprList->ExprType <= HB_ET_VARIABLE ) - { - /* replace the list with a simple expression - * ( EXPR ) -> EXPR - */ - HB_EXPR_PTR pExpr = pSelf; - - pSelf = pSelf->value.asList.pExprList; - pExpr->value.asList.pExprList = NULL; - hb_compExprDelete( pExpr ); - } - } - return pSelf; -} - - -/* Generates pcodes for compound operators += -= *= /= %= ^= - * - * pExpr is an expression created by hb_compExprNewEq functions - */ -#ifdef HB_MACRO_SUPPORT -static void hb_compExprPushOperEqMC( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL ) -#else -static void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) -#endif -{ - /* NOTE: an object instance variable needs special handling - */ - if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) - { - HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; - - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - /* Push _message for later use */ - hb_compGenMessageData( pObj->value.asMessage.szMessage ); - - /* Now push current value of variable */ -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - /* push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); -#else - /* NOTE: this duplicate optimization requires that HB_P_MESSAGE - * reverts items on the stack ! - * duplicate object on the stack - */ - hb_compGenPCode1( HB_P_DUPLICATE ); -#endif - /* now send the message */ - hb_compGenMessage( pObj->value.asMessage.szMessage ); - hb_compGenPCode3( HB_P_FUNCTION, 0, 0 ); - -/* NOTE: COMPATIBILITY ISSUE: - * The above HARBOUR_STRICT_CLIPPER_COMPATIBILITY setting determines - * the way the chained send messages are handled. - * For example, the following code: - * - * a:b( COUNT() ):c += 1 - * - * will be handled as: - * - * a:b( COUNT() ):c := a:b( COUNT() ):c + 1 - * - * in strict Clipper compatibility mode and - * - * temp := a:b( COUNT() ), temp:c += 1 - * - * in non-strict mode. - * In practice in Clipper it will call COUNT() function two times: the - * first time before addition and the second one after addition - in Harbour, - * COUNT() function will be called only once, before addition. - * The Harbour (non-strict) method is: - * 1) faster - * 2) it guarantees that the same instance variable of the same object will - * be changed - */ - - /* push increment value */ - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - /* increase operation */ - hb_compGenPCode1( bOpEq ); - - /* call pop message with one argument */ - hb_compGenPCode3( HB_P_FUNCTION, 1, 0 ); - } - /* TODO: add a special code for arrays to correctly handle a[ i++ ]++ - */ - else - { - /* push old value */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - /* push increment value */ - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - /* perform operation and duplicate the new value */ - hb_compGenPCode1( bOpEq ); - hb_compGenPCode1( HB_P_DUPLICATE ); - /* pop the new value into variable and leave the copy on the stack */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); - } -} - -/* Generates pcodes for = syntax - * used standalone as a statement (it cannot leave the value on the stack) - */ -#ifdef HB_MACRO_SUPPORT -static void hb_compExprUseOperEqMC( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL ) -#else -static void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) -#endif -{ - /* NOTE: an object instance variable needs special handling - */ - if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) - { - HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; - - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - /* Push _message for later use */ - hb_compGenMessageData( pObj->value.asMessage.szMessage ); - - /* Now push current value of variable */ -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - /* push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); -#else - /* duplicate object on the stack */ - hb_compGenPCode1( HB_P_DUPLICATE ); -#endif - /* now send the message */ - hb_compGenMessage( pObj->value.asMessage.szMessage ); - hb_compGenPCode3( HB_P_FUNCTION, 0, 0 ); - - /* push increment value */ - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - /* increase operation */ - hb_compGenPCode1( bOpEq ); - - /* call pop message with one argument */ - hb_compGenPCode3( HB_P_FUNCTION, 1, 0 ); - /* pop the value from the stack */ - hb_compGenPCode1( HB_P_POP ); - } - else - { - /* push old value */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - /* push increment value */ - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - /* add */ - hb_compGenPCode1( bOpEq ); - /* pop the new value into variable and remove it from the stack */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); - } -} - -/* Generates the pcodes for pre- increment/decrement expressions - */ -#ifdef HB_MACRO_SUPPORT -static void hb_compExprPushPreOpMC( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) -#else -static void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper ) -#endif -{ - /* NOTE: an object instance variable needs special handling - */ - if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) - { - HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; - - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - /* Push _message for later use */ - hb_compGenMessageData( pObj->value.asMessage.szMessage ); - - /* Now push current value of variable */ -#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY - /* push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); -#else - /* duplicate object on the stack */ - hb_compGenPCode1( HB_P_DUPLICATE ); -#endif - /* now send the message */ - hb_compGenMessage( pObj->value.asMessage.szMessage ); - hb_compGenPCode3( HB_P_FUNCTION, 0, 0 ); - - /* increase/decrease operation */ - hb_compGenPCode1( bOper ); - - /* call pop message with one argument - it leaves the value on the stack */ - hb_compGenPCode3( HB_P_FUNCTION, 1, 0 ); - } - else - { - /* Push current value */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - /* Increment */ - hb_compGenPCode1( bOper ); - /* duplicate a value */ - hb_compGenPCode1( HB_P_DUPLICATE ); - /* pop new value and leave the duplicated copy of it on the stack */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); - } -} - -/* Generates the pcodes for post- increment/decrement expressions - */ -#ifdef HB_MACRO_SUPPORT -static void hb_compExprPushPostOpMC( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) -#else -static void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper ) -#endif -{ - /* NOTE: an object instance variable needs special handling - */ - if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) - { - /* push current value - it will be a result of whole expression */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - /* now increment the value */ - hb_compExprPushPreOp( pSelf, bOper ); - /* pop the value from the stack */ - hb_compGenPCode1( HB_P_POP ); - } - else - { - /* Push current value */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - /* Duplicate value */ - hb_compGenPCode1( HB_P_DUPLICATE ); - /* Increment */ - hb_compGenPCode1( bOper ); - /* pop new value from the stack */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); - } -} - -/* Generates the pcodes for increment/decrement operations - * used standalone as a statement - */ -#ifdef HB_MACRO_SUPPORT -static void hb_compExprUsePreOpMC( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) -#else -static void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper ) -#endif -{ - /* NOTE: an object instance variable needs special handling - */ - if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) - { - hb_compExprPushPreOp( pSelf, bOper ); - /* pop the value from the stack */ - hb_compGenPCode1( HB_P_POP ); - } - else - { - /* Push current value */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - /* Increment */ - hb_compGenPCode1( bOper ); - /* pop new value from the stack */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); - } -} - -/* Generate pcode for aliased expression which contains macro operator on - * the left or right side of the alias operator - * expression->¯o or ¯o->expression or ¯o->¯o - */ -#ifdef HB_MACRO_SUPPORT -static void hb_compExprUseAliasMacroMC( HB_EXPR_PTR pAliasedVar, BYTE bAction, HB_MACRO_DECL ) -#else -static void hb_compExprUseAliasMacro( HB_EXPR_PTR pAliasedVar, BYTE bAction ) -#endif -{ - HB_EXPR_PTR pAlias, pVar; - - /* Alias->Var - */ - pAlias = pAliasedVar->value.asAlias.pAlias; - pVar = pAliasedVar->value.asAlias.pVar; - if( pAlias->ExprType == HB_ET_ALIAS ) - { - /* database alias */ - /* Push alias identifier as string so it can be joined with - * variable at runtime - * NOTE: - * ALIAS->&var is the same as &( "ALIAS->" + var ) - * - */ - hb_compGenPushString( pAlias->value.asSymbol, strlen(pAlias->value.asSymbol) ); - HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE ); - if( bAction == HB_EA_PUSH_PCODE ) - hb_compGenPCode1( HB_P_MACROPUSHALIASED ); - else - hb_compGenPCode1( HB_P_MACROPOPALIASED ); - } - else if( pVar->ExprType == HB_ET_VARIABLE ) - { - /* NOTE: - * ¯o->var is the same as: &( macro + "->var" ) - */ - HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); - hb_compGenPushString( pVar->value.asSymbol, strlen(pVar->value.asSymbol) ); - if( bAction == HB_EA_PUSH_PCODE ) - hb_compGenPCode1( HB_P_MACROPUSHALIASED ); - else - hb_compGenPCode1( HB_P_MACROPOPALIASED ); - } - else - { - HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE ); - if( bAction == HB_EA_PUSH_PCODE ) - hb_compGenPCode1( HB_P_MACROPUSHALIASED ); - else - hb_compGenPCode1( HB_P_MACROPOPALIASED ); - } - -} - -static BOOL hb_compExprCheckMacroVar( char * szText ) -{ - char * pTmp = szText; - BOOL bTextSubst = FALSE; - - while( ( pTmp = strchr( pTmp, '&' ) ) != NULL ) - { - /* Check if macro operator is used inside a string - * Macro operator is ignored if it is the last char or - * next char is '(' e.g. "this is &(ignored)" - * - * NOTE: This uses _a-zA-Z pattern to check for - * variable name beginning - */ - - ++pTmp; - bTextSubst = ( *pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') ); -#ifndef HB_MACRO_SUPPORT - /* NOTE: All variables are assumed memvars in macro compiler - - * there is no need to check for a valid name - */ - if( bTextSubst ) - { - /* There is a valid character after '&' that can be used in - * variable name - check if the whole variable name is valid - * (local, static and field variable names are invalid because - * they are not visible at runtime) - */ - char * pStart = pTmp; - char cSave; - - /* NOTE: This uses _a-zA-Z0-9 pattern to check for - * variable name - */ - while( *pTmp && (*pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') || (*pTmp >= '0' && *pTmp <= '9')) ) - ++pTmp; - - cSave = *pTmp; - *pTmp = '\0'; - hb_compVariableMacroCheck( pStart ); - *pTmp = cSave; - } -#endif - } - return bTextSubst; -} - -/* ************************************************************************* */ - -/* Create a new declaration for codeblock local variable - */ -static HB_CBVAR_PTR hb_compExprCBVarNew( char * szVarName, BYTE bType ) -{ - HB_CBVAR_PTR pVar; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprCBVarNew(%s)", szVarName)); - - pVar = ( HB_CBVAR_PTR ) HB_XGRAB( sizeof( HB_CBVAR ) ); - - pVar->szName = szVarName; - pVar->bType = bType; - pVar->pNext = NULL; - - return pVar; -} - -/* NOTE: This deletes all linked variable - */ -static void hb_compExprCBVarDel( HB_CBVAR_PTR pVars ) -{ - HB_CBVAR_PTR pDel; - - while( pVars ) - { - pDel = pVars; - pVars = pVars->pNext; -#ifdef HB_MACRO_SUPPORT - HB_XFREE( pDel->szName ); -#endif - HB_XFREE( pDel ); - } -} - -#ifndef HB_MACRO_SUPPORT -static void hb_compExprCheckStaticInitializers( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) -{ - HB_EXPR_PTR pElem = pRightExpr->value.asList.pExprList; - HB_EXPR_PTR pNext; - HB_EXPR_PTR * pPrev; - - pPrev = &pRightExpr->value.asList.pExprList; - while( pElem ) - { - /* NOTE: During reduction the expression can be replaced by the - * new one - this will break the linked list of expressions. - * (classical case of replacing an item in a linked list) - */ - pNext = pElem->pNext; /* store next expression in case the current will be reduced */ - pElem = hb_compExprListStrip( HB_EXPR_USE( pElem, HB_EA_REDUCE ) ); - if( pElem->ExprType > HB_ET_FUNREF ) - hb_compErrorStatic( pLeftExpr->value.asSymbol, pElem ); - *pPrev = pElem; /* store a new expression into the previous one */ - pElem->pNext = pNext; /* restore the link to next expression */ - pPrev = &pElem->pNext; - pElem = pNext; - } -} -#endif diff --git a/harbour/include/hbexpra.c b/harbour/include/hbexpra.c new file mode 100644 index 0000000000..992aa7c5bd --- /dev/null +++ b/harbour/include/hbexpra.c @@ -0,0 +1,585 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Compiler Expression Optimizer + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* TOFIX: Split the code, since MSC8 can't compile it, even in Huge model. */ + +/* TODO: + * - Correct post- and pre- operations to correctly handle the following code + * a[ i++ ]++ + * Notice: in current implementation (an in Clipper too) 'i++' is evaluated + * two times! This causes that the new value (after incrementation) is + * stored in next element of the array. + */ + +#include +#include "hbcomp.h" + +/* memory allocation + */ +#define HB_XGRAB( size ) hb_xgrab( (size) ) +#define HB_XFREE( pPtr ) hb_xfree( (void *)(pPtr) ) + + +/* Table with operators precedence + * NOTE: + * HB_ET_NIL is used for an ordinary values and post- operators + * HB_ET_NONE is used for invalid syntax, e.g. var := var1 += 2 + */ +static BYTE s_PrecedTable[] = { + HB_ET_NIL, /* HB_ET_NONE = 0, */ + HB_ET_NIL, /* HB_ET_NIL, */ + HB_ET_NIL, /* HB_ET_NUMERIC, */ + HB_ET_NIL, /* HB_ET_STRING, */ + HB_ET_NIL, /* HB_ET_CODEBLOCK, */ + HB_ET_NIL, /* HB_ET_LOGICAL, */ + HB_ET_NIL, /* HB_ET_SELF, */ + HB_ET_NIL, /* HB_ET_ARRAY, */ + HB_ET_NIL, /* HB_ET_VARREF, */ + HB_ET_NIL, /* HB_ET_FUNREF, */ + HB_ET_NIL, /* HB_ET_IIF, */ + HB_ET_NIL, /* HB_ET_LIST, */ + HB_ET_NIL, /* HB_ET_ARGLIST, */ + HB_ET_NIL, /* HB_ET_ARRAYAT, */ + HB_ET_NIL, /* HB_ET_MACRO, */ + HB_ET_NIL, /* HB_ET_FUNCALL, */ + HB_ET_NIL, /* HB_ET_ALIASVAR, */ + HB_ET_NIL, /* HB_ET_ALIASEXPR, */ + HB_ET_NIL, /* HB_ET_SEND, */ + HB_ET_NIL, /* HB_ET_FUNNAME, */ + HB_ET_NIL, /* HB_ET_ALIAS, */ + HB_ET_NIL, /* HB_ET_RTVARIABLE, */ + HB_ET_NIL, /* HB_ET_VARIABLE, */ + HB_ET_NIL, /* HB_EO_POSTINC, post-operators */ + HB_ET_NIL, /* HB_EO_POSTDEC, */ + HB_ET_NONE, /* HB_EO_ASSIGN, assigments */ + HB_ET_NONE, /* HB_EO_PLUSEQ, Invalid syntax */ + HB_ET_NONE, /* HB_EO_MINUSEQ, */ + HB_ET_NONE, /* HB_EO_MULTEQ, */ + HB_ET_NONE, /* HB_EO_DIVEQ, */ + HB_ET_NONE, /* HB_EO_MODEQ, */ + HB_ET_NONE, /* HB_EO_EXPEQ, */ + HB_EO_OR, /* HB_EO_OR, logical operators */ + HB_EO_AND, /* HB_EO_AND, */ + HB_ET_NIL, /* HB_EO_NOT, */ + HB_EO_EQUAL, /* HB_EO_EQUAL, relational operators */ + HB_EO_EQUAL, /* HB_EO_EQ, */ + HB_EO_EQUAL, /* HB_EO_LT, */ + HB_EO_EQUAL, /* HB_EO_GT, */ + HB_EO_EQUAL, /* HB_EO_LE, */ + HB_EO_EQUAL, /* HB_EO_GE, */ + HB_EO_EQUAL, /* HB_EO_NE, */ + HB_EO_EQUAL, /* HB_EO_IN, */ + HB_EO_PLUS, /* HB_EO_PLUS, addition */ + HB_EO_PLUS, /* HB_EO_MINUS, */ + HB_EO_MULT, /* HB_EO_MULT, multiple */ + HB_EO_MULT, /* HB_EO_DIV, */ + HB_EO_MULT, /* HB_EO_MOD, */ + HB_EO_POWER, /* HB_EO_POWER, */ + HB_ET_NIL, /* HB_EO_NEGATE, sign operator */ + HB_ET_NIL, /* HB_EO_PREINC, */ + HB_ET_NIL /* HB_EO_PREDEC, pre-operators */ +}; + + +static HB_CBVAR_PTR hb_compExprCBVarNew( char *, BYTE ); + +/* ************************************************************************ */ + +/* Delete all components and delete self + */ +#if defined( HB_MACRO_SUPPORT ) +void hb_compExprDelete( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else +void hb_compExprDelete( HB_EXPR_PTR pExpr ) +#endif +{ + HB_TRACE(HB_TR_DEBUG, ("hb_compExprDelete()")); + HB_EXPR_USE( pExpr, HB_EA_DELETE ); + HB_XFREE( pExpr ); +} + +/* Delete all components and delete self + */ +void hb_compExprFree( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_compExprFree()")); + HB_EXPR_USE( pExpr, HB_EA_DELETE ); + HB_XFREE( pExpr ); + HB_SYMBOL_UNUSED( HB_MACRO_VARNAME ); +} + +void hb_compExprErrorType( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_compExprErrorType()")); + hb_compErrorType( pExpr ); + HB_SYMBOL_UNUSED( HB_MACRO_VARNAME ); +} + +/* Add a new local variable declaration + */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, BYTE bType ) +#endif +{ + HB_CBVAR_PTR pVar; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprCBVarAdd(%s)", szVarName)); + + if( pCB->value.asList.pIndex ) + { + /* add it to the end of the list + */ + pVar = ( HB_CBVAR_PTR ) pCB->value.asList.pIndex; + while( pVar ) + { + if( strcmp( szVarName, pVar->szName ) == 0 ) + hb_compErrorDuplVar( szVarName ); + + if( pVar->pNext ) + pVar = pVar->pNext; + else + { +#ifdef HB_MACRO_SUPPORT + pVar->pNext = hb_compExprCBVarNew( szVarName, ' ' ); +#else + pVar->pNext = hb_compExprCBVarNew( szVarName, bType ); +#endif + pVar = NULL; + } + } + } + else +#ifdef HB_MACRO_SUPPORT + pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, ' ' ); +#else + pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, bType ); +#endif + + return pCB; +} + +/* Create a new IIF() expression or set arguments + * + * pIIF is a list of three expressions + */ +HB_EXPR_PTR hb_compExprNewIIF( HB_EXPR_PTR pExpr ) +{ +#ifndef HB_MACRO_SUPPORT + HB_EXPR_PTR pTmp; + + pExpr->ExprType = HB_ET_IIF; + + pTmp = pExpr->value.asList.pExprList; /* get first expression */ + if( pTmp->ExprType == HB_ET_NONE ) + { + /* there is no conditional expression e.g. IIF( , true, false ) + */ + hb_compErrorSyntax( pExpr ); + } +#else + pExpr->ExprType = HB_ET_IIF; +#endif + + return pExpr; +} + +/* Create function call + */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) +#endif +{ + HB_EXPR_PTR pExpr = NULL; + + if( pName->ExprType == HB_ET_FUNNAME ) + { + /* The name of a function is specified at compile time + * e.g. MyFunc() + * + * NOTE: 'pName' can be a macro expression that will be resolved + * at runtime - in this case pName is an expression of HB_ET_MACRO type + * e.g. &MyVar() + */ + int iCount; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunCall(%s)", pName->value.asSymbol)); + + if( pParms ) + { + iCount = hb_compExprListLen( pParms ); + /* Check the special case when no parameters are passed - in this case + * pParms is an expression of type HB_ET_NONE and we shouldn't + * replace it with NIL value + */ + if( iCount == 1 && pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) + --iCount; + } + else + iCount = 0; + +#ifndef HB_MACRO_SUPPORT + hb_compFunCallCheck( pName->value.asSymbol, iCount ); +#endif + + /* TODO: AT() (also done by Clipper, already mentioned) + LEN() (also done by Clipper) + ASC() (not done by Clipper) + EMPTY() (not done by Clipper) */ + + if( ( strcmp( "CHR", pName->value.asSymbol ) == 0 ) && iCount ) + { + /* try to change it into a string */ + HB_EXPR_PTR pArg = pParms->value.asList.pExprList; + + if( pArg->ExprType == HB_ET_NUMERIC ) + { + /* NOTE: CA-Cl*pper's compiler optimizer will be wrong for those + CHR() cases where the passed parameter is a constant which + can be divided by 256 but it's not zero, in this case it + will return an empty string instead of a Chr(0). [vszakats] */ + + pExpr = hb_compExprNew( HB_ET_STRING ); + pExpr->ValType = HB_EV_STRING; + if( pArg->value.asNum.NumType == HB_ET_LONG ) + { + if( ( pArg->value.asNum.lVal % 256 ) == 0 && pArg->value.asNum.lVal != 0 ) + { + pExpr->value.asString = ( char * ) HB_XGRAB( 1 ); + pExpr->value.asString[ 0 ] = '\0'; + pExpr->ulLength = 0; + } + else + { + pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); + pExpr->value.asString[ 0 ] = ( pArg->value.asNum.lVal % 256 ); + pExpr->value.asString[ 1 ] = '\0'; + pExpr->ulLength = 1; + } + } + else + { + pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); + pExpr->value.asString[ 0 ] = ( ( long ) pArg->value.asNum.dVal % 256 ); + pExpr->value.asString[ 1 ] = '\0'; + pExpr->ulLength = 1; + } + HB_EXPR_PCODE1( hb_compExprDelete, pParms ); + HB_EXPR_PCODE1( hb_compExprDelete, pName ); + } + } + } + else if( pName->ExprType == HB_ET_MACRO ) + { + /* Signal that macro compiler have to generate a pcode that will + * return function name as symbol instead of usual value + */ + pName->value.asMacro.SubType = HB_ET_MACRO_SYMBOL; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunCall(&)")); + } + + if( pExpr == NULL ) + { + pExpr = hb_compExprNew( HB_ET_FUNCALL ); + pExpr->value.asFunCall.pParms = pParms; + pExpr->value.asFunCall.pFunName = pName; + } + + return pExpr; +} + +/* Creates new array access expression + * pArray[ pIndex ] + * NOTE: In case of multiple indexes it is called recursively + * array[ idx1, idx2 ] => ( array[ idx1 ] )[ idx2 ] + */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex ) +#endif +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArrayAt()")); + + pExpr = hb_compExprNew( HB_ET_ARRAYAT ); + + /* Check if this expression can be indexed */ + HB_EXPR_USE( pArray, HB_EA_ARRAY_AT ); + /* Check if this expression can be an index */ + HB_EXPR_USE( pIndex, HB_EA_ARRAY_INDEX ); + pExpr->value.asList.pExprList = pArray; + pExpr->value.asList.pIndex = pIndex; + + return pExpr; +} + + +/* ************************************************************************* */ + +#ifndef HB_MACRO_SUPPORT +static void hb_compExprCheckStaticInitializers( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) +{ + HB_EXPR_PTR pElem = pRightExpr->value.asList.pExprList; + HB_EXPR_PTR pNext; + HB_EXPR_PTR * pPrev; + + pPrev = &pRightExpr->value.asList.pExprList; + while( pElem ) + { + /* NOTE: During reduction the expression can be replaced by the + * new one - this will break the linked list of expressions. + * (classical case of replacing an item in a linked list) + */ + pNext = pElem->pNext; /* store next expression in case the current will be reduced */ + pElem = hb_compExprListStrip( HB_EXPR_USE( pElem, HB_EA_REDUCE ), HB_MACRO_PARAM ); + if( pElem->ExprType > HB_ET_FUNREF ) + hb_compErrorStatic( pLeftExpr->value.asSymbol, pElem ); + *pPrev = pElem; /* store a new expression into the previous one */ + pElem->pNext = pNext; /* restore the link to next expression */ + pPrev = &pElem->pNext; + pElem = pNext; + } +} + +/* It initializes static variable. + * It is called in the following context: + * STATIC sVar := expression + * + * pLeftExpr - is a variable name + * pRightExpr - can be an expression of any type + */ +HB_EXPR_PTR hb_compExprAssignStatic( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprAssignStatic()")); + + pExpr = hb_compExprNew( HB_EO_ASSIGN ); + + pExpr->value.asOperator.pLeft = pLeftExpr; + /* Try to reduce the assigned value */ + pRightExpr = hb_compExprListStrip( HB_EXPR_USE( pRightExpr, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pExpr->value.asOperator.pRight = pRightExpr; + + if( pRightExpr->ExprType == HB_ET_ARGLIST ) + { + /* HB_ET_ARGLIST is used in case of STATIC var[dim1, dim2, dimN] + * was used - we have to check if all array dimensions are + * constant values + */ + hb_compExprCheckStaticInitializers( pLeftExpr, pRightExpr ); + } + else if( pRightExpr->ExprType > HB_ET_FUNREF ) + { + /* Illegal initializer for static variable (not a constant value) + */ + hb_compErrorStatic( pLeftExpr->value.asSymbol, pRightExpr ); + } + else if( pRightExpr->ExprType == HB_ET_ARRAY ) + { + /* { elem1, elem2, elemN } was used as initializer + * Scan an array for illegal initializers. + * An array item have to be a const value too. + */ + hb_compExprCheckStaticInitializers( pLeftExpr, pRightExpr ); + } + + return pExpr; +} +#endif + + +/* Sets the argument of an operation found previously + */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem ) +#endif +{ + BYTE ucRight; + + ucRight = s_PrecedTable[ pItem->ExprType ]; + if( ucRight == HB_ET_NIL ) + { + /* the right side of an operator is an ordinary value + * e.g. a := 1 + */ + pExpr->value.asOperator.pRight = pItem; + } + else if( ucRight == HB_ET_NONE ) + { + /* the right side of an operator is an invalid expression + * e.g. + * a := 1 + b:=2 + * a := 1 + b += 2 + */ + hb_compErrorSyntax( pItem ); + } + else + { + /* the right side of an operator is an expression with other operator + * e.g. a := 2 + b * 3 + * We have to set the proper order of evaluation using + * precedence rules + */ + BYTE ucLeft = s_PrecedTable[ pExpr->ExprType ]; + if( ucLeft >= ucRight ) + { + /* Left operator has the same or lower precedence then the right one + * e.g. a * b + c + * pItem -> b + c -> L=b R=c O=+ + * pExpr -> a * -> l=a r= o=* + * + * -> (a * b) + c -> Lelf=(a * b) Right=c Oper=+ + * Left := l (o) L + * Right := R + * Oper := O + */ +#ifdef HB_MACRO_SUPPORT + pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft, HB_MACRO_PARAM ); +#else + pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft ); +#endif + pExpr = pItem; + } + else + { + /* Left operator has a lower precedence then the right one + * e.g. a + b * c + * pItem -> b * c -> L=b R=c O=* + * pExpr -> a + -> l=a r= o=+ + * + * -> a + (b * c) -> Left=a Right=(b * c) Oper=+ + * Left := l + * Right := L (O) R := pItem + * Oper := o + */ + pExpr->value.asOperator.pRight = pItem; + } + } + + return pExpr; +} + +/* ************************************************************************* */ + +/* Generates pcode for inline expression used as a statement + * NOTE: It doesn't not leave any value on the eval stack + */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr ) +#endif +{ + HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenStatement(%i)", pExpr->ExprType)); + + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); + HB_EXPR_USE( pExpr, HB_EA_STATEMENT ); + return pExpr; +} + +/* Generates pcode to push an expressions + * NOTE: It pushes a value on the stack and leaves this value on the stack + */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr ) +#endif +{ + HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenPush(%i)", pExpr->ExprType)); + + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + return pExpr; +} + +/* Generates pcode to pop an expressions + */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr ) +#endif +{ + HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenPop(%i)", pExpr->ExprType)); + + return HB_EXPR_USE( pExpr, HB_EA_POP_PCODE ); +} + +/* ************************************************************************* */ + +/* Create a new declaration for codeblock local variable + */ +static HB_CBVAR_PTR hb_compExprCBVarNew( char * szVarName, BYTE bType ) +{ + HB_CBVAR_PTR pVar; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprCBVarNew(%s)", szVarName)); + + pVar = ( HB_CBVAR_PTR ) HB_XGRAB( sizeof( HB_CBVAR ) ); + + pVar->szName = szVarName; + pVar->bType = bType; + pVar->pNext = NULL; + + return pVar; +} + +/* NOTE: This deletes all linked variables + */ +void hb_compExprCBVarDel( HB_CBVAR_PTR pVars ) +{ + HB_CBVAR_PTR pDel; + + while( pVars ) + { + pDel = pVars; + pVars = pVars->pNext; +#ifdef HB_MACRO_SUPPORT + HB_XFREE( pDel->szName ); +#endif + HB_XFREE( pDel ); + } +} + diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c new file mode 100644 index 0000000000..297d9de20e --- /dev/null +++ b/harbour/include/hbexprb.c @@ -0,0 +1,3178 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Compiler Expression Optimizer + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* TOFIX: Split the code, since MSC8 can't compile it, even in Huge model. */ + +/* TODO: + * - Correct post- and pre- operations to correctly handle the following code + * a[ i++ ]++ + * Notice: in current implementation (an in Clipper too) 'i++' is evaluated + * two times! This causes that the new value (after incrementation) is + * stored in next element of the array. + */ + +#include +#include "hbcomp.h" + +/* memory allocation + */ +#define HB_XGRAB( size ) hb_xgrab( (size) ) +#define HB_XFREE( pPtr ) hb_xfree( (void *)(pPtr) ) + +/* Forward declarations + */ + +#if defined( HB_MACRO_SUPPORT ) + void hb_compExprDelOperator( HB_EXPR_PTR, HB_MACRO_DECL ); + void hb_compExprUseOperEq( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); + void hb_compExprPushPreOp( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); + void hb_compExprPushPostOp( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); + void hb_compExprUsePreOp( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); + void hb_compExprUseAliasMacro( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); + void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL ); + ULONG hb_compExprReduceList( HB_EXPR_PTR, HB_MACRO_DECL ); +#else + void hb_compExprDelOperator( HB_EXPR_PTR ); + void hb_compExprUseOperEq( HB_EXPR_PTR, BYTE ); + void hb_compExprPushPreOp( HB_EXPR_PTR, BYTE ); + void hb_compExprPushPostOp( HB_EXPR_PTR, BYTE ); + void hb_compExprUsePreOp( HB_EXPR_PTR, BYTE ); + void hb_compExprUseAliasMacro( HB_EXPR_PTR, BYTE ); + void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ); + ULONG hb_compExprReduceList( HB_EXPR_PTR ); +#endif + +HB_EXPR_PTR hb_compExprReduceMod( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceDiv( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceMult( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceMinus( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReducePlus( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceIN( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceGE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceLE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceGT( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceLT( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceEQ( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceAnd( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceOr( HB_EXPR_PTR pSelf, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprReduceIIF( HB_EXPR_PTR, HB_MACRO_DECL ); + + +/* 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_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_compExprUseVarRef ); +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_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 ); + +HB_EXPR_FUNC_PTR hb_comp_ExprTable[] = { + hb_compExprUseDummy, + hb_compExprUseNil, + hb_compExprUseNumeric, + hb_compExprUseString, + hb_compExprUseCodeblock, + hb_compExprUseLogical, + hb_compExprUseSelf, + hb_compExprUseArray, + hb_compExprUseVarRef, + hb_compExprUseFunRef, + hb_compExprUseIIF, + hb_compExprUseList, + hb_compExprUseArgList, + 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_compExprUseLT, + hb_compExprUseGT, + hb_compExprUseLE, + hb_compExprUseGE, + hb_compExprUseNE, + hb_compExprUseIN, + 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_compErrorType( pSelf ); + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + HB_EXPR_PCODE1( hb_compGenPCode1, 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_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* NIL cannot be used as index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_PUSHNIL ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( 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_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + if( pSelf->value.asNum.NumType == HB_ET_DOUBLE ) + HB_EXPR_PCODE2( hb_compGenPushDouble, pSelf->value.asNum.dVal, pSelf->value.asNum.bDec ); + else + HB_EXPR_PCODE1( hb_compGenPushLong, pSelf->value.asNum.lVal ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( 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_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* string cannot be used as index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_PCODE2( hb_compGenPushString, pSelf->value.asString, pSelf->ulLength ); +#if !defined( HB_MACRO_SUPPORT ) + /* only memvar variables are allowed in macro compilation - there is no + * need to check for locals or static variables + */ + if( hb_compExprCheckMacroVar( pSelf->value.asString ) ) + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROTEXT ); +#endif + } + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + break; + case HB_EA_DELETE: + HB_XFREE( pSelf->value.asString ); + 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_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* codeblock cannot be used as index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_PTR pExpr, pNext; + HB_EXPR_PTR * pPrev; + + HB_EXPR_PCODE0( hb_compCodeBlockStart ); + /* Define requested local variables + */ +#if defined( HB_MACRO_SUPPORT ) + HB_PCODE_DATA->pLocals = ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex; +#else + { + HB_CBVAR_PTR pVar; + + pVar = ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex; + while( pVar ) + { + hb_compVariableAdd( pVar->szName, pVar->bType ); + pVar =pVar->pNext; + } + } +#endif + pExpr = pSelf->value.asList.pExprList; + pPrev = &pSelf->value.asList.pExprList; + while( pExpr ) + { + /* 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( pNext ) + HB_EXPR_USE( pExpr, HB_EA_PUSH_POP ); + else + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + pPrev = &pExpr->pNext; + pExpr = pNext; + } + HB_EXPR_PCODE0( hb_compCodeBlockEnd ); + } + break; + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + break; + case HB_EA_DELETE: + hb_compExprCBVarDel( ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex ); + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asList.pExprList ); + 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_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* logical cannot be used as array index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + HB_EXPR_PCODE1( hb_compGenPushLogical, pSelf->value.asLogical ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( 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: + hb_compErrorType( pSelf ); /* QUESTION: Is this OK ? */ + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* SELF cannot be used as array index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_PUSHSELF ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( 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: + HB_EXPR_PCODE1( hb_compExprReduceList, pSelf ); + break; + + case HB_EA_ARRAY_AT: + break; + + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* array cannot be used as index element */ + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + HB_EXPR_PTR pElem = pSelf->value.asList.pExprList; + /* Push all elements of the array + */ + if( ( pElem == NULL ) || ( pElem->ExprType == HB_ET_NONE && pElem->pNext == NULL ) ) + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_ARRAYGEN, 0, 0 ); + else + { + while( pElem ) + { + HB_EXPR_USE( pElem, HB_EA_PUSH_PCODE ); + pElem = pElem->pNext; + } + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_ARRAYGEN, HB_LOBYTE( pSelf->ulLength ), HB_HIBYTE( pSelf->ulLength ) ); + } + } + 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( 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_EXPR_PCODE1( hb_compExprDelete, 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_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + HB_EXPR_PCODE1( hb_compGenPushVarRef, pSelf->value.asSymbol ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( 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_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + HB_EXPR_PCODE1( hb_compGenPushFunCall, pSelf->value.asSymbol ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_FUNCPTR ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +/* actions for HB_ET_IIF expression + */ +static HB_EXPR_FUNC( hb_compExprUseIIF ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + HB_EXPR_PCODE1( hb_compExprReduceList, pSelf ); + pSelf = hb_compExprReduceIIF( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenJumpFalse, 0 ); + pExpr =pExpr->pNext; + + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + lPosEnd = HB_EXPR_PCODE1( hb_compGenJump, 0 ); + pExpr =pExpr->pNext; + + HB_EXPR_PCODE1( hb_compGenJumpHere, lPosFalse ); + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenJumpHere, lPosEnd ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + { + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); /* remove a value if used in 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_EXPR_PCODE1( hb_compExprDelete, 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: + { + HB_EXPR_PCODE1( hb_compExprReduceList, pSelf ); + /* NOTE: if the list contains a single expression then the list + * is not reduced to this expression - if you need that reduction + * then call hb_compExprListStrip() additionaly + */ + } + 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( pSelf->value.asList.pExprList ); + } + else + hb_compErrorLValue( 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_compErrorSyntax( pExpr ); + } + else + { + while( pExpr ) + { + 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 ) + { + 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_EXPR_PCODE1( hb_compExprDelete, 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: + HB_EXPR_PCODE1( hb_compExprReduceList, pSelf ); + 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; + + 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_EXPR_PCODE1( hb_compExprDelete, 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; + + 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 */ + + if( pExpr->ExprType == HB_ET_ARRAY ) /* is it a literal array */ + { + LONG lIndex; + + pExpr = pExpr->value.asList.pExprList; /* the first element in the array */ + if( pIdx->value.asNum.NumType == HB_ET_LONG ) + lIndex = pIdx->value.asNum.lVal; + else + lIndex = ( LONG ) pIdx->value.asNum.dVal; + + if( lIndex > 0 ) + { + while( --lIndex && pExpr ) + pExpr = pExpr->pNext; + } + else + pExpr = NULL; /* index is <= 0 - generate bound error */ + + if( pExpr ) /* found ? */ + { + /* extract a single expression from the array + */ + HB_EXPR_PTR pNew = hb_compExprNew( 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_EXPR_PCODE1( hb_compExprDelete, pSelf ); + pSelf = pNew; + } + else + { + hb_compErrorBound( pIdx ); + } + } + else + { + LONG lIndex; + + if( pIdx->value.asNum.NumType == HB_ET_LONG ) + lIndex = pIdx->value.asNum.lVal; + else + lIndex = ( LONG ) pIdx->value.asNum.dVal; + + if( lIndex > 0 ) + HB_EXPR_USE( pExpr, HB_EA_ARRAY_AT ); + else + hb_compErrorBound( pIdx ); /* index <= 0 - bound error */ + } + } + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_ARRAYPUSH ); + } + break; + + case HB_EA_POP_PCODE: + { + HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, 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( pSelf ); + break; + case HB_EA_DELETE: + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asList.pExprList ); + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asList.pIndex ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseMacro ) +{ + 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.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_EXPR_PCODE1( hb_compGenPushVar, pSelf->value.asMacro.szMacro ); + } + else + { + /* complex macro expression: prefix&var.suffix + * all components should be placed as a string that will + * be compiled after text susbstitution + */ + HB_EXPR_PCODE2( hb_compGenPushString, pSelf->value.asMacro.szMacro, strlen(pSelf->value.asMacro.szMacro) ); + } + } + /* compile & run - leave a result on the eval stack + */ + if( pSelf->value.asMacro.SubType == HB_ET_MACRO_SYMBOL ) + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROSYMBOL ); + else if( pSelf->value.asMacro.SubType != HB_ET_MACRO_ALIASED ) + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPUSH ); + /* 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_EXPR_PCODE1( hb_compGenPushVar, pSelf->value.asMacro.szMacro ); + } + else + { + /* complex macro expression: prefix&var.suffix + * all components should be placed as a string that will + * be compiled after text susbstitution + */ + HB_EXPR_PCODE2( hb_compGenPushString, pSelf->value.asMacro.szMacro, strlen(pSelf->value.asMacro.szMacro) ); + } + } + /* 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPOP ); + } + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); + break; + + case HB_EA_DELETE: + if( pSelf->value.asMacro.pExprList ) + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMacro.pExprList ); +/* NOTE: This will be released during releasing of symbols' table + * + * if( pSelf->value.asMacro.szMacro ); + * HB_XFREE( pSelf->value.asMacro.szMacro ); + */ + 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 ); + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + USHORT usCount; + + HB_EXPR_USE( pSelf->value.asFunCall.pFunName, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_PUSHNIL ); + + if( pSelf->value.asFunCall.pParms ) + { + /* NOTE: pParms will be NULL in 'DO procname' (if there is + * no WITH keyword) + */ + usCount = ( USHORT ) hb_compExprListLen( pSelf->value.asFunCall.pParms ); + if( usCount == 1 && pSelf->value.asFunCall.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) + --usCount; + if( usCount ) + HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_PUSH_PCODE ); + } + else + usCount = 0; + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + { + USHORT usCount; + + HB_EXPR_USE( pSelf->value.asFunCall.pFunName, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_PUSHNIL ); + + if( pSelf->value.asFunCall.pParms ) + { + usCount = ( USHORT ) hb_compExprListLen( pSelf->value.asFunCall.pParms ); + if( usCount == 1 && pSelf->value.asFunCall.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) + --usCount; + if( usCount ) + HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_PUSH_PCODE ); + } + else + usCount = 0; + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_DO, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) ); + } + break; + + case HB_EA_DELETE: + if( pSelf->value.asFunCall.pParms ) + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asFunCall.pParms ); + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asFunCall.pFunName ); + break; + } + return pSelf; +} + +/* handler for expression->identifier syntax + */ +static HB_EXPR_FUNC( hb_compExprUseAliasVar ) +{ + 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_EXPR_PTR pAlias = pSelf->value.asAlias.pAlias; + BOOL bReduced = FALSE; + + if( pAlias->ExprType == HB_ET_LIST ) + { + /* ( expr1, expr2, ... )->variable + */ + pSelf->value.asAlias.pAlias = HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_REDUCE ); + bReduced = TRUE; + } + + 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_EXPR_PCODE4( hb_compGenPushAliasedVar, 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_EXPR_PCODE4( hb_compGenPushAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, TRUE, NULL, pAlias->value.asNum.lVal ); + else + hb_compErrorAlias( pAlias ); + } + else if( bReduced ) + { + /* + * ( expression )->var + * + * NOTE: FALSE = don't push alias value + */ + HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE4( hb_compGenPushAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, FALSE, NULL, 0 ); + } + else + hb_compErrorAlias( pAlias ); + } + break; + + case HB_EA_POP_PCODE: + { + HB_EXPR_PTR pAlias = pSelf->value.asAlias.pAlias; + BOOL bReduced = FALSE; + + if( pAlias->ExprType == HB_ET_LIST ) + { + pSelf->value.asAlias.pAlias = HB_EXPR_USE( pSelf->value.asAlias.pAlias, HB_EA_REDUCE ); + bReduced = TRUE; + } + + 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_EXPR_PCODE4( hb_compGenPopAliasedVar, 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_EXPR_PCODE4( hb_compGenPopAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, TRUE, NULL, pAlias->value.asNum.lVal ); + else + hb_compErrorAlias( pAlias ); + } + else if( bReduced ) + { + /* + * ( expression )->var + * + * NOTE: FALSE = don't push alias value + */ + if( pAlias->ExprType == HB_ET_NONE ) + { + /* empty expression -> ()->var + */ + hb_compErrorAlias( pAlias ); + } + else + { + HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE4( hb_compGenPopAliasedVar, pSelf->value.asAlias.pVar->value.asSymbol, FALSE, NULL, 0 ); + } + } + else + hb_compErrorAlias( pAlias ); + } + break; + + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); + break; + + case HB_EA_DELETE: + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asAlias.pAlias ); + /* NOTE: variable name is released only during macro compilation */ +#if defined( HB_MACRO_SUPPORT ) + if( pSelf->value.asAlias.pVar ) + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asAlias.pVar ); +#endif + break; + } + return pSelf; +} + +/* handler for expression->( exression, ... ) syntax + */ +static HB_EXPR_FUNC( hb_compExprUseAliasExpr ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + /* save currently selected workarea + */ + HB_EXPR_PCODE1( hb_compGenPCode1, 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_EXPR_PCODE1( hb_compGenPCode1, 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_SWAPALIAS ); + } + break; + + case HB_EA_POP_PCODE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + { + /* save currently selected workarea + */ + HB_EXPR_PCODE1( hb_compGenPCode1, 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_EXPR_PCODE1( hb_compGenPCode1, 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_POPALIAS ); + } + break; + case HB_EA_DELETE: + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asAlias.pAlias ); + HB_EXPR_PCODE1( hb_compExprDelete, 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_EXPR_PCODE2( hb_compGenPushSymbol, pSelf->value.asSymbol, FALSE ); + break; + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + break; + case HB_EA_DELETE: +#if defined( HB_MACRO_SUPPORT ) + HB_XFREE( pSelf->value.asSymbol ); +#endif + 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_EXPR_PCODE1( hb_compGenPushFunCall, pSelf->value.asSymbol ); + break; + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + case HB_EA_DELETE: +#if defined( HB_MACRO_SUPPORT ) + HB_XFREE( pSelf->value.asSymbol ); +#endif + 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_EXPR_PCODE2( hb_compGenPushSymbol, pSelf->value.asRTVar.szName, 0 ); /* this is not a functio */ + else + HB_EXPR_USE( pSelf->value.asRTVar.pMacro, HB_EA_PUSH_PCODE ); + break; + case HB_EA_POP_PCODE: + if( pSelf->value.asRTVar.szName ) + HB_EXPR_PCODE1( hb_compGenPopVar, 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: + case HB_EA_DELETE: + 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_EXPR_PCODE4( hb_compGenPushAliasedVar, pSelf->value.asSymbol, FALSE, NULL, 0 ); + else + HB_EXPR_PCODE1( hb_compGenPushVar, pSelf->value.asSymbol ); + } +#else + HB_EXPR_PCODE1( hb_compGenPushVar, pSelf->value.asSymbol ); +#endif + break; + + case HB_EA_POP_PCODE: +#if defined( HB_MACRO_SUPPORT ) + { + if( HB_MACRO_DATA->Flags & HB_MACRO_GEN_ALIASED ) + HB_EXPR_PCODE4( hb_compGenPopAliasedVar, pSelf->value.asSymbol, FALSE, NULL, 0 ); + else + HB_EXPR_PCODE1( hb_compGenPopVar, pSelf->value.asSymbol ); + } +#else + HB_EXPR_PCODE1( hb_compGenPopVar, pSelf->value.asSymbol ); +#endif + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + HB_EXPR_PCODE1( hb_compGenPushVar, pSelf->value.asSymbol ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); + break; + + case HB_EA_DELETE: + /* NOTE: variable name should be released if macro compilation */ +#if defined( HB_MACRO_SUPPORT ) + HB_XFREE( pSelf->value.asSymbol ); +#endif + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseSend ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + pSelf->value.asMessage.pObject = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_REDUCE ), HB_MACRO_PARAM ); + 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: + case HB_EA_LVALUE: + break; + + case HB_EA_PUSH_PCODE: + { + if( pSelf->value.asMessage.pParms ) /* Is it a method call ? */ + { + int iParms = hb_compExprListLen( pSelf->value.asMessage.pParms ); + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenMessage, pSelf->value.asMessage.szMessage ); + /* NOTE: if method with no parameters is called then the list + * of parameters contain only one expression of type HB_ET_NONE + * There is no need to push this parameter + */ + if( iParms == 1 && pSelf->value.asMessage.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) + --iParms; + if( iParms ) + HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, HB_LOBYTE( iParms ), HB_HIBYTE( iParms ) ); + } + else + { + /* acces to instance variable */ + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenMessage, pSelf->value.asMessage.szMessage ); + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 0, 0 ); + } + } + break; + + case HB_EA_POP_PCODE: + { + /* NOTE: This is an exception from the rule - this leaves + * the return value on the stack + */ + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenMessageData, pSelf->value.asMessage.szMessage ); + HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 1, 0 ); + } + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, 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( pSelf ); + } + + case HB_EA_DELETE: +#if defined( HB_MACRO_SUPPORT ) + { + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pObject ); + if( pSelf->value.asMessage.pParms ) + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pParms ); + HB_XFREE( pSelf->value.asMessage.szMessage ); + } +#endif + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePostInc ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + 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( 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_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asOperator.pLeft ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePostDec ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + 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( 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_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asOperator.pLeft ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseAssign ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); + 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_EXPR_PCODE1( hb_compGenPCode1, 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceOr( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + if( hb_comp_bShortCuts ) + { + LONG lEndPos; + + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); + lEndPos = HB_EXPR_PCODE1( hb_compGenJumpTrue, 0 ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_OR ); + HB_EXPR_PCODE1( hb_compGenJumpHere, 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_OR ); + } + break; + + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceAnd( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + if( hb_comp_bShortCuts ) + { + LONG lEndPos; + + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); + lEndPos = HB_EXPR_PCODE1( hb_compGenJumpFalse, 0 ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_AND ); + HB_EXPR_PCODE1( hb_compGenJumpHere, 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_AND ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + 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_EXPR_PCODE1( hb_compExprDelete, pSelf ); + pSelf = pExpr; + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_NOT ); + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asOperator.pLeft ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseEqual ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + /* '=' used in an expression - compare values + */ + /* Try to optimize expression - we cannot optimize in HB_EA_REDUCE + * because it is not decided yet if it is assigment or comparision + */ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asLogical == pRight->value.asLogical) ); + break; + + case HB_ET_STRING: + /* NOTE: the result depends on SET EXACT setting then it + * cannot be optimized except the case when NULL string are + * compared - the result is always TRUE regardless of EXACT + * setting + */ + if( (pLeft->ulLength | pRight->ulLength) == 0 ) + HB_EXPR_PCODE1( hb_compGenPushLogical, TRUE ); /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ + else + { + HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_EQUAL ); + } + break; + + case HB_ET_NIL: + /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ + HB_EXPR_PCODE1( hb_compGenPushLogical, TRUE ); /* NIL = NIL is always TRUE */ + break; + + case HB_ET_NUMERIC: + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asNum.lVal == pRight->value.asNum.lVal) ); + break; + case HB_ET_DOUBLE: + HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asNum.dVal == pRight->value.asNum.dVal) ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asNum.lVal == pRight->value.asNum.dVal) ); + else + HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asNum.dVal == pRight->value.asNum.lVal) ); + } + break; + } + break; + + default: + { + HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_EQUAL ); + } + } + else + { + /* TODO: check for incompatible types + */ + HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_EQUAL ); + } + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + { + /* '=' used standalone in a statement - assign a value + * it assigns a value and removes it from the stack + * */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + /* Send messages are implemented as function calls + */ + 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); + } + else + { + 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; +} + +/* handler for == operator + */ +static HB_EXPR_FUNC( hb_compExprUseEQ ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceEQ( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_EXACTLYEQUAL ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceLT( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_LESS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceGT( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_GREATER ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceLE( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_LESSEQUAL ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceGE( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_GREATEREQUAL ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceNE( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_NOTEQUAL ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceIN( pSelf, HB_MACRO_PARAM ); + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_INSTRING ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReducePlus( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_PLUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceMinus( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_MINUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceMult( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_MULT ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf = hb_compExprReduceDiv( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_DIVIDE ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pSelf =hb_compExprReduceMod( pSelf, HB_MACRO_PARAM ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_MODULUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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: /* Clipper doesn't optimize it */ + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compGenPCode1, HB_P_POWER ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( 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: + { + HB_EXPR_PTR pExpr; + + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + pExpr = pSelf->value.asOperator.pLeft; + + if( pExpr->ExprType == HB_ET_NUMERIC ) + { + if( pExpr->value.asNum.NumType == HB_ET_DOUBLE ) + pExpr->value.asNum.dVal = - pExpr->value.asNum.dVal; + else + pExpr->value.asNum.lVal = - pExpr->value.asNum.lVal; + pSelf->ExprType = HB_ET_NONE; /* do not delete operator parameter - we are still using it */ + HB_EXPR_PCODE1( hb_compExprDelete, pSelf ); + pSelf = pExpr; + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_NEGATE ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); +#else + /* 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 ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + if( pSelf->value.asOperator.pLeft ) + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asOperator.pLeft ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePreInc ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asOperator.pLeft ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePreDec ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_MACRO_PARAM ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( 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_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asOperator.pLeft ); + break; + } + return pSelf; +} + diff --git a/harbour/include/hbexprc.c b/harbour/include/hbexprc.c new file mode 100644 index 0000000000..df57c4ea7d --- /dev/null +++ b/harbour/include/hbexprc.c @@ -0,0 +1,450 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Compiler Expression Optimizer - utilities + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* TOFIX: Split the code, since MSC8 can't compile it, even in Huge model. */ + +/* TODO: + * - Correct post- and pre- operations to correctly handle the following code + * a[ i++ ]++ + * Notice: in current implementation (an in Clipper too) 'i++' is evaluated + * two times! This causes that the new value (after incrementation) is + * stored in next element of the array. + */ + +#include +#include "hbcomp.h" + +/* ************************************************************************* */ + +#if defined( HB_MACRO_SUPPORT ) +void hb_compExprDelOperator( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else +void hb_compExprDelOperator( HB_EXPR_PTR pExpr ) +#endif +{ + if( pExpr->value.asOperator.pLeft ) + HB_EXPR_PCODE1( hb_compExprDelete, pExpr->value.asOperator.pLeft ); + if( pExpr->value.asOperator.pRight ) + HB_EXPR_PCODE1( hb_compExprDelete, pExpr->value.asOperator.pRight ); +} + + +/* Generates pcodes for compound operators += -= *= /= %= ^= + * + * pExpr is an expression created by hb_compExprNewEq functions + */ +#if defined( HB_MACRO_SUPPORT ) +void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL ) +#else +void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) +#endif +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + + /* Push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + /* Push _message for later use */ + HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage ); + + /* Now push current value of variable */ +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + /* push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); +#else + /* NOTE: this duplicate optimization requires that HB_P_MESSAGE + * reverts items on the stack ! + * duplicate object on the stack + */ + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); +#endif + /* now send the message */ + HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 0, 0 ); + +/* NOTE: COMPATIBILITY ISSUE: + * The above HARBOUR_STRICT_CLIPPER_COMPATIBILITY setting determines + * the way the chained send messages are handled. + * For example, the following code: + * + * a:b( COUNT() ):c += 1 + * + * will be handled as: + * + * a:b( COUNT() ):c := a:b( COUNT() ):c + 1 + * + * in strict Clipper compatibility mode and + * + * temp := a:b( COUNT() ), temp:c += 1 + * + * in non-strict mode. + * In practice in Clipper it will call COUNT() function two times: the + * first time before addition and the second one after addition - in Harbour, + * COUNT() function will be called only once, before addition. + * The Harbour (non-strict) method is: + * 1) faster + * 2) it guarantees that the same instance variable of the same object will + * be changed + */ + + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* increase operation */ + HB_EXPR_PCODE1( hb_compGenPCode1, bOpEq ); + + /* call pop message with one argument */ + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 1, 0 ); + } + /* TODO: add a special code for arrays to correctly handle a[ i++ ]++ + */ + else + { + /* push old value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* perform operation and duplicate the new value */ + HB_EXPR_PCODE1( hb_compGenPCode1, bOpEq ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); + /* pop the new value into variable and leave the copy on the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* Generates pcodes for = syntax + * used standalone as a statement (it cannot leave the value on the stack) + */ +#if defined( HB_MACRO_SUPPORT ) +void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL ) +#else +void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) +#endif +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + + /* Push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + /* Push _message for later use */ + HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage ); + + /* Now push current value of variable */ +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + /* push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); +#else + /* duplicate object on the stack */ + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); +#endif + /* now send the message */ + HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 0, 0 ); + + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* increase operation */ + HB_EXPR_PCODE1( hb_compGenPCode1, bOpEq ); + + /* call pop message with one argument */ + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 1, 0 ); + /* pop the value from the stack */ + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); + } + else + { + /* push old value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* add */ + HB_EXPR_PCODE1( hb_compGenPCode1, bOpEq ); + /* pop the new value into variable and remove it from the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* Generates the pcodes for pre- increment/decrement expressions + */ +#if defined( HB_MACRO_SUPPORT ) +void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) +#else +void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper ) +#endif +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + + /* Push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + /* Push _message for later use */ + HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage ); + + /* Now push current value of variable */ +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + /* push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); +#else + /* duplicate object on the stack */ + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); +#endif + /* now send the message */ + HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 0, 0 ); + + /* increase/decrease operation */ + HB_EXPR_PCODE1( hb_compGenPCode1, bOper ); + + /* call pop message with one argument - it leaves the value on the stack */ + HB_EXPR_PCODE3( hb_compGenPCode3, HB_P_FUNCTION, 1, 0 ); + } + else + { + /* Push current value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* Increment */ + HB_EXPR_PCODE1( hb_compGenPCode1, bOper ); + /* duplicate a value */ + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); + /* pop new value and leave the duplicated copy of it on the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* Generates the pcodes for post- increment/decrement expressions + */ +#if defined( HB_MACRO_SUPPORT ) +void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) +#else +void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper ) +#endif +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + /* push current value - it will be a result of whole expression */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* now increment the value */ + HB_EXPR_PCODE2( hb_compExprPushPreOp, pSelf, bOper ); + /* pop the value from the stack */ + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); + } + else + { + /* Push current value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* Duplicate value */ + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); + /* Increment */ + HB_EXPR_PCODE1( hb_compGenPCode1, bOper ); + /* pop new value from the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* Generates the pcodes for increment/decrement operations + * used standalone as a statement + */ +#if defined( HB_MACRO_SUPPORT ) +void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) +#else +void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper ) +#endif +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PCODE2( hb_compExprPushPreOp, pSelf, bOper ); + /* pop the value from the stack */ + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); + } + else + { + /* Push current value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* Increment */ + HB_EXPR_PCODE1( hb_compGenPCode1, bOper ); + /* pop new value from the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* Generate pcode for aliased expression which contains macro operator on + * the left or right side of the alias operator + * expression->¯o or ¯o->expression or ¯o->¯o + */ +#if defined( HB_MACRO_SUPPORT ) +void hb_compExprUseAliasMacro( HB_EXPR_PTR pAliasedVar, BYTE bAction, HB_MACRO_DECL ) +#else +void hb_compExprUseAliasMacro( HB_EXPR_PTR pAliasedVar, BYTE bAction ) +#endif +{ + HB_EXPR_PTR pAlias, pVar; + + /* Alias->Var + */ + pAlias = pAliasedVar->value.asAlias.pAlias; + pVar = pAliasedVar->value.asAlias.pVar; + if( pAlias->ExprType == HB_ET_ALIAS ) + { + /* database alias */ + /* Push alias identifier as string so it can be joined with + * variable at runtime + * NOTE: + * ALIAS->&var is the same as &( "ALIAS->" + var ) + * + */ + HB_EXPR_PCODE2( hb_compGenPushString, pAlias->value.asSymbol, strlen(pAlias->value.asSymbol) ); + HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE ); + if( bAction == HB_EA_PUSH_PCODE ) + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPUSHALIASED ); + else + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPOPALIASED ); + } + else if( pVar->ExprType == HB_ET_VARIABLE ) + { + /* NOTE: + * ¯o->var is the same as: &( macro + "->var" ) + */ + HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE2( hb_compGenPushString, pVar->value.asSymbol, strlen(pVar->value.asSymbol) ); + if( bAction == HB_EA_PUSH_PCODE ) + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPUSHALIASED ); + else + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPOPALIASED ); + } + else + { + HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE ); + if( bAction == HB_EA_PUSH_PCODE ) + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPUSHALIASED ); + else + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_MACROPOPALIASED ); + } + +} + + +/* Reduces the list of expressions + * + * pExpr is the first expression on the list + */ +#if defined( HB_MACRO_SUPPORT ) +ULONG hb_compExprReduceList( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else +ULONG hb_compExprReduceList( HB_EXPR_PTR pExpr ) +#endif +{ + HB_EXPR_PTR pNext; + HB_EXPR_PTR * pPrev; + ULONG ulCnt = 0; + + /* NOTE: During optimalization an expression on the list can be + * replaced by the new one + */ + + pPrev = &pExpr->value.asList.pExprList; + pExpr = pExpr->value.asList.pExprList; + while( pExpr ) + { + pNext = pExpr->pNext; /* store next expression in case the current will be reduced */ + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); + *pPrev = pExpr; /* store a new expression into the previous one */ + pExpr->pNext = pNext; /* restore the link to next expression */ + pPrev = &pExpr->pNext; + pExpr = pNext; + ++ulCnt; + } + return ulCnt; +} + +BOOL hb_compExprCheckMacroVar( char * szText ) +{ + char * pTmp = szText; + BOOL bTextSubst = FALSE; + + while( ( pTmp = strchr( pTmp, '&' ) ) != NULL ) + { + /* Check if macro operator is used inside a string + * Macro operator is ignored if it is the last char or + * next char is '(' e.g. "this is &(ignored)" + * + * NOTE: This uses _a-zA-Z pattern to check for + * variable name beginning + */ + + ++pTmp; + bTextSubst = ( *pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') ); + /* NOTE: All variables are assumed memvars in macro compiler - + * there is no need to check for a valid name + */ +#if !defined( HB_MACRO_SUPPORT ) + if( bTextSubst ) + { + /* There is a valid character after '&' that can be used in + * variable name - check if the whole variable name is valid + * (local, static and field variable names are invalid because + * they are not visible at runtime) + */ + char * pStart = pTmp; + char cSave; + + /* NOTE: This uses _a-zA-Z0-9 pattern to check for + * variable name + */ + while( *pTmp && (*pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') || (*pTmp >= '0' && *pTmp <= '9')) ) + ++pTmp; + + cSave = *pTmp; + *pTmp = '\0'; + hb_compVariableMacroCheck( pStart ); + *pTmp = cSave; + } +#endif + } + return bTextSubst; +} + diff --git a/harbour/include/hbexprop.h b/harbour/include/hbexprop.h index deed63603d..91d37f8117 100644 --- a/harbour/include/hbexprop.h +++ b/harbour/include/hbexprop.h @@ -38,6 +38,110 @@ #include "hbapi.h" +/* value types seen at language level + */ +#define HB_EV_UNKNOWN 0 +#define HB_EV_NIL 1 +#define HB_EV_NUMERIC 2 +#define HB_EV_STRING 4 +#define HB_EV_CODEBLOCK 8 +#define HB_EV_LOGICAL 16 +#define HB_EV_OBJECT 32 +#define HB_EV_ARRAY 64 +#define HB_EV_SYMBOL 128 +#define HB_EV_VARREF 256 +#define HB_EV_FUNREF 512 + +/* messages sent to expressions + */ +typedef enum +{ + HB_EA_REDUCE = 0, /* reduce the expression into optimized one */ + HB_EA_ARRAY_AT, /* check if the expession can be used as array */ + HB_EA_ARRAY_INDEX, /* check if the expession can be used as index */ + HB_EA_LVALUE, /* check if the expression can be used as lvalue (left side of an assigment) */ + HB_EA_PUSH_PCODE, /* generate the pcodes to push the value of expression */ + HB_EA_POP_PCODE, /* generate the pcodes to pop the value of expression */ + HB_EA_PUSH_POP, /* generate the pcodes to push and pop the expression */ + HB_EA_STATEMENT, /* generate the pcodes for a statement */ + HB_EA_DELETE /* delete components of the expression */ +} HB_EXPR_MESSAGE; + +/* additional definitions used to distinguish numeric expressions + */ +#define HB_ET_LONG 1 +#define HB_ET_DOUBLE 2 + +/* additional definitions used to distinguish macro expressions + */ +#define HB_ET_MACRO_VAR 0 /* &variable */ +#define HB_ET_MACRO_SYMBOL 1 /* &fimcall() */ +#define HB_ET_MACRO_ALIASED 2 /* &alias->&variable */ +#define HB_ET_MACRO_EXPR 4 /* &( expr ) */ + +/* types of expressions + * NOTE: the order of these definition is important - change it carefully + * All types <= HB_ET_FUNREF are constant values + * All types <= HB_ET_VARIABLE are a simple values + * All types > HB_ET_VARIABLE are operators + */ +typedef enum +{ + HB_ET_NONE = 0, + HB_ET_NIL, + HB_ET_NUMERIC, + HB_ET_STRING, + HB_ET_CODEBLOCK, + HB_ET_LOGICAL, + HB_ET_SELF, + HB_ET_ARRAY, + HB_ET_VARREF, + HB_ET_FUNREF, + HB_ET_IIF, + HB_ET_LIST, + HB_ET_ARGLIST, + HB_ET_ARRAYAT, + HB_ET_MACRO, + HB_ET_FUNCALL, + HB_ET_ALIASVAR, + HB_ET_ALIASEXPR, + HB_ET_SEND, + HB_ET_FUNNAME, + HB_ET_ALIAS, + HB_ET_RTVAR, /* PRIVATE or PUBLIC declaration of variable */ + HB_ET_VARIABLE, + HB_EO_POSTINC, /* post-operators -> lowest precedence */ + HB_EO_POSTDEC, + HB_EO_ASSIGN, /* assigments */ + HB_EO_PLUSEQ, + HB_EO_MINUSEQ, + HB_EO_MULTEQ, + HB_EO_DIVEQ, + HB_EO_MODEQ, + HB_EO_EXPEQ, + HB_EO_OR, /* logical operators */ + HB_EO_AND, + HB_EO_NOT, + HB_EO_EQUAL, /* relational operators */ + HB_EO_EQ, + HB_EO_LT, + HB_EO_GT, + HB_EO_LE, + HB_EO_GE, + HB_EO_NE, + HB_EO_IN, + HB_EO_PLUS, /* addition */ + HB_EO_MINUS, + HB_EO_MULT, /* multiple */ + HB_EO_DIV, + HB_EO_MOD, + HB_EO_POWER, + HB_EO_NEGATE, /* sign operator */ + HB_EO_PREINC, + HB_EO_PREDEC /* pre-operators -> the highest precedence */ +} HB_EXPR_OPERATOR; + + typedef struct HB_EXPR_ { union @@ -101,31 +205,55 @@ typedef struct HB_EXPR_ /* Definitions of function templates used in expression's message * handling */ - #ifdef HB_MACRO_SUPPORT /* Compilation for macro compiler */ #define HB_EXPR_FUNC( proc ) HB_EXPR_PTR proc( HB_EXPR_PTR pSelf, int iMessage, void * pMacro ) typedef HB_EXPR_FUNC( HB_EXPR_FUNC_ ); typedef HB_EXPR_FUNC_ *HB_EXPR_FUNC_PTR; + +extern HB_EXPR_FUNC_PTR hb_comp_ExprTable[]; + #define HB_EXPR_USE( pSelf, iMessage ) \ - s_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage), pMacro ) + hb_comp_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage), pMacro ) typedef HB_EXPR_PTR HB_EXPR_ACTION( HB_EXPR_PTR pSelf, int iMessage, void * pMacro ); +#define HB_EXPR_PCODE0( action ) action( pMacro ) +#define HB_EXPR_PCODE1( action, p1 ) action( (p1), pMacro ) +#define HB_EXPR_PCODE2( action, p1, p2 ) action( (p1), (p2), pMacro ) +#define HB_EXPR_PCODE3( action, p1, p2, p3 ) action( (p1), (p2), (p3), pMacro ) +#define HB_EXPR_PCODE4( action, p1, p2, p3, p4 ) action( (p1), (p2), (p3), (p4), pMacro ) + +#define HB_MACRO_VARNAME pMacro + #else #define HB_EXPR_FUNC( proc ) HB_EXPR_PTR proc( HB_EXPR_PTR pSelf, int iMessage ) typedef HB_EXPR_FUNC( HB_EXPR_FUNC_ ); typedef HB_EXPR_FUNC_ *HB_EXPR_FUNC_PTR; + +extern HB_EXPR_FUNC_PTR hb_comp_ExprTable[]; + #define HB_EXPR_USE( pSelf, iMessage ) \ - s_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage) ) + hb_comp_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage) ) typedef HB_EXPR_PTR HB_EXPR_ACTION( HB_EXPR_PTR pSelf, int iMessage ); +#define HB_EXPR_PCODE0( action ) action( ) +#define HB_EXPR_PCODE1( action, p1 ) action( (p1) ) +#define HB_EXPR_PCODE2( action, p1, p2 ) action( (p1), (p2) ) +#define HB_EXPR_PCODE3( action, p1, p2, p3 ) action( (p1), (p2), (p3) ) +#define HB_EXPR_PCODE4( action, p1, p2, p3, p4 ) action( (p1), (p2), (p3), (p4) ) + +/* pass NULL instead of macro structure pointer */ +#define HB_MACRO_DECL void *pMacro +#define HB_MACRO_PARAM NULL +#define HB_MACRO_VARNAME pMacro #endif +HB_EXPR_PTR hb_compExprNew( int ); HB_EXPR_PTR hb_compExprNewEmpty( void ); HB_EXPR_PTR hb_compExprNewNil( void ); HB_EXPR_PTR hb_compExprNewDouble( double, BYTE ); @@ -189,6 +317,12 @@ ULONG hb_compExprListLen( HB_EXPR_PTR ); void hb_compExprClear( HB_EXPR_PTR ); char * hb_compExprDescription( HB_EXPR_PTR ); +void hb_compExprFree( HB_EXPR_PTR, HB_MACRO_DECL ); +void hb_compExprErrorType( HB_EXPR_PTR, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR, HB_MACRO_DECL ); +BOOL hb_compExprCheckMacroVar( char * ); +void hb_compExprCBVarDel( HB_CBVAR_PTR ); + #ifdef HB_MACRO_SUPPORT HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR, HB_EXPR_PTR, HB_MACRO_DECL ); @@ -197,8 +331,8 @@ HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR, HB_MACRO_DECL ); HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR, HB_MACRO_DECL ); HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR, HB_MACRO_DECL ); HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR, HB_EXPR_PTR, HB_MACRO_DECL ); -void hb_compExprDelete( HB_EXPR_PTR, HB_MACRO_DECL ); HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR, char *, HB_MACRO_DECL ); +void hb_compExprDelete( HB_EXPR_PTR, HB_MACRO_DECL ); #else @@ -208,8 +342,8 @@ HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR ); HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR ); HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR ); HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR, HB_EXPR_PTR ); -void hb_compExprDelete( HB_EXPR_PTR ); HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR, char *, BYTE ); +void hb_compExprDelete( HB_EXPR_PTR ); #endif diff --git a/harbour/makefile.bc b/harbour/makefile.bc index b064fc6857..8fe65ca9a1 100644 --- a/harbour/makefile.bc +++ b/harbour/makefile.bc @@ -337,6 +337,8 @@ COMMON_LIB_OBJS = \ $(OBJ_DIR)\hbfsapi.obj \ $(OBJ_DIR)\hbstr.obj \ $(OBJ_DIR)\hbtrace.obj \ + $(OBJ_DIR)\expropt1.obj \ + $(OBJ_DIR)\expropt2.obj \ $(OBJ_DIR)\reserved.obj # @@ -389,6 +391,9 @@ HARBOUR_EXE_OBJS = \ $(OBJ_DIR)\genrc.obj \ $(OBJ_DIR)\genhrb.obj \ $(OBJ_DIR)\expropt.obj \ + $(OBJ_DIR)\expropta.obj \ + $(OBJ_DIR)\exproptb.obj \ + $(OBJ_DIR)\exproptc.obj \ $(OBJ_DIR)\hbfunchk.obj # @@ -480,6 +485,14 @@ $(OBJ_DIR)\hbtrace.obj : $(COMMON_DIR)\hbtrace.c $(CC) $(CLIBFLAGS) -o$@ $** tlib $(COMMON_LIB) -+$@,, +$(OBJ_DIR)\expropt1.obj : $(COMMON_DIR)\expropt1.c + $(CC) $(CLIBFLAGS) -o$@ $** + tlib $(COMMON_LIB) -+$@,, + +$(OBJ_DIR)\expropt2.obj : $(COMMON_DIR)\expropt2.c + $(CC) $(CLIBFLAGS) -o$@ $** + tlib $(COMMON_LIB) -+$@,, + # # PP.LIB dependencies # @@ -521,7 +534,9 @@ $(HARBOUR_EXE) : $(HARBOUR_EXE_OBJS) echo. $(OBJ_DIR)\genpas.obj >> make.tmp echo. $(OBJ_DIR)\genrc.obj >> make.tmp echo. $(OBJ_DIR)\genhrb.obj >> make.tmp - echo. $(OBJ_DIR)\expropt.obj >> make.tmp + echo. $(OBJ_DIR)\expropta.obj >> make.tmp + echo. $(OBJ_DIR)\exproptb.obj >> make.tmp + echo. $(OBJ_DIR)\exproptc.obj >> make.tmp echo. $(OBJ_DIR)\hbfunchk.obj >> make.tmp echo. $(COMMON_LIB) $(PP_LIB) >> make.tmp $(CC) @make.tmp @@ -572,7 +587,13 @@ $(OBJ_DIR)\genrc.obj : $(COMPILER_DIR)\genrc.c $(OBJ_DIR)\genhrb.obj : $(COMPILER_DIR)\genhrb.c $(CC) $(CLIBFLAGS) -o$@ $** -$(OBJ_DIR)\expropt.obj : $(COMPILER_DIR)\expropt.c +$(OBJ_DIR)\expropta.obj : $(COMPILER_DIR)\expropta.c + $(CC) $(CLIBFLAGS) -o$@ $** + +$(OBJ_DIR)\exproptb.obj : $(COMPILER_DIR)\exproptb.c + $(CC) $(CLIBFLAGS) -o$@ $** + +$(OBJ_DIR)\exproptc.obj : $(COMPILER_DIR)\exproptc.c $(CC) $(CLIBFLAGS) -o$@ $** $(OBJ_DIR)\hbfunchk.obj : $(COMPILER_DIR)\hbfunchk.c @@ -1531,6 +1552,18 @@ $(OBJ_DIR)\macro.obj : $(MACRO_DIR)\macro.c $(CC) $(CLIBFLAGS) -o$@ $** tlib $(MACRO_LIB) -+$@,, +$(OBJ_DIR)\macroa.obj : $(MACRO_DIR)\macroa.c + $(CC) $(CLIBFLAGS) -o$@ $** + tlib $(MACRO_LIB) -+$@,, + +$(OBJ_DIR)\macrob.obj : $(MACRO_DIR)\macrob.c + $(CC) $(CLIBFLAGS) -o$@ $** + tlib $(MACRO_LIB) -+$@,, + +$(OBJ_DIR)\macroc.obj : $(MACRO_DIR)\macroc.c + $(CC) $(CLIBFLAGS) -o$@ $** + tlib $(MACRO_LIB) -+$@,, + # # NULSYS.LIB dependencies # diff --git a/harbour/makefile.vc b/harbour/makefile.vc index 73df438943..a125b3e7ed 100644 --- a/harbour/makefile.vc +++ b/harbour/makefile.vc @@ -344,6 +344,9 @@ TOOLS_LIB_OBJS = \ MACRO_LIB_OBJS = \ $(OBJ_DIR)\macrol.obj \ $(OBJ_DIR)\macroy.obj \ + $(OBJ_DIR)\macroa.obj \ + $(OBJ_DIR)\macrob.obj \ + $(OBJ_DIR)\macroc.obj \ $(OBJ_DIR)\macro.obj # @@ -472,6 +475,8 @@ DEBUG_LIB_OBJS = \ COMMON_LIB_OBJS = \ $(OBJ_DIR)\hbfsapi.obj \ $(OBJ_DIR)\hbstr.obj \ + $(OBJ_DIR)\expropt1.obj \ + $(OBJ_DIR)\expropt2.obj \ $(OBJ_DIR)\hbtrace.obj \ $(OBJ_DIR)\reserved.obj @@ -655,7 +660,9 @@ $(HARBOUR_EXE) : \ $(COMPILER_DIR)\genrc.c \ $(COMPILER_DIR)\genjava.c \ $(COMPILER_DIR)\genpas.c \ - $(COMPILER_DIR)\expropt.c + $(COMPILER_DIR)\expropta.c \ + $(COMPILER_DIR)\exproptb.c \ + $(COMPILER_DIR)\exproptc.c \ -echo. > $(INCLUDE_DIR)\unistd.h $(CC) $(CFLAGS) -Fo$(OBJ_DIR)\ -w $** -o $(HARBOUR_EXE) /link $(PP_LIB) $(COMMON_LIB) -del $(INCLUDE_DIR)\unistd.h diff --git a/harbour/source/common/Makefile b/harbour/source/common/Makefile index 9276e8b344..83e7a4ac7f 100644 --- a/harbour/source/common/Makefile +++ b/harbour/source/common/Makefile @@ -9,6 +9,8 @@ C_SOURCES=\ hbstr.c \ hbtrace.c \ reserved.c \ + expropt1.c \ + expropt2.c \ PRG_SOURCES=\ diff --git a/harbour/source/common/expropt1.c b/harbour/source/common/expropt1.c new file mode 100644 index 0000000000..e1f9e788a8 --- /dev/null +++ b/harbour/source/common/expropt1.c @@ -0,0 +1,836 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Compiler Expression Optimizer - common expressions + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* TOFIX: Split the code, since MSC8 can't compile it, even in Huge model. */ + +/* TODO: + * - Correct post- and pre- operations to correctly handle the following code + * a[ i++ ]++ + * Notice: in current implementation (an in Clipper too) 'i++' is evaluated + * two times! This causes that the new value (after incrementation) is + * stored in next element of the array. + */ + +/* NOTE: This must be the first definition + * This is a common code shared by macro and standalone compiler + */ +#define HB_MACRO_SUPPORT + +#include +#include "hbmacro.h" +#include "hbcomp.h" + +/* memory allocation + */ +#define HB_XGRAB( size ) hb_xgrab( (size) ) +#define HB_XFREE( pPtr ) hb_xfree( (void *)(pPtr) ) + +static char * s_OperTable[] = { + "", + "NIL", + "Numeric", + "String", + "Codeblock", + "Logical", + "SELF", + "Array", + "@", + "@", + "IIF", + ",", + ",", + "[", + "&", + "()", + "->", + "->", + ":", + "", /* symbol */ + "", /* alias */ + "", /* RunTime variable */ + "", /* variable */ + "++", /* post-operators -> lowest precedence */ + "--", + ":=", /* assigments */ + "+=", + "-=", + "*=", + "/=", + "%=", + "^=", + ".OR.", /* logical operators */ + ".AND.", + ".NOT.", + "=", /* relational operators */ + "==", + "<", + ">", + "<=", + ">=", + "!=", + "$", + "+", /* addition */ + "-", + "*", /* multiple */ + "/", + "%", + "^", + "-", /* sign operator */ + "++", + "--" +}; + +/* ************************************************************************* */ + +HB_EXPR_PTR hb_compExprNew( int iType ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNew(%i)", iType)); + + pExpr = ( HB_EXPR_PTR ) HB_XGRAB( sizeof( HB_EXPR ) ); + + pExpr->ExprType = iType; + pExpr->pNext = NULL; + pExpr->ValType = HB_EV_UNKNOWN; + + return pExpr; +} + +/* Delete self - all components will be deleted somewhere else + */ +void hb_compExprClear( HB_EXPR_PTR pExpr ) +{ + HB_XFREE( pExpr ); +} + +char * hb_compExprDescription( HB_EXPR_PTR pExpr ) +{ + if( pExpr ) + return s_OperTable[ pExpr->ExprType ]; + else + return s_OperTable[ 0 ]; +} + +/* ************************************************************************* */ + +HB_EXPR_PTR hb_compExprNewEmpty( void ) +{ + return hb_compExprNew( HB_ET_NONE ); +} + +HB_EXPR_PTR hb_compExprNewDouble( double dValue, BYTE ucDec ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewDouble(%f, %i)", dValue, ucDec)); + + pExpr =hb_compExprNew( HB_ET_NUMERIC ); + + pExpr->value.asNum.dVal = dValue; + pExpr->value.asNum.bDec = ucDec; + pExpr->value.asNum.NumType = HB_ET_DOUBLE; + pExpr->ValType = HB_EV_NUMERIC; + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewLong( long lValue ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewLong(%li)", lValue)); + + pExpr =hb_compExprNew( HB_ET_NUMERIC ); + + pExpr->value.asNum.lVal = lValue; + pExpr->value.asNum.bDec = 0; + pExpr->value.asNum.NumType = HB_ET_LONG; + pExpr->ValType = HB_EV_NUMERIC; + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewString( char *szValue ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewString(%s)", szValue)); + + pExpr =hb_compExprNew( HB_ET_STRING ); + + pExpr->value.asString = szValue; + pExpr->ulLength = strlen( szValue ); + pExpr->ValType = HB_EV_STRING; + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewCodeBlock( void ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewCodeBlock()")); + + pExpr =hb_compExprNew( HB_ET_CODEBLOCK ); + + pExpr->value.asList.pExprList = NULL; + pExpr->value.asList.pIndex = NULL; /* this will hold local variables declarations */ + pExpr->ValType = HB_EV_CODEBLOCK; + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewLogical( int iValue ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewLogical(%i)", iValue)); + + pExpr =hb_compExprNew( HB_ET_LOGICAL ); + + pExpr->value.asLogical = iValue; + pExpr->ValType = HB_EV_LOGICAL; + + return pExpr; +} + + +HB_EXPR_PTR hb_compExprNewNil( void ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewNil()")); + + pExpr = hb_compExprNew( HB_ET_NIL ); + + pExpr->ValType = HB_EV_NIL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewSelf( void ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewSelf()")); + + pExpr =hb_compExprNew( HB_ET_SELF ); + + pExpr->ValType = HB_EV_OBJECT; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewVarRef( char * szVarName ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewVarRef(%s)", szVarName)); + + pExpr =hb_compExprNew( HB_ET_VARREF ); + + pExpr->value.asSymbol = szVarName; + pExpr->ValType = HB_EV_VARREF; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewFunRef( char * szFunName ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunRef(%s)", szFunName)); + + pExpr =hb_compExprNew( HB_ET_FUNREF ); + + pExpr->value.asSymbol = szFunName; + pExpr->ValType = HB_EV_FUNREF; + return pExpr; +} + +/* Creates a new literal array { item1, item2, ... itemN } + * 'pArrList' is a list of array elements + */ +HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArray()")); + + pArrList->ExprType = HB_ET_ARRAY; /* change type from ET_LIST */ + pArrList->ValType = HB_EV_ARRAY; + pArrList->ulLength = 0; + + pExpr = pArrList->value.asList.pExprList; /* get first element on the list */ + /* Now we need to replace all EO_NONE expressions with ET_NIL expressions + * If EO_NONE is the first expression and there is no more expressions + * then it is an empty array {} and ET_NIL cannot be used + */ + if( pExpr->ExprType == HB_ET_NONE && pExpr->pNext == NULL ) + { + pArrList->value.asList.pExprList = NULL; + } + else + { + /* there are at least one non-empty element specified + */ + while( pExpr ) + { + /* if empty element was specified replace it with NIL value */ + if( pExpr->ExprType == HB_ET_NONE ) + pExpr->ExprType = HB_ET_NIL; + pExpr = pExpr->pNext; + ++pArrList->ulLength; + } + } + pArrList->value.asList.pIndex = NULL; + return pArrList; +} + +/* Creates new macro expression + */ +HB_EXPR_PTR hb_compExprNewMacro( HB_EXPR_PTR pMacroExpr, unsigned char cMacroOp, char * szName ) +{ + HB_EXPR_PTR pExpr; + + if( szName ) + { + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewMacro(%s)", szName)); + + /* Macro variable is used: &identifier + * or macro text: [text]&variable[more_macro_text] + */ + /* + * NOTE: Clipper assumes that all variables used in macro expressions + * are memvar variables + * NOTE: Clipper pushes the complete macro expression converted + * to string in case complex expression is used, e.g. + * My&var.1 + * is pushed as: + * "MY&VAR.1" + */ + pExpr = hb_compExprNew( HB_ET_MACRO ); + pExpr->value.asMacro.cMacroOp = cMacroOp; /* '&' if variable or 0 if text */ + pExpr->value.asMacro.szMacro = szName; /* variable name or macro text */ + pExpr->value.asMacro.pExprList = NULL; /* this is not a parenthesized expressions */ + pExpr->value.asMacro.SubType = HB_ET_MACRO_VAR; + + if( cMacroOp == 0 ) + { + /* check if variable with valid scope is used in macro text + * (local, static and field variables are not allowed) + * e.g. + * LOCAL var + * ? &var // this is OK + * ? &var.ext // this is invalid + */ + hb_compExprCheckMacroVar( szName ); + } + } + else + { + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewMacro(&)")); + + /* Macro expression: &( expression_list ) + */ + pExpr = hb_compExprNew( HB_ET_MACRO ); + pExpr->value.asMacro.pExprList = pMacroExpr; + pExpr->value.asMacro.szMacro = NULL; /* this is used to distinguish &(...) from &ident */ + pExpr->value.asMacro.SubType = HB_ET_MACRO_EXPR; + } + + return pExpr; +} + +/* Creates new aliased variable + * aliasexpr -> identifier + */ +HB_EXPR_PTR hb_compExprNewAliasVar( HB_EXPR_PTR pAlias, HB_EXPR_PTR pVariable ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAliasVar()")); + + pExpr = hb_compExprNew( HB_ET_ALIASVAR ); + + pExpr->value.asAlias.pAlias = pAlias; + pExpr->value.asAlias.pVar = pVariable; + pExpr->value.asAlias.pExpList = NULL; + + /* macro expressions in alias context require a special handling + */ + if( pAlias->ExprType == HB_ET_MACRO ) + pAlias->value.asMacro.SubType = HB_ET_MACRO_ALIASED; + if( pVariable->ExprType == HB_ET_MACRO ) + pVariable->value.asMacro.SubType = HB_ET_MACRO_ALIASED; + + return pExpr; +} + +/* Creates new aliased expression + * alias_expr -> ( expression ) + */ +HB_EXPR_PTR hb_compExprNewAliasExpr( HB_EXPR_PTR pAlias, HB_EXPR_PTR pExpList ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAliasExpr()")); + + pExpr = hb_compExprNew( HB_ET_ALIASEXPR ); + + pExpr->value.asAlias.pAlias = pAlias; + pExpr->value.asAlias.pExpList = pExpList; + pExpr->value.asAlias.pVar = NULL; + + return pExpr; +} + +/* Creates new send expression + * pObject : szMessage + */ +HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR pObject, char * szMessage ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewSend(%p, %s)", pObject, szMessage)); + + pExpr = hb_compExprNew( HB_ET_SEND ); + pExpr->value.asMessage.szMessage = szMessage; + pExpr->value.asMessage.pObject = pObject; + pExpr->value.asMessage.pParms = NULL; + + return pExpr; +} + +/* Creates new method call + * pObject : identifier ( pArgList ) + * + * pObject = is an expression returned by hb_compExprNewSend + * pArgList = list of passed arguments - it will be HB_ET_NONE if no arguments + * are passed + */ +HB_EXPR_PTR hb_compExprNewMethodCall( HB_EXPR_PTR pObject, HB_EXPR_PTR pArgList ) +{ + pObject->value.asMessage.pParms = pArgList; + + return pObject; +} + +/* Creates a list - all elements will be used + * This list can be used to create an array or function's call arguments + */ +HB_EXPR_PTR hb_compExprNewList( HB_EXPR_PTR pFirstItem ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewList()")); + + pExpr = hb_compExprNew( HB_ET_LIST ); + pExpr->value.asList.pExprList = pFirstItem; + return pExpr; +} + +/* Creates a list of function call arguments + */ +HB_EXPR_PTR hb_compExprNewArgList( HB_EXPR_PTR pFirstItem ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArgList()")); + + pExpr = hb_compExprNew( HB_ET_ARGLIST ); + pExpr->value.asList.pExprList = pFirstItem; + return pExpr; +} + +/* Adds new element to the list + */ +HB_EXPR_PTR hb_compExprAddListExpr( HB_EXPR_PTR pList, HB_EXPR_PTR pNewItem ) +{ + if( pList->value.asList.pExprList ) + { + HB_EXPR_PTR pExpr; + + /* add new item to the end of the list */ + pExpr = pList->value.asList.pExprList; + while( pExpr->pNext ) + pExpr = pExpr->pNext; + pExpr->pNext = pNewItem; + } + else + pList->value.asList.pExprList = pNewItem; + + return pList; +} + +HB_EXPR_PTR hb_compExprNewVar( char * szName ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewVar(%s)", szName)); + + pExpr = hb_compExprNew( HB_ET_VARIABLE ); + pExpr->value.asSymbol = szName; + return pExpr; +} + +/* Create a new declaration of PUBLIC or PRIVATE variable. + * + * szName is a string with variable name if 'PUBLIC varname' context + * pMacroVar is a macro expression if 'PUBLIC &varname' context + */ +HB_EXPR_PTR hb_compExprNewRTVar( char * szName, HB_EXPR_PTR pMacroVar ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewRTVar(%s, %p)", szName, pMacroVar)); + + pExpr = hb_compExprNew( HB_ET_RTVAR ); + pExpr->value.asRTVar.szName = szName; + pExpr->value.asRTVar.pMacro = pMacroVar; + if( pMacroVar ) + pMacroVar->value.asMacro.SubType = HB_ET_MACRO_SYMBOL; + return pExpr; +} + +/* Create a new symbol used in function calls + */ +HB_EXPR_PTR hb_compExprNewFunName( char * szName ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewFunName(%s)", szName)); + + pExpr = hb_compExprNew( HB_ET_FUNNAME ); + pExpr->value.asSymbol = szName; + return pExpr; +} + +/* Create a new symbol used in an alias expressions + */ +HB_EXPR_PTR hb_compExprNewAlias( char * szName ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewAlias(%s)", szName)); + + pExpr = hb_compExprNew( HB_ET_ALIAS ); + pExpr->value.asSymbol = szName; + return pExpr; +} + + +/* ************************************************************************* */ + +HB_EXPR_PTR hb_compExprNewEqual( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EQUAL ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPlus( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PLUS ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMinus( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MINUS ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMult( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MULT ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewDiv( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_DIV ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMod( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MOD ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPower( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POWER ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPostInc( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POSTINC ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPostDec( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POSTDEC ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPreInc( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PREINC ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPreDec( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PREDEC ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPlusEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PLUSEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMinusEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MINUSEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMultEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MULTEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewDivEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_DIVEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewModEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MODEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewExpEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EXPEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewAnd( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_AND ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewOr( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_OR ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewNot( HB_EXPR_PTR pNotExpr ) +{ + HB_EXPR_PTR pExpr; + + if( pNotExpr->ExprType == HB_ET_LOGICAL ) + { + pNotExpr->value.asLogical = ! pNotExpr->value.asLogical; + pExpr = pNotExpr; + } + else + { + pExpr = hb_compExprNew( HB_EO_NOT ); + pExpr->value.asOperator.pLeft = pNotExpr; + pExpr->value.asOperator.pRight = NULL; + } + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewEQ( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewLT( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_LT ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewGT( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_GT ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewLE( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_LE ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewGE( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_GE ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewNE( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_NE ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewIN( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_IN ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +/* NOTE: all invalid cases are handled by yacc rules + */ +HB_EXPR_PTR hb_compExprNewNegate( HB_EXPR_PTR pNegExpr ) +{ + HB_EXPR_PTR pExpr; + + if( pNegExpr->ExprType == HB_ET_NUMERIC ) + { + if( pNegExpr->value.asNum.NumType == HB_ET_DOUBLE ) + pNegExpr->value.asNum.dVal = - pNegExpr->value.asNum.dVal; + else + pNegExpr->value.asNum.lVal = - pNegExpr->value.asNum.lVal; + pExpr = pNegExpr; + } + else + { + pExpr = hb_compExprNew( HB_EO_NEGATE ); + pExpr->value.asOperator.pLeft = pNegExpr; + pExpr->value.asOperator.pRight = NULL; + } + return pExpr; +} + +/* ************************************************************************* */ + +/* Handles (expression := expression) syntax + */ +HB_EXPR_PTR hb_compExprAssign( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprAssign()")); + + pExpr = hb_compExprNew( HB_EO_ASSIGN ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = pRightExpr; + return pExpr; +} + +/* Return a number of elements on the linked list + */ +ULONG hb_compExprListLen( HB_EXPR_PTR pExpr ) +{ + ULONG ulLen = 0; + + pExpr = pExpr->value.asList.pExprList; + while( pExpr ) + { + pExpr = pExpr->pNext; + ++ulLen; + } + + return ulLen; +} + diff --git a/harbour/source/common/expropt2.c b/harbour/source/common/expropt2.c new file mode 100644 index 0000000000..1c3eb615c8 --- /dev/null +++ b/harbour/source/common/expropt2.c @@ -0,0 +1,1099 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Compiler Expression Optimizer - reducing expressions + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* TOFIX: Split the code, since MSC8 can't compile it, even in Huge model. */ + +/* TODO: + * - Correct post- and pre- operations to correctly handle the following code + * a[ i++ ]++ + * Notice: in current implementation (an in Clipper too) 'i++' is evaluated + * two times! This causes that the new value (after incrementation) is + * stored in next element of the array. + */ + +/* NOTE: This must be the first definition + * This is a common code shared by macro and standalone compiler + */ +#define HB_MACRO_SUPPORT + +#include +#include "hbmacro.h" +#include "hbcomp.h" + +HB_EXPR_PTR hb_compExprReduceMod( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + if( pLeft->value.asNum.NumType == HB_ET_LONG && pRight->value.asNum.NumType == HB_ET_LONG ) + { + if( pRight->value.asNum.lVal ) + { + double dVal = pLeft->value.asNum.lVal % pRight->value.asNum.lVal; + + if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) + { + pSelf->value.asNum.lVal = ( long ) dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); + } + } + } + else + { + /* TODO: Check for incompatible types e.g. 3 % "txt" + */ + } + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceDiv( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + + if( pRight->value.asNum.lVal ) + { + double dVal = ( double ) pLeft->value.asNum.lVal / ( double ) pRight->value.asNum.lVal; + + if( fmod( dVal, 1.0 ) == 0.0 ) + { + /* Return integer results as long */ + pSelf->value.asNum.lVal = ( long ) dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + /* Return non-integer results as double */ + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + pSelf->ExprType = HB_ET_NUMERIC; + } + break; + + case HB_ET_DOUBLE: + + if( pRight->value.asNum.dVal != 0.0 ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal / pRight->value.asNum.dVal; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; + pSelf->ExprType = HB_ET_NUMERIC; + } + break; + + default: + + if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) + { + if( pRight->value.asNum.lVal ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal / ( double ) pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; + } + } + else + { + if( pRight->value.asNum.dVal != 0.0 ) + { + pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal / pRight->value.asNum.dVal; + pSelf->value.asNum.bDec = HB_DEFAULT_DECIMALS; + } + } + + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + pSelf->ExprType = HB_ET_NUMERIC; + + } /* switch bType */ + + if( pSelf->ExprType == HB_ET_NUMERIC ) + { + /* The expression was reduced - delete old components */ + pSelf->ValType = HB_EV_NUMERIC; + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); + } + } + else + { + /* TODO: Check for incompatible types e.g. 3 / "txt" + */ + } + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceMult( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + { + double dVal = ( double ) pLeft->value.asNum.lVal * ( double ) pRight->value.asNum.lVal; + + if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) + { + pSelf->value.asNum.lVal = ( long ) dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + + break; + } + + case HB_ET_DOUBLE: + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal * pRight->value.asNum.dVal; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec + pRight->value.asNum.bDec; + + break; + } + + default: + { + if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal * ( double ) pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + else + { + pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal * pRight->value.asNum.dVal; + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + } + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); + } + else + { + /* TODO: Check for incompatible types e.g. 3 * "txt" + */ + } + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceMinus( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + { + double dVal = ( double ) pLeft->value.asNum.lVal - ( double ) pRight->value.asNum.lVal; + + if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) + { + pSelf->value.asNum.lVal = ( long ) dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + + break; + } + + case HB_ET_DOUBLE: + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal - pRight->value.asNum.dVal; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + if( pLeft->value.asNum.bDec < pRight->value.asNum.bDec ) + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + else + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + + break; + } + + default: + { + if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal - ( double ) pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + else + { + pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal - pRight->value.asNum.dVal; + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + } + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); + } + else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING ) + { + /* TODO: + */ + } + else + { + /* TODO: Check for incompatible types e.g. "txt" - 3 + */ + } + return pSelf; +} + +HB_EXPR_PTR hb_compExprReducePlus( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + BYTE bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + { + double dVal = ( double ) pLeft->value.asNum.lVal + ( double ) pRight->value.asNum.lVal; + + if( ( double ) LONG_MIN <= dVal && dVal <= ( double ) LONG_MAX ) + { + pSelf->value.asNum.lVal = ( long ) dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + + break; + } + + case HB_ET_DOUBLE: + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal + pRight->value.asNum.dVal; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + if( pLeft->value.asNum.bDec < pRight->value.asNum.bDec ) + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + else + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + + break; + } + + default: + { + if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal + ( double ) pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + else + { + pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal + pRight->value.asNum.dVal; + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + } + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); + } + else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING ) + { + pSelf->ExprType = HB_ET_NONE; /* suppress deletion of operator components */ + hb_compExprFree( pSelf, HB_MACRO_PARAM ); + if( pRight->ulLength == 0 ) + { + pSelf = pLeft; + hb_compExprFree( pRight, HB_MACRO_PARAM ); + } + else if( pLeft->ulLength == 0 ) + { + pSelf = pRight; + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + } + else + { + pLeft->value.asString = (char *) hb_xrealloc( pLeft->value.asString, pLeft->ulLength + pRight->ulLength + 1 ); + memcpy( pLeft->value.asString + pLeft->ulLength, + pRight->value.asString, pRight->ulLength ); + pLeft->ulLength += pRight->ulLength; + pLeft->value.asString[ pLeft->ulLength ] = '\0'; + pSelf = pLeft; + hb_compExprFree( pRight, HB_MACRO_PARAM ); + } + } + else + { + /* TODO: Check for incompatible types e.g. "txt" + 3 + */ + } + return pSelf; +} + + +HB_EXPR_PTR hb_compExprReduceIN( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + if( ( pSelf->value.asOperator.pLeft->ExprType == pSelf->value.asOperator.pRight->ExprType ) && pSelf->value.asOperator.pLeft->ExprType == HB_ET_STRING ) + { + /* Both arguments are literal strings + */ + BOOL bResult; + + /* NOTE: CA-Cl*pper has a bug where the $ operator returns .T. + when an empty string is searched [vszakats] */ + + if( pSelf->value.asOperator.pLeft->ulLength == 0 ) + bResult = TRUE; + else + bResult = ( hb_strAt( pSelf->value.asOperator.pLeft->value.asString, pSelf->value.asOperator.pLeft->ulLength, + pSelf->value.asOperator.pRight->value.asString, pSelf->value.asOperator.pRight->ulLength ) != 0 ); + + /* NOTE: + * "" $ "XXX" = .T. + * "" $ "" = .T. + */ + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + /* TODO: add checking for incompatible types + */ + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .F. != .T. = .T. + * .T. != .T. = .F. + * .F. != .F. = .F. + * .T. != .F. = .T. + */ + BOOL bResult = ( pLeft->value.asLogical != pRight->value.asLogical ); + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_STRING: + /* NOTE: the result depends on SET EXACT setting then it + * cannot be optimized except the case when NULL string are + * compared - "" != "" is always FALSE regardless of EXACT + * setting + */ + if( (pLeft->ulLength | pRight->ulLength) == 0 ) + { + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = FALSE; + + /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal != pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal != pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal != pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal != pRight->value.asNum.lVal ); + } + break; + } + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + } + /* TODO: add checking of incompatible types + else + { + } + */ + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceGE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .T. >= .F. = .T. + * .T. >= .T. = .T. + * .F. >= .F. = .T. + * .F. >= .T. = .f. + */ + BOOL bResult = ! ( ! pLeft->value.asLogical && pRight->value.asLogical ); + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal >= pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal >= pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal >= pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal >= pRight->value.asNum.lVal ); + } + break; + } + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + } + /* TODO: add checking of incompatible types + else + { + } + */ + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceLE( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .T. <= .F. = .F. + * .T. <= .T. = .T. + * .F. <= .F. = .T. + * .F. <= .T. = .T. + */ + BOOL bResult = ! ( pLeft->value.asLogical && ! pRight->value.asLogical ); + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal <= pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal <= pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal <= pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal <= pRight->value.asNum.lVal ); + } + break; + } + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + } + /* TODO: add checking of incompatible types + else + { + } + */ + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceGT( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .T. > .F. = .T. + * .T. > .T. = .F. + * .F. > .F. = .F. + * .F. > .T. = .F. + */ + BOOL bResult = ( pLeft->value.asLogical && ! pRight->value.asLogical ); + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal > pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal > pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal > pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal > pRight->value.asNum.lVal ); + } + break; + } + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + } + /* TODO: add checking of incompatible types + else + { + } + */ + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceLT( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .F. < .T. = .T. + * .T. < .T. = .F. + * .F. < .F. = .F. + * .T. < .F. = .F. + */ + BOOL bResult = ( ! pLeft->value.asLogical && pRight->value.asLogical ); + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal < pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal < pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal < pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal < pRight->value.asNum.lVal ); + } + break; + } + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + default: + break; + } + /* TODO: add checking of incompatible types + else + { + } + */ + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceEQ( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + { + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + BOOL bResult = ( pLeft->value.asLogical == pRight->value.asLogical ); + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_STRING: + { + BOOL bResult = FALSE; + + if( pLeft->ulLength == pRight->ulLength ) + bResult = ( strcmp( pLeft->value.asString, pRight->value.asString ) == 0 ); + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal == pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal == pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal == pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal == pRight->value.asNum.lVal ); + } + break; + } + hb_compExprFree( pSelf->value.asOperator.pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pSelf->value.asOperator.pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + } + } + /* TODO: add checking of incompatible types + else + { + } + */ + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceAnd( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_LOGICAL && pRight->ExprType == HB_ET_LOGICAL ) + { + BOOL bResult; + + bResult = pLeft->value.asLogical && pRight->value.asLogical; + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + else if( pLeft->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) + { + if( pLeft->value.asLogical ) + { + /* .T. .AND. expr => expr + */ + hb_compExprFree( pLeft, HB_MACRO_PARAM); + pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ + hb_compExprFree( pSelf, HB_MACRO_PARAM ); + pSelf = pRight; + } + else + { + /* .F. .AND. expr => .F. + */ + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); /* discard expression */ + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = FALSE; + } + } + else if( pRight->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) + { + if( pRight->value.asLogical ) + { + /* expr .AND. .T. => expr + */ + hb_compExprFree( pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ + hb_compExprFree( pSelf, HB_MACRO_PARAM ); + pSelf = pLeft; + } + else + { + /* expr .AND. .F. => .F. + */ + hb_compExprFree( pLeft, HB_MACRO_PARAM ); /* discard expression */ + hb_compExprFree( pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = FALSE; + } + } + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceOr( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_LOGICAL && pRight->ExprType == HB_ET_LOGICAL ) + { + BOOL bResult; + + bResult = pLeft->value.asLogical || pRight->value.asLogical; + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + else if( pLeft->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) + { + if( pLeft->value.asLogical ) + { + /* .T. .OR. expr => .T. + */ + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + hb_compExprFree( pRight, HB_MACRO_PARAM ); /* discard expression */ + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = TRUE; + } + else + { + /* .F. .OR. expr => expr + */ + hb_compExprFree( pLeft, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ + hb_compExprFree( pSelf, HB_MACRO_PARAM ); + pSelf = pRight; + } + } + else if( pRight->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) + { + if( pRight->value.asLogical ) + { + /* expr .OR. .T. => .T. + */ + hb_compExprFree( pLeft, HB_MACRO_PARAM ); /* discard expression */ + hb_compExprFree( pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = TRUE; + } + else + { + /* expr .OR. .F. => expr + */ + hb_compExprFree( pRight, HB_MACRO_PARAM ); + pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ + hb_compExprFree( pSelf, HB_MACRO_PARAM ); + pSelf = pLeft; + } + } + return pSelf; +} + +HB_EXPR_PTR hb_compExprReduceIIF( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + HB_EXPR_PTR pExpr; + + pExpr =pSelf->value.asList.pExprList; /* get conditional expression */ + if( pExpr->ExprType == HB_ET_LOGICAL ) + { + /* the condition was reduced to a logical value: .T. or .F. + */ + if( pExpr->value.asLogical ) + { + /* .T. was specified + */ + pExpr = pExpr->pNext; /* skip to TRUE expression */ + /* delete condition - it is no longer needed + */ + hb_compExprFree( pSelf->value.asList.pExprList, HB_MACRO_PARAM ); + /* assign NULL to a start of expressions list to suppress + * deletion of expression's components - we are deleting them + * here + */ + pSelf->value.asList.pExprList = NULL; + hb_compExprFree( pSelf, HB_MACRO_PARAM ); + /* store the TRUE expression as a result of reduction + */ + pSelf = pExpr; + pExpr = pExpr->pNext; /* skip to FALSE expression */ + hb_compExprFree( pExpr, HB_MACRO_PARAM ); /* delete FALSE expr */ + pSelf->pNext = NULL; + } + else + { + /* .F. was specified + */ + pExpr = pExpr->pNext; /* skip to TRUE expression */ + /* delete condition - it is no longer needed + */ + hb_compExprFree( pSelf->value.asList.pExprList, HB_MACRO_PARAM ); + /* assign NULL to a start of expressions list to suppress + * deletion of expression's components - we are deleting them + * here + */ + pSelf->value.asList.pExprList = NULL; + hb_compExprFree( pSelf, HB_MACRO_PARAM ); + /* store the FALSE expression as a result of reduction + */ + pSelf = pExpr->pNext; + hb_compExprFree( pExpr, HB_MACRO_PARAM ); /* delete TRUE expr */ + pSelf->pNext = NULL; + } + } + /* check if valid expression is passed + */ + else if( ( pExpr->ExprType == HB_ET_DOUBLE ) || + ( pExpr->ExprType == HB_ET_LONG ) || + ( pExpr->ExprType == HB_ET_NIL ) || + ( pExpr->ExprType == HB_ET_STRING ) || + ( pExpr->ExprType == HB_ET_CODEBLOCK ) || + ( pExpr->ExprType == HB_ET_SELF ) || + ( pExpr->ExprType == HB_ET_ARRAY ) ) + { + hb_compExprErrorType( pExpr, HB_MACRO_PARAM ); + } + return pSelf; +} + +/* replace the list containing a single expression with a simple expression + * - strips parenthesis + * ( EXPR ) -> EXPR + */ +HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +{ + if( pSelf->ExprType == HB_ET_LIST ) + { + ULONG ulCount = hb_compExprListLen( pSelf ); + + if( ulCount == 1 && pSelf->value.asList.pExprList->ExprType <= HB_ET_VARIABLE ) + { + /* replace the list with a simple expression + * ( EXPR ) -> EXPR + */ + HB_EXPR_PTR pExpr = pSelf; + + pSelf = pSelf->value.asList.pExprList; + pExpr->value.asList.pExprList = NULL; + hb_compExprFree( pExpr, HB_MACRO_PARAM ); + } + } + return pSelf; +} + diff --git a/harbour/source/compiler/Makefile b/harbour/source/compiler/Makefile index f74de9fe9b..8b31e8468c 100644 --- a/harbour/source/compiler/Makefile +++ b/harbour/source/compiler/Makefile @@ -33,7 +33,9 @@ C_SOURCES=\ hbgenerr.c \ hbpcode.c \ hbusage.c \ - expropt.c \ + expropta.c \ + exproptb.c \ + exproptc.c \ C_MAIN=harbour.c diff --git a/harbour/source/compiler/expropt.c b/harbour/source/compiler/expropt.c deleted file mode 100644 index 043e303fa6..0000000000 --- a/harbour/source/compiler/expropt.c +++ /dev/null @@ -1,10 +0,0 @@ -/* - * $Id$ - */ - -/* hbexpr.c is also included from ../macro/macro.c - * However it produces a slighty different code if used in - * macro compiler - * 3 - ignore this magic number - this is used to force compilation -*/ -#include "hbexpr.c" diff --git a/harbour/source/compiler/expropta.c b/harbour/source/compiler/expropta.c new file mode 100644 index 0000000000..05d09311d8 --- /dev/null +++ b/harbour/source/compiler/expropta.c @@ -0,0 +1,10 @@ +/* + * $Id$ + */ + +/* hbexpra.c is also included from ../macro/macro.c + * However it produces a slighty different code if used in + * macro compiler (there is an additional parameter passed to some functions) + * 0 - ignore this magic number - this is used to force compilation +*/ +#include "hbexpra.c" diff --git a/harbour/source/compiler/exproptb.c b/harbour/source/compiler/exproptb.c new file mode 100644 index 0000000000..30e7ad04d1 --- /dev/null +++ b/harbour/source/compiler/exproptb.c @@ -0,0 +1,10 @@ +/* + * $Id$ + */ + +/* hbexprb.c is also included from ../macro/macro.c + * However it produces a slighty different code if used in + * macro compiler (there is an additional parameter passed to some functions) + * 0 - ignore this magic number - this is used to force compilation +*/ +#include "hbexprb.c" diff --git a/harbour/source/compiler/exproptc.c b/harbour/source/compiler/exproptc.c new file mode 100644 index 0000000000..c2c531cca0 --- /dev/null +++ b/harbour/source/compiler/exproptc.c @@ -0,0 +1,10 @@ +/* + * $Id$ + */ + +/* hbexprc.c is also included from ../macro/macro.c + * However it produces a slighty different code if used in + * macro compiler (there is an additional parameter passed to some functions) + * 0 - ignore this magic number - this is used to force compilation +*/ +#include "hbexprc.c"