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<TYPENAME> 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 <ClassName> 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 <SomeFunc>
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.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user