diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 4ebbc91913..6417b90dba 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,12 @@ +19991018-00:03 GMT+1 Victor Szel + * source/vm/hvm.c + + Support for overloading the following operators: + *, /, %, ^, **, !, .NOT., .AND., .OR. + * tests/rtl_test.prg + + Tests added for new operator overloading features. + * source/vm/dynsym.c + ! Small formatting fixes. + 19991017-21:24 GMT+1 Victor Szel * source/rtl/samples.c ! hb_SecToTimeStr() bug (typo) fixed. diff --git a/harbour/source/vm/dynsym.c b/harbour/source/vm/dynsym.c index dc6c73deb5..7c34428848 100644 --- a/harbour/source/vm/dynsym.c +++ b/harbour/source/vm/dynsym.c @@ -168,6 +168,7 @@ PHB_DYNS hb_dynsymFind( char * szName ) s_pDynItems->pDynSym->hMemvar = 0; s_pDynItems->pDynSym->pSymbol = NULL; s_pDynItems->pDynSym->pFunPtr = NULL; + return NULL; } else @@ -201,18 +202,18 @@ PHB_DYNS hb_dynsymFind( char * szName ) switch( hb_strgreater( s_pDynItems[ uiMiddle ].pDynSym->pSymbol->szName, szName ) ) { case HB_STRGREATER_EQUAL: /* they are equals */ - s_uiClosestDynSym = uiMiddle; - return s_pDynItems[ uiMiddle ].pDynSym; + s_uiClosestDynSym = uiMiddle; + return s_pDynItems[ uiMiddle ].pDynSym; case HB_STRGREATER_LEFT: /* pMiddle is greater */ - uiLast = uiMiddle; - s_uiClosestDynSym = uiMiddle; - break; + uiLast = uiMiddle; + s_uiClosestDynSym = uiMiddle; + break; case HB_STRGREATER_RIGHT: /* szName is greater */ - uiFirst = uiMiddle + 1; - s_uiClosestDynSym = uiFirst; - break; + uiFirst = uiMiddle + 1; + s_uiClosestDynSym = uiFirst; + break; } uiMiddle = uiFirst + ( ( uiLast - uiFirst ) / 2 ); @@ -231,7 +232,6 @@ void hb_dynsymEval( PHB_DYNS_FUNC pFunction, void * Cargo ) bCont = ( pFunction )( s_pDynItems[ uiPos ].pDynSym, Cargo ); } - void hb_dynsymRelease( void ) { USHORT uiPos; diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 216fb0292a..bbf6e7fc28 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -1192,6 +1192,10 @@ static void hb_vmMult( void ) hb_vmPushNumber( d1 * d2, iDec1 + iDec2 ); } + + else if( IS_OBJECT( hb_stack.pPos - 2 ) && hb_objHasMsg( hb_stack.pPos - 2, "*" ) ) + hb_vmOperatorCall( hb_stack.pPos - 2, hb_stack.pPos - 1, "*" ); + else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1083, NULL, "*" ); @@ -1235,6 +1239,10 @@ static void hb_vmDivide( void ) hb_vmPushNumber( d1 / d2, hb_set.HB_SET_DECIMALS ); } } + + else if( IS_OBJECT( hb_stack.pPos - 2 ) && hb_objHasMsg( hb_stack.pPos - 2, "/" ) ) + hb_vmOperatorCall( hb_stack.pPos - 2, hb_stack.pPos - 1, "/" ); + else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1084, NULL, "/" ); @@ -1272,6 +1280,10 @@ static void hb_vmModulus( void ) with the SET number of decimal places. */ hb_vmPushNumber( fmod( d1, d2 ), hb_set.HB_SET_DECIMALS ); } + + else if( IS_OBJECT( hb_stack.pPos - 2 ) && hb_objHasMsg( hb_stack.pPos - 2, "%" ) ) + hb_vmOperatorCall( hb_stack.pPos - 2, hb_stack.pPos - 1, "%" ); + else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1085, NULL, "%" ); @@ -1298,6 +1310,13 @@ static void hb_vmPower( void ) with the SET number of decimal places. */ hb_vmPushNumber( pow( d1, d2 ), hb_set.HB_SET_DECIMALS ); } + + else if( IS_OBJECT( hb_stack.pPos - 2 ) && hb_objHasMsg( hb_stack.pPos - 2, "^" ) ) + hb_vmOperatorCall( hb_stack.pPos - 2, hb_stack.pPos - 1, "^" ); + + else if( IS_OBJECT( hb_stack.pPos - 2 ) && hb_objHasMsg( hb_stack.pPos - 2, "**" ) ) + hb_vmOperatorCall( hb_stack.pPos - 2, hb_stack.pPos - 1, "**" ); + else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1088, NULL, "^" ); @@ -1790,6 +1809,13 @@ static void hb_vmNot( void ) if( IS_LOGICAL( pItem ) ) pItem->item.asLogical.value = ! pItem->item.asLogical.value; + + else if( IS_OBJECT( pItem ) && hb_objHasMsg( pItem, "!" ) ) + hb_vmOperatorCallUnary( pItem, "!" ); + + else if( IS_OBJECT( pItem ) && hb_objHasMsg( pItem, ".NOT." ) ) + hb_vmOperatorCallUnary( pItem, ".NOT." ); + else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1077, NULL, ".NOT." ); @@ -1817,6 +1843,10 @@ static void hb_vmAnd( void ) hb_stackPop(); hb_vmPushLogical( bResult ); } + + else if( IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, ".AND." ) ) + hb_vmOperatorCall( pItem1, pItem2, ".AND." ); + else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1078, NULL, ".AND." ); @@ -1843,6 +1873,10 @@ static void hb_vmOr( void ) hb_stackDec(); hb_vmPushLogical( bResult ); } + + else if( IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, ".OR." ) ) + hb_vmOperatorCall( pItem1, pItem2, ".OR." ); + else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1079, NULL, ".OR." ); diff --git a/harbour/tests/rtl_test.prg b/harbour/tests/rtl_test.prg index c409d2bb4a..244a24243b 100644 --- a/harbour/tests/rtl_test.prg +++ b/harbour/tests/rtl_test.prg @@ -2409,6 +2409,17 @@ STATIC FUNCTION Main_OPOVERL() TEST_LINE( oString <= "Hello" , .T. ) TEST_LINE( oString + "Hello" , "HelloHello" ) TEST_LINE( oString - "Hello" , "HelloHello" ) + TEST_LINE( oString * 3 , "HelloHelloHello" ) + TEST_LINE( oString / 2 , "He" ) + TEST_LINE( oString % "TST" , "Hello % TST" ) + TEST_LINE( oString ^ "TST" , "Hello ^ TST" ) + TEST_LINE( oString ** "TST" , "Hello ^ TST" ) + IF !TEST_OPT_Z() + TEST_LINE( oString .AND. "TST" , "Hello AND TST" ) + TEST_LINE( oString .OR. "TST" , "Hello OR TST" ) + ENDIF + TEST_LINE( .NOT. oString , "¸›””‘" ) + TEST_LINE( !oString , "¸›””‘" ) TEST_LINE( oString++ , "HB_TSTRING Object" ) TEST_LINE( oString:cValue , "Hello " ) TEST_LINE( oString-- , "HB_TSTRING Object" ) @@ -2425,17 +2436,26 @@ STATIC FUNCTION HB_TString() oClass:AddData( "cValue" ) - oClass:AddInline( "==", {| self, cTest | ::cValue == cTest } ) - oClass:AddInline( "!=", {| self, cTest | ::cValue != cTest } ) - oClass:AddInline( "<" , {| self, cTest | ::cValue < cTest } ) - oClass:AddInline( "<=", {| self, cTest | ::cValue <= cTest } ) - oClass:AddInline( ">" , {| self, cTest | ::cValue > cTest } ) - oClass:AddInline( ">=", {| self, cTest | ::cValue >= cTest } ) - oClass:AddInline( "+" , {| self, cTest | ::cValue + cTest } ) - oClass:AddInline( "-" , {| self, cTest | ::cValue - cTest } ) - oClass:AddInline( "++", {| self | ::cValue += " ", self } ) - oClass:AddInline( "--", {| self | iif( Len( ::cValue ) > 0, ::cValue := Left( ::cValue, Len( ::cValue ) - 1 ), ::cValue ), self } ) - oClass:AddInline( "$" , {| self, cTest | ::cValue $ cTest } ) + oClass:AddInline( "==" , {| self, cTest | ::cValue == cTest } ) + oClass:AddInline( "!=" , {| self, cTest | ::cValue != cTest } ) + oClass:AddInline( "<" , {| self, cTest | ::cValue < cTest } ) + oClass:AddInline( "<=" , {| self, cTest | ::cValue <= cTest } ) + oClass:AddInline( ">" , {| self, cTest | ::cValue > cTest } ) + oClass:AddInline( ">=" , {| self, cTest | ::cValue >= cTest } ) + oClass:AddInline( "+" , {| self, cTest | ::cValue + cTest } ) + oClass:AddInline( "-" , {| self, cTest | ::cValue - cTest } ) + oClass:AddInline( "++" , {| self | ::cValue += " ", self } ) + oClass:AddInline( "--" , {| self | iif( Len( ::cValue ) > 0, ::cValue := Left( ::cValue, Len( ::cValue ) - 1 ), ::cValue ), self } ) + oClass:AddInline( "$" , {| self, cTest | ::cValue $ cTest } ) + oClass:AddInline( "*" , {| self, nVal | Replicate( ::cValue, nVal ) } ) + oClass:AddInline( "/" , {| self, nVal | Left( ::cValue, Len( ::cValue ) / nVal ) } ) + oClass:AddInline( "%" , {| self, cTest | ::cValue + " % " + cTest } ) + oClass:AddInline( "^" , {| self, cTest | ::cValue + " ^ " + cTest } ) + oClass:AddInline( "**" , {| self, cTest | ::cValue + " ** " + cTest } ) + oClass:AddInline( "!" , {| self | Descend( ::cValue ) } ) + oClass:AddInline( ".NOT.", {| self | Descend( ::cValue ) } ) + oClass:AddInline( ".AND.", {| self, cTest | ::cValue + " AND " + cTest } ) + oClass:AddInline( ".OR." , {| self, cTest | ::cValue + " OR " + cTest } ) oClass:AddInline( "HasMsg", {| self, cMsg | __ObjHasMsg( QSelf(), cMsg ) } )