factor/basis/cocoa/messages/messages.factor

245 lines
6.5 KiB
Factor
Raw Normal View History

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.
USING: accessors alien alien.c-types alien.strings arrays assocs
2008-10-13 15:01:33 -04:00
combinators compiler compiler.alien kernel math namespaces make
parser prettyprint prettyprint.sections quotations sequences
strings words cocoa.runtime io macros memoize debugger
io.encodings.ascii effects libc libc.private parser lexer init
core-foundation ;
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
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 object_getClass class_getSuperclass r>
2007-09-20 18:09:08 -04:00
set-objc-super-class
] keep
[ set-objc-super-receiver ] keep ;
TUPLE: selector name object ;
MEMO: <selector> ( name -- sel ) f \ selector boa ;
2007-09-20 18:09:08 -04:00
: selector ( selector -- alien )
2008-08-29 11:24:22 -04:00
dup object>> expired? [
dup name>> sel_registerName
[ >>object drop ] keep
2007-09-20 18:09:08 -04:00
] [
2008-08-29 11:24:22 -04:00
object>>
2007-09-20 18:09:08 -04:00
] 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
[ ] [ "No such method: " prepend throw ] ?if ;
2007-09-20 18:09:08 -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
swap <selector> , \ selector ,
2007-09-20 18:09:08 -04:00
] [ ] make
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
[ ] [ "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) ;
SYMBOL: objc>alien-types
H{
{ "c" "char" }
{ "i" "int" }
{ "s" "short" }
{ "C" "uchar" }
{ "I" "uint" }
{ "S" "ushort" }
{ "f" "float" }
{ "d" "double" }
{ "B" "bool" }
{ "v" "void" }
{ "*" "char*" }
{ "?" "unknown_type" }
2007-09-20 18:09:08 -04:00
{ "@" "id" }
2008-09-12 23:01:07 -04:00
{ "#" "Class" }
2007-09-20 18:09:08 -04:00
{ ":" "SEL" }
}
"ptrdiff_t" heap-size {
{ 4 [ H{
{ "l" "long" }
{ "q" "longlong" }
{ "L" "ulong" }
{ "Q" "ulonglong" }
} ] }
{ 8 [ H{
{ "l" "long32" }
{ "q" "long" }
{ "L" "ulong32" }
{ "Q" "ulong" }
} ] }
} case
assoc-union objc>alien-types set-global
2007-09-20 18:09:08 -04:00
! The transpose of the above map
SYMBOL: alien>objc-types
objc>alien-types get [ swap ] assoc-map
! A hack...
"ptrdiff_t" heap-size {
{ 4 [ H{
2008-09-11 00:40:41 -04:00
{ "NSPoint" "{_NSPoint=ff}" }
{ "NSRect" "{_NSRect={_NSPoint=ff}{_NSSize=ff}}" }
{ "NSSize" "{_NSSize=ff}" }
{ "NSRange" "{_NSRange=II}" }
{ "NSInteger" "i" }
{ "NSUInteger" "I" }
{ "CGFloat" "f" }
} ] }
{ 8 [ H{
2008-09-11 00:40:41 -04:00
{ "NSPoint" "{CGPoint=dd}" }
{ "NSRect" "{CGRect={CGPoint=dd}{CGSize=dd}}" }
{ "NSSize" "{CGSize=dd}" }
{ "NSRange" "{_NSRange=QQ}" }
{ "NSInteger" "q" }
{ "NSUInteger" "Q" }
{ "CGFloat" "d" }
} ] }
} case
assoc-union alien>objc-types set-global
2007-09-20 18:09:08 -04:00
: objc-struct-type ( i string -- ctype )
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-type ( method i -- type )
method_copyArgumentType
[ ascii alien>string parse-objc-type ] keep
(free) ;
2007-09-20 18:09:08 -04:00
: method-arg-types ( method -- args )
dup method_getNumberOfArguments
[ method-arg-type ] with map ;
2007-09-20 18:09:08 -04:00
: method-return-type ( method -- ctype )
method_copyReturnType
[ ascii alien>string parse-objc-type ] keep
(free) ;
2007-09-20 18:09:08 -04:00
: register-objc-method ( method -- )
dup method-return-type over method-arg-types 2array
dup cache-stubs
swap method_getName sel_getName
2007-09-20 18:09:08 -04:00
objc-methods get set-at ;
2008-09-13 12:32:47 -04:00
: each-method-in-class ( class quot -- )
[ 0 <uint> [ class_copyMethodList ] keep *uint over ] dip
'[ _ void*-nth @ ] each (free) ; inline
2007-09-20 18:09:08 -04:00
: register-objc-methods ( class -- )
2008-09-13 12:32:47 -04:00
[ register-objc-method ] each-method-in-class ;
: method. ( method -- )
{
[ method_getName sel_getName ]
[ method-return-type ]
[ method-arg-types ]
[ method_getImplementation ]
} cleave 4array . ;
: methods. ( class -- )
[ method. ] each-method-in-class ;
2007-09-20 18:09:08 -04:00
: 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 class_getSuperclass [ root-class ] [ ] ?if ;