From 64509ea87127742c65bcfb5f5b7832bda2c8bb8f Mon Sep 17 00:00:00 2001 From: Ryszard Glab Date: Fri, 29 Sep 2006 08:59:17 +0000 Subject: [PATCH] + added support for passing methods as macro eg: o:&send() o:&send.end() o:&(expr)() o:&var++ o:&var := 0 o:&(expr)++ WITH OBJECT obj ++:&var :&var += :&(var2+"oo") END NOTICE: For simple assigments (=,:=), compound assignments (+=,-=,*=,/=) and for pre/post increment operators( ++,--) the macro should evaluate to a symbol that starts with underscore '_'. To access a variable the macro should evaluate to a symbol with no '_' char. --- harbour/ChangeLog | 39 +++++++++++++++ harbour/include/hbexpra.c | 45 +++++++++++------ harbour/include/hbexprb.c | 43 +++++++++++++++-- harbour/include/hbexprc.c | 77 ++++++++++++++++++++---------- harbour/include/hbexprop.h | 5 +- harbour/source/common/expropt1.c | 2 +- harbour/source/compiler/expropta.c | 2 +- harbour/source/compiler/exproptb.c | 2 +- harbour/source/compiler/exproptc.c | 2 +- harbour/source/compiler/harbour.c | 22 ++++++--- harbour/source/compiler/harbour.y | 63 +++++++++++++----------- harbour/source/macro/macro.y | 40 ++++++++-------- harbour/source/macro/macroa.c | 2 +- harbour/source/macro/macrob.c | 2 +- harbour/source/macro/macroc.c | 2 +- harbour/source/vm/hvm.c | 22 ++++++++- harbour/tests/omacro.prg | 48 +++++++++++++++++++ 17 files changed, 313 insertions(+), 105 deletions(-) create mode 100644 harbour/tests/omacro.prg diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 6336832ea3..81d8a5f4e4 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,45 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2006-09-28 11:10 UTC+0100 Ryszard Glab + + * harbour/source/rdd/workarea.c + * minor modification + + * harbour/source/rdd/dbfcdx/dbfcdx1.c + * minor Clipper compatibility update + +2006-09-29 11:20 UTC+0100 Ryszard Glab + * tests/Makefile + + added omacro.prg and varparam.prg + * ChangeLog + * fixed date in previous commit + +2006-09-29 11:10 UTC+0100 Ryszard Glab + * include/hbexpra.c + * include/hbexprb.c + * include/hbexprc.c + * include/hbexprop.h + * source/common/expropt1.c + * source/compiler/expropta.c + * source/compiler/exproptb.c + * source/compiler/exproptc.c + * source/compiler/harbour.c + * source/compiler/harbour.y + * source/macro/macro.y + * source/macro/macroa.c + * source/macro/macrob.c + + * source/vm/hvm.c + + added support for passing methods as macro + + o:&send() + o:&send.end() + and for pre/post increment operators( ++,--) the macro should + o:&var++ + o:&var := 0 + o:&(expr)++ + WITH OBJECT obj ++:&var :&var += :&(var2+"oo") END diff --git a/harbour/include/hbexpra.c b/harbour/include/hbexpra.c index dd64bf551b..2beed743ea 100644 --- a/harbour/include/hbexpra.c +++ b/harbour/include/hbexpra.c @@ -392,9 +392,9 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) /* Optimize Eval( bBlock, [ArgList] ) to: bBlock:Eval( [ArgList] ) */ pEval = hb_compExprNewMethodCall( #ifndef HB_MACRO_SUPPORT - hb_compExprNewSend( pParms->value.asList.pExprList, hb_compIdentifierNew( "EVAL", TRUE ) ), + hb_compExprNewSend( pParms->value.asList.pExprList, hb_compIdentifierNew( "EVAL", TRUE ), NULL ), #else - hb_compExprNewSend( pParms->value.asList.pExprList, hb_strdup("EVAL") ), + hb_compExprNewSend( pParms->value.asList.pExprList, hb_strdup("EVAL"), NULL ), #endif hb_compExprNewArgList( pParms->value.asList.pExprList->pNext ) ); @@ -651,34 +651,51 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) /* Creates new send expression * pObject : szMessage */ -HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR pObject, char * szMessage ) +HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR pObject, char * szMessage, HB_EXPR_PTR pMessage ) { 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; -#ifndef HB_MACRO_SUPPORT - if( (strcmp( "__ENUMINDEX", szMessage ) == 0) || - (strcmp( "__ENUMBASE", szMessage ) == 0 ) || - (strcmp( "__ENUMVALUE", szMessage ) == 0 ) ) + if( szMessage != NULL ) { - if( pObject->ExprType == HB_ET_VARIABLE ) + pExpr->value.asMessage.szMessage = szMessage; + pExpr->value.asMessage.pMessage = NULL; +#ifndef HB_MACRO_SUPPORT + if( (strcmp( "__ENUMINDEX", szMessage ) == 0) || + (strcmp( "__ENUMBASE", szMessage ) == 0 ) || + (strcmp( "__ENUMVALUE", szMessage ) == 0 ) ) { - if( ! hb_compForEachVarError( pObject->value.asSymbol ) ) + if( pObject->ExprType == HB_ET_VARIABLE ) { + if( ! hb_compForEachVarError( pObject->value.asSymbol ) ) + { /* pExpr->value.asMessage.pObject = hb_compExprNewVarRef( pObject->value.asSymbol );*/ - /* NOTE: direct type change */ - pObject->ExprType = HB_ET_VARREF; - pExpr->value.asMessage.pObject = pObject; + /* NOTE: direct type change */ + pObject->ExprType = HB_ET_VARREF; + pExpr->value.asMessage.pObject = pObject; + } } } - } #endif + } + else + { + pExpr->value.asMessage.pMessage = pMessage; + pExpr->value.asMessage.szMessage = NULL; + if( pMessage->ExprType == HB_ET_MACRO ) + { + /* Signal that macro compiler have to generate a pcode that will + * return function name as symbol instead of usual value + */ + pMessage->value.asMacro.SubType = HB_ET_MACRO_SYMBOL; + } + } + return pExpr; } diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c index bed73ee931..9fa2a498e6 100644 --- a/harbour/include/hbexprb.c +++ b/harbour/include/hbexprb.c @@ -2217,7 +2217,18 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) { BOOL fMacroList = FALSE; int iParms = hb_compExprListLen( pSelf->value.asMessage.pParms ); - HB_EXPR_PCODE2( hb_compGenMessage, pSelf->value.asMessage.szMessage, bIsObject ); + if( pSelf->value.asMessage.szMessage ) + { + HB_EXPR_PCODE2( hb_compGenMessage, pSelf->value.asMessage.szMessage, bIsObject ); + } + else + { + HB_EXPR_USE( pSelf->value.asMessage.pMessage, HB_EA_PUSH_PCODE ); + if( ! bIsObject ) + { + HB_EXPR_PCODE2( hb_compGenMessage, NULL, bIsObject ); + } + } if( bIsObject ) { HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); @@ -2267,7 +2278,18 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) else { /* acces to instance variable */ - HB_EXPR_PCODE2( hb_compGenMessage, pSelf->value.asMessage.szMessage, bIsObject ); + if( pSelf->value.asMessage.szMessage ) + { + HB_EXPR_PCODE2( hb_compGenMessage, pSelf->value.asMessage.szMessage, bIsObject ); + } + else + { + HB_EXPR_USE( pSelf->value.asMessage.pMessage, HB_EA_PUSH_PCODE ); + if( ! bIsObject ) + { + HB_EXPR_PCODE2( hb_compGenMessage, NULL, bIsObject ); + } + } if( bIsObject ) { HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); @@ -2285,7 +2307,18 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) /* NOTE: This is an exception from the rule - this leaves * the return value on the stack */ - HB_EXPR_PCODE2( hb_compGenMessageData, pSelf->value.asMessage.szMessage, bIsObject ); + if( pSelf->value.asMessage.szMessage ) + { + HB_EXPR_PCODE2( hb_compGenMessageData, pSelf->value.asMessage.szMessage, bIsObject ); + } + else + { + HB_EXPR_USE( pSelf->value.asMessage.pMessage, HB_EA_PUSH_PCODE ); + if( ! bIsObject ) + { + HB_EXPR_PCODE2( hb_compGenMessage, NULL, bIsObject ); + } + } if( bIsObject ) { HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); @@ -2319,6 +2352,10 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) { HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pParms ); } + if( pSelf->value.asMessage.pMessage ) + { + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pMessage ); + } #if defined( HB_MACRO_SUPPORT ) HB_XFREE( pSelf->value.asMessage.szMessage ); #endif diff --git a/harbour/include/hbexprc.c b/harbour/include/hbexprc.c index e0629a4748..81795c737a 100644 --- a/harbour/include/hbexprc.c +++ b/harbour/include/hbexprc.c @@ -80,21 +80,30 @@ static void hb_compExprSendPopPush( HB_EXPR_PTR pObj ) if( pObj->value.asMessage.pObject ) { /* Push _message for later use */ - HB_EXPR_PCODE2( hb_compGenMessageData, pObj->value.asMessage.szMessage, TRUE ); - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - - /* Now push current value of variable */ - HB_EXPR_PCODE2( hb_compGenMessage, pObj->value.asMessage.szMessage, TRUE ); + if( pObj->value.asMessage.szMessage ) + { + HB_EXPR_PCODE2( hb_compGenMessageData, pObj->value.asMessage.szMessage, TRUE ); + } + else + { + HB_EXPR_USE( pObj->value.asMessage.pMessage, HB_EA_PUSH_PCODE ); + } /* Push object */ HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); } else { /* Push _message for later use */ - HB_EXPR_PCODE2( hb_compGenMessageData, pObj->value.asMessage.szMessage, FALSE ); - /* Now push current value of variable */ - HB_EXPR_PCODE2( hb_compGenMessage, pObj->value.asMessage.szMessage, FALSE ); + if( pObj->value.asMessage.szMessage ) + { + HB_EXPR_PCODE2( hb_compGenMessageData, pObj->value.asMessage.szMessage, FALSE ); + } + else + { + HB_EXPR_USE( pObj->value.asMessage.pMessage, HB_EA_PUSH_PCODE ); + /* Push WITHOBJECTMESSAGE pcode */ + HB_EXPR_PCODE2( hb_compGenMessage, NULL, FALSE ); + } } } @@ -127,7 +136,7 @@ void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) { HB_EXPR_PCODE1( hb_compExprSendPopPush, pSelf->value.asOperator.pLeft ); /* Do it. */ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); + HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_PUSHOVARREF ); /* NOTE: COMPATIBILITY ISSUE: * The above HB_C52_STRICT setting determines @@ -157,10 +166,22 @@ void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) /* push increment value */ HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); /* increase operation */ + switch( bOpEq ) + { + case HB_P_PLUS: + bOpEq = HB_P_PLUSEQ; + break; + case HB_P_MINUS: + bOpEq = HB_P_MINUSEQ; + break; + case HB_P_MULT: + bOpEq = HB_P_MULTEQ; + break; + case HB_P_DIVIDE: + bOpEq = HB_P_DIVEQ; + break; + } HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); - - /* call pop message with one argument */ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); return; } @@ -287,18 +308,27 @@ void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) { HB_EXPR_PCODE1( hb_compExprSendPopPush, pSelf->value.asOperator.pLeft ); /* Do it.*/ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); + HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_PUSHOVARREF ); /* push increment value */ HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - /* increase operation */ + /* increase operation and pop the unneeded value from the stack */ + switch( bOpEq ) + { + case HB_P_PLUS: + bOpEq = HB_P_PLUSEQPOP; + break; + case HB_P_MINUS: + bOpEq = HB_P_MINUSEQPOP; + break; + case HB_P_MULT: + bOpEq = HB_P_MULTEQPOP; + break; + case HB_P_DIVIDE: + bOpEq = HB_P_DIVEQPOP; + break; + } HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); - - /* Now do the assignment - call pop message with one argument */ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); - - /* pop the unneeded value from the stack */ - HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_POP ); return; } @@ -425,13 +455,10 @@ void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper ) { HB_EXPR_PCODE1( hb_compExprSendPopPush, pSelf->value.asOperator.pLeft ); /* Do it. */ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); + HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_PUSHOVARREF ); /* increase/decrease operation */ HB_EXPR_GENPCODE1( hb_compGenPCode1, bOper ); - - /* Now, do the assignment - call pop message with one argument - it leaves the value on the stack */ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); } else { diff --git a/harbour/include/hbexprop.h b/harbour/include/hbexprop.h index 80868ba38c..e9924ef650 100644 --- a/harbour/include/hbexprop.h +++ b/harbour/include/hbexprop.h @@ -231,8 +231,9 @@ typedef struct HB_EXPR_ struct { struct HB_EXPR_ *pObject; /* object */ - char * szMessage; /* message */ struct HB_EXPR_ *pParms; /* method parameters */ + char * szMessage; /* message as string */ + struct HB_EXPR_ *pMessage; /* message as macro */ } asMessage; struct { @@ -359,7 +360,7 @@ HB_EXPR_PTR hb_compExprNewFunRef( char * ); HB_EXPR_PTR hb_compExprNewRef( HB_EXPR_PTR ); HB_EXPR_PTR hb_compExprNewCodeblockExpr( HB_EXPR_PTR, HB_EXPR_PTR ); HB_EXPR_PTR hb_compExprNewFunCallArg( HB_EXPR_PTR, HB_EXPR_PTR ); -HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR, char * ); +HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR, char *szMessage, HB_EXPR_PTR pMessage ); HB_EXPR_PTR hb_compExprNewMethodCall( HB_EXPR_PTR, HB_EXPR_PTR ); HB_EXPR_PTR hb_compExprNewList( HB_EXPR_PTR ); HB_EXPR_PTR hb_compExprNewArgList( HB_EXPR_PTR ); diff --git a/harbour/source/common/expropt1.c b/harbour/source/common/expropt1.c index 9a768dea7d..f5be0abc35 100644 --- a/harbour/source/common/expropt1.c +++ b/harbour/source/common/expropt1.c @@ -499,7 +499,7 @@ HB_EXPR_PTR hb_compExprNewAliasExpr( HB_EXPR_PTR pAlias, HB_EXPR_PTR pExpList ) /* Creates new method call * pObject : identifier ( pArgList ) * - * pObject = is an expression returned by hb_compExprNewSend + * pObject = is an expression returned by hb_compExprNewSend * pArgList = list of passed arguments - it will be HB_ET_NONE if no arguments * are passed */ diff --git a/harbour/source/compiler/expropta.c b/harbour/source/compiler/expropta.c index 3dfb87c7da..bd062e3f85 100644 --- a/harbour/source/compiler/expropta.c +++ b/harbour/source/compiler/expropta.c @@ -5,6 +5,6 @@ /* 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) - * 1.22 - ignore this magic number - this is used to force compilation + * 1.23 - 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 index 05e5d1727a..ec613a8318 100644 --- a/harbour/source/compiler/exproptb.c +++ b/harbour/source/compiler/exproptb.c @@ -5,6 +5,6 @@ /* 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) - * 1.19 - ignore this magic number - this is used to force compilation + * 1.20 - 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 index 8127e1992d..7f477dd6a7 100644 --- a/harbour/source/compiler/exproptc.c +++ b/harbour/source/compiler/exproptc.c @@ -5,6 +5,6 @@ /* 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) - * 1.10 - ignore this magic number - this is used to force compilation + * 1.11 - ignore this magic number - this is used to force compilation */ #include "hbexprc.c" diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 1049d7003b..5b614f420a 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -2903,15 +2903,25 @@ void hb_compGenVarPCode( BYTE bPCode, char * szVarName ) void hb_compGenMessage( char * szMsgName, BOOL bIsObject ) { USHORT wSym; - PCOMSYMBOL pSym = hb_compSymbolFind( szMsgName, &wSym, HB_SYM_MSGNAME ); + PCOMSYMBOL pSym; + + if( szMsgName ) + { + pSym = hb_compSymbolFind( szMsgName, &wSym, HB_SYM_MSGNAME ); - if( ! pSym ) /* the symbol was not found on the symbol table */ - pSym = hb_compSymbolAdd( szMsgName, &wSym, HB_SYM_MSGNAME ); - pSym->cScope |= HB_FS_MESSAGE; - if( bIsObject ) - hb_compGenPCode3( HB_P_MESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), ( BOOL ) 1 ); + if( ! pSym ) /* the symbol was not found on the symbol table */ + pSym = hb_compSymbolAdd( szMsgName, &wSym, HB_SYM_MSGNAME ); + pSym->cScope |= HB_FS_MESSAGE; + if( bIsObject ) + hb_compGenPCode3( HB_P_MESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), ( BOOL ) 1 ); + else + hb_compGenPCode3( HB_P_WITHOBJECTMESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), ( BOOL ) 1 ); + } else + { + wSym = 0xFFFF; hb_compGenPCode3( HB_P_WITHOBJECTMESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), ( BOOL ) 1 ); + } } void hb_compGenMessageData( char * szMsg, BOOL bIsObject ) /* generates an underscore-symbol name for a data assignment */ diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 2be46499b0..39c9a5e270 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -212,6 +212,15 @@ static void hb_compDebugStart( void ) { }; BOOL lateEval; /* Flag for early {|| ¯o} (0) or late {|| &(macro)} (1) binding */ BOOL isMacro; } asCodeblock; + struct + { + BOOL bMacro; + union + { + char *string; + HB_EXPR_PTR macro; + } value; + } asMessage; void * pVoid; /* to hold any memory structure we may need */ }; @@ -258,7 +267,7 @@ static void hb_compDebugStart( void ) { }; %right '\n' ';' ',' /*the highest precedence*/ -%type IdentName IDENTIFIER LITERAL SendId MACROVAR MACROTEXT CompTimeStr +%type IdentName IDENTIFIER LITERAL MACROVAR MACROTEXT CompTimeStr %type DOIDENT WHILE %type NUM_DOUBLE %type NUM_INTEGER @@ -305,6 +314,7 @@ static void hb_compDebugStart( void ) { }; %type ForVar ForList ForExpr %type CBSTART %type DateValue +%type SendId %% @@ -743,33 +753,34 @@ FunCallAlias : FunCall ALIASOP { $$ = $1; } /* Object's instance variable */ -SendId : IdentName { $$ = $1; } - | MacroVar { $$ = "&"; hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_INVALID_SEND, "&", NULL); } +SendId : IdentName { $$.value.string = $1; $$.bMacro=FALSE; } + | MacroVar { $$.value.macro = $1; $$.bMacro=TRUE; } + | MacroExpr { $$.value.macro = $1; $$.bMacro=TRUE; } ; -ObjectData : NumValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | NilValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | DateValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | LiteralValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | Variable ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | CodeBlock ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | Logical ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | SelfValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | Array ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | ArrayAt ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | AliasVar ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | AliasExpr ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | MacroVar ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | MacroExpr ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | FunCall ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | IfInline ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | PareExpList ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | VariableAt ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | ObjectMethod ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } - | ObjectData ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } +ObjectData : NumValue ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | NilValue ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | DateValue ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | LiteralValue ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | Variable ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | CodeBlock ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | Logical ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | SelfValue ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | Array ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | ArrayAt ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | AliasVar ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | AliasExpr ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | MacroVar ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | MacroExpr ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | FunCall ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | IfInline ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | PareExpList ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | VariableAt ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | ObjectMethod ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } + | ObjectData ':' SendId { $$ = ($3.bMacro ? hb_compExprNewSend( $1, NULL, $3.value.macro ) : hb_compExprNewSend( $1, $3.value.string, NULL )); } | ':' SendId { if( hb_comp_wWithObjectCnt == 0 ) hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_WITHOBJECT, NULL, NULL ); - $$ = hb_compExprNewSend( NULL, $2 ); + $$ = ($2.bMacro ? hb_compExprNewSend( NULL, NULL, $2.value.macro ) : hb_compExprNewSend( NULL, $2.value.string, NULL )); } ; @@ -1906,9 +1917,7 @@ DoArgument : IdentName { $$ = hb_compExprNewVarRef( $1 ); } | '@' MacroVar { $$ = hb_compExprNewRef( $2 ); } | '@' AliasVar { $$ = hb_compExprNewRef( $2 ); } ; -/* - | '@' IdentName { $$ = hb_compExprNewVarRef( $2 ); } -*/ + WithObject : WITHOBJECT Expression Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); diff --git a/harbour/source/macro/macro.y b/harbour/source/macro/macro.y index 17068aa8ed..068434bd27 100644 --- a/harbour/source/macro/macro.y +++ b/harbour/source/macro/macro.y @@ -443,26 +443,26 @@ Argument : EmptyExpression { $$ = $1; } /* Object's instance variable */ -ObjectData : NumValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | NilValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | DateValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | LiteralValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | CodeBlock ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | Logical ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | SelfValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | Array ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | ArrayAt ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | Variable ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | AliasVar ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | AliasExpr ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | MacroVar ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | MacroExpr ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | FunCall ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | IfInline ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | PareExpList ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | VariableAt ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | ObjectMethod ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } - | ObjectData ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } +ObjectData : NumValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | NilValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | DateValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | LiteralValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | CodeBlock ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | Logical ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | SelfValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | Array ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | ArrayAt ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | Variable ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | AliasVar ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | AliasExpr ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | MacroVar ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | MacroExpr ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | FunCall ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | IfInline ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | PareExpList ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | VariableAt ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | ObjectMethod ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } + | ObjectData ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3, NULL ); } ; /* Object's method diff --git a/harbour/source/macro/macroa.c b/harbour/source/macro/macroa.c index 6dfa8f10c9..8c85c4cad8 100644 --- a/harbour/source/macro/macroa.c +++ b/harbour/source/macro/macroa.c @@ -5,7 +5,7 @@ /* hbexpra.c is also included from ../compiler/expropta.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.20 - ignore this magic number - this is used to force compilation + * 1.21 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/macro/macrob.c b/harbour/source/macro/macrob.c index 94d1c609b8..073052f318 100644 --- a/harbour/source/macro/macrob.c +++ b/harbour/source/macro/macrob.c @@ -5,7 +5,7 @@ /* hbexprb.c is also included from ../compiler/exproptb.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.17 - ignore this magic number - this is used to force compilation + * 1.18 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/macro/macroc.c b/harbour/source/macro/macroc.c index 5262cff19c..ec57ac4c90 100644 --- a/harbour/source/macro/macroc.c +++ b/harbour/source/macro/macroc.c @@ -5,7 +5,7 @@ /* hbexprc.c is also included from ../compiler/exproptc.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.9 - ignore this magic number - this is used to force compilation + * 1.10 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 8e850988ed..1795630b40 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -1801,10 +1801,20 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) /* WITH OBJECT */ case HB_P_WITHOBJECTMESSAGE: - hb_vmPushSymbol( pSymbols + HB_PCODE_MKUSHORT( &( pCode[ w + 1 ] ) ) ); + { + USHORT wSymPos = HB_PCODE_MKUSHORT( &( pCode[ w + 1 ] ) ); + if( wSymPos != 0xFFFF ) + { + /* NOTE: 0xFFFF is passed when ':&varmacro' syntax is used. + * In this case symbol is already pushed on the stack + * using HB_P_MACROSYMBOL. + */ + hb_vmPushSymbol( pSymbols + wSymPos ); + } hb_vmPush( hb_stackWithObjectItem() ); w += 3; break; + } case HB_P_WITHOBJECTSTART: hb_vmWithObjectStart(); @@ -2450,6 +2460,11 @@ static void hb_vmInc( void ) pItem = hb_stackItemFromTop( -1 ); + if( HB_IS_BYREF( pItem ) ) + { + pItem = hb_itemUnRef( pItem ); + } + if( HB_IS_DATE( pItem ) ) pItem->item.asDate.value++; else if( HB_IS_NUMINT( pItem ) ) @@ -2497,6 +2512,11 @@ static void hb_vmDec( void ) pItem = hb_stackItemFromTop( -1 ); + if( HB_IS_BYREF( pItem ) ) + { + pItem = hb_itemUnRef( pItem ); + } + if( HB_IS_DATE( pItem ) ) pItem->item.asDate.value--; else if( HB_IS_NUMINT( pItem ) ) diff --git a/harbour/tests/omacro.prg b/harbour/tests/omacro.prg new file mode 100644 index 0000000000..0e81bfa94e --- /dev/null +++ b/harbour/tests/omacro.prg @@ -0,0 +1,48 @@ +/* + * $Id$ + * + * This file tests support for passing object methods and vars + * using macro syntax + */ +PROCEDURE MAIN() +LOCAL obj:=ErrorNew() +MEMVAR send1, send2 + + PRIVATE send1:="_description" + PRIVATE send2:="_tries" + + obj:tries := 1 + obj:&send1 := 'test' + + obj:tries += 1 + obj:tries++ + ++obj:tries + + WITH OBJECT obj + :tries += 1 + :tries++ + ++:tries + +/* + Notice that for post/pre increment decrement operators and + for assigments (:=,+=,-=,*=,/=) the macro have to + start from the underscore symbol '_' + + To access the object variable using macro the '_' should be omitted +*/ + :&send2 +=1 + :&send2++ + ++:&send2 + ++:&(send2) + + :&( send2 ) := :&( SUBSTR(send2,2) ) +1 + + :&send1 +=' description' + :&(send1) += ' of ' + END + + obj:&( "_"+ SUBSTR(send1,2) ) += "Error object" + ? send1, "=", obj:&( SUBSTR(send1,2) ) + ? send2, "=", obj:tries + +RETURN \ No newline at end of file