| 
									
										
										
										
											2008-04-20 06:15:46 -04:00
										 |  |  | ! Copyright (C) 2006, 2008 Slava Pestov. | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2008-04-20 06:15:46 -04:00
										 |  |  | USING: alien alien.c-types alien.strings alien.compiler | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | arrays assocs combinators compiler inference.transforms kernel | 
					
						
							|  |  |  | math namespaces parser prettyprint prettyprint.sections | 
					
						
							| 
									
										
										
										
											2007-10-06 13:39:59 -04:00
										 |  |  | quotations sequences strings words cocoa.runtime io macros | 
					
						
							| 
									
										
										
										
											2008-06-08 16:32:55 -04:00
										 |  |  | memoize debugger io.encodings.ascii effects ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | IN: cocoa.messages | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : make-sender ( method function -- quot )
 | 
					
						
							|  |  |  |     [ over first , f , , second , \ alien-invoke , ] [ ] make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : sender-stub-name ( method function -- string )
 | 
					
						
							|  |  |  |     [ % "_" % unparse % ] "" make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : sender-stub ( method function -- word )
 | 
					
						
							| 
									
										
										
										
											2007-12-26 20:41:02 -05:00
										 |  |  |     [ sender-stub-name f <word> dup ] 2keep
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     over first large-struct? [ "_stret" append ] when
 | 
					
						
							| 
									
										
										
										
											2008-01-09 01:36:11 -05:00
										 |  |  |     make-sender define ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: message-senders | 
					
						
							|  |  |  | SYMBOL: super-message-senders | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-06 13:39:59 -04:00
										 |  |  | message-senders global [ H{ } assoc-like ] change-at
 | 
					
						
							|  |  |  | super-message-senders global [ H{ } assoc-like ] change-at
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : cache-stub ( method function hash -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         over get [ 2drop ] [ over >r sender-stub r> set ] if
 | 
					
						
							|  |  |  |     ] bind ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : cache-stubs ( method -- )
 | 
					
						
							|  |  |  |     dup
 | 
					
						
							|  |  |  |     "objc_msgSendSuper" super-message-senders get cache-stub | 
					
						
							|  |  |  |     "objc_msgSend" message-senders get cache-stub ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <super> ( receiver -- super )
 | 
					
						
							|  |  |  |     "objc-super" <c-object> [ | 
					
						
							|  |  |  |         >r dup objc-object-isa objc-class-super-class r> | 
					
						
							|  |  |  |         set-objc-super-class | 
					
						
							|  |  |  |     ] keep
 | 
					
						
							|  |  |  |     [ set-objc-super-receiver ] keep ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: selector name object ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-13 16:06:27 -04:00
										 |  |  | MEMO: <selector> ( name -- sel ) f \ selector boa ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : selector ( selector -- alien )
 | 
					
						
							|  |  |  |     dup selector-object expired? [ | 
					
						
							|  |  |  |         dup selector-name sel_registerName | 
					
						
							|  |  |  |         dup rot set-selector-object | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         selector-object | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: objc-methods | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-06 13:39:59 -04:00
										 |  |  | objc-methods global [ H{ } assoc-like ] change-at
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : lookup-method ( selector -- method )
 | 
					
						
							|  |  |  |     dup objc-methods get at
 | 
					
						
							| 
									
										
										
										
											2008-03-19 20:15:32 -04:00
										 |  |  |     [ ] [ "No such method: " prepend throw ] ?if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-03 17:34:59 -04:00
										 |  |  | : make-dip ( quot n -- quot' )
 | 
					
						
							|  |  |  |     dup
 | 
					
						
							|  |  |  |     \ >r <repetition> >quotation -rot
 | 
					
						
							|  |  |  |     \ r> <repetition> >quotation 3append ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-06 13:39:59 -04:00
										 |  |  | MEMO: make-prepare-send ( selector method super? -- quot )
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         [ \ <super> , ] when
 | 
					
						
							| 
									
										
										
										
											2007-10-07 18:16:17 -04:00
										 |  |  |         swap <selector> , \ selector , | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     ] [ ] make | 
					
						
							| 
									
										
										
										
											2007-10-03 17:34:59 -04:00
										 |  |  |     swap second length 2 - make-dip ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | MACRO: (send) ( selector super? -- quot )
 | 
					
						
							| 
									
										
										
										
											2007-10-06 13:39:59 -04:00
										 |  |  |     >r dup lookup-method r> | 
					
						
							|  |  |  |     [ make-prepare-send ] 2keep
 | 
					
						
							|  |  |  |     super-message-senders message-senders ? get at
 | 
					
						
							|  |  |  |     [ slip execute ] 2curry ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-24 18:20:27 -05:00
										 |  |  | : send ( receiver args... selector -- return... ) f (send) ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | \ send soft "break-after" set-word-prop | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-24 18:20:27 -05:00
										 |  |  | : super-send ( receiver args... selector -- return... ) t (send) ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | \ super-send soft "break-after" set-word-prop | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Runtime introspection | 
					
						
							|  |  |  | : (objc-class) ( string word -- class )
 | 
					
						
							|  |  |  |     dupd execute
 | 
					
						
							| 
									
										
										
										
											2008-03-19 20:15:32 -04:00
										 |  |  |     [ ] [ "No such class: " prepend throw ] ?if ; inline
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : objc-class ( string -- class )
 | 
					
						
							|  |  |  |     \ objc_getClass (objc-class) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : objc-protocol ( string -- class )
 | 
					
						
							|  |  |  |     \ objc_getProtocol (objc-class) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : objc-meta-class ( string -- class )
 | 
					
						
							|  |  |  |     \ objc_getMetaClass (objc-class) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : method-arg-type ( method i -- type )
 | 
					
						
							|  |  |  |     f <void*> 0 <int> over
 | 
					
						
							|  |  |  |     >r method_getArgumentInfo drop
 | 
					
						
							| 
									
										
										
										
											2008-04-20 06:15:46 -04:00
										 |  |  |     r> *void* ascii alien>string ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: objc>alien-types | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | H{ | 
					
						
							|  |  |  |     { "c" "char" } | 
					
						
							|  |  |  |     { "i" "int" } | 
					
						
							|  |  |  |     { "s" "short" } | 
					
						
							|  |  |  |     { "l" "long" } | 
					
						
							|  |  |  |     { "q" "longlong" } | 
					
						
							|  |  |  |     { "C" "uchar" } | 
					
						
							|  |  |  |     { "I" "uint" } | 
					
						
							|  |  |  |     { "S" "ushort" } | 
					
						
							|  |  |  |     { "L" "ulong" } | 
					
						
							|  |  |  |     { "Q" "ulonglong" } | 
					
						
							|  |  |  |     { "f" "float" } | 
					
						
							|  |  |  |     { "d" "double" } | 
					
						
							|  |  |  |     { "B" "bool" } | 
					
						
							|  |  |  |     { "v" "void" } | 
					
						
							|  |  |  |     { "*" "char*" } | 
					
						
							|  |  |  |     { "@" "id" } | 
					
						
							|  |  |  |     { "#" "id" } | 
					
						
							|  |  |  |     { ":" "SEL" } | 
					
						
							|  |  |  | } objc>alien-types set-global
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! The transpose of the above map | 
					
						
							|  |  |  | SYMBOL: alien>objc-types | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | objc>alien-types get [ swap ] assoc-map
 | 
					
						
							|  |  |  | ! A hack... | 
					
						
							|  |  |  | H{ | 
					
						
							|  |  |  |     { "NSPoint" "{_NSPoint=ff}" } | 
					
						
							|  |  |  |     { "NSRect" "{_NSRect=ffff}" } | 
					
						
							|  |  |  |     { "NSSize" "{_NSSize=ff}" } | 
					
						
							|  |  |  |     { "NSRange" "{_NSRange=II}" } | 
					
						
							| 
									
										
										
										
											2008-04-13 23:58:07 -04:00
										 |  |  | } assoc-union alien>objc-types set-global
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : objc-struct-type ( i string -- ctype )
 | 
					
						
							| 
									
										
										
										
											2008-04-26 00:17:08 -04:00
										 |  |  |     2dup CHAR: = -rot index-from swap subseq
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     dup c-types get key? [ | 
					
						
							|  |  |  |         "Warning: no such C type: " write dup print
 | 
					
						
							|  |  |  |         drop "void*" | 
					
						
							|  |  |  |     ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (parse-objc-type) ( i string -- ctype )
 | 
					
						
							|  |  |  |     2dup nth >r >r 1+ r> r> { | 
					
						
							|  |  |  |         { [ dup "rnNoORV" member? ] [ drop (parse-objc-type) ] } | 
					
						
							|  |  |  |         { [ dup CHAR: ^ = ] [ 3drop "void*" ] } | 
					
						
							|  |  |  |         { [ dup CHAR: { = ] [ drop objc-struct-type ] } | 
					
						
							|  |  |  |         { [ dup CHAR: [ = ] [ 3drop "void*" ] } | 
					
						
							| 
									
										
										
										
											2008-04-11 13:55:57 -04:00
										 |  |  |         [ 2nip 1string objc>alien-types get at ] | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     } cond ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : parse-objc-type ( string -- ctype ) 0 swap (parse-objc-type) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : method-arg-types ( method -- args )
 | 
					
						
							|  |  |  |     dup method_getNumberOfArguments | 
					
						
							| 
									
										
										
										
											2008-01-09 17:36:30 -05:00
										 |  |  |     [ method-arg-type parse-objc-type ] with map ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : method-return-type ( method -- ctype )
 | 
					
						
							|  |  |  |     #! Undocumented hack! Apple does not support this feature! | 
					
						
							|  |  |  |     objc-method-types parse-objc-type ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : register-objc-method ( method -- )
 | 
					
						
							|  |  |  |     dup method-return-type over method-arg-types 2array
 | 
					
						
							|  |  |  |     dup cache-stubs | 
					
						
							|  |  |  |     swap objc-method-name sel_getName | 
					
						
							|  |  |  |     objc-methods get set-at ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : method-list@ ( ptr -- ptr )
 | 
					
						
							|  |  |  |     "objc-method-list" heap-size swap <displaced-alien> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (register-objc-methods) ( objc-class iterator -- )
 | 
					
						
							|  |  |  |     2dup class_nextMethodList [ | 
					
						
							|  |  |  |         dup objc-method-list-count swap method-list@ [ | 
					
						
							|  |  |  |             objc-method-nth register-objc-method | 
					
						
							|  |  |  |         ] curry each (register-objc-methods) | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         2drop
 | 
					
						
							|  |  |  |     ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : register-objc-methods ( class -- )
 | 
					
						
							|  |  |  |     f <void*> (register-objc-methods) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : class-exists? ( string -- class ) objc_getClass >boolean ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : unless-defined ( class quot -- )
 | 
					
						
							|  |  |  |     >r class-exists? r> unless ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : define-objc-class-word ( name quot -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         over , , \ unless-defined , dup , \ objc-class , | 
					
						
							| 
									
										
										
										
											2008-06-08 16:32:55 -04:00
										 |  |  |     ] [ ] make >r "cocoa.classes" create r> | 
					
						
							|  |  |  |     (( -- class )) define-declared ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : import-objc-class ( name quot -- )
 | 
					
						
							|  |  |  |     2dup unless-defined | 
					
						
							|  |  |  |     dupd define-objc-class-word | 
					
						
							| 
									
										
										
										
											2007-11-24 16:28:40 -05:00
										 |  |  |     [ | 
					
						
							|  |  |  |         dup
 | 
					
						
							|  |  |  |         objc-class register-objc-methods | 
					
						
							|  |  |  |         objc-meta-class register-objc-methods | 
					
						
							|  |  |  |     ] curry try ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : root-class ( class -- root )
 | 
					
						
							|  |  |  |     dup objc-class-super-class [ root-class ] [ ] ?if ;
 |