diff --git a/harbour/ChangeLog b/harbour/ChangeLog index c5f2ad22e7..23d39bfab3 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,20 @@ +20000502-10:41 GMT+1 Victor Szakats + + * include/hbpcode.h + * include/hbexprb.c + * include/hbexprc.c + * include/hbvm.h + * source/compiler/hbpcode.c + * source/compiler/hbfix.c + * source/compiler/genc.c + * source/vm/hvm.c + + HB_P_SEND and HB_P_SENDSHORT pcodes added. At this moment they are + exactly the same as HB_P_FUNCTION[SHORT]. More work is needed to + optimize the stack usage for SEND/DO/FUNCTION. + + hb_vmSend() function added. + + ! WARNING ! All sources must be recompiled. + 20000502-01:30 GMT-8 Ron Pinkas * source/compiler/harbour.c diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c index 4b46dc51dc..66848120c6 100644 --- a/harbour/include/hbexprb.c +++ b/harbour/include/hbexprb.c @@ -1526,16 +1526,16 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE ); if( iParms > 255 ) - HB_EXPR_GENPCODE3( hb_compGenPCode3, HB_P_FUNCTION, HB_LOBYTE( iParms ), HB_HIBYTE( iParms ), ( BOOL ) 1 ); + HB_EXPR_GENPCODE3( hb_compGenPCode3, HB_P_SEND, HB_LOBYTE( iParms ), HB_HIBYTE( iParms ), ( BOOL ) 1 ); else - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, ( BYTE ) iParms, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, ( BYTE ) iParms, ( BOOL ) 1 ); } 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_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, 0, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); } } break; @@ -1548,7 +1548,7 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) 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_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, 1, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); } break; diff --git a/harbour/include/hbexprc.c b/harbour/include/hbexprc.c index 3659403526..cc903c3dc2 100644 --- a/harbour/include/hbexprc.c +++ b/harbour/include/hbexprc.c @@ -95,7 +95,7 @@ void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) #endif /* now send the message */ HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, 0, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); /* NOTE: COMPATIBILITY ISSUE: * The above HB_C52_STRICT setting determines @@ -128,7 +128,7 @@ void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); /* call pop message with one argument */ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, 1, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); } /* TODO: add a special code for arrays to correctly handle a[ i++ ]++ */ @@ -176,7 +176,7 @@ void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) #endif /* now send the message */ HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, 0, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); /* push increment value */ HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); @@ -184,7 +184,7 @@ void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); /* call pop message with one argument */ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, 1, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); /* pop the value from the stack */ HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_POP ); } @@ -230,13 +230,13 @@ void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper ) #endif /* now send the message */ HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, 0, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); /* increase/decrease operation */ HB_EXPR_GENPCODE1( hb_compGenPCode1, bOper ); /* call pop message with one argument - it leaves the value on the stack */ - HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_FUNCTIONSHORT, 1, ( BOOL ) 1 ); + HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); } else { diff --git a/harbour/include/hbpcode.h b/harbour/include/hbpcode.h index 62adb7ff29..9dca93243f 100644 --- a/harbour/include/hbpcode.h +++ b/harbour/include/hbpcode.h @@ -153,6 +153,8 @@ typedef enum HB_P_PUSHSYMNEAR, /* places a symbol on the virtual machine stack */ HB_P_PUSHVARIABLE, /* pushes the contains of an undeclared variable to the virtual machine stack */ HB_P_RETVALUE, /* instructs the virtual machine to return the latest stack value */ + HB_P_SEND, /* send operator */ + HB_P_SENDSHORT, /* send operator */ HB_P_SEQBEGIN, /* BEGIN SEQUENCE */ HB_P_SEQEND, /* END SEQUENCE */ HB_P_SEQRECOVER, /* RECOVER statement */ diff --git a/harbour/include/hbvm.h b/harbour/include/hbvm.h index 531a7cd464..ce56eb2519 100644 --- a/harbour/include/hbvm.h +++ b/harbour/include/hbvm.h @@ -72,6 +72,7 @@ extern void hb_vmMessage( PHB_SYMB pSymMsg ); /* sends a message to an object /* Execution */ extern void hb_vmDo( USHORT uiParams ); /* invoke the virtual machine */ extern void hb_vmFunction( USHORT uiParams ); /* executes a function saving its result */ +extern void hb_vmSend( USHORT uiParams ); /* sends a message to an object */ extern PHB_ITEM hb_vmEvalBlock( PHB_ITEM pBlockItem ); /* executes passed codeblock with no arguments */ /* executes passed codeblock with variable number of arguments */ extern PHB_ITEM hb_vmEvalBlockV( PHB_ITEM pBlockItem, USHORT uiArgCount, ... ); diff --git a/harbour/source/compiler/genc.c b/harbour/source/compiler/genc.c index 9e5f5afc69..73f8172c8d 100644 --- a/harbour/source/compiler/genc.c +++ b/harbour/source/compiler/genc.c @@ -1452,6 +1452,20 @@ static HB_GENC_FUNC( hb_p_retvalue ) return 1; } +static HB_GENC_FUNC( hb_p_send ) +{ + fprintf( cargo->yyc, "\tHB_P_SEND, %i, %i,\n", + pFunc->pCode[ lPCodePos + 1 ], + pFunc->pCode[ lPCodePos + 2 ] ); + return 3; +} + +static HB_GENC_FUNC( hb_p_sendshort ) +{ + fprintf( cargo->yyc, "\tHB_P_SENDSHORT, %i,\n", pFunc->pCode[ lPCodePos + 1 ] ); + return 2; +} + static HB_GENC_FUNC( hb_p_seqbegin ) { fprintf( cargo->yyc, "\tHB_P_SEQBEGIN, %i, %i, %i,", @@ -1681,6 +1695,8 @@ static HB_GENC_FUNC_PTR s_verbose_table[] = { hb_p_pushsymnear, hb_p_pushvariable, hb_p_retvalue, + hb_p_send, + hb_p_sendshort, hb_p_seqbegin, hb_p_seqend, hb_p_seqrecover, diff --git a/harbour/source/compiler/hbfix.c b/harbour/source/compiler/hbfix.c index 154560c157..c200e1d63e 100644 --- a/harbour/source/compiler/hbfix.c +++ b/harbour/source/compiler/hbfix.c @@ -330,6 +330,8 @@ static HB_FIX_FUNC_PTR s_fixlocals_table[] = NULL, /* HB_P_PUSHSYMNEAR, */ NULL, /* HB_P_PUSHVARIABLE, */ NULL, /* HB_P_RETVALUE, */ + NULL, /* HB_P_SEND, */ + NULL, /* HB_P_SENDSHORT, */ NULL, /* HB_P_SEQBEGIN, */ NULL, /* HB_P_SEQEND, */ NULL, /* HB_P_SEQRECOVER, */ diff --git a/harbour/source/compiler/hbpcode.c b/harbour/source/compiler/hbpcode.c index 707d5860a6..56c90de8d6 100644 --- a/harbour/source/compiler/hbpcode.c +++ b/harbour/source/compiler/hbpcode.c @@ -158,6 +158,8 @@ static BYTE s_pcode_len[] = { 2, /* HB_P_PUSHSYMNEAR, */ 3, /* HB_P_PUSHVARIABLE, */ 1, /* HB_P_RETVALUE, */ + 3, /* HB_P_SEND, */ + 2, /* HB_P_SENDSHORT, */ 4, /* HB_P_SEQBEGIN, */ 4, /* HB_P_SEQEND, */ 1, /* HB_P_SEQRECOVER, */ diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 61e3dc907e..137caef589 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -131,6 +131,7 @@ static void hb_vmSFrame( PHB_SYMB pSym ); /* sets the statics frame for a static void hb_vmStatics( PHB_SYMB pSym, USHORT uiStatics ); /* increases the the global statics array to hold a PRG statics */ static void hb_vmEndBlock( void ); /* copies the last codeblock pushed value into the return value */ static void hb_vmRetValue( void ); /* pops the latest stack value into stack.Return */ +static void hb_vmSendFunc( USHORT uiParams ); static void hb_vmDebuggerShowLine( USHORT uiLine ); /* makes the debugger shows a specific source code line */ static void hb_vmDebuggerEndProc( void ); /* notifies the debugger for an endproc */ @@ -560,6 +561,16 @@ void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) w += 2; break; + case HB_P_SEND: + hb_vmSendFunc( pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) ); + w += 3; + break; + + case HB_P_SENDSHORT: + hb_vmSendFunc( pCode[ w + 1 ] ); + w += 2; + break; + case HB_P_LINE: HB_TRACE(HB_TR_INFO, ("Opcode: HB_P_LINE: %s (%i)", hb_stack.pBase->item.asSymbol.value->szName, hb_stack.pBase->item.asSymbol.lineno)); @@ -2798,6 +2809,113 @@ void hb_vmDo( USHORT uiParams ) s_bDebugging = bDebugPrevState; } +void hb_vmSend( USHORT uiParams ) +{ + PHB_ITEM pItem; + PHB_SYMB pSym; + LONG wStackBase; + LONG wItemIndex; + PHB_ITEM pSelf; + PHB_BASEARRAY pSelfBase; + PHB_FUNC pFunc; + int iStatics; + BOOL bDebugPrevState; + + HB_TRACE(HB_TR_DEBUG, ("hb_vmSend(%hu)", uiParams)); + + pItem = hb_stack.pPos - uiParams - 2; /* procedure name */ + pSym = pItem->item.asSymbol.value; + wStackBase = hb_stack.pBase - hb_stack.pItems; /* as the stack memory block could change */ + wItemIndex = pItem - hb_stack.pItems; + pSelf = hb_stack.pPos - uiParams - 1; /* NIL, OBJECT or BLOCK */ + iStatics = hb_stack.iStatics; /* Return iStatics position */ + bDebugPrevState = s_bDebugging; + s_bDebugging = FALSE; + + if( ! HB_IS_SYMBOL( pItem ) ) + { + /* QUESTION: Is this call needed ? [vszakats] */ + hb_stackDispLocal(); + hb_errInternal( IE_VMNOTSYMBOL, NULL, "hb_vmSend()", NULL ); + } + +#if 0 + if( ! HB_IS_NIL( pSelf ) ) + { + /* QUESTION: Is this call needed ? [vszakats] */ + hb_stackDispLocal(); + hb_errInternal( IE_VMINVSYMBOL, NULL, "hb_vmSend()", NULL ); + } +#endif + + pItem->item.asSymbol.lineno = 0; + pItem->item.asSymbol.paramcnt = uiParams; + hb_stack.pBase = hb_stack.pItems + pItem->item.asSymbol.stackbase; + pItem->item.asSymbol.stackbase = wStackBase; + + if( ! HB_IS_NIL( pSelf ) ) /* are we sending a message ? */ + { + if( pSym == &( hb_symEval ) && HB_IS_BLOCK( pSelf ) ) + pFunc = pSym->pFunPtr; /* __EVAL method = function */ + else + { + pFunc = hb_objGetMethod( pSelf, pSym ); + if( HB_IS_OBJECT( pSelf ) ) /* Object passed */ + { + pSelfBase = pSelf->item.asArray.value; + if( pSelfBase->uiPrevCls ) /* Is is a Super cast ? */ + { + pSelfBase->uiClass = pSelfBase->uiPrevCls; + pSelfBase->uiPrevCls = 0; + } + } + } + + if( pFunc ) + pFunc(); + else + { + PHB_ITEM pResult; + + if( pSym->szName[ 0 ] == '_' ) + pResult = hb_errRT_BASE_Subst( EG_NOVARMETHOD, 1005, NULL, pSym->szName + 1 ); + else + pResult = hb_errRT_BASE_Subst( EG_NOMETHOD, 1004, NULL, pSym->szName ); + + if( pResult ) + { + hb_itemReturn( pResult ); + hb_itemRelease( pResult ); + } + } + } + else /* it is a function */ + { + pFunc = pSym->pFunPtr; + + if( pFunc ) + pFunc(); + else + { + /* Attempt to call an undefined function + * - generate unrecoverable runtime error + */ + hb_errRT_BASE( EG_NOFUNC, 1001, NULL, pSym->szName ); + } + } + + while( hb_stack.pPos > hb_stack.pItems + wItemIndex ) + hb_stackPop(); + + hb_stack.pBase = hb_stack.pItems + wStackBase; + hb_stack.iStatics = iStatics; + + if( s_bDebugging ) + hb_vmDebuggerEndProc(); + + s_bDebugging = bDebugPrevState; +} + static HARBOUR hb_vmDoBlock( void ) { PHB_ITEM pBlock; @@ -2881,6 +2999,16 @@ void hb_vmFunction( USHORT uiParams ) hb_stackPush(); } +static void hb_vmSendFunc( USHORT uiParams ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_vmSendFunc(%hu)", uiParams)); + + hb_itemClear( &hb_stack.Return ); + hb_vmSend( uiParams ); + hb_itemCopy( hb_stack.pPos, &hb_stack.Return ); + hb_stackPush(); +} + static void hb_vmLocalName( USHORT uiLocal, char * szLocalName ) /* locals and parameters index and name information for the debugger */ { HB_TRACE(HB_TR_DEBUG, ("hb_vmLocalName(%hu, %s)", uiLocal, szLocalName));