harbour / core

Portable, xBase compatible programming language and environment
https://harbour.github.io/
Other
319 stars 207 forks source link

Hbclass Metaclass directive #211

Open Hovestar opened 4 years ago

Hovestar commented 4 years ago

In hbclass.ch (https://github.com/harbour/core/blob/master/include/hbclass.ch) currrently metaclasses are defined like so: oClass := iif( <.metaClass.>, <(metaClass)>, HBClass():new( ... ) ) ;; This means that upon preprocessing a normal class gets turned into something like this:

class test metaclass meta

to ...;s_oClass := IIF(.T., "meta", HBClass():New( "test" , { HBObject():Classh } ) ); instead of the (I think expected) ...;s_oClass := IIF(.T., meta(), HBClass()):New( "test" , { HBObject():Classh } ) ;

I believe that the correct directive is this (just moving+adding a paren and removing the smart stringify): oClass := iif( <.metaClass.>, <metaClass>(), HBClass()):new( ... ) ;;

Otherwise the only runtime correct way to use meta classes it to specify classes like so:

class test metaclass (meta():New( "test" , { HBObject():Classh } ))

and it ignores all super classes that you specify unless you manually add them to the array with HBObject.

That all said, the use of metaclasses is extremely rare (likely non existent considering this) and this change may break backwards compatibility in a way where issues only manifest at runtime.

Hovestar commented 2 years ago

Just following up on this since it piqued my interest again, the fix I had listed causes an issue since if the meta class is undefined there's a () embedded in the code that's invalid, a proper fix is this:

oClass := iif( <.metaClass.>, <metaClass>(nil), HBClass()):new( <(ClassName)>, __HB_CLS_PAR( [ @<SuperClass1>() ] [ , @<SuperClassN>() ] ), @__HB_CLS_OPT([__HB_CLS_ASID(<FuncName>),] <ClassName>)() [, <.modulfriend.> ] ) ;;