2006-09-13 03:10 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)

* harbour/source/vm/classes.c
    * keep class shared data in separate array
    + added __CLS_CNTSHRDATA( hClass ) -> nSharedDatas
    % some minor optimizations

  * harbour/tests/clsscast.prg
    + added test code for shared class data allocating and casting

  * harbour/include/hbapicls.h
  * harbour/source/vm/hvm.c
  * harbour/source/vm/itemapi.c
    + added support for FOR EACH overloading - it's work in progress
      do not create any code which may use current solution - it may
      change in the nearest future
This commit is contained in:
Przemyslaw Czerpak
2006-09-13 01:12:18 +00:00
parent 509d14e639
commit 77d31074e8
6 changed files with 556 additions and 99 deletions

View File

@@ -8,6 +8,22 @@
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
*/
is not supported now. This is sth what I'd like to discuss soon when
I'll add destructors. Please think now if we should allow to execute
destructors and other cleanup user code when we are returning to
nearest expection trap (BEGIN SEQUENCE / [ RECOVER /] END) cleaning
the HVM stack.
2006-09-13 14:00 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/source/compiler/genc.c
* harbour/source/compiler/gencli.c
* harbour/source/compiler/harbour.c
! fixed number of compiled functions shown in compilation status
! added workaround for GPF in empty #pragma begindump/enddump
statement
2006-09-13 03:10 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/source/vm/classes.c
* keep class shared data in separate array
+ added __CLS_CNTSHRDATA( hClass ) -> nSharedDatas
% some minor optimizations

View File

@@ -80,13 +80,14 @@ HB_EXTERN_BEGIN
#define HB_OO_OP_AND 18
#define HB_OO_OP_OR 19
#define HB_OO_OP_ARRAYINDEX 20
#define HB_OO_OP_ENUMNEXT 21
#define HB_OO_OP_ENUMPREV 22
#define HB_OO_OP_ENUMINDEX 23
#define HB_OO_OP_ENUMBASE 24
#define HB_OO_OP_ENUMVALUE 25
#define HB_OO_OP_ENUMINDEX 21
#define HB_OO_OP_ENUMBASE 22
#define HB_OO_OP_ENUMVALUE 23
#define HB_OO_OP_ENUMSTART 24
#define HB_OO_OP_ENUMSKIP 25
#define HB_OO_OP_ENUMSTOP 26
#define HB_OO_MAX_OPERATOR 25
#define HB_OO_MAX_OPERATOR 26
extern void hb_clsInit( void ); /* initialize Classy/OO system at HVM startup */
extern void hb_clsReleaseAll( void ); /* releases all defined classes */

View File

@@ -182,7 +182,8 @@ typedef struct
PHB_DYNS pClassSym; /* Class symbolic name */
PMETHOD pMethods; /* Class methods */
PINITDATA pInitData; /* Class/instance Initialization data */
PHB_ITEM pClassDatas; /* Harbour Array for ClassDatas and shared */
PHB_ITEM pClassDatas; /* Harbour Array for Class Datas */
PHB_ITEM pSharedDatas; /* Harbour Array for Class Shared Datas */
PHB_ITEM pInlines; /* Array for inline codeblocks */
PHB_SYMB pFunError; /* error handler for not defined messages */
ULONG ulOpFlags; /* Flags for overloaded operators */
@@ -197,9 +198,9 @@ typedef struct
#define BUCKETSIZE ( 1 << BUCKETBITS )
#define BUCKETMASK ( BUCKETSIZE - 1 )
#define HASHBITS 3
#define HASH_KEY ( 1 << HASHBITS )
#define HASH_KEY ( ( 1 << HASHBITS ) - 1 )
#define HASH_KEYMAX ( 1 << ( 16 - BUCKETBITS ) )
#define hb_clsMthNum(p) ( ( ULONG ) (p)->uiHashKey << BUCKETBITS )
#define hb_clsMthNum(p) ( ( ( ULONG ) (p)->uiHashKey + 1 ) << BUCKETBITS )
static HARBOUR hb___msgGetData( void );
static HARBOUR hb___msgSetData( void );
@@ -227,32 +228,33 @@ static HARBOUR hb___msgEval( void );
* to HB_OO_OP_* constants in hbapicls.h, [druzus]
*/
static HB_SYMB s_opSymbols[ HB_OO_MAX_OPERATOR + 1 ] = {
{ "__OPPLUS", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 01 */
{ "__OPMINUS", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 02 */
{ "__OPMULT", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 03 */
{ "__OPDIVIDE", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 04 */
{ "__OPMOD", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 05 */
{ "__OPPOWER", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 06 */
{ "__OPINC", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 07 */
{ "__OPDEC", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 08 */
{ "__OPEQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 09 */
{ "__OPEXACTEQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 10 */
{ "__OPNOTEQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 11 */
{ "__OPLESS", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 12 */
{ "__OPLESSEQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 13 */
{ "__OPGREATER", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 14 */
{ "__OPGREATEREQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 15 */
{ "__OPADDIGN", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 16 */
{ "__OPINSTRING", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 17 */
{ "__OPNOT", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 18 */
{ "__OPAND", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 19 */
{ "__OPOR", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 20 */
{ "__OPARRAYINDEX", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 21 */
{ "__ENUMNEXT", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 22 */
{ "__ENUMPREV", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 23 */
{ "__ENUMINDEX", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 24 */
{ "__ENUMBASE", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 25 */
{ "__ENUMVALUE", {HB_FS_MESSAGE}, {NULL}, NULL } /* 26 */
{ "__OPPLUS", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 00 */
{ "__OPMINUS", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 01 */
{ "__OPMULT", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 02 */
{ "__OPDIVIDE", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 03 */
{ "__OPMOD", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 04 */
{ "__OPPOWER", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 05 */
{ "__OPINC", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 06 */
{ "__OPDEC", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 07 */
{ "__OPEQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 08 */
{ "__OPEXACTEQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 09 */
{ "__OPNOTEQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 10 */
{ "__OPLESS", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 11 */
{ "__OPLESSEQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 12 */
{ "__OPGREATER", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 13 */
{ "__OPGREATEREQUAL", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 14 */
{ "__OPADDIGN", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 15 */
{ "__OPINSTRING", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 16 */
{ "__OPNOT", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 17 */
{ "__OPAND", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 18 */
{ "__OPOR", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 19 */
{ "__OPARRAYINDEX", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 20 */
{ "__ENUMINDEX", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 21 */
{ "__ENUMBASE", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 22 */
{ "__ENUMVALUE", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 23 */
{ "__ENUMSTART", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 24 */
{ "__ENUMSKIP", {HB_FS_MESSAGE}, {NULL}, NULL }, /* 25 */
{ "__ENUMSTOP", {HB_FS_MESSAGE}, {NULL}, NULL } /* 26 */
};
static HB_SYMB s___msgSetData = { "__msgSetData", {HB_FS_MESSAGE}, {hb___msgSetData}, NULL };
@@ -334,7 +336,7 @@ static BOOL hb_clsDictRealloc( PCLASS pClass )
HB_TRACE(HB_TR_DEBUG, ("hb_clsDictRealloc(%p)", pClass));
ulNewHashKey = pClass->uiHashKey;
ulNewHashKey = ( ULONG ) pClass->uiHashKey + 1;
ulLimit = ulNewHashKey << BUCKETBITS;
do
@@ -379,7 +381,7 @@ static BOOL hb_clsDictRealloc( PCLASS pClass )
}
while( ul < ulLimit );
pClass->uiHashKey = ( USHORT ) ulNewHashKey;
pClass->uiHashKey = ( USHORT ) ( ulNewHashKey - 1 );
hb_xfree( pClass->pMethods );
pClass->pMethods = pNewMethods;
@@ -392,7 +394,7 @@ static void hb_clsDictInit( PCLASS pClass, USHORT uiHashKey )
HB_TRACE(HB_TR_DEBUG, ("hb_clsDictInit(%p,%hu)", pClass, uiHashKey));
ulSize = ( ( ULONG ) uiHashKey << BUCKETBITS ) * sizeof( METHOD );
ulSize = ( ( ( ULONG ) uiHashKey + 1 ) << BUCKETBITS ) * sizeof( METHOD );
pClass->uiHashKey = uiHashKey;
pClass->pMethods = ( PMETHOD ) hb_xgrab( ulSize );
memset( pClass->pMethods, 0, ulSize );
@@ -405,7 +407,7 @@ static PMETHOD hb_clsFindMsg( PCLASS pClass, PHB_DYNS pMsg )
HB_TRACE(HB_TR_DEBUG, ("hb_clsFindMsg(%p,%p)", pClass, pMsg));
pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey - 1 );
pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey );
uiBucket = BUCKETSIZE;
do
@@ -431,6 +433,8 @@ static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc )
/* CLASS DATA Not Shared ( new array, new value ) */
pClsDst->pClassDatas = hb_arrayClone( pClsSrc->pClassDatas );
/* do not copy shared data array - just simply create new one */
pClsDst->pSharedDatas = hb_itemArrayNew( 0 );
pClsDst->pInlines = hb_arrayClone( pClsSrc->pInlines );
pClsDst->uiDatas = pClsSrc->uiDatas;
pClsDst->ulOpFlags = pClsSrc->ulOpFlags;
@@ -474,7 +478,7 @@ static PMETHOD hb_clsAllocMsg( PCLASS pClass, PHB_DYNS pMsg )
do
{
PMETHOD pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey - 1 );
PMETHOD pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey );
USHORT uiBucket = BUCKETSIZE;
do
@@ -507,7 +511,7 @@ static void hb_clsFreeMsg( PCLASS pClass, PHB_DYNS pMsg )
HB_TRACE(HB_TR_DEBUG, ("hb_clsFreeMsg(%p,%p)", pClass, pMsg));
pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey - 1 );
pMethod = pClass->pMethods + hb_clsMsgBucket( pMsg, pClass->uiHashKey );
uiBucket = BUCKETSIZE;
do
@@ -636,10 +640,16 @@ static void hb_clsRelease( PCLASS pClass )
hb_xfree( pClass->pInitData );
}
hb_xfree( pClass->szName );
hb_xfree( pClass->pMethods );
hb_itemRelease( pClass->pClassDatas );
hb_itemRelease( pClass->pInlines );
if( pClass->szName )
hb_xfree( pClass->szName );
if( pClass->pMethods )
hb_xfree( pClass->pMethods );
if( pClass->pClassDatas )
hb_itemRelease( pClass->pClassDatas );
if( pClass->pSharedDatas )
hb_itemRelease( pClass->pSharedDatas );
if( pClass->pInlines )
hb_itemRelease( pClass->pInlines );
}
@@ -688,16 +698,13 @@ void hb_clsIsClassRef( void )
while( uiClass-- )
{
if( pClass->pInlines )
{
if( HB_IS_GCITEM( pClass->pInlines ) )
hb_gcItemRef( pClass->pInlines );
}
hb_gcItemRef( pClass->pInlines );
if( pClass->pClassDatas )
{
if( HB_IS_GCITEM( pClass->pClassDatas ) )
hb_gcItemRef( pClass->pClassDatas );
}
hb_gcItemRef( pClass->pClassDatas );
if( pClass->pSharedDatas )
hb_gcItemRef( pClass->pSharedDatas );
if( pClass->uiInitDatas )
{
@@ -1823,24 +1830,31 @@ HB_FUNC( __CLSADDMSG )
pNewMeth->uiScope = hb_clsUpdateScope( uiScope, TRUE );
pNewMeth->uiData = uiIndex;
if( hb_arrayLen( pClass->pClassDatas ) < ( ULONG ) pNewMeth->uiData )
hb_arraySize( pClass->pClassDatas, pNewMeth->uiData );
if( pNewMeth->uiScope & HB_OO_CLSTP_SHARED )
{
if( hb_arrayLen( pClass->pSharedDatas ) < ( ULONG ) pNewMeth->uiData )
hb_arraySize( pClass->pSharedDatas, pNewMeth->uiData );
pNewMeth->pFuncSym = &s___msgSetShrData;
}
else
{
if( hb_arrayLen( pClass->pClassDatas ) < ( ULONG ) pNewMeth->uiData )
hb_arraySize( pClass->pClassDatas, pNewMeth->uiData );
pNewMeth->pFuncSym = &s___msgSetClsData;
}
break;
case HB_OO_MSG_CLSACCESS:
pNewMeth->uiScope = hb_clsUpdateScope( uiScope, FALSE );
pNewMeth->uiData = uiIndex;
if( hb_arrayLen( pClass->pClassDatas ) < ( ULONG ) pNewMeth->uiData )
hb_arraySize( pClass->pClassDatas, pNewMeth->uiData );
if( pNewMeth->uiScope & HB_OO_CLSTP_SHARED )
{
PHB_ITEM pInit = hb_param( 5, HB_IT_ANY );
if( hb_arrayLen( pClass->pSharedDatas ) < ( ULONG ) pNewMeth->uiData )
hb_arraySize( pClass->pSharedDatas, pNewMeth->uiData );
if( pInit && ! HB_IS_NIL( pInit ) ) /* Initializer found */
{
/* Shared Classdata need to be initialized only once
@@ -1849,13 +1863,15 @@ HB_FUNC( __CLSADDMSG )
* to keep the init value. [druzus]
*/
pInit = hb_itemClone( pInit );
hb_arraySet( pClass->pClassDatas, pNewMeth->uiData, pInit );
hb_arraySet( pClass->pSharedDatas, pNewMeth->uiData, pInit );
hb_itemRelease( pInit );
}
pNewMeth->pFuncSym = &s___msgGetShrData;
}
else
{
if( hb_arrayLen( pClass->pClassDatas ) < ( ULONG ) pNewMeth->uiData )
hb_arraySize( pClass->pClassDatas, pNewMeth->uiData );
pNewMeth->uiOffset = hb_clsAddInitValue( pClass,
hb_param( 5, HB_IT_ANY ), HB_OO_MSG_CLASSDATA,
pNewMeth->uiData, 0, uiClass );
@@ -2102,6 +2118,7 @@ HB_FUNC( __CLSNEW )
{
hb_clsDictInit( pNewCls, HASH_KEY );
pNewCls->pClassDatas = hb_itemArrayNew( 0 );
pNewCls->pSharedDatas = hb_itemArrayNew( 0 );
pNewCls->pInlines = hb_itemArrayNew( 0 );
}
@@ -2440,6 +2457,20 @@ HB_FUNC( __CLS_CNTCLSDATA )
}
/*
* <nSeq> = __cls_CntShrData( <hClass> )
*
* Return number of class datas
*/
HB_FUNC( __CLS_CNTSHRDATA )
{
USHORT uiClass = ( USHORT ) hb_parni( 1 );
hb_retni( uiClass && uiClass <= s_uiClasses ?
hb_arrayLen( s_pClasses[ uiClass - 1 ].pSharedDatas ) : 0 );
}
/*
* <nSeq> = __cls_CntData( <hClass> )
*
@@ -2960,7 +2991,7 @@ static HARBOUR hb___msgGetShrData( void )
if( uiSprCls && uiSprCls <= s_uiClasses )
{
hb_arrayGet( s_pClasses[ uiSprCls - 1 ].pClassDatas,
hb_arrayGet( s_pClasses[ uiSprCls - 1 ].pSharedDatas,
pMethod->uiData, hb_stackReturnItem() );
}
}
@@ -2982,7 +3013,7 @@ static HARBOUR hb___msgSetShrData( void )
if( uiSprCls && uiSprCls <= s_uiClasses )
{
hb_arraySet( s_pClasses[ uiSprCls - 1 ].pClassDatas,
hb_arraySet( s_pClasses[ uiSprCls - 1 ].pSharedDatas,
pMethod->uiData, pReturn );
}

View File

@@ -3033,25 +3033,17 @@ static HB_GARBAGE_FUNC( hb_enumHolderRelease )
static void hb_vmEnumStart( BYTE nVars, BYTE nDescend )
{
HB_ITEM_PTR pItem;
ULONG ulMax;
BOOL fStart = TRUE;
int i;
pItem = hb_itemUnRef( hb_stackItemFromTop( -( ( int ) nVars << 1 ) ) );
if( HB_IS_ARRAY( pItem ) )
{
ulMax = pItem->item.asArray.value->ulLen;
}
else if( HB_IS_STRING( pItem ) )
{
ulMax = pItem->item.asString.length;
}
else
if( !HB_IS_ARRAY( pItem ) && ! HB_IS_STRING( pItem ) )
{
hb_errRT_BASE( EG_ARG, 1068, NULL, hb_langDGetErrorDesc( EG_ARRACCESS ), 1, pItem );
return;
}
for( i = ( int ) nVars << 1; i > 0; i -= 2 )
for( i = ( int ) nVars << 1; i > 0 && fStart; i -= 2 )
{
HB_ITEM_PTR pValue, pOldValue, pEnum, pEnumRef;
PHB_ENUMHOLDER pHolder;
@@ -3093,25 +3085,45 @@ static void hb_vmEnumStart( BYTE nVars, BYTE nDescend )
pEnum->item.asEnum.basePtr = pItem;
pEnum->item.asEnum.valuePtr = NULL;
if( HB_IS_OBJECT( pItem ) && hb_objHasOperator( pItem, HB_OO_OP_ENUMSTART ) )
{
pEnum->item.asEnum.offset = 0;
pEnum->item.asEnum.valuePtr = hb_itemNew( NULL );
hb_vmPushNil();
hb_vmPushLogical( nDescend == 0 );
hb_objOperatorCall( HB_OO_OP_ENUMSTART, hb_stackItemFromTop( -2 ),
pItem, pEnumRef, hb_stackItemFromTop( -1 ) );
hb_stackPop();
if( ! hb_vmPopLogical() )
{
fStart = FALSE;
break;
}
else if( hb_objHasOperator( pItem, HB_OO_OP_ENUMSKIP ) )
continue;
hb_itemRelease( pEnum->item.asEnum.valuePtr );
pEnum->item.asEnum.valuePtr = NULL;
}
if( HB_IS_ARRAY( pItem ) )
{
/* the index into an array */
pEnum->item.asEnum.offset = ( nDescend > 0 ) ? 1 :
pItem->item.asArray.value->ulLen;
if( ulMax > pItem->item.asArray.value->ulLen )
ulMax = pItem->item.asArray.value->ulLen;
if( pItem->item.asArray.value->ulLen == 0 )
fStart = FALSE;
}
else if( HB_IS_STRING( pItem ) )
{
/* storage item for single characters */
pEnum->item.asEnum.offset = ( nDescend > 0 ) ? 1 :
pItem->item.asString.length;
if( pItem->item.asString.length ) /* TODO: RT error if not? */
if( pItem->item.asString.length )
pEnum->item.asEnum.valuePtr =
hb_itemPutCL( NULL, pItem->item.asString.value +
pEnum->item.asEnum.offset - 1, 1 );
if( ulMax > pItem->item.asString.length )
ulMax = pItem->item.asString.length;
else
fStart = FALSE;
}
else
{
@@ -3122,7 +3134,7 @@ static void hb_vmEnumStart( BYTE nVars, BYTE nDescend )
hb_vmPushInteger( nVars ); /* number of iterators */
/* empty array/string - do not start enumerations loop */
hb_vmPushLogical( ulMax != 0 );
hb_vmPushLogical( fStart );
}
@@ -3134,16 +3146,30 @@ static void hb_vmEnumStart( BYTE nVars, BYTE nDescend )
*/
static void hb_vmEnumNext( void )
{
HB_ITEM_PTR pEnum;
HB_ITEM_PTR pEnumRef, pEnum;
int i;
for( i = ( int ) hb_stackItemFromTop( -1 )->item.asInteger.value; i > 0; --i )
{
pEnum = hb_itemUnRefOnce( hb_stackItemFromTop( -( i << 1 ) ) );
pEnumRef = hb_stackItemFromTop( -( i << 1 ) );
pEnum = hb_itemUnRefOnce( pEnumRef );
if( HB_IS_ARRAY( pEnum->item.asEnum.basePtr ) )
{
if( ( ULONG ) ++pEnum->item.asEnum.offset >
pEnum->item.asEnum.basePtr->item.asArray.value->ulLen )
if( HB_IS_OBJECT( pEnum->item.asEnum.basePtr ) &&
hb_objHasOperator( pEnum->item.asEnum.basePtr, HB_OO_OP_ENUMSKIP ) )
{
++pEnum->item.asEnum.offset;
hb_vmPushNil();
hb_vmPushLogical( FALSE );
hb_objOperatorCall( HB_OO_OP_ENUMSKIP, hb_stackItemFromTop( -2 ),
pEnum->item.asEnum.basePtr, pEnumRef,
hb_stackItemFromTop( -1 ) );
hb_stackPop();
if( ! hb_vmPopLogical() )
break;
}
else if( ( ULONG ) ++pEnum->item.asEnum.offset >
pEnum->item.asEnum.basePtr->item.asArray.value->ulLen )
break;
}
else if( HB_IS_STRING( pEnum->item.asEnum.basePtr ) )
@@ -3172,15 +3198,29 @@ static void hb_vmEnumNext( void )
*/
static void hb_vmEnumPrev( void )
{
HB_ITEM_PTR pEnum;
HB_ITEM_PTR pEnumRef, pEnum;
int i;
for( i = hb_stackItemFromTop( -1 )->item.asInteger.value; i > 0; --i )
{
pEnum = hb_itemUnRefOnce( hb_stackItemFromTop( -( i << 1 ) ) );
pEnumRef = hb_stackItemFromTop( -( i << 1 ) );
pEnum = hb_itemUnRefOnce( pEnumRef );
if( HB_IS_ARRAY( pEnum->item.asEnum.basePtr ) )
{
if( --pEnum->item.asEnum.offset == 0 )
if( HB_IS_OBJECT( pEnum->item.asEnum.basePtr ) &&
hb_objHasOperator( pEnum->item.asEnum.basePtr, HB_OO_OP_ENUMSKIP ) )
{
--pEnum->item.asEnum.offset;
hb_vmPushNil();
hb_vmPushLogical( TRUE );
hb_objOperatorCall( HB_OO_OP_ENUMSKIP, hb_stackItemFromTop( -2 ),
pEnum->item.asEnum.basePtr, pEnumRef,
hb_stackItemFromTop( -1 ) );
hb_stackPop();
if( ! hb_vmPopLogical() )
break;
}
else if( --pEnum->item.asEnum.offset == 0 )
break;
}
else if( HB_IS_STRING( pEnum->item.asEnum.basePtr ) )

View File

@@ -1433,28 +1433,23 @@ PHB_ITEM hb_itemUnRefOnce( PHB_ITEM pItem )
else if( HB_IS_ENUM( pItem ) ) /* FOR EACH control variable */
{
/* enumerator variable */
if( HB_IS_ARRAY( pItem->item.asEnum.basePtr ) )
if( pItem->item.asEnum.valuePtr )
return pItem->item.asEnum.valuePtr;
else if( HB_IS_ARRAY( pItem->item.asEnum.basePtr ) )
{
PHB_ITEM pResult = hb_arrayGetItemPtr( pItem->item.asEnum.basePtr,
pItem->item.asEnum.offset );
if( pResult )
return pResult;
}
else if( pItem->item.asEnum.valuePtr )
return pItem->item.asEnum.valuePtr;
/* to avoid recursive RT error generation */
if( pItem->item.asEnum.offset >= 0 )
{
hb_itemPutNInt( hb_stackAllocItem(), pItem->item.asEnum.offset );
pItem->item.asEnum.offset = -1;
if( !pItem->item.asEnum.valuePtr )
pItem->item.asEnum.valuePtr = hb_itemNew( NULL );
/* put it here to avoid recursive RT error generation */
pItem->item.asEnum.valuePtr = hb_itemNew( NULL );
hb_itemPutNInt( hb_stackAllocItem(), pItem->item.asEnum.offset );
hb_errRT_BASE( EG_BOUND, 1132, NULL, hb_langDGetErrorDesc( EG_ARRACCESS ),
2, pItem->item.asEnum.basePtr, hb_stackItemFromTop( -1 ) );
hb_errRT_BASE( EG_BOUND, 1132, NULL, hb_langDGetErrorDesc( EG_ARRACCESS ),
2, pItem->item.asEnum.basePtr, hb_stackItemFromTop( -1 ) );
/* break() was executed by error block */
}
return pItem->item.asEnum.valuePtr;
}
else

374
harbour/tests/clsscast.prg Normal file
View File

@@ -0,0 +1,374 @@
/*
* $Id$
*/
/*
* Harbour Project source code:
* demonstration/test code for shared class variables casting and allocating
* in multiinherited classes
*
* Copyright 2006 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* www - http://www.harbour-project.org
*
*/
#define EOL chr(10)
#xtranslate QQOUT([<x,...>]) => [OUTSTD(<x>)]
#xtranslate QOUT([<x,...>]) => OUTSTD(EOL)[;OUTSTD(<x>)]
#ifdef __HARBOUR__
#include "hbclass.ch"
#translate MESSAGE <message> INLINE <*expr*> ;
=> ;
METHOD <message> INLINE <expr>
#else
#include "class(y).ch"
#xtranslate __SENDER( => SENDER(
#endif
proc main()
local o:=myclass4():new(), i, cbErr
? DATE(), TIME(), VERSION(), OS()
?
? "myclass1 class vars:", str( __CLS_CNTCLSDATA(o:myclass1:classH), 3), " => should be: 3"
? "myclass2 class vars:", str( __CLS_CNTCLSDATA(o:myclass2:classH), 3), " => should be: 3"
? "myclass3 class vars:", str( __CLS_CNTCLSDATA(o:myclass3:classH), 3), " => should be: 3"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "myclass4 class vars:", str( __CLS_CNTCLSDATA(o:myclass4:classH), 3), " => should be: 3"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? "myclass4 class vars:", str( __CLS_CNTCLSDATA(o:classH), 3), " => should be: 3"
?
/* direct assignment, possible because the variables have differ names */
? "instance variables ["+ltrim(str(len(o)))+"]:"; ?
for i:=1 to len(o); ?? "",o[i]; next
? " => shoule be [0]:"
?
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: (x1) (y1) (z1)"
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: (x1) (y1) (z1)"
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: (x2) (y2) (z2)"
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: (x1) (y1) (z1)"
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: (x2) (y2) (z2)"
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: (x3) (y3) (z3)"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: (x1) (y1) (z1)"
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: (x2) (y2) (z2)"
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: (x3) (y3) (z3)"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: (x4) (y4) (z4)"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: (x1) (y1) (z1)"
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: (x2) (y2) (z2)"
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: (x3) (y3) (z3)"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: (x4) (y4) (z4)"
?
? "initialization..."
o:x1:=" X1 "; o:y1:=" Y1 "; o:z1:=" Z1 "
o:x2:=" X2 "; o:y2:=" Y2 "; o:z2:=" Z2 "
o:x3:=" X3 "; o:y3:=" Y3 "; o:z3:=" Z3 "
o:x4:=" X4 "; o:y4:=" Y4 "; o:z4:=" Z4 "
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: X1 Y1 Z1"
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: X1 Y1 Z1"
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: X2 Y2 Z2"
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: X1 Y1 Z1"
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: X2 Y2 Z2"
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: X3 Y3 Z3"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: X1 Y1 Z1"
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: X2 Y2 Z2"
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: X3 Y3 Z3"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: X4 Y4 Z4"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: X1 Y1 Z1"
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: X2 Y2 Z2"
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: X3 Y3 Z3"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: X4 Y4 Z4"
?
? "instance variables ["+ltrim(str(len(o)))+"]:"; ?
for i:=1 to len(o); ?? "",o[i]; next
? " => shoule be [0]:"
?
? "Setting MYCLASS1 class variables..."
o:myclass1:x1:="[X1]"
o:myclass1:y1:="[Y1]"
o:myclass1:z1:="[Z1]"
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: [X1] [Y1] [Z1]"
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: [X1] [Y1] [Z1]"
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: X2 Y2 Z2"
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: [X1] [Y1] [Z1]"
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: X2 Y2 Z2"
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: X3 Y3 Z3"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: [X1] [Y1] [Z1]"
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: X2 Y2 Z2"
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: X3 Y3 Z3"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: X4 Y4 Z4"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: [X1] [Y1] [Z1]"
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: X2 Y2 Z2"
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: X3 Y3 Z3"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: X4 Y4 Z4"
?
? "Setting MYCLASS2 class variables..."
o:myclass2:x1:="{X1}"
o:myclass2:y1:="{Y1}"
o:myclass2:z1:="{Z1}"
o:myclass2:x2:="{X2}"
o:myclass2:y2:="{Y2}"
o:myclass2:z2:="{Z2}"
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: {X1} {Y1} {Z1}"
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: {X1} {Y1} {Z1}"
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: {X2} {Y2} {Z2}"
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: {X1} {Y1} {Z1}"
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: {X2} {Y2} {Z2}"
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: X3 Y3 Z3"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: {X1} {Y1} {Z1}"
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: {X2} {Y2} {Z2}"
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: X3 Y3 Z3"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: X4 Y4 Z4"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: {X1} {Y1} {Z1}"
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: {X2} {Y2} {Z2}"
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: X3 Y3 Z3"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: X4 Y4 Z4"
?
? "Setting MYCLASS3 class variables..."
o:myclass3:x1:="<X1>"
o:myclass3:y1:="<Y1>"
o:myclass3:z1:="<Z1>"
o:myclass3:x2:="<X2>"
o:myclass3:y2:="<Y2>"
o:myclass3:z2:="<Z2>"
o:myclass3:x3:="<X3>"
o:myclass3:y3:="<Y3>"
o:myclass3:z3:="<Z3>"
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: <X1> <Y1> <Z1>"
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: <X1> <Y1> <Z1>"
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: <X2> <Y2> <Z2>"
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: <X1> <Y1> <Z1>"
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: <X2> <Y2> <Z2>"
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: <X3> <Y3> <Z3>"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: <X1> <Y1> <Z1>"
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: <X2> <Y2> <Z2>"
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: <X3> <Y3> <Z3>"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: X4 Y4 Z4"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: <X1> <Y1> <Z1>"
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: <X2> <Y2> <Z2>"
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: <X3> <Y3> <Z3>"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: X4 Y4 Z4"
?
? "Setting MYCLASS4 class variables..."
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
o:myclass4:x1:="|X1|"
o:myclass4:y1:="|Y1|"
o:myclass4:z1:="|Z1|"
o:myclass4:x2:="|X2|"
o:myclass4:y2:="|Y2|"
o:myclass4:z2:="|Z2|"
o:myclass4:x3:="|X3|"
o:myclass4:y3:="|Y3|"
o:myclass4:z3:="|Z3|"
o:myclass4:x4:="|X4|"
o:myclass4:y4:="|Y4|"
o:myclass4:z4:="|Z4|"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: |X1| |Y1| |Z1|"
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: |X1| |Y1| |Z1|"
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: |X2| |Y2| |Z2|"
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: |X1| |Y1| |Z1|"
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: |X2| |Y2| |Z2|"
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: |X3| |Y3| |Z3|"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: |X1| |Y1| |Z1|"
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: |X2| |Y2| |Z2|"
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: |X3| |Y3| |Z3|"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: |X4| |Y4| |Z4|"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: |X1| |Y1| |Z1|"
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: |X2| |Y2| |Z2|"
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: |X3| |Y3| |Z3|"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: |X4| |Y4| |Z4|"
?
? "Setting MYCLASS3:MYCLASS1 class variables..."
o:myclass3:myclass1:x1:="^X1^"
o:myclass3:myclass1:y1:="^Y1^"
o:myclass3:myclass1:z1:="^Z1^"
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: ^X1^ ^Y1^ ^Z1^"
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: ^X1^ ^Y1^ ^Z1^"
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: |X2| |Y2| |Z2|"
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: ^X1^ ^Y1^ ^Z1^"
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: |X2| |Y2| |Z2|"
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: |X3| |Y3| |Z3|"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: ^X1^ ^Y1^ ^Z1^"
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: |X2| |Y2| |Z2|"
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: |X3| |Y3| |Z3|"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: |X4| |Y4| |Z4|"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: ^X1^ ^Y1^ ^Z1^"
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: |X2| |Y2| |Z2|"
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: |X3| |Y3| |Z3|"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: |X4| |Y4| |Z4|"
?
? "Setting MYCLASS3:MYCLASS2 class variables..."
o:myclass3:myclass2:x1:="=X1="
o:myclass3:myclass2:y1:="=Y1="
o:myclass3:myclass2:z1:="=Z1="
o:myclass3:myclass2:x2:="=X2="
o:myclass3:myclass2:y2:="=Y2="
o:myclass3:myclass2:z2:="=Z2="
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: =X1= =Y1= =Z1="
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: =X1= =Y1= =Z1="
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: =X2= =Y2= =Z2="
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: =X1= =Y1= =Z1="
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: =X2= =Y2= =Z2="
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: |X3| |Y3| |Z3|"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: =X1= =Y1= =Z1="
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: =X2= =Y2= =Z2="
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: |X3| |Y3| |Z3|"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: |X4| |Y4| |Z4|"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: =X1= =Y1= =Z1="
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: =X2= =Y2= =Z2="
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: |X3| |Y3| |Z3|"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: |X4| |Y4| |Z4|"
?
? "Setting SUPER class variables..."
o:super:x1:="*X1*"
o:super:y1:="*Y1*"
o:super:z1:="*Z1*"
o:super:x2:="*X2*"
o:super:y2:="*Y2*"
o:super:z2:="*Z2*"
o:super:x3:="*X3*"
o:super:y3:="*Y3*"
o:super:z3:="*Z3*"
? "[1] MYCLASS1 VARS:", o:myclass1:x1, o:myclass1:y1, o:myclass1:z1, " => should be: *X1* *Y1* *Z1*"
? "[2] MYCLASS1 VARS:", o:myclass2:x1, o:myclass2:y1, o:myclass2:z1, " => should be: *X1* *Y1* *Z1*"
? "[2] MYCLASS2 VARS:", o:myclass2:x2, o:myclass2:y2, o:myclass2:z2, " => should be: *X2* *Y2* *Z2*"
? "[3] MYCLASS1 VARS:", o:myclass3:x1, o:myclass3:y1, o:myclass3:z1, " => should be: *X1* *Y1* *Z1*"
? "[3] MYCLASS2 VARS:", o:myclass3:x2, o:myclass3:y2, o:myclass3:z2, " => should be: *X2* *Y2* *Z2*"
? "[3] MYCLASS3 VARS:", o:myclass3:x3, o:myclass3:y3, o:myclass3:z3, " => should be: *X3* *Y3* *Z3*"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "[4] MYCLASS1 VARS:", o:myclass4:x1, o:myclass4:y1, o:myclass4:z1, " => should be: *X1* *Y1* *Z1*"
? "[4] MYCLASS2 VARS:", o:myclass4:x2, o:myclass4:y2, o:myclass4:z2, " => should be: *X2* *Y2* *Z2*"
? "[4] MYCLASS3 VARS:", o:myclass4:x3, o:myclass4:y3, o:myclass4:z3, " => should be: *X3* *Y3* *Z3*"
? "[4] MYCLASS4 VARS:", o:myclass4:x4, o:myclass4:y4, o:myclass4:z4, " => should be: |X4| |Y4| |Z4|"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? " MYCLASS1 VARS:", o:x1, o:y1, o:z1, " => should be: *X1* *Y1* *Z1*"
? " MYCLASS2 VARS:", o:x2, o:y2, o:z2, " => should be: *X2* *Y2* *Z2*"
? " MYCLASS3 VARS:", o:x3, o:y3, o:z3, " => should be: *X3* *Y3* *Z3*"
? " MYCLASS4 VARS:", o:x4, o:y4, o:z4, " => should be: |X4| |Y4| |Z4|"
?
? "instance variables ["+ltrim(str(len(o)))+"]:"; ?
for i:=1 to len(o); ?? "",o[i]; next
? " => shoule be [0]:"
?
? "myclass1 class vars:", str( __CLS_CNTCLSDATA(o:myclass1:classH), 3), " => should be: 3"
? "myclass2 class vars:", str( __CLS_CNTCLSDATA(o:myclass2:classH), 3), " => should be: 3"
? "myclass3 class vars:", str( __CLS_CNTCLSDATA(o:myclass3:classH), 3), " => should be: 3"
cbErr:=errorBlock({|oErr|break(oErr)})
begin sequence
? "myclass4 class vars:", str( __CLS_CNTCLSDATA(o:myclass4:classH), 3), " => should be: 3"
recover
? "ERROR: no selfclass casting"
end
errorBlock(cbErr)
? "myclass4 class vars:", str( __CLS_CNTCLSDATA(o:classH), 3), " => should be: 3"
?
return
create class myclass1
export:
class var x1 init "(x1)" shared
class var y1 init "(y1)" shared
class var z1 init "(z1)" shared
endclass
create class myclass2 from myclass1
export:
class var x2 init "(x2)" shared
class var y2 init "(y2)" shared
class var z2 init "(z2)" shared
endclass
create class myclass3 from myclass1, myclass2
export:
class var x3 init "(x3)" shared
class var y3 init "(y3)" shared
class var z3 init "(z3)" shared
endclass
create class myclass4 from myclass3, myclass2
export:
class var x4 init "(x4)" shared
class var y4 init "(y4)" shared
class var z4 init "(z4)" shared
endclass