diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 3e62114f76..2c1a61dcfa 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,73 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2006-09-10 14:02 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/ChangeLog + ! added missing changelog entry about __MVPUT() fix + + * harbour/source/vm/itemapi.c + * removed redundant pItem->type = HB_IT_NIL (thanks for Manu Exposito) + +2006-09-10 14:02 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/ChangeLog + ! added missing changelog entry about __MVPUT() fix + + * harbour/source/vm/itemapi.c + * removed redundant pItem->type = HB_IT_NIL (thanks for Manu Exposito) + +2006-09-10 13:05 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbapi.h + * harbour/source/vm/hvm.c + * harbour/source/vm/codebloc.c + * harbour/source/vm/arrays.c + * moved static base offset from hb_struBlock structure + to HB_CODEBLOCK structure + + added hclass member to hb_struBlock - it will be used in + the future for checking codeblock scope in classy so we will + real scope checking also for messages sent from codeblocks. + - removed supercast and superoffset members from hb_struArray + structure. + + * harbour/include/hbclass.ch + * added class(y) like + @:([]) + send operator. It's not exactly the same as in class(y) where + this operator is hardcoded to executing function directly, + needs method name instead of message name and is linked statically. + In Harbour this operator uses message name so can be used also for + instance variables and make dynamic casting to the class from which + current method is inherited. In short words sending messages to @: + instead of :: causes that they work like non-virtual messages in + C++ mode. + If you do not use the same method body in different classes + then you can also use explicitly self casting: + :::[(...)] + and it will be a little bit faster + + * harbour/include/hboo.ch + + added: HB_OO_MSG_ASSIGN, HB_OO_MSG_ACCESS, + HB_OO_MSG_CLSASSIGN, HB_OO_MSG_CLSACCESS + They should be used insted of HB_OO_MSG_DATA and HB_OO_MSG_CLSDATA + This resolves problems with name conflicts when we were detecting + type of message (ACCESS/ASSIGN) by checking the first character + in message name. F.e. now it's possible to create exported instance + variable called __WithObject and it will be used in all WITH OBJECT + statement instead of the base object value. It's simple and effective + WITH OBJECT overloading. + I kept backward compatibility for HB_OO_MSG_DATA and HB_OO_MSG_CLSDATA + but I strongly suggest to update code to use new constants. + + added HB_OO_MSG_REALCLASS + + * harbour/source/rtl/objfunc.prg + * harbour/source/rtl/tobject.prg + * harbour/source/rtl/tclass.prg + * use HB_OO_MSG_[CLS]{ASSIGN,ACCESS} instead of HB_OO_MSG_[CLS]DATA + + * harbour/source/rtl/tclass.prg + + added REALCLASS message to creted classes - it's used for @: operator + + * harbour/source/vm/classes.c + * updated for above modifications ! fixed GPF in __CLSINSTSUPER() class function generate HVM exception % do not inherit unaccessible inline blocks * some other minor optimization, fixes and code cleanups diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 9acf39033d..f6ef5e85b5 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -238,16 +238,14 @@ typedef struct _HB_STACK_STATE struct hb_struArray { struct _HB_BASEARRAY * value; - USHORT supercast; - USHORT superoffset; }; struct hb_struBlock { - LONG statics; + struct _HB_CODEBLOCK * value; USHORT lineno; USHORT paramcnt; - struct _HB_CODEBLOCK * value; + USHORT hclass; }; struct hb_struDate @@ -363,6 +361,7 @@ typedef struct _HB_CODEBLOCK PHB_SYMB pSymbols; /* codeblocks symbols */ PHB_SYMB pDefSymb; /* symbol where the codeblock was created */ PHB_ITEM pLocals; /* table with referenced local variables */ + LONG lStatics; /* STATICs base address */ USHORT uiLocals; /* number of referenced local variables */ SHORT dynBuffer; /* is pcode buffer allocated dynamically, SHORT used instead of BOOL intentionally to force optimal alignment */ } HB_CODEBLOCK, * PHB_CODEBLOCK, * HB_CODEBLOCK_PTR; diff --git a/harbour/include/hbclass.ch b/harbour/include/hbclass.ch index 3b0e32fa6e..a7832780e9 100644 --- a/harbour/include/hbclass.ch +++ b/harbour/include/hbclass.ch @@ -150,6 +150,10 @@ DECLARE HBClass ; #xtranslate CREATE CLASS => CLASS #xtranslate _HB_MEMBER {AS Num => _HB_MEMBER {AS Numeric #xtranslate _HB_MEMBER {AS Char => _HB_MEMBER {AS Character + +#translate @:([]) => ; + ::realclass:([]) + #endif #ifdef HB_CLS_ALLOWCLASS /* DONT DECLARE IT ! WORK IN PROGRESS !!! */ diff --git a/harbour/include/hboo.ch b/harbour/include/hboo.ch index 2a4ca12e0d..f6241e98df 100644 --- a/harbour/include/hboo.ch +++ b/harbour/include/hboo.ch @@ -93,7 +93,13 @@ #define HB_OO_MSG_SUPER 5 #define HB_OO_MSG_ONERROR 6 #define HB_OO_MSG_CLSMTHD 7 /* for the future */ -#define HB_OO_MSG_INITIALIZED 8 +#define HB_OO_MSG_ASSIGN 8 +#define HB_OO_MSG_ACCESS 9 +#define HB_OO_MSG_CLSASSIGN 10 +#define HB_OO_MSG_CLSACCESS 11 +#define HB_OO_MSG_REALCLASS 12 +#define HB_OO_MSG_INITIALIZED 13 + /* Data */ #define HB_OO_DATA_SYMBOL 1 #define HB_OO_DATA_VALUE 2 diff --git a/harbour/source/rdd/usrrdd/usrrdd.c b/harbour/source/rdd/usrrdd/usrrdd.c index 02b52b2a5f..4add3237f6 100644 --- a/harbour/source/rdd/usrrdd/usrrdd.c +++ b/harbour/source/rdd/usrrdd/usrrdd.c @@ -2305,7 +2305,7 @@ static ERRCODE hb_usrFilterText( AREAP pArea, PHB_ITEM pFilter ) { LONG lOffset; - HB_TRACE(HB_TR_DEBUG, ("hb_usrFilterText(%p,%hu,%p)", pArea, uiRelNo, pFilter)); + HB_TRACE(HB_TR_DEBUG, ("hb_usrFilterText(%p,%p)", pArea, pFilter)); lOffset = hb_stackTopOffset() - hb_stackBaseOffset(); hb_vmPush( pFilter ); diff --git a/harbour/source/rtl/errorapi.c b/harbour/source/rtl/errorapi.c index 335d712fd4..aa7a417647 100644 --- a/harbour/source/rtl/errorapi.c +++ b/harbour/source/rtl/errorapi.c @@ -176,7 +176,11 @@ PHB_ITEM hb_errNew( void ) hb_vmPushNil(); hb_vmDo( 0 ); - hb_itemCopy( pReturn, hb_stackReturnItem() ); + hb_itemMove( pReturn, hb_stackReturnItem() ); + if( ! HB_IS_OBJECT( pReturn ) ) + { + hb_errInternal( HB_EI_ERRRECFAILURE, NULL, NULL, NULL ); + } return pReturn; } @@ -215,7 +219,7 @@ USHORT hb_errLaunch( PHB_ITEM pError ) */ s_errorHandler->Error = pError; s_errorHandler->ErrorBlock = s_errorBlock; - pResult = (s_errorHandler->Func)( s_errorHandler ); + pResult = ( s_errorHandler->Func )( s_errorHandler ); s_errorHandler->Error = NULL; } else diff --git a/harbour/source/rtl/objfunc.prg b/harbour/source/rtl/objfunc.prg index b27c4bde37..c52371a187 100644 --- a/harbour/source/rtl/objfunc.prg +++ b/harbour/source/rtl/objfunc.prg @@ -211,8 +211,8 @@ FUNCTION __objAddData( oObject, cSymbol ) ELSEIF !__objHasMsg( oObject, cSymbol ) .AND. !__objHasMsg( oObject, "_" + cSymbol ) hClass := oObject:ClassH nSeq := __cls_IncData( hClass ) // Allocate new Seq# - __clsAddMsg( hClass, cSymbol, nSeq, HB_OO_MSG_DATA, NIL, 1 ) - __clsAddMsg( hClass, "_" + cSymbol, nSeq, HB_OO_MSG_DATA, NIL, 1 ) + __clsAddMsg( hClass, cSymbol, nSeq, HB_OO_MSG_ACCESS, NIL, 1 ) + __clsAddMsg( hClass, "_" + cSymbol, nSeq, HB_OO_MSG_ASSIGN, NIL, 1 ) ENDIF RETURN oObject diff --git a/harbour/source/rtl/tclass.prg b/harbour/source/rtl/tclass.prg index 82496ddf5f..8def9a17ad 100644 --- a/harbour/source/rtl/tclass.prg +++ b/harbour/source/rtl/tclass.prg @@ -101,28 +101,28 @@ FUNCTION HBClass() __clsAddMsg( s_hClass, "InitClass" , @InitClass() , HB_OO_MSG_METHOD ) __clsAddMsg( s_hClass, "cSuper" , {| Self | iif( ::acSuper == NIL .OR. Len( ::acSuper ) == 0, NIL, ::acSuper[ 1 ] ) }, HB_OO_MSG_INLINE ) __clsAddMsg( s_hClass, "_cSuper" , {| Self, xVal | iif( ::acSuper == NIL .OR. Len( ::acSuper ) == 0, ( ::acSuper := { xVal } ), ::acSuper[ 1 ] := xVal ), xVal }, HB_OO_MSG_INLINE ) - __clsAddMsg( s_hClass, "hClass" , 1, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_hClass" , 1, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "cName" , 2, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_cName" , 2, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "aDatas" , 3, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_aDatas" , 3, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "aMethods" , 4, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_aMethods" , 4, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "aClsDatas" , 5, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_aClsDatas" , 5, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "aClsMethods" , 6, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_aClsMethods" , 6, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "aInlines" , 7, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_aInlines" , 7, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "aVirtuals" , 8, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_aVirtuals" , 8, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "acSuper" , 9, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_acSuper" , 9, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "nOnError" , 10, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_nOnError" , 10, HB_OO_MSG_DATA ) - /* __clsAddMsg( s_hClass, "class" , 11, HB_OO_MSG_DATA ) - __clsAddMsg( s_hClass, "_class" , 11, HB_OO_MSG_DATA ) */ + __clsAddMsg( s_hClass, "hClass" , 1, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_hClass" , 1, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "cName" , 2, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_cName" , 2, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "aDatas" , 3, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_aDatas" , 3, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "aMethods" , 4, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_aMethods" , 4, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "aClsDatas" , 5, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_aClsDatas" , 5, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "aClsMethods" , 6, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_aClsMethods" , 6, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "aInlines" , 7, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_aInlines" , 7, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "aVirtuals" , 8, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_aVirtuals" , 8, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "acSuper" , 9, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_acSuper" , 9, HB_OO_MSG_ASSIGN ) + __clsAddMsg( s_hClass, "nOnError" , 10, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_nOnError" , 10, HB_OO_MSG_ASSIGN ) + /* __clsAddMsg( s_hClass, "class" , 11, HB_OO_MSG_ACCESS ) + __clsAddMsg( s_hClass, "_class" , 11, HB_OO_MSG_ASSIGN ) */ ENDIF @@ -205,7 +205,8 @@ STATIC PROCEDURE Create() nClassBegin += __cls_CntClsData( ahSuper[ n ] ) // Get offset for new ClassData NEXT ENDIF - __clsAddMsg( hClass, ::cName , 0, HB_OO_MSG_SUPER, hClass, HB_OO_CLSTP_EXPORTED ) + __clsAddMsg( hClass, ::cName , 0, HB_OO_MSG_SUPER , hClass, HB_OO_CLSTP_EXPORTED ) + __clsAddMsg( hClass, "REALCLASS" , 0, HB_OO_MSG_REALCLASS, 0 , HB_OO_CLSTP_EXPORTED ) ::hClass := hClass @@ -221,10 +222,10 @@ STATIC PROCEDURE Create() FOR n := 1 TO nLenDatas __clsAddMsg( hClass, ::aDatas[ n ][ HB_OO_DATA_SYMBOL ] , n + nDataBegin, ; - HB_OO_MSG_DATA, ::aDatas[ n ][ HB_OO_DATA_VALUE ], ::aDatas[ n ][ HB_OO_DATA_SCOPE ],; + HB_OO_MSG_ACCESS, ::aDatas[ n ][ HB_OO_DATA_VALUE ], ::aDatas[ n ][ HB_OO_DATA_SCOPE ],; ::aDatas[ n ][ HB_OO_DATA_PERSISTENT ] ) __clsAddMsg( hClass, "_" + ::aDatas[ n ][ HB_OO_DATA_SYMBOL ] , n + nDataBegin, ; - HB_OO_MSG_DATA, , ::aDatas[ n ][ HB_OO_DATA_SCOPE ] ) + HB_OO_MSG_ASSIGN, , ::aDatas[ n ][ HB_OO_DATA_SCOPE ] ) NEXT nLen := Len( ::aMethods ) @@ -236,9 +237,9 @@ STATIC PROCEDURE Create() nLen := Len( ::aClsDatas ) FOR n := 1 TO nLen __clsAddMsg( hClass, ::aClsDatas[ n ][ HB_OO_CLSD_SYMBOL ] , n + nClassBegin,; - HB_OO_MSG_CLASSDATA, ::aClsDatas[ n ][ HB_OO_CLSD_VALUE ], ::aClsDatas[ n ][ HB_OO_CLSD_SCOPE ] ) + HB_OO_MSG_CLSACCESS, ::aClsDatas[ n ][ HB_OO_CLSD_VALUE ], ::aClsDatas[ n ][ HB_OO_CLSD_SCOPE ] ) __clsAddMsg( hClass, "_" + ::aClsDatas[ n ][ HB_OO_CLSD_SYMBOL ], n + nClassBegin,; - HB_OO_MSG_CLASSDATA, , ::aClsDatas[ n ][ HB_OO_CLSD_SCOPE ] ) + HB_OO_MSG_CLSASSIGN, , ::aClsDatas[ n ][ HB_OO_CLSD_SCOPE ] ) NEXT nLen := Len( ::aInlines ) diff --git a/harbour/source/rtl/tobject.prg b/harbour/source/rtl/tobject.prg index 6ab213d20e..a54362b5d3 100644 --- a/harbour/source/rtl/tobject.prg +++ b/harbour/source/rtl/tobject.prg @@ -107,8 +107,8 @@ FUNCTION HBObject() /*s_oClass:AddMultiData(,,nScope,{"CLASS"}, .F. )*/ /*s_oClass:AddInline( "ADDMETHOD" , { | Self, cMeth, pFunc, nScopeMeth | __clsAddMsg( __CLASSH( Self ) , cMeth , pFunc ,HB_OO_MSG_METHOD , NIL, iif(nScopeMeth==NIL,1,nScopeMeth) ) }, nScope ) */ - /*s_oClass:AddInline( "ADDVAR" , { | Self, cVAR, nScopeMeth, uiData , hClass | __clsAddMsg( hClass:=__CLASSH( Self ) , cVar , uidata := __CLS_INCDATA(hClass) , HB_OO_MSG_DATA, NIL , iif(nScopeMeth==NIL,1,nScopeMeth) ) , ; */ - /* __clsAddMsg( hClass , "_"+cVar , uiData , HB_OO_MSG_DATA, NIL , iif(nScopeMeth==NIL,1,nScopeMeth) ) }, nScope ) */ + /*s_oClass:AddInline( "ADDVAR" , { | Self, cVAR, nScopeMeth, uiData , hClass | __clsAddMsg( hClass:=__CLASSH( Self ) , cVar , uidata := __CLS_INCDATA(hClass) , HB_OO_MSG_ACCESS, NIL , iif(nScopeMeth==NIL,1,nScopeMeth) ) , ; */ + /* __clsAddMsg( hClass , "_"+cVar , uiData , HB_OO_MSG_ASSIGN, NIL , iif(nScopeMeth==NIL,1,nScopeMeth) ) }, nScope ) */ /* Those one exist within Class(y), so we will probably try to implement it */ diff --git a/harbour/source/vm/arrays.c b/harbour/source/vm/arrays.c index 8360d94276..5dd96808d3 100644 --- a/harbour/source/vm/arrays.c +++ b/harbour/source/vm/arrays.c @@ -134,7 +134,6 @@ HB_EXPORT BOOL hb_arrayNew( PHB_ITEM pItem, ULONG ulLen ) /* creates a new array pItem->type = HB_IT_ARRAY; pItem->item.asArray.value = pBaseArray; - pItem->item.asArray.superoffset = 0; return TRUE; } diff --git a/harbour/source/vm/classes.c b/harbour/source/vm/classes.c index 9dcc2c090e..791409eac9 100644 --- a/harbour/source/vm/classes.c +++ b/harbour/source/vm/classes.c @@ -155,18 +155,18 @@ typedef struct { PHB_ITEM pInitValue; /* Init Value for data */ - USHORT uiType; /* HB_OO_MSG_DATA or HB_OO_MSG_CLASSDATA */ + USHORT uiType; /* HB_OO_MSG_DATA, HB_OO_MSG_CLASSDATA or HB_OO_MSG_INITIALIZED */ USHORT uiData; /* Item position in instance area or in class data */ } INITDATA, * PINITDATA; typedef struct { - PHB_DYNS pMessage; /* Method Symbolic name */ + PHB_DYNS pMessage; /* Method symbolic name */ PHB_SYMB pFuncSym; /* Function symbol */ - USHORT uiData; /* Item position for instance data or shared data (Harbour like, begin from 1) or supercast offset (from 0) */ USHORT uiSprClass; /* Originalclass'handel (super or current class'handel if not herited). */ /*Added by RAC&JF*/ USHORT uiScope; /* Scoping value */ - USHORT bClsDataInitiated; /* There is one value assigned at init time */ + USHORT uiData; /* Item position for instance data or shared data (Harbour like, begin from 1) or supercast offset (from 0) */ + USHORT uiInit; /* position in pInitData (from 1) or 0 */ #ifndef HB_NO_PROFILER ULONG ulCalls; /* profiler support */ ULONG ulTime; /* profiler support */ @@ -177,6 +177,7 @@ typedef struct typedef struct { char * szName; /* Class name */ + 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 */ @@ -207,7 +208,9 @@ static HARBOUR hb___msgSetShrData( void ); static HARBOUR hb___msgEvalInline( void ); static HARBOUR hb___msgVirtual( void ); static HARBOUR hb___msgSuper( void ); +static HARBOUR hb___msgRealClass( void ); static HARBOUR hb___msgNoMethod( void ); +static HARBOUR hb___msgScopeErr( void ); static HARBOUR hb___msgNull( void ); static HARBOUR hb___msgClsH( void ); @@ -259,7 +262,9 @@ static HB_SYMB s___msgGetShrData = { "__msgGetShrData", {HB_FS_MESSAGE}, {hb___m static HB_SYMB s___msgEvalInline = { "__msgEvalInline", {HB_FS_MESSAGE}, {hb___msgEvalInline}, NULL }; static HB_SYMB s___msgVirtual = { "__msgVirtual", {HB_FS_MESSAGE}, {hb___msgVirtual}, NULL }; static HB_SYMB s___msgSuper = { "__msgSuper", {HB_FS_MESSAGE}, {hb___msgSuper}, NULL }; +static HB_SYMB s___msgRealClass = { "__RealClass", {HB_FS_MESSAGE}, {hb___msgRealClass}, NULL }; static HB_SYMB s___msgNoMethod = { "__msgNoMethod", {HB_FS_MESSAGE}, {hb___msgNoMethod}, NULL }; +static HB_SYMB s___msgScopeErr = { "__msgScopeErr", {HB_FS_MESSAGE}, {hb___msgScopeErr}, NULL }; static HB_SYMB s___msgClassName = { "CLASSNAME", {HB_FS_MESSAGE}, {hb___msgClsName}, NULL }; static HB_SYMB s___msgClassH = { "CLASSH", {HB_FS_MESSAGE}, {hb___msgClsH}, NULL }; @@ -412,6 +417,57 @@ static PMETHOD hb_clsFindMsg( PCLASS pClass, PHB_DYNS pMsg ) return NULL; } +static void hb_clsCopyClass( PCLASS pClsDst, PCLASS pClsSrc ) +{ + PMETHOD pMethod; + ULONG ulLimit; + + HB_TRACE(HB_TR_DEBUG, ("hb_clsCopyClass(%p,%p)", pClsDst, pClsSrc)); + + hb_clsDictInit( pClsDst, pClsSrc->uiHashKey ); + pClsDst->pFunError = pClsSrc->pFunError; + + /* CLASS DATA Not Shared ( new array, new value ) */ + pClsDst->pClassDatas = hb_arrayClone( pClsSrc->pClassDatas ); + pClsDst->pInlines = hb_arrayClone( pClsSrc->pInlines ); + + if( pClsSrc->uiInitDatas ) + { + USHORT uiData, uiType; + + pClsDst->uiInitDatas = pClsSrc->uiInitDatas; + pClsDst->pInitData = ( PINITDATA ) hb_xgrab( pClsSrc->uiInitDatas * + sizeof( INITDATA ) ); + for( uiData = 0; uiData < pClsSrc->uiInitDatas; ++uiData ) + { + uiType = pClsSrc->pInitData[ uiData ].uiType; + if( uiType == HB_OO_MSG_INITIALIZED ) + uiType = HB_OO_MSG_CLASSDATA; + + pClsDst->pInitData[ uiData ].pInitValue = + hb_itemNew( pClsSrc->pInitData[ uiData ].pInitValue ); + pClsDst->pInitData[ uiData ].uiType = uiType; + pClsDst->pInitData[ uiData ].uiData = + pClsSrc->pInitData[ uiData ].uiData; + } + } + + ulLimit = hb_clsMthNum( pClsDst ); + memcpy( pClsDst->pMethods, pClsSrc->pMethods, ulLimit * sizeof( METHOD ) ); + pClsDst->uiMethods = pClsSrc->uiMethods; + + pMethod = pClsDst->pMethods; + do + { + if( pMethod->pMessage ) + { + pMethod->uiScope |= HB_OO_CLSTP_SUPER; + } + ++pMethod; + } + while( --ulLimit ); +} + static PMETHOD hb_clsAllocMsg( PCLASS pClass, PHB_DYNS pMsg ) { HB_TRACE(HB_TR_DEBUG, ("hb_clsAllocMsg(%p,%p)", pClass, pMsg)); @@ -434,6 +490,16 @@ static PMETHOD hb_clsAllocMsg( PCLASS pClass, PHB_DYNS pMsg ) return NULL; } +static BOOL hb_clsClearMsg( PCLASS pClass, PMETHOD pMethod ) +{ + if( pMethod->pFuncSym == &s___msgEvalInline ) + { /* INLINE method deleted, delete INLINE block */ + hb_itemClear( hb_arrayGetItemPtr( pClass->pInlines, pMethod->uiData ) ); + } + + return TRUE; +} + static void hb_clsFreeMsg( PCLASS pClass, PHB_DYNS pMsg ) { PMETHOD pMethod; @@ -446,21 +512,19 @@ static void hb_clsFreeMsg( PCLASS pClass, PHB_DYNS pMsg ) do { - if( ! pMethod->pMessage || pMethod->pMessage == pMsg ) + if( pMethod->pMessage == pMsg ) { - if( pMethod->pFuncSym == &s___msgEvalInline ) - { /* INLINE method deleted, delete INLINE block */ - hb_itemClear( hb_arrayGetItemPtr( pClass->pInlines, - pMethod->uiData ) ); - } - /* Move messages */ - while( --uiBucket ) + if( hb_clsClearMsg( pClass, pMethod ) ) { - memcpy( pMethod, pMethod + 1, sizeof( METHOD ) ); - pMethod++; + /* Move messages */ + while( --uiBucket ) + { + memcpy( pMethod, pMethod + 1, sizeof( METHOD ) ); + pMethod++; + } + memset( pMethod, 0, sizeof( METHOD ) ); + pClass->uiMethods--; /* Decrease number of messages */ } - memset( pMethod, 0, sizeof( METHOD ) ); - pClass->uiMethods--; /* Decrease number of messages */ return; } ++pMethod; @@ -468,13 +532,15 @@ static void hb_clsFreeMsg( PCLASS pClass, PHB_DYNS pMsg ) while( --uiBucket ); } - -static void hb_clsAddInitValue( PCLASS pClass, PHB_ITEM pItem, - USHORT uiType, USHORT uiData ) +static USHORT hb_clsAddInitValue( PCLASS pClass, PHB_ITEM pItem, + USHORT uiType, USHORT uiData ) { PINITDATA pInitData; - HB_TRACE(HB_TR_DEBUG, ("hb_clsAddInitValue(%p,%p,%hu,%hu)", pClass, pMsg, uiType, uiData)); + HB_TRACE(HB_TR_DEBUG, ("hb_clsAddInitValue(%p,%p,%hu,%hu)", pClass, pItem, uiType, uiData)); + + if( ! pItem || HB_IS_NIL( pItem ) ) + return 0; if( ! pClass->uiInitDatas ) pClass->pInitData = ( PINITDATA ) hb_xgrab( sizeof( INITDATA ) ); @@ -487,6 +553,8 @@ static void hb_clsAddInitValue( PCLASS pClass, PHB_ITEM pItem, pInitData->pInitValue = hb_itemClone( pItem ); pInitData->uiType = uiType; pInitData->uiData = uiData; + + return pClass->uiInitDatas; } /* @@ -802,6 +870,20 @@ char * hb_clsName( USHORT uiClass ) return NULL; } +static BOOL hb_clsHasParent( PCLASS pClass, PHB_DYNS pParentSym ) +{ + PMETHOD pMethod = hb_clsFindMsg( pClass, pParentSym ); + + return pMethod && pMethod->pFuncSym == &s___msgSuper; +} + +static USHORT hb_clsParentInstanceOffset( PCLASS pClass, PHB_DYNS pParentSym ) +{ + PMETHOD pMethod = hb_clsFindMsg( pClass, pParentSym ); + + return ( pMethod && pMethod->pFuncSym == &s___msgSuper ) ? pMethod->uiData : 0; +} + BOOL hb_clsIsParent( USHORT uiClass, char * szParentName ) { if( uiClass && uiClass <= s_uiClasses ) @@ -812,10 +894,10 @@ BOOL hb_clsIsParent( USHORT uiClass, char * szParentName ) return TRUE; else { - PHB_DYNS pMsg = hb_dynsymFindName( pClass->szName ); + PHB_DYNS pMsg = hb_dynsymFindName( szParentName ); - if( hb_clsFindMsg( s_pClasses + uiClass - 1, pMsg ) ) - return TRUE; + if( pMsg ) + return hb_clsHasParent( s_pClasses + ( uiClass - 1 ), pMsg ); } } @@ -935,70 +1017,114 @@ char * hb_objGetRealClsName( PHB_ITEM pObject, char * szName ) return hb_objGetClsName( pObject ); } -static BOOL hb_clsValidScope( PHB_ITEM pObject, PMETHOD pMethod ) +static LONG hb_clsSenderOffset( void ) +{ + LONG lOffset = hb_stackBaseProcOffset( 1 ); + + if( lOffset >=0 ) + { + /* Is it inline method? */ + if( lOffset > 0 && HB_IS_BLOCK( hb_stackItem( lOffset + 1 ) ) && + ( hb_stackItem( lOffset )->item.asSymbol.value == &hb_symEval || + hb_stackItem( lOffset )->item.asSymbol.value->pDynSym == + s___msgEval.pDynSym ) ) + { + lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem; + + /* I do not like it but Class(y) makes sth like that. [druzus] */ + while( lOffset > 0 && + hb_stackItem( lOffset )->item.asSymbol.stackstate->uiClass == 0 ) + lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem; + } + return lOffset; + } + return -1; +} + +#if 0 +static USHORT hb_clsSenderClasss( void ) +{ + LONG lOffset = hb_clsSenderOffset(); + + if( lOffset >=0 ) + return hb_stackItem( lOffset )->item.asSymbol.stackstate->uiClass; + else + return 0; +} +#endif + +static USHORT hb_clsSenderMethodClasss( void ) +{ + LONG lOffset = hb_clsSenderOffset(); + + if( lOffset >=0 ) + { + PHB_STACK_STATE pStack = hb_stackItem( lOffset )->item.asSymbol.stackstate; + + if( pStack->uiClass ) + return ( ( s_pClasses + ( pStack->uiClass - 1 ) )->pMethods + + pStack->uiMethod )->uiSprClass; + } + return 0; +} + +static USHORT hb_clsSenderObjectClasss( void ) +{ + LONG lOffset = hb_clsSenderOffset(); + + if( lOffset >=0 ) + { + PHB_ITEM pSender = hb_stackItem( lOffset + 1 ); + + if( pSender->type == HB_IT_ARRAY ) + return pSender->item.asArray.value->uiClass; + } + return 0; +} + +static PHB_SYMB hb_clsValidScope( PHB_ITEM pObject, PMETHOD pMethod ) { - char szProcName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ]; USHORT uiScope = pMethod->uiScope; if( uiScope & ( HB_OO_CLSTP_HIDDEN | HB_OO_CLSTP_PROTECTED ) ) { - LONG lOffset = hb_stackBaseProcOffset( 1 ); + USHORT uiSenderClass = hb_clsSenderMethodClasss(); - if( lOffset >=0 ) + if( uiSenderClass ) { - /* Is it inline method? */ - if( lOffset > 0 && HB_IS_BLOCK( hb_stackItem( lOffset + 1 ) ) && - ( hb_stackItem( lOffset )->item.asSymbol.value == &hb_symEval || - hb_stackItem( lOffset )->item.asSymbol.value->pDynSym == - s___msgEval.pDynSym ) ) - { - lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem; - - /* I do not like it but Class(y) makes sth like that. [druzus] */ - while( lOffset > 0 && - hb_stackItem( lOffset )->item.asSymbol.stackstate->uiClass == 0 ) - lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem; - } - if( uiScope & HB_OO_CLSTP_HIDDEN ) { /* Class(y) does not allow to write to HIDDEN+READONLY instance variables, [druzus] */ if( ( uiScope & HB_OO_CLSTP_READONLY ) == 0 ) { - PHB_STACK_STATE pStack = hb_stackItem( lOffset )->item.asSymbol.stackstate; - - if( pStack->uiClass && - ( ( s_pClasses + ( pStack->uiClass - 1 ) )->pMethods + - pStack->uiMethod )->uiSprClass == pMethod->uiSprClass ) - return TRUE; + if( uiSenderClass == pMethod->uiSprClass ) + return pMethod->pFuncSym; } } else { - PHB_ITEM pSender = hb_stackItem( lOffset + 1 ); - - if( pSender->type == HB_IT_ARRAY && - pSender->item.asArray.value->uiClass == - pObject->item.asArray.value->uiClass ) - return TRUE; +#ifdef HB_STATIC_PROTECT_SCOPE + if( uiSenderClass == pMethod->uiSprClass || + hb_clsHasParent( s_pClasses + ( uiSenderClass - 1 ), + ( s_pClasses + ( pMethod->uiSprClass - 1 ) )->pClassSym ) ) +#elif HB_CASTED_PROTECT_SCOPE + if( uiSenderClass == pMethod->uiSprClass || + hb_clsHasParent( s_pClasses + ( hb_clsSenderClasss() - 1 ), + ( s_pClasses + ( pMethod->uiSprClass - 1 ) )->pClassSym ) ) +#else + if( uiSenderClass == pMethod->uiSprClass || + hb_clsHasParent( s_pClasses + ( pObject->item.asArray.value->uiClass - 1 ), + ( s_pClasses + ( pMethod->uiSprClass - 1 ) )->pClassSym ) ) +#endif + return pMethod->pFuncSym; } } - strcpy( szProcName, ( s_pClasses + - ( pObject->item.asArray.value->uiClass - 1 ) )->szName ); - strcat( szProcName, ":" ); - strcat( szProcName, pMethod->pMessage->pSymbol->szName ); - - if( uiScope & HB_OO_CLSTP_HIDDEN ) - hb_errRT_BASE( EG_NOMETHOD, 41, "Scope violation (hidden)", szProcName, 0 ); - else - hb_errRT_BASE( EG_NOMETHOD, 42, "Scope violation (protected)", szProcName, 0 ); - - return FALSE; + return &s___msgScopeErr; } - return TRUE; + return pMethod->pFuncSym; } /* @@ -1027,15 +1153,11 @@ PHB_SYMB hb_objGetMethod( PHB_ITEM pObject, PHB_SYMB pMessage, PHB_STACK_STATE p PHB_ITEM pRealObj; pRealObj = hb_itemNew( pObject->item.asArray.value->pItems ); - pRealObj->item.asArray.superoffset = pObject->item.asArray.superoffset; - /* Now I should exchnage it with the current stacked value */ hb_itemMove( pObject, pRealObj ); /* and release the fake one */ hb_itemRelease( pRealObj ); } - else - pObject->item.asArray.superoffset = 0; } if( uiClass && uiClass <= s_uiClasses ) @@ -1049,8 +1171,7 @@ PHB_SYMB hb_objGetMethod( PHB_ITEM pObject, PHB_SYMB pMessage, PHB_STACK_STATE p if( pStack ) { pStack->uiMethod = pMethod - pClass->pMethods; - if( ! hb_clsValidScope( pObject, pMethod ) ) - return &s___msgVirtual; + return hb_clsValidScope( pObject, pMethod ); } return pMethod->pFuncSym; } @@ -1210,10 +1331,7 @@ BOOL hb_objOperatorCall( USHORT uiOperator, HB_ITEM_PTR pResult, PHB_ITEM pObjec { hb_vmPushSymbol( s_opSymbols + uiOperator ); hb_vmPush( pObject ); - if( HB_IS_COMPLEX( hb_stackReturnItem() ) ) - hb_itemClear( hb_stackReturnItem() ); - else - hb_stackReturnItem()->type = HB_IT_NIL; + hb_itemSetNil( hb_stackReturnItem() ); if( pMsgArg1 ) { hb_vmPush( pMsgArg1 ); @@ -1395,6 +1513,14 @@ static PHB_DYNS hb_objMsgParam( int iParam ) return pDynSym; } +static void hb_clsSetInlineClass( PCLASS pClass, USHORT uiIndex, + USHORT uiClass ) +{ + PHB_ITEM pBlock = hb_arrayGetItemPtr( pClass->pInlines, uiIndex ); + + pBlock->item.asBlock.hclass = uiClass; +} + static USHORT hb_clsUpdateScope( USHORT uiScope, BOOL fAssign ) { if( uiScope & HB_OO_CLSTP_READONLY ) @@ -1421,10 +1547,15 @@ static USHORT hb_clsUpdateScope( USHORT uiScope, BOOL fAssign ) * Class handle * Message * HB_OO_MSG_METHOD : Pointer to function - * HB_OO_MSG_DATA : Index number in array - * HB_OO_MSG_CLASSDATA : Index number in array + * HB_OO_MSG_DATA : \ + * HB_OO_MSG_ASSIGN : > Index to instance area array + * HB_OO_MSG_ACCESS : / + * HB_OO_MSG_CLASSDATA : \ + * HB_OO_MSG_CLSASSIGN : > Index class data array + * HB_OO_MSG_CLSACCESS : / * HB_OO_MSG_INLINE : Code block * HB_OO_MSG_SUPER : Handle of super class + * HB_OO_MSG_REALCLASS : Handle of real method class * * see HB_OO_MSG_* * @@ -1533,6 +1664,8 @@ HB_FUNC( __CLSADDMSG ) } } + fAssign = pMessage->pSymbol->szName[ 0 ] == '_'; + /* basic parameter validation */ switch( nType ) { @@ -1551,19 +1684,30 @@ HB_FUNC( __CLSADDMSG ) uiIndex = ( USHORT ) hb_parni( 3 ); uiSprClass = ( USHORT ) hb_parni( 5 ); fOK = uiSprClass && uiSprClass <= s_uiClasses && - (uiIndex == 0 || uiIndex < pClass->uiDatas); + uiIndex <= pClass->uiDatas; + break; + + case HB_OO_MSG_REALCLASS: + uiIndex = ( USHORT ) hb_parni( 3 ); + fOK = TRUE; break; case HB_OO_MSG_DATA: + nType = fAssign ? HB_OO_MSG_ASSIGN : HB_OO_MSG_ACCESS; /* This validation can break buggy .prg code which wrongly * sets data offsets but IMHO it will help to clean the code. * [druzus] */ + case HB_OO_MSG_ASSIGN: + case HB_OO_MSG_ACCESS: uiIndex = ( USHORT ) hb_parni( 3 ); fOK = uiIndex && uiIndex <= pClass->uiDatas; break; case HB_OO_MSG_CLASSDATA: + nType = fAssign ? HB_OO_MSG_CLSASSIGN : HB_OO_MSG_CLSACCESS; + case HB_OO_MSG_CLSASSIGN: + case HB_OO_MSG_CLSACCESS: uiIndex = ( USHORT ) hb_parni( 3 ); fOK = uiIndex != 0; break; @@ -1587,28 +1731,13 @@ HB_FUNC( __CLSADDMSG ) return; if( ! pNewMeth->pMessage ) - { - pNewMeth->pMessage = pMessage; pClass->uiMethods++; /* One more message */ - } + else if( ! hb_clsClearMsg( pClass, pNewMeth ) ) + return; else - { - if( pNewMeth->pFuncSym == &s___msgEvalInline ) - { /* INLINE method deleted, delete INLINE block */ - hb_itemClear( hb_arrayGetItemPtr( pClass->pInlines, - pNewMeth->uiData ) ); - } - pNewMeth->pFuncSym = NULL; - } - + memset( pNewMeth, 0, sizeof( METHOD ) ); + pNewMeth->pMessage = pMessage; pNewMeth->uiSprClass = uiClass ; /* now used !! */ -#ifndef HB_NO_PROFILER - pNewMeth->ulCalls = 0; - pNewMeth->ulTime = 0; - pNewMeth->ulRecurse = 0; -#endif - - fAssign = pMessage->pSymbol->szName[ 0 ] == '_'; switch( nType ) { @@ -1616,68 +1745,65 @@ HB_FUNC( __CLSADDMSG ) pNewMeth->pFuncSym = pFuncSym; pNewMeth->uiScope = uiScope; - pNewMeth->uiData = 0; break; - case HB_OO_MSG_DATA: + case HB_OO_MSG_ASSIGN: pNewMeth->uiData = uiIndex; pNewMeth->uiScope = hb_clsUpdateScope( uiScope, fAssign ); - if( fAssign ) - pNewMeth->pFuncSym = &s___msgSetData; - else - { - PHB_ITEM pInit = hb_param( 5, HB_IT_ANY ); - - if( pInit && ! HB_IS_NIL( pInit ) ) /* Initializer found */ - hb_clsAddInitValue( pClass, pInit, HB_OO_MSG_DATA, - pNewMeth->uiData ); - pNewMeth->pFuncSym = &s___msgGetData; - } + pNewMeth->pFuncSym = &s___msgSetData; break; - case HB_OO_MSG_CLASSDATA: + case HB_OO_MSG_ACCESS: + + pNewMeth->uiData = uiIndex; + pNewMeth->uiScope = hb_clsUpdateScope( uiScope, fAssign ); + pNewMeth->pFuncSym = &s___msgGetData; + pNewMeth->uiInit = hb_clsAddInitValue( pClass, + hb_param( 5, HB_IT_ANY ), HB_OO_MSG_DATA, pNewMeth->uiData ); + break; + + case HB_OO_MSG_CLSASSIGN: pNewMeth->uiData = uiIndex; pNewMeth->uiScope = hb_clsUpdateScope( uiScope, fAssign ); if( hb_arrayLen( pClass->pClassDatas ) < ( ULONG ) pNewMeth->uiData ) hb_arraySize( pClass->pClassDatas, pNewMeth->uiData ); + if( pNewMeth->uiScope & HB_OO_CLSTP_SHARED ) + pNewMeth->pFuncSym = &s___msgSetShrData; + else + pNewMeth->pFuncSym = &s___msgSetClsData; + break; + case HB_OO_MSG_CLSACCESS: + + pNewMeth->uiData = uiIndex; + pNewMeth->uiScope = hb_clsUpdateScope( uiScope, fAssign ); + if( hb_arrayLen( pClass->pClassDatas ) < ( ULONG ) pNewMeth->uiData ) + hb_arraySize( pClass->pClassDatas, pNewMeth->uiData ); if( pNewMeth->uiScope & HB_OO_CLSTP_SHARED ) { - if( fAssign ) - pNewMeth->pFuncSym = &s___msgSetShrData; - else - { - PHB_ITEM pInit = hb_param( 5, HB_IT_ANY ); + PHB_ITEM pInit = hb_param( 5, HB_IT_ANY ); - if( pInit && ! HB_IS_NIL( pInit ) ) /* Initializer found */ - { - /* Shared Classdata need to be initialized only once - * ACCESS/ASSIGN methods will be inherited by subclasses - * and will operate on this value so it's not necessary - * to keep the init value. [druzus] - */ - pInit = hb_itemClone( pInit ); - hb_arraySet( pClass->pClassDatas, pNewMeth->uiData, pInit ); - hb_itemRelease( pInit ); - } - pNewMeth->pFuncSym = &s___msgGetShrData; + if( pInit && ! HB_IS_NIL( pInit ) ) /* Initializer found */ + { + /* Shared Classdata need to be initialized only once + * ACCESS/ASSIGN methods will be inherited by subclasses + * and will operate on this value so it's not necessary + * to keep the init value. [druzus] + */ + pInit = hb_itemClone( pInit ); + hb_arraySet( pClass->pClassDatas, pNewMeth->uiData, pInit ); + hb_itemRelease( pInit ); } + pNewMeth->pFuncSym = &s___msgGetShrData; } else { - if( fAssign ) - pNewMeth->pFuncSym = &s___msgSetClsData; - else - { - PHB_ITEM pInit = hb_param( 5, HB_IT_ANY ); - - if( pInit && ! HB_IS_NIL( pInit ) ) /* Initializer found */ - hb_clsAddInitValue( pClass, pInit, HB_OO_MSG_CLASSDATA, - pNewMeth->uiData ); - pNewMeth->pFuncSym = &s___msgGetClsData; - } + pNewMeth->uiInit = hb_clsAddInitValue( pClass, + hb_param( 5, HB_IT_ANY ), HB_OO_MSG_CLASSDATA, + pNewMeth->uiData ); + pNewMeth->pFuncSym = &s___msgGetClsData; } break; @@ -1687,6 +1813,7 @@ HB_FUNC( __CLSADDMSG ) pNewMeth->uiScope = uiScope; hb_arraySize( pClass->pInlines, pNewMeth->uiData ); hb_arraySet( pClass->pInlines, pNewMeth->uiData, pBlock ); + hb_clsSetInlineClass( pClass, pNewMeth->uiData, uiClass ); pNewMeth->pFuncSym = &s___msgEvalInline; break; @@ -1704,6 +1831,12 @@ HB_FUNC( __CLSADDMSG ) pNewMeth->pFuncSym = &s___msgSuper; break; + case HB_OO_MSG_REALCLASS: + pNewMeth->uiData = uiIndex; /* offset to instance area */ + pNewMeth->uiScope = uiScope; + pNewMeth->pFuncSym = &s___msgRealClass; + break; + case HB_OO_MSG_ONERROR: pClass->pFunError = pFuncSym; @@ -1736,7 +1869,6 @@ HB_FUNC( __CLSNEW ) PCLASS pNewCls; PHB_ITEM pahSuper; USHORT ui, uiSuper, uiSuperCls; - USHORT nLenClsDatas = 0, nLenInlines = 0; pahSuper = hb_param( 3, HB_IT_ARRAY ); uiSuper = ( USHORT ) ( pahSuper ? hb_arrayLen( pahSuper ) : 0 ); @@ -1749,33 +1881,30 @@ HB_FUNC( __CLSNEW ) pNewCls = s_pClasses + s_uiClasses++; memset( pNewCls, 0, sizeof( CLASS ) ); pNewCls->szName = hb_strdup( hb_parc( 1 ) ); + pNewCls->pClassSym = hb_dynsymGet( pNewCls->szName ); for( ui = 1; ui <= uiSuper; ++ui ) { uiSuperCls = ( USHORT ) hb_arrayGetNI( pahSuper, ui ); if( uiSuperCls && uiSuperCls <= s_uiClasses ) { - PHB_DYNS pMsg; - PHB_ITEM pClsAnyTmp; PCLASS pSprCls; - ULONG ul, ulLimit, ulLen; pSprCls = s_pClasses + ( uiSuperCls - 1 ); - ulLimit = hb_clsMthNum( pSprCls ); if( !pNewCls->pMethods ) /* This is the first superclass */ { - hb_clsDictInit( pNewCls, pSprCls->uiHashKey ); - pNewCls->pFunError = pSprCls->pFunError; - - /* CLASS DATA Not Shared ( new array, new value ) */ - pNewCls->pClassDatas = hb_arrayClone( pSprCls->pClassDatas ); - pNewCls->pInlines = hb_arrayClone( pSprCls->pInlines ); + hb_clsCopyClass( pNewCls, pSprCls ); } else { + PHB_DYNS pMsg; + PHB_ITEM pClsAnyTmp; + ULONG ul, ulLimit, ulLen; + USHORT nLenClsDatas; + + ulLimit = hb_clsMthNum( pSprCls ); /* Ok add now the previous len to the offset */ nLenClsDatas = ( USHORT ) hb_itemSize( pNewCls->pClassDatas ); - nLenInlines = ( USHORT ) hb_itemSize( pNewCls->pInlines ); /* ClassDatas */ ulLen = hb_itemSize( pSprCls->pClassDatas ); @@ -1792,85 +1921,75 @@ HB_FUNC( __CLSNEW ) hb_itemRelease( pClsAnyTmp ); } - /* Copy Inline codeblocks */ - ulLen = hb_arrayLen( pSprCls->pInlines ); - if( ulLen ) + /* Copy init datas */ + if( pSprCls->uiInitDatas ) { - hb_arraySize( pNewCls->pInlines, nLenInlines + ulLen ); - for( ul = 1; ul <= ulLen; ul++ ) - { - hb_itemCopy( hb_arrayGetItemPtr( pNewCls->pInlines, - nLenInlines + ul ), - hb_arrayGetItemPtr( pSprCls->pInlines, ul ) ); - } - } - } + USHORT uiData, uiStart = pNewCls->uiInitDatas, uiType; - if( pSprCls->uiInitDatas ) - { - USHORT uiData, uiStart = pNewCls->uiInitDatas, uiType; - - pNewCls->uiInitDatas += pSprCls->uiInitDatas; - if( ! uiStart ) - pNewCls->pInitData = ( PINITDATA ) + pNewCls->uiInitDatas += pSprCls->uiInitDatas; + if( ! uiStart ) + pNewCls->pInitData = ( PINITDATA ) hb_xgrab( pNewCls->uiInitDatas * sizeof( INITDATA ) ); - else - pNewCls->pInitData = ( PINITDATA ) hb_xrealloc( pNewCls->pInitData, + else + pNewCls->pInitData = ( PINITDATA ) hb_xrealloc( pNewCls->pInitData, pNewCls->uiInitDatas * sizeof( INITDATA ) ); - for( uiData = 0; uiData < pSprCls->uiInitDatas; ++uiData ) - { - uiType = pSprCls->pInitData[ uiData ].uiType; - if( uiType == HB_OO_MSG_INITIALIZED ) - uiType = HB_OO_MSG_CLASSDATA; - - pNewCls->pInitData[ uiData + uiStart ].pInitValue = - hb_itemNew( pSprCls->pInitData[ uiData ].pInitValue ); - pNewCls->pInitData[ uiData + uiStart ].uiType = uiType; - pNewCls->pInitData[ uiData + uiStart ].uiData = - pSprCls->pInitData[ uiData ].uiData + - ( uiType == HB_OO_MSG_CLASSDATA ? nLenClsDatas : - ( uiType == HB_OO_MSG_DATA ? pNewCls->uiDatas : 0 ) ); - } - } - - /* Now working on pMethods */ - for( ul = 0; ul < ulLimit; ul++ ) - { - pMsg = ( PHB_DYNS ) pSprCls->pMethods[ ul ].pMessage; - - if( pMsg ) - { - PMETHOD pMethod = hb_clsAllocMsg( pNewCls, pMsg ); - - if( ! pMethod ) - return; - - /* Ok, this bucket is empty */ - if( pMethod->pMessage == NULL ) + for( uiData = 0; uiData < pSprCls->uiInitDatas; ++uiData ) { - /* Now, we can increment the msg count */ - pNewCls->uiMethods++; + uiType = pSprCls->pInitData[ uiData ].uiType; + if( uiType == HB_OO_MSG_INITIALIZED ) + uiType = HB_OO_MSG_CLASSDATA; - memcpy( pMethod, pSprCls->pMethods + ul, sizeof( METHOD ) ); + pNewCls->pInitData[ uiData + uiStart ].pInitValue = + hb_itemNew( pSprCls->pInitData[ uiData ].pInitValue ); + pNewCls->pInitData[ uiData + uiStart ].uiType = uiType; + pNewCls->pInitData[ uiData + uiStart ].uiData = + pSprCls->pInitData[ uiData ].uiData + + ( uiType == HB_OO_MSG_CLASSDATA ? nLenClsDatas : + ( uiType == HB_OO_MSG_DATA ? pNewCls->uiDatas : 0 ) ); + } + } - if( pMethod->pFuncSym == &s___msgEvalInline ) - { - pMethod->uiData += nLenInlines; - } - else if( pMethod->pFuncSym == &s___msgSetClsData || - pMethod->pFuncSym == &s___msgGetClsData ) - { - pMethod->uiData += nLenClsDatas; - } - else if( pMethod->pFuncSym == &s___msgSetData || - pMethod->pFuncSym == &s___msgGetData || - pMethod->pFuncSym == &s___msgSuper ) - { - pMethod->uiData += pNewCls->uiDatas; - } + /* Now working on pMethods */ + for( ul = 0; ul < ulLimit; ul++ ) + { + pMsg = ( PHB_DYNS ) pSprCls->pMethods[ ul ].pMessage; - pMethod->uiScope = pSprCls->pMethods[ ul ].uiScope | HB_OO_CLSTP_SUPER; + if( pMsg ) + { + PMETHOD pMethod = hb_clsAllocMsg( pNewCls, pMsg ); + + if( ! pMethod ) + return; + + /* Ok, this bucket is empty */ + if( pMethod->pMessage == NULL ) + { + /* Now, we can increment the msg count */ + pNewCls->uiMethods++; + memcpy( pMethod, pSprCls->pMethods + ul, sizeof( METHOD ) ); + + if( pMethod->pFuncSym == &s___msgEvalInline ) + { + hb_arrayAdd( pNewCls->pInlines, + hb_arrayGetItemPtr( pSprCls->pInlines, pMethod->uiData ) ); + pMethod->uiData = ( USHORT ) hb_arrayLen( pNewCls->pInlines ); + } + else if( pMethod->pFuncSym == &s___msgSetClsData || + pMethod->pFuncSym == &s___msgGetClsData ) + { + pMethod->uiData += nLenClsDatas; + } + else if( pMethod->pFuncSym == &s___msgSetData || + pMethod->pFuncSym == &s___msgGetData || + pMethod->pFuncSym == &s___msgSuper || + pMethod->pFuncSym == &s___msgRealClass ) + { + pMethod->uiData += pNewCls->uiDatas; + } + + pMethod->uiScope |= HB_OO_CLSTP_SUPER; + } } } } @@ -2019,7 +2138,10 @@ HB_FUNC( __CLSMODMSG ) if( pBlock == NULL ) hb_errRT_BASE( EG_ARG, 3000, "Cannot modify INLINE method", "__CLSMODMSG", 0 ); else + { hb_arraySet( pClass->pInlines, pMethod->uiData, pBlock ); + hb_clsSetInlineClass( pClass, pMethod->uiData, uiClass ); + } } else /* Modify METHOD */ { @@ -2128,7 +2250,7 @@ HB_FUNC( __OBJCLONE ) HB_FUNC( __CLSINSTSUPER ) { char * szString = hb_parc( 1 ); - BOOL bFound = FALSE; + USHORT uiClassH = 0; if( szString && *szString ) { @@ -2136,27 +2258,31 @@ HB_FUNC( __CLSINSTSUPER ) if( pDynSym ) /* Find function */ { - USHORT uiClass; + USHORT uiClass = 0; + + /* TODO: optimize this function */ hb_vmPushSymbol( pDynSym->pSymbol ); /* Push function name */ hb_vmPushNil(); hb_vmFunction( 0 ); /* Execute super class */ - /* TODO: optimize this function */ - if( HB_IS_OBJECT( hb_stackReturnItem() ) ) + if( hb_vmRequestQuery() == 0 ) { - for( uiClass = 0; ! bFound && uiClass < s_uiClasses; uiClass++ ) - { /* Locate the entry */ - if( hb_stricmp( szString , s_pClasses[ uiClass ].szName ) == 0 ) - { - hb_retni( uiClass + 1 ); /* Entry + 1 = hb___msgClsH */ - bFound = TRUE; + if( HB_IS_OBJECT( hb_stackReturnItem() ) ) + { + for( uiClass = 0; uiClass < s_uiClasses; uiClass++ ) + { /* Locate the entry */ + if( s_pClasses[ uiClass ].pClassSym == pDynSym ) + { + uiClassH = uiClass + 1; /* Entry + 1 = hb___msgClsH */ + break; + } } } - } - else - { - hb_errRT_BASE( EG_ARG, 3002, "Super class does not return an object", "__CLSINSTSUPER", 0 ); + else + { + hb_errRT_BASE( EG_ARG, 3002, "Super class does not return an object", "__CLSINSTSUPER", 0 ); + } } } else @@ -2165,10 +2291,7 @@ HB_FUNC( __CLSINSTSUPER ) } } - if( ! bFound ) - { - hb_retni( 0 ); - } + hb_retni( uiClassH ); } /* @@ -2577,6 +2700,30 @@ static HARBOUR hb___msgNoMethod( void ) #endif } +/* + * __msgScopeErr() + * + * Internal function for generating error when not existing message is sent + */ +static HARBOUR hb___msgScopeErr( void ) +{ + char szProcName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ]; + PHB_ITEM pObject = hb_stackSelfItem(); + PMETHOD pMethod = ( s_pClasses + + hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1 )->pMethods + + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; + + strcpy( szProcName, ( s_pClasses + + ( pObject->item.asArray.value->uiClass - 1 ) )->szName ); + strcat( szProcName, ":" ); + strcat( szProcName, pMethod->pMessage->pSymbol->szName ); + + if( pMethod->uiScope & HB_OO_CLSTP_HIDDEN ) + hb_errRT_BASE( EG_NOMETHOD, 41, "Scope violation (hidden)", szProcName, 0 ); + else + hb_errRT_BASE( EG_NOMETHOD, 42, "Scope violation (protected)", szProcName, 0 ); +} + /* * __msgSuper() * @@ -2598,11 +2745,42 @@ static HARBOUR hb___msgSuper( void ) pCopy->item.asArray.value->uiPrevCls = pObject->item.asArray.value->uiClass; /* superclass handel casting */ pCopy->item.asArray.value->uiClass = pMethod->uiSprClass; - pCopy->item.asArray.superoffset = pMethod->uiData; hb_itemRelease( hb_itemReturn( pCopy ) ); } +/* + * __msgRealClass() + * + * Internal function to return a superobject of class where the method was + * defined + */ +static HARBOUR hb___msgRealClass( void ) +{ + PHB_ITEM pObject = hb_stackSelfItem(); + USHORT uiClass = hb_clsSenderMethodClasss(); + + if( uiClass && + hb_clsSenderObjectClasss() == pObject->item.asArray.value->uiClass ) + { + PHB_ITEM pCopy = hb_itemArrayNew(1); + + /* Now save the Self object as the 1st elem. */ + hb_arraySet( pCopy, 1, pObject ); + + /* And transform it into a fake object */ + /* backup of actual handel */ + pCopy->item.asArray.value->uiPrevCls = pObject->item.asArray.value->uiClass; + /* superclass handel casting */ + pCopy->item.asArray.value->uiClass = uiClass; + hb_itemRelease( hb_itemReturn( pCopy ) ); + } + else + { + hb_itemReturn( pObject ); + } +} + /* * __msgGetClsData() * @@ -2687,12 +2865,19 @@ static HARBOUR hb___msgSetShrData( void ) */ static HARBOUR hb___msgGetData( void ) { - PHB_ITEM pObject = hb_stackSelfItem(); - PCLASS pClass = s_pClasses + - hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1; - PMETHOD pMethod = pClass->pMethods + - hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; - ULONG ulIndex = pMethod->uiData + pObject->item.asArray.superoffset; + 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 - 1 ); + PMETHOD pMethod = pClass->pMethods + + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; + ULONG ulIndex = pMethod->uiData; + + if( uiClass != pObject->item.asArray.value->uiClass ) + { + ulIndex += hb_clsParentInstanceOffset( s_pClasses + ( uiObjClass - 1 ), + pClass->pClassSym ); + } /* will arise only if the class has been modified after first instance */ if( ulIndex > hb_arrayLen( pObject ) ) /* Resize needed */ @@ -2708,13 +2893,20 @@ static HARBOUR hb___msgGetData( void ) */ static HARBOUR hb___msgSetData( void ) { - PHB_ITEM pReturn = hb_stackItemFromBase( 1 ); - PHB_ITEM pObject = hb_stackSelfItem(); - PCLASS pClass = s_pClasses + - hb_stackBaseItem()->item.asSymbol.stackstate->uiClass - 1; - PMETHOD pMethod = pClass->pMethods + - hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; - ULONG ulIndex = pMethod->uiData + pObject->item.asArray.superoffset; + PHB_ITEM pReturn = hb_stackItemFromBase( 1 ); + 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 - 1 ); + PMETHOD pMethod = pClass->pMethods + + hb_stackBaseItem()->item.asSymbol.stackstate->uiMethod; + ULONG ulIndex = pMethod->uiData; + + if( uiClass != pObject->item.asArray.value->uiClass ) + { + ulIndex += hb_clsParentInstanceOffset( s_pClasses + ( uiObjClass - 1 ), + pClass->pClassSym ); + } /* will arise only if the class has been modified after first instance */ if( ulIndex > hb_arrayLen( pObject ) ) /* Resize needed ? */ diff --git a/harbour/source/vm/codebloc.c b/harbour/source/vm/codebloc.c index db5cac6bb5..56f9d2b198 100644 --- a/harbour/source/vm/codebloc.c +++ b/harbour/source/vm/codebloc.c @@ -210,6 +210,7 @@ HB_CODEBLOCK_PTR hb_codeblockNew( const BYTE * pBuffer, pCBlock->dynBuffer = usLen != 0; pCBlock->pDefSymb = hb_stackBaseItem()->item.asSymbol.value; pCBlock->pSymbols = pSymbols; + pCBlock->lStatics = hb_stackGetStaticsBase(); pCBlock->uiLocals = uiLocals; pCBlock->pLocals = pLocals; @@ -240,12 +241,13 @@ HB_CODEBLOCK_PTR hb_codeblockMacroNew( BYTE * pBuffer, USHORT usLen ) pCBlock = ( HB_CODEBLOCK_PTR ) hb_gcAlloc( sizeof( HB_CODEBLOCK ), hb_codeblockDeleteGarbage ); /* Store the number of referenced local variables */ - pCBlock->uiLocals = 0; - pCBlock->pLocals = NULL; pCBlock->pCode = pCode; pCBlock->dynBuffer = TRUE; pCBlock->pDefSymb = hb_stackBaseItem()->item.asSymbol.value; pCBlock->pSymbols = NULL; /* macro-compiled codeblock cannot acces a local symbol table */ + pCBlock->lStatics = hb_stackGetStaticsBase(); + pCBlock->uiLocals = 0; + pCBlock->pLocals = NULL; HB_TRACE(HB_TR_INFO, ("codeblock created %p", pCBlock)); @@ -262,7 +264,7 @@ void hb_codeblockEvaluate( HB_ITEM_PTR pItem ) { HB_TRACE(HB_TR_DEBUG, ("hb_codeblockEvaluate(%p)", pItem)); - hb_stackSetStaticsBase( pItem->item.asBlock.statics ); + hb_stackSetStaticsBase( pItem->item.asBlock.value->lStatics ); hb_vmExecute( pItem->item.asBlock.value->pCode, pItem->item.asBlock.value->pSymbols ); } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index da69bf9e3c..637cbf016d 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -4633,16 +4633,13 @@ static void hb_vmPushBlock( const BYTE * pCode, PHB_SYMB pSymbols, USHORT usLen usLen ); pItem->type = HB_IT_BLOCK; - - /* store the statics base of function where the codeblock was defined - */ - pItem->item.asBlock.statics = hb_stackGetStaticsBase(); /* store the number of expected parameters */ pItem->item.asBlock.paramcnt = HB_PCODE_MKUSHORT( pCode ); /* store the line number where the codeblock was defined */ pItem->item.asBlock.lineno = hb_stackBaseItem()->item.asSymbol.lineno; + pItem->item.asBlock.hclass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; } /* -2 -> HB_P_PUSHBLOCKSHORT @@ -4666,15 +4663,13 @@ static void hb_vmPushBlockShort( const BYTE * pCode, PHB_SYMB pSymbols, USHORT u pItem->type = HB_IT_BLOCK; - /* store the statics base of function where the codeblock was defined - */ - pItem->item.asBlock.statics = hb_stackGetStaticsBase(); /* store the number of expected parameters */ pItem->item.asBlock.paramcnt = 0; /* store the line number where the codeblock was defined */ pItem->item.asBlock.lineno = hb_stackBaseItem()->item.asSymbol.lineno; + pItem->item.asBlock.hclass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; } /* +0 -> HB_P_MPUSHBLOCK @@ -4696,15 +4691,13 @@ static void hb_vmPushMacroBlock( BYTE * pCode, PHB_SYMB pSymbols ) pItem->type = HB_IT_BLOCK; - /* store the statics base of function where the codeblock was defined - */ - pItem->item.asBlock.statics = hb_stackGetStaticsBase(); /* store the number of expected parameters */ pItem->item.asBlock.paramcnt = HB_PCODE_MKUSHORT( &( pCode[ 3 ] ) ); /* store the line number where the codeblock was defined */ pItem->item.asBlock.lineno = hb_stackBaseItem()->item.asSymbol.lineno; + pItem->item.asBlock.hclass = hb_stackBaseItem()->item.asSymbol.stackstate->uiClass; } /* pushes current workarea number on the eval stack @@ -5612,7 +5605,7 @@ HB_EXPORT PHB_SYMB hb_vmProcessSymbolsEx( PHB_SYMB pSymbols, USHORT uiModuleSymb char * szModuleName, ULONG ulID, USHORT uiPCodeVer ) { - HB_TRACE(HB_TR_DEBUG, ("hb_vmProcessSymbolsEx(%p,%hu,%s,%lu,%hu)", pSymbols, uiModuleSymbols, szModuleName, ulID, uiPcodeVer)); + HB_TRACE(HB_TR_DEBUG, ("hb_vmProcessSymbolsEx(%p,%hu,%s,%lu,%hu)", pSymbols, uiModuleSymbols, szModuleName, ulID, uiPCodeVer)); if( uiPCodeVer != 0 ) {