=head1 MOH Integration plan The integration of MOH with Pugs's current runtime needs to be done in a lockstep fashion: =head2 Calling Convention -- Accomodating for both oldland and newland callconvs: instance Arguments [Val] instance Arguments Capture -- Augment the Arguments API to introduce: withInvocant :: a -> Object -> a getInvocant :: a -> Maybe Object We can reuse the MI Class as the canonical Pugs class, but the C3 linearize as well as the actual call (i.e. ivDispatch) needs to be lifted into the Eval monad. However, metaobjects stays utterly functional. =head2 Instance Layout class C { has $.x } my $fido = C.new; # augmentation eval "class C is also { has $.y is rw }"; $fido.y = 123; class C { has $.x is Int; has $.y is Int } (Integer, Integer) # PDL structures class C { has $.x is int8; has $.y is int16 } # Equiv Haskell codegen using libGHC or hs-plugins MkC { x :: !Int8, y :: !Int16 } invStatic :: Array Int Val -- or Map ID Val invDynamic :: Hash ID Val -- conveniently ignore this in the 1st pass The layout of instances is to be a (Array Int Val) for the static parts, and also (maybe later?) a (HashTable ID Val) for the slots augmented through runtime-modified classes. A single lookup routine will take care of looking up the Int from the called ID, and goes into e HashTable fallback without introducing another level of explicit API indirection. Object attributes are truly unbindable; they are initialized as Scalar, Array, Hash etc by boxed instances for Real this time. That is, the Val can be NativeInt to allow for truly unassignable (even for class-local methods) slots: # Essentially a class for value object: class C { has $.foo is Int; method BUILD ($.foo = 0) { # The BUILD autoinit magick here needs to be changed to # allow this; instead of initializing a slot and then # assigning it a value supplied by the constructor method, # we need to mangle the CREATE call so it happens right # _after_ the binding stage for BUILD, but _before_ any # ENTER block fires for the BUILD method body. } method foo { $.foo = 1; # the accessor fails as it's not generated rw. $!foo = 1; # FAILS as well because Int can't be assigned to. } } # Instances of the D clas maps to a fresh (Scalar of Int) object: class D { has Int $.foo; method foo { $.foo = 1; # the accessor fails as it's not generated rw. $!foo = 1; # private accessor call; works by assigning to Scalar. } } (It's also possible to simply take the Object WHICH to be the Seq of WHICHs for all its current slots. That seems 1) fun 2) simple.) =head2 Primitive Methods To make Pugs.Prim transition to the new land of methods, we _remove_ methods from he main package symbol table completely. That means you can no longer write C and expect it to work. On the other hand, C<&Str::chars> will still return a method object by the normal package lookup protocol. =head2 Autoboxing Autoboxing of native projects is accomplished with a global (Map TypeRep InstanceMethods) that simply assumes a layout of native Haskell types and respond to them using IT. globalMap = fromList [ (typeOf (undefined :: Socket), socketMethods) , (typeOf (undefined :: Thread), threadMethods) , (typeOf (undefined :: AnyClass), classMethods) -- Magically: Metaobject Protocol! , ... ] There should be an easy wrap method to promote any Haskell native methods into callconv-friendly Eval ones: module Pugs.Runtime.Socket socketMethods :: InstanceMethods socketMethods = fromList [ ("close", wrap closeSocket) , ("accept", wrap acceptSocket) ] closeSocket :: Socket -> IO () ------------ wrap fun = case Typeable.cast ivInvocant of Just rightType -> fun rightType _ -> fail "Trying to call socket methods without a native socket layout" It's unfortunate that we'll have to use fromTypeable on this one, but since it's all monotypes (we don't have parametric types until 6.2831 anyway), this layout should carry us forward for another couple of milestones. (And by that time we'll have acces to GHC 6.8's type families.) =head2 Runtime Augmentation Runtime metaclass augmentation needs one level of indirection. The Main class maintains a runtimeAttributes (etc) field in addition to the compile-time attributes, and each instance's layout will then neccessarily contain the HashTable part (see above) to make up for those. One way to go about this is to make an AugmentableMI structure that is simply (TVar MI), and maintain its identity thru (addressOf :: TVar MI -> Word), so objects close over the TVar instead of the actual MI records in it, and all (class Class) methods go over one indirection of readTVar. =cut