Fix adding methods to existing classes
							parent
							
								
									c3ca5a8191
								
							
						
					
					
						commit
						12c8ffc194
					
				| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
IN: cocoa.tests
 | 
			
		||||
USING: cocoa cocoa.messages cocoa.subclassing cocoa.types
 | 
			
		||||
compiler kernel namespaces cocoa.classes tools.test memory
 | 
			
		||||
compiler.units ;
 | 
			
		||||
compiler.units math ;
 | 
			
		||||
 | 
			
		||||
CLASS: {
 | 
			
		||||
    { +superclass+ "NSObject" }
 | 
			
		||||
| 
						 | 
				
			
			@ -45,3 +45,27 @@ Bar [
 | 
			
		|||
[ 2.0 ] [ "x" get NSRect-y ] unit-test
 | 
			
		||||
[ 101.0 ] [ "x" get NSRect-w ] unit-test
 | 
			
		||||
[ 102.0 ] [ "x" get NSRect-h ] unit-test
 | 
			
		||||
 | 
			
		||||
! Make sure that we can add methods
 | 
			
		||||
CLASS: {
 | 
			
		||||
    { +superclass+ "NSObject" }
 | 
			
		||||
    { +name+ "Bar" }
 | 
			
		||||
} {
 | 
			
		||||
    "bar"
 | 
			
		||||
    "NSRect"
 | 
			
		||||
    { "id" "SEL" }
 | 
			
		||||
    [ 2drop test-foo "x" get ]
 | 
			
		||||
} {
 | 
			
		||||
    "babb"
 | 
			
		||||
    "int"
 | 
			
		||||
    { "id" "SEL" "int" }
 | 
			
		||||
    [ 2nip sq ]
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
[ 144 ] [
 | 
			
		||||
    Bar [
 | 
			
		||||
        -> alloc -> init
 | 
			
		||||
        dup 12 -> babb
 | 
			
		||||
        swap -> release
 | 
			
		||||
    ] compile-call
 | 
			
		||||
] unit-test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,9 @@
 | 
			
		|||
! Copyright (C) 2006, 2008 Slava Pestov
 | 
			
		||||
! Copyright (C) 2006, 2008 Slava Pestov, Joe Groff.
 | 
			
		||||
! See http://factorcode.org/license.txt for BSD license.
 | 
			
		||||
USING: alien alien.c-types alien.strings arrays assocs
 | 
			
		||||
combinators compiler hashtables kernel libc math namespaces
 | 
			
		||||
parser sequences words cocoa.messages cocoa.runtime
 | 
			
		||||
compiler.units io.encodings.ascii generalizations
 | 
			
		||||
continuations make ;
 | 
			
		||||
parser sequences words cocoa.messages cocoa.runtime locals
 | 
			
		||||
compiler.units io.encodings.ascii continuations make fry ;
 | 
			
		||||
IN: cocoa.subclassing
 | 
			
		||||
 | 
			
		||||
: init-method ( method -- sel imp types )
 | 
			
		||||
| 
						 | 
				
			
			@ -12,22 +11,25 @@ IN: cocoa.subclassing
 | 
			
		|||
    [ sel_registerName ] [ execute ] [ ascii string>alien ]
 | 
			
		||||
    tri* ;
 | 
			
		||||
 | 
			
		||||
: throw-if-false ( YES/NO -- )
 | 
			
		||||
    zero? [ "Failed to add method or protocol to class" throw ]
 | 
			
		||||
    when ;
 | 
			
		||||
: throw-if-false ( obj what -- )
 | 
			
		||||
    swap { f 0 } member?
 | 
			
		||||
    [ "Failed to " prepend throw ] [ drop ] if ;
 | 
			
		||||
 | 
			
		||||
: add-method ( class sel imp types -- )
 | 
			
		||||
    class_addMethod "add method to class" throw-if-false ;
 | 
			
		||||
 | 
			
		||||
: add-methods ( methods class -- )
 | 
			
		||||
    swap
 | 
			
		||||
    [ init-method class_addMethod throw-if-false ] with each ;
 | 
			
		||||
    '[ [ _ ] dip init-method add-method ] each ;
 | 
			
		||||
 | 
			
		||||
: add-protocol ( class protocol -- )
 | 
			
		||||
    class_addProtocol "add protocol to class" throw-if-false ;
 | 
			
		||||
 | 
			
		||||
: add-protocols ( protocols class -- )
 | 
			
		||||
    swap [ objc-protocol class_addProtocol throw-if-false ]
 | 
			
		||||
    with each ;
 | 
			
		||||
    '[ [ _ ] dip objc-protocol add-protocol ] each ;
 | 
			
		||||
 | 
			
		||||
: (define-objc-class) ( protocols superclass name imeth -- )
 | 
			
		||||
    -rot
 | 
			
		||||
: (define-objc-class) ( imeth protocols superclass name -- )
 | 
			
		||||
    [ objc-class ] dip 0 objc_allocateClassPair
 | 
			
		||||
    [ add-methods ] [ add-protocols ] [ objc_registerClassPair ]
 | 
			
		||||
    [ add-protocols ] [ add-methods ] [ objc_registerClassPair ]
 | 
			
		||||
    tri ;
 | 
			
		||||
 | 
			
		||||
: encode-types ( return types -- encoding )
 | 
			
		||||
| 
						 | 
				
			
			@ -45,28 +47,19 @@ IN: cocoa.subclassing
 | 
			
		|||
        [ first4 prepare-method 3array ] map
 | 
			
		||||
    ] with-compilation-unit ;
 | 
			
		||||
 | 
			
		||||
: types= ( a b -- ? )
 | 
			
		||||
    [ ascii alien>string ] bi@ = ;
 | 
			
		||||
 | 
			
		||||
: (verify-method-type) ( class sel types -- )
 | 
			
		||||
    [ class_getInstanceMethod method_getTypeEncoding ]
 | 
			
		||||
    dip types=
 | 
			
		||||
    [ "Objective-C method types cannot be changed once defined" throw ]
 | 
			
		||||
    unless ;
 | 
			
		||||
: verify-method-type ( class sel imp types -- class sel imp types )
 | 
			
		||||
    4 ndup nip (verify-method-type) ;
 | 
			
		||||
 | 
			
		||||
: (redefine-objc-method) ( class method -- )
 | 
			
		||||
    init-method ! verify-method-type
 | 
			
		||||
    drop
 | 
			
		||||
    [ class_getInstanceMethod ] dip method_setImplementation drop ;
 | 
			
		||||
:: (redefine-objc-method) ( class method -- )
 | 
			
		||||
    method init-method [| sel imp types |
 | 
			
		||||
        class sel class_getInstanceMethod [
 | 
			
		||||
            imp method_setImplementation drop
 | 
			
		||||
        ] [
 | 
			
		||||
            class sel imp types add-method
 | 
			
		||||
        ] if*
 | 
			
		||||
    ] call ;
 | 
			
		||||
    
 | 
			
		||||
: redefine-objc-methods ( imeth name -- )
 | 
			
		||||
    dup class-exists? [
 | 
			
		||||
        objc_getClass swap [ (redefine-objc-method) ] with each
 | 
			
		||||
    ] [
 | 
			
		||||
        2drop
 | 
			
		||||
    ] if ;
 | 
			
		||||
        objc_getClass '[ [ _ ] dip (redefine-objc-method) ] each
 | 
			
		||||
    ] [ 2drop ] if ;
 | 
			
		||||
 | 
			
		||||
SYMBOL: +name+
 | 
			
		||||
SYMBOL: +protocols+
 | 
			
		||||
| 
						 | 
				
			
			@ -76,10 +69,10 @@ SYMBOL: +superclass+
 | 
			
		|||
    clone [
 | 
			
		||||
        prepare-methods
 | 
			
		||||
        +name+ get "cocoa.classes" create drop
 | 
			
		||||
        +name+ get 2dup redefine-objc-methods swap [
 | 
			
		||||
            +protocols+ get , +superclass+ get , +name+ get , ,
 | 
			
		||||
            \ (define-objc-class) ,
 | 
			
		||||
        ] [ ] make import-objc-class
 | 
			
		||||
        +name+ get 2dup redefine-objc-methods swap
 | 
			
		||||
        +protocols+ get +superclass+ get +name+ get
 | 
			
		||||
        '[ _ _ _ _ (define-objc-class) ]
 | 
			
		||||
        import-objc-class
 | 
			
		||||
    ] bind ;
 | 
			
		||||
 | 
			
		||||
: CLASS:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue