|
From: <cod...@go...> - 2008-12-10 16:24:15
|
Author: jam...@us...
Date: Wed Dec 10 07:59:54 2008
New Revision: 374
Modified:
branches/objc2/hoc/HOC/HOC.hs
branches/objc2/hoc/HOC/HOC/Class.hs
branches/objc2/hoc/HOC/HOC/DeclareClass.hs
branches/objc2/hoc/Tests/TestFoundation.hs
Log:
Experimental patch (committed to objc2 branch only for now, though it's not
at all specific to objective c 2.0 - I just wasn't sure if it was too
disruptive to push to the trunk) extending previous work on super calls to
cover class methods.
This involved adding a fair bit to the output of declareClass - if anyone
sees a better way to do this, I'd love to hear about it. One thing I
thought about was using an instance of the form:
instance ClassAndObject meta $(metaClsType) => ClassObject meta
where classObject = unsafeGetMetaclassForClass classObject
I believe this would have "worked" with slightly less clutter in the
namespace, but it would require adding FlexibleContexts to the LANGUAGE
pragma
of every source file that calls declareClass, which seemed even more
disruptive.
Modified: branches/objc2/hoc/HOC/HOC.hs
==============================================================================
--- branches/objc2/hoc/HOC/HOC.hs (original)
+++ branches/objc2/hoc/HOC/HOC.hs Wed Dec 10 07:59:54 2008
@@ -4,6 +4,7 @@
nil,
Object(..),
Class,
+ MetaClass,
ClassAndObject,
ClassObject,
classObject,
Modified: branches/objc2/hoc/HOC/HOC/Class.hs
==============================================================================
--- branches/objc2/hoc/HOC/HOC/Class.hs (original)
+++ branches/objc2/hoc/HOC/HOC/Class.hs Wed Dec 10 07:59:54 2008
@@ -11,15 +11,13 @@
import Foreign
import Foreign.C.String
-
data Class_ a
type Class a = ID (Class_ a)
-
+type MetaClass a = Class (Class_ a)
unsafeGetClassObject :: String -> Class a
-
foreign import ccall unsafe "Class.h getClassByName"
c_getClassByName :: CString -> IO (Ptr ObjCObject)
@@ -30,6 +28,16 @@
getClassByName name >>= importImmortal
+unsafeGetMetaclassForClass :: Class a -> MetaClass a
+
+foreign import ccall unsafe "Class.h getClassForObject"
+ c_getClassForObject :: Ptr ObjCObject -> IO (Ptr ObjCObject)
+
+getClassForObject obj = withExportedArgument obj c_getClassForObject
+
+{-# NOINLINE unsafeGetMetaclassForClass #-}
+unsafeGetMetaclassForClass obj = unsafePerformIO $
+ getClassForObject obj >>= importImmortal
class (Object a, Object b) => ClassAndObject a b | a -> b, b -> a
Modified: branches/objc2/hoc/HOC/HOC/DeclareClass.hs
==============================================================================
--- branches/objc2/hoc/HOC/HOC/DeclareClass.hs (original)
+++ branches/objc2/hoc/HOC/HOC/DeclareClass.hs Wed Dec 10 07:59:54 2008
@@ -31,6 +31,12 @@
`appT` (conT (mkName phantomName)
`appT` varT (mkName "a"))),
+ -- type $(metaMetaClassName) a = $(superMetaMetaClassName)
($(phantomName) a)
+ tySynD (mkName metaMetaClassName) [mkName "a"]
+ (conT (mkName superMetaMetaClassName)
+ `appT` (conT (mkName phantomName)
+ `appT` varT (mkName "a"))),
+
-- $(classObjectName) :: $(metaClassName) ()
sigD (mkName classObjectName) (conT (mkName metaClassName)
`appT` [t| () |]),
@@ -39,6 +45,11 @@
valD (return $ VarP (mkName classObjectName))
(normalB [| unsafeGetClassObject $(stringE name) |]) [],
+ -- $(metaClassObjectName) = unsafeGetMetaclassForClass
$(classObjectName)
+ valD (return $ VarP (mkName metaClassObjectName))
+ (normalB [| unsafeGetMetaclassForClass $(varE (mkName
classObjectName)) |]) [],
+
+ -- $(superName) :: String
sigD (mkName superName) [t| String |],
-- $(superName) = "super"
@@ -47,20 +58,35 @@
-- instance SuperClass (name ()) (super ())
instanceD (cxt []) (conT ''SuperClass `appT` clsType `appT`
superType) [],
+ -- instance SuperClass (clsName ()) (superClsName ())
+ instanceD (cxt []) (conT ''SuperClass `appT` metaClsType `appT`
superMetaType) [],
+
-- instance ClassObject (metaClsName ())
-- where classObject = classObject
instanceD (cxt []) (conT ''ClassObject `appT` metaClsType)
- [funD 'classObject [clause [] (normalB $ varE (mkName
classObjectName)) []]]
+ [funD 'classObject [clause [] (normalB $ varE (mkName
classObjectName)) []]],
+
+ -- instance ClassObject metaMetaCls
+ -- where classObject = unsafeGetMetaclassForClass classObject
+ -- {- metaclass object, to support super calls in class methods -}
+ instanceD (cxt []) (conT ''ClassObject `appT` metaMetaClsType)
+ [funD 'classObject [clause [] (normalB $ varE (mkName
metaClassObjectName)) []]]
]
where
phantomName = name ++ "_"
metaClassName = name ++ "Class"
+ metaMetaClassName = name ++ "MetaClass"
metaPhantomName = metaClassName ++ "_"
superMetaClassName | super == "ID" = "Class"
| otherwise = super ++ "Class"
+ superMetaMetaClassName | super == "ID" = "MetaClass"
+ | otherwise = super ++ "MetaClass"
classObjectName = "_" ++ name
+ metaClassObjectName = "_" ++ metaClassName
superName = "super_" ++ name
+ metaMetaClsType = conT (mkName metaMetaClassName) `appT` [t| () |]
metaClsType = conT (mkName metaClassName) `appT` [t| () |]
clsType = conT (mkName name) `appT` [t| () |]
superType = conT (mkName super) `appT` [t| () |]
+ superMetaType = conT (mkName superMetaClassName) `appT` [t| () |]
Modified: branches/objc2/hoc/Tests/TestFoundation.hs
==============================================================================
--- branches/objc2/hoc/Tests/TestFoundation.hs (original)
+++ branches/objc2/hoc/Tests/TestFoundation.hs Wed Dec 10 07:59:54 2008
@@ -94,16 +94,19 @@
$(declareClass "HaskellObjectCountingInvocations" "NSObject")
$(exportClass "HaskellObjectCountingInvocations" "hoci_1_" [
- InstanceMethod 'countInvocationsUpto
+ InstanceMethod 'countInvocationsUpto,
+ ClassMethod 'countInvocationsUpto
])
instance Has_countInvocationsUpto (HaskellObjectCountingInvocations a)
+instance Has_countInvocationsUpto (HaskellObjectCountingInvocationsClass a)
hoci_1_countInvocationsUpto start limit self = return (start + 1)
$(declareClass "HaskellObjectUsingSuper" "HaskellObjectCountingInvocations")
$(exportClass "HaskellObjectUsingSuper" "hoci_2_" [
- InstanceMethod 'countInvocationsUpto
+ InstanceMethod 'countInvocationsUpto,
+ ClassMethod 'countInvocationsUpto
])
hoci_2_countInvocationsUpto start limit self
@@ -268,7 +271,7 @@
str <- hobj # description
fromNSString str @?= "<HaskellObjectWithDescription: TEST>"
),
- "chaining" ~: test [
+ "instanceChaining" ~: test [
"base" ~: (assertNoLeaks $ do
hobj <- _HaskellObjectCountingInvocations # alloc >>=
init
count <- hobj # countInvocationsUpto 0 100
@@ -284,6 +287,22 @@
count <- hobj # countInvocationsUpto 0 100
count @?= 2
)
+
+ ],
+ "classChaining" ~: test [
+ "base" ~: (assertNoLeaks $ do
+ count <- _HaskellObjectCountingInvocations #
countInvocationsUpto 0 100
+ count @?= 1
+ ),
+ "subclass" ~: (assertNoLeaks $ do
+ count <- _HaskellObjectUsingSuper #
countInvocationsUpto 0 100
+ count @?= 2
+ ),
+ "subsubclass" ~: (assertNoLeaks $ do
+ count <- _HaskellSubclassOfObjectUsingSuper #
countInvocationsUpto 0 100
+ count @?= 2
+ )
+
]
],
"structs" ~: test [
|