From 9d4258aa4736ab02aca6ff92c85e33a11d59b0df Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Mon, 17 Sep 2007 22:48:39 +0000 Subject: [PATCH] 2007-09-18 00:45 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbapicls.h * harbour/source/vm/hvm.c + added hb_clsDoInit() function to initialize classy .prg functions * harbour/source/compiler/complex.c * allow to use NIL as class name * harbour/source/compiler/harbour.yyc * harbour/source/compiler/harbour.y * harbour/source/compiler/harbour.yyh % optimize automatically var[0] declaration and generate the same PCODE as for var:={} * harbour/source/rtl/tscalar.prg + added HASH, POINTER and SYMBOL scalar classes * changed NIL class to not use any instance variables * harbour/source/vm/classes.c + added support for scalar classes. Now at startup classy code looks for hb functions and try to execute them to register scalar classes. It's Class(y) compatible behavior and only the prefix of scalar ceases class function is different: 'CSY' in class(y) and 'HB' in Harbour, f.e.: hbNumeric() If you prefer xHarbour like not automatic scalar class registration with some PP commands: ASSOCIATE CLASS WITH TYPE ARRAY|BLOCK|CHARACTER|DATE|HASH|LOGICAL|NIL| NUMERIC|POINTER|SYMBOL ENABLE CLASS TYPE ALL ENABLE TYPE CLASS ARRAY|BLOCK|CHARACTER|DATE|HASH|LOGICAL|NIL| NUMERIC|POINTER|SYMBOL EXTEND [TYPE] ARRAY|BLOCK|CHARACTER|DATE|HASH|LOGICAL|NIL| NUMERIC|POINTER|SYMBOL WITH METHOD Then I can replace current code with it. If not then we should divide scalar cases definitions into separated files to allow easier overloading. I'm interesting in your opinions. --- harbour/source/vm/classes.c | 217 ++++++++++++++++++++++-------------- 1 file changed, 135 insertions(+), 82 deletions(-) diff --git a/harbour/source/vm/classes.c b/harbour/source/vm/classes.c index 3d7e8007d4..2e00c7364d 100644 --- a/harbour/source/vm/classes.c +++ b/harbour/source/vm/classes.c @@ -1190,6 +1190,51 @@ HB_EXPORT USHORT hb_objSetClass( PHB_ITEM pItem, const char * szClass, const cha /* ================================================ */ +/* + * Get the class handle + */ +static USHORT hb_objGetClassH( PHB_ITEM pObject ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_objGetClassH(%p)", pObject)); + + if( HB_IS_ARRAY( pObject ) ) + { + if( pObject->item.asArray.value->uiClass != 0 ) + return pObject->item.asArray.value->uiClass; + else + return s_uiArrayClass; + } + /* built in types */ + else if( HB_IS_NIL( pObject ) ) + return s_uiNilClass; + + else if( HB_IS_STRING( pObject ) ) + return s_uiCharacterClass; + + else if( HB_IS_NUMERIC( pObject ) ) + return s_uiNumericClass; + + else if( HB_IS_DATE( pObject ) ) + return s_uiDateClass; + + else if( HB_IS_LOGICAL( pObject ) ) + return s_uiLogicalClass; + + else if( HB_IS_BLOCK( pObject ) ) + return s_uiBlockClass; + + else if( HB_IS_HASH( pObject ) ) + return s_uiHashClass; + + else if( HB_IS_POINTER( pObject ) ) + return s_uiPointerClass; + + else if( HB_IS_SYMBOL( pObject ) ) + return s_uiSymbolClass; + + return 0; +} + /* * Get the class name of an object */ @@ -1277,26 +1322,23 @@ HB_EXPORT USHORT hb_clsFindClass( const char * szClass, const char * szFunc ) */ HB_EXPORT const char * hb_objGetRealClsName( PHB_ITEM pObject, const char * szName ) { + USHORT uiClass; + HB_TRACE(HB_TR_DEBUG, ("hb_objGetrealClsName(%p,%s)", pObject, szName)); - if( HB_IS_OBJECT( pObject ) ) + uiClass = hb_objGetClassH( pObject ); + if( uiClass && uiClass <= uiClass ) { - USHORT uiClass; + PHB_DYNS pMsg = hb_dynsymFindName( szName ); - uiClass = pObject->item.asArray.value->uiClass; - if( uiClass && uiClass <= uiClass ) + if( pMsg ) { - PHB_DYNS pMsg = hb_dynsymFindName( szName ); - - if( pMsg ) - { - PMETHOD pMethod = hb_clsFindMsg( &s_pClasses[ uiClass ], pMsg ); - if( pMethod ) - uiClass = pMethod->uiSprClass; - } - if( uiClass && uiClass <= s_uiClasses ) - return s_pClasses[ uiClass ].szName; + PMETHOD pMethod = hb_clsFindMsg( &s_pClasses[ uiClass ], pMsg ); + if( pMethod ) + uiClass = pMethod->uiSprClass; } + if( uiClass && uiClass <= s_uiClasses ) + return s_pClasses[ uiClass ].szName; } return hb_objGetClsName( pObject ); @@ -1485,7 +1527,7 @@ static void hb_clsMakeSuperObject( PHB_ITEM pDest, PHB_ITEM pObject, hb_arraySet( pDest, 1, pObject ); /* And transform it into a fake object */ /* backup of actual handel */ - pDest->item.asArray.value->uiPrevCls = pObject->item.asArray.value->uiClass; + pDest->item.asArray.value->uiPrevCls = hb_objGetClassH( pObject ); /* superclass handel casting */ pDest->item.asArray.value->uiClass = uiSuperClass; } @@ -1991,12 +2033,14 @@ void hb_objDestructorCall( PHB_ITEM pObject ) */ BOOL hb_objHasOperator( PHB_ITEM pObject, USHORT uiOperator ) { + USHORT uiClass; + HB_TRACE(HB_TR_DEBUG, ("hb_objHasOperator(%p,%hu)", pObject, uiOperator)); - if( HB_IS_OBJECT( pObject ) ) + uiClass = hb_objGetClassH( pObject ); + if( uiClass && uiClass <= s_uiClasses ) { - PCLASS pClass = &s_pClasses[ pObject->item.asArray.value->uiClass ]; - return ( pClass->ulOpFlags & ( 1UL << uiOperator ) ) != 0; + return ( s_pClasses[ uiClass ].ulOpFlags & ( 1UL << uiOperator ) ) != 0; } return FALSE; @@ -3601,9 +3645,9 @@ HB_FUNC( __SENDER ) */ HB_FUNC( __CLASSH ) { - PHB_ITEM pObject = hb_param( 1, HB_IT_OBJECT ); + PHB_ITEM pObject = hb_param( 1, HB_IT_ANY ); - hb_retni( pObject ? pObject->item.asArray.value->uiClass : 0 ); + hb_retni( pObject ? hb_objGetClassH( pObject ) : 0 ); } /* ================================================ */ @@ -3865,9 +3909,8 @@ static HARBOUR hb___msgScopeErr( void ) hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ].pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; - pszProcName = hb_xstrcpy( NULL, - s_pClasses[ pObject->item.asArray.value->uiClass ].szName, - ":", pMethod->pMessage->pSymbol->szName, NULL ); + pszProcName = hb_xstrcpy( NULL, hb_objGetClsName( pObject ), ":", + pMethod->pMessage->pSymbol->szName, NULL ); if( pMethod->uiScope & HB_OO_CLSTP_HIDDEN ) hb_errRT_BASE( EG_NOMETHOD, 41, "Scope violation (hidden)", pszProcName, 0 ); else @@ -3883,9 +3926,8 @@ static HARBOUR hb___msgTypeErr( void ) hb_stackBaseItem()->item.asSymbol.stackstate->uiClass ].pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; - pszProcName = hb_xstrcpy( NULL, - s_pClasses[ pObject->item.asArray.value->uiClass ].szName, - ":", pMethod->pMessage->pSymbol->szName + 1, NULL ); + pszProcName = hb_xstrcpy( NULL, hb_objGetClsName( pObject ), ":", + pMethod->pMessage->pSymbol->szName + 1, NULL ); hb_errRT_BASE( EG_NOMETHOD, 44, "Assigned value is wrong class", pszProcName, HB_ERR_ARGS_BASEPARAMS ); hb_xfree( pszProcName ); } @@ -3913,9 +3955,10 @@ static HARBOUR hb___msgRealClass( void ) { PHB_ITEM pObject = hb_stackSelfItem(); USHORT uiClass = hb_clsSenderMethodClasss(); + USHORT uiCurClass = hb_objGetClassH( pObject ); - if( uiClass && uiClass != pObject->item.asArray.value->uiClass && - hb_clsSenderObjectClasss() == pObject->item.asArray.value->uiClass ) + if( uiClass && uiClass != uiCurClass && + hb_clsSenderObjectClasss() == uiCurClass ) { hb_clsMakeSuperObject( hb_stackReturnItem(), pObject, uiClass ); } @@ -4034,24 +4077,28 @@ static HARBOUR hb___msgSetShrData( void ) static HARBOUR hb___msgGetData( void ) { PHB_ITEM pObject = hb_stackSelfItem(); - USHORT uiObjClass = pObject->item.asArray.value->uiClass; - USHORT uiClass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; - PCLASS pClass = &s_pClasses[ uiClass ]; - PMETHOD pMethod = pClass->pMethods + - hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; - ULONG ulIndex = pMethod->uiData; - if( uiClass != uiObjClass ) + if( HB_IS_ARRAY( pObject ) ) { - ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass ], - s_pClasses[ pMethod->uiSprClass ].pClassSym ); - } - else - { - ulIndex += pMethod->uiOffset; - } + USHORT uiObjClass = pObject->item.asArray.value->uiClass; + USHORT uiClass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; + PCLASS pClass = &s_pClasses[ uiClass ]; + PMETHOD pMethod = pClass->pMethods + + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; + ULONG ulIndex = pMethod->uiData; - hb_arrayGet( pObject, ulIndex, hb_stackReturnItem() ); + if( uiClass != uiObjClass ) + { + ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass ], + s_pClasses[ pMethod->uiSprClass ].pClassSym ); + } + else + { + ulIndex += pMethod->uiOffset; + } + + hb_arrayGet( pObject, ulIndex, hb_stackReturnItem() ); + } } /* @@ -4061,46 +4108,50 @@ static HARBOUR hb___msgGetData( void ) */ static HARBOUR hb___msgSetData( void ) { - PHB_ITEM pReturn = hb_param( 1, HB_IT_ANY ); PHB_ITEM pObject = hb_stackSelfItem(); - USHORT uiObjClass = pObject->item.asArray.value->uiClass; - USHORT uiClass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; - PCLASS pClass = &s_pClasses[ uiClass ]; - PMETHOD pMethod = pClass->pMethods + - hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; - ULONG ulIndex = pMethod->uiData; - if( uiClass != uiObjClass ) + if( HB_IS_ARRAY( pObject ) ) { - ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass ], - s_pClasses[ pMethod->uiSprClass ].pClassSym ); - } - else - { - ulIndex += pMethod->uiOffset; - } + PHB_ITEM pReturn = hb_param( 1, HB_IT_ANY ); + USHORT uiObjClass = pObject->item.asArray.value->uiClass; + USHORT uiClass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; + PCLASS pClass = &s_pClasses[ uiClass ]; + PMETHOD pMethod = pClass->pMethods + + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; + ULONG ulIndex = pMethod->uiData; - if( !pReturn ) - hb_arrayGet( pObject, ulIndex, hb_stackReturnItem() ); - - else - { - if( pMethod->itemType && ! ( pMethod->itemType & pReturn->type ) ) + if( uiClass != uiObjClass ) { - if( pMethod->itemType == HB_IT_NUMINT && HB_IS_NUMERIC( pReturn ) ) - hb_itemPutNInt( pReturn, hb_itemGetNInt( pReturn ) ); - else - { - (s___msgTypeErr.value.pFunPtr)(); - return; - } + ulIndex += hb_clsParentInstanceOffset( &s_pClasses[ uiObjClass ], + s_pClasses[ pMethod->uiSprClass ].pClassSym ); + } + else + { + ulIndex += pMethod->uiOffset; } - /* will arise only if the class has been modified after first instance */ - if( ulIndex > hb_arrayLen( pObject ) ) /* Resize needed ? */ - hb_arraySize( pObject, ulIndex ); /* Make large enough */ - hb_arraySet( pObject, ulIndex, pReturn ); - hb_itemReturnForward( pReturn ); + if( !pReturn ) + hb_arrayGet( pObject, ulIndex, hb_stackReturnItem() ); + + else + { + if( pMethod->itemType && ! ( pMethod->itemType & pReturn->type ) ) + { + if( pMethod->itemType == HB_IT_NUMINT && HB_IS_NUMERIC( pReturn ) ) + hb_itemPutNInt( pReturn, hb_itemGetNInt( pReturn ) ); + else + { + (s___msgTypeErr.value.pFunPtr)(); + return; + } + } + + /* will arise only if the class has been modified after first instance */ + if( ulIndex > hb_arrayLen( pObject ) ) /* Resize needed ? */ + hb_arraySize( pObject, ulIndex ); /* Make large enough */ + hb_arraySet( pObject, ulIndex, pReturn ); + hb_itemReturnForward( pReturn ); + } } } @@ -4119,12 +4170,14 @@ static HARBOUR hb___msgNull( void ) #ifndef HB_NO_PROFILER void hb_mthAddTime( ULONG ulClockTicks ) { - PMETHOD pMethod = - s_pClasses[ hb_stackSelfItem()->item.asArray.value->uiClass ]. - pMethods + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; - - pMethod->ulCalls++; - pMethod->ulTime += ulClockTicks; + PMETHOD pMethod = s_pClasses[ hb_objGetClassH( hb_stackSelfItem() ) ]. + pMethods; + if( pMethod ) + { + pMethod += hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; + pMethod->ulCalls++; + pMethod->ulTime += ulClockTicks; + } } #endif