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:
Przemyslaw Czerpak
2007-09-17 22:48:39 +00:00
parent 72eca3d3e9
commit 9d4258aa47

View File

@@ -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