]> gitweb.factorcode.org Git - factor.git/blob - basis/cocoa/messages/messages.factor
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / basis / cocoa / messages / messages.factor
1 ! Copyright (C) 2006, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.c-types alien.strings arrays assocs
4 combinators compiler kernel math namespaces make parser
5 prettyprint prettyprint.sections quotations sequences strings
6 words cocoa.runtime io macros memoize debugger
7 io.encodings.ascii effects compiler.generator libc libc.private ;
8 IN: cocoa.messages
9
10 : make-sender ( method function -- quot )
11     [ over first , f , , second , \ alien-invoke , ] [ ] make ;
12
13 : sender-stub-name ( method function -- string )
14     [ % "_" % unparse % ] "" make ;
15
16 : sender-stub ( method function -- word )
17     [ sender-stub-name f <word> dup ] 2keep
18     over first large-struct? [ "_stret" append ] when
19     make-sender define ;
20
21 SYMBOL: message-senders
22 SYMBOL: super-message-senders
23
24 message-senders global [ H{ } assoc-like ] change-at
25 super-message-senders global [ H{ } assoc-like ] change-at
26
27 : cache-stub ( method function hash -- )
28     [
29         over get [ 2drop ] [ over >r sender-stub r> set ] if
30     ] bind ;
31
32 : cache-stubs ( method -- )
33     dup
34     "objc_msgSendSuper" super-message-senders get cache-stub
35     "objc_msgSend" message-senders get cache-stub ;
36
37 : <super> ( receiver -- super )
38     "objc-super" <c-object> [
39         >r dup object_getClass class_getSuperclass r>
40         set-objc-super-class
41     ] keep
42     [ set-objc-super-receiver ] keep ;
43
44 TUPLE: selector name object ;
45
46 MEMO: <selector> ( name -- sel ) f \ selector boa ;
47
48 : selector ( selector -- alien )
49     dup object>> expired? [
50         dup name>> sel_registerName
51         [ >>object drop ] keep
52     ] [
53         object>>
54     ] if ;
55
56 SYMBOL: objc-methods
57
58 objc-methods global [ H{ } assoc-like ] change-at
59
60 : lookup-method ( selector -- method )
61     dup objc-methods get at
62     [ ] [ "No such method: " prepend throw ] ?if ;
63
64 : make-dip ( quot n -- quot' )
65     dup
66     \ >r <repetition> >quotation -rot
67     \ r> <repetition> >quotation 3append ;
68
69 MEMO: make-prepare-send ( selector method super? -- quot )
70     [
71         [ \ <super> , ] when
72         swap <selector> , \ selector ,
73     ] [ ] make
74     swap second length 2 - make-dip ;
75
76 MACRO: (send) ( selector super? -- quot )
77     >r dup lookup-method r>
78     [ make-prepare-send ] 2keep
79     super-message-senders message-senders ? get at
80     [ slip execute ] 2curry ;
81
82 : send ( receiver args... selector -- return... ) f (send) ; inline
83
84 \ send soft "break-after" set-word-prop
85
86 : super-send ( receiver args... selector -- return... ) t (send) ; inline
87
88 \ super-send soft "break-after" set-word-prop
89
90 ! Runtime introspection
91 : (objc-class) ( string word -- class )
92     dupd execute
93     [ ] [ "No such class: " prepend throw ] ?if ; inline
94
95 : objc-class ( string -- class )
96     \ objc_getClass (objc-class) ;
97
98 : objc-protocol ( string -- class )
99     \ objc_getProtocol (objc-class) ;
100
101 : objc-meta-class ( string -- class )
102     \ objc_getMetaClass (objc-class) ;
103
104 SYMBOL: objc>alien-types
105
106 H{
107     { "c" "char" }
108     { "i" "int" }
109     { "s" "short" }
110     { "C" "uchar" }
111     { "I" "uint" }
112     { "S" "ushort" }
113     { "f" "float" }
114     { "d" "double" }
115     { "B" "bool" }
116     { "v" "void" }
117     { "*" "char*" }
118     { "?" "unknown_type" }
119     { "@" "id" }
120     { "#" "id" }
121     { ":" "SEL" }
122 }
123 "ptrdiff_t" heap-size {
124     { 4 [ H{
125         { "l" "long" }
126         { "q" "longlong" }
127         { "L" "ulong" }
128         { "Q" "ulonglong" }
129     } ] }
130     { 8 [ H{
131         { "l" "long32" }
132         { "q" "long" }
133         { "L" "ulong32" }
134         { "Q" "ulong" }
135     } ] }
136 } case
137 assoc-union objc>alien-types set-global
138
139 ! The transpose of the above map
140 SYMBOL: alien>objc-types
141
142 objc>alien-types get [ swap ] assoc-map
143 ! A hack...
144 "ptrdiff_t" heap-size {
145     { 4 [ H{
146         { "NSPoint"    "{_NSPoint=ff}" }
147         { "NSRect"     "{_NSRect={_NSPoint=ff}{_NSSize=ff}}" }
148         { "NSSize"     "{_NSSize=ff}" }
149         { "NSRange"    "{_NSRange=II}" }
150         { "NSInteger"  "i" }
151         { "NSUInteger" "I" }
152         { "CGFloat"    "f" }
153     } ] }
154     { 8 [ H{
155         { "NSPoint"    "{CGPoint=dd}" }
156         { "NSRect"     "{CGRect={CGPoint=dd}{CGSize=dd}}" }
157         { "NSSize"     "{CGSize=dd}" }
158         { "NSRange"    "{_NSRange=QQ}" }
159         { "NSInteger"  "q" }
160         { "NSUInteger" "Q" }
161         { "CGFloat"    "d" }
162     } ] }
163 } case
164 assoc-union alien>objc-types set-global
165
166 : objc-struct-type ( i string -- ctype )
167     2dup CHAR: = -rot index-from swap subseq
168     dup c-types get key? [
169         "Warning: no such C type: " write dup print
170         drop "void*"
171     ] unless ;
172
173 : (parse-objc-type) ( i string -- ctype )
174     2dup nth >r >r 1+ r> r> {
175         { [ dup "rnNoORV" member? ] [ drop (parse-objc-type) ] }
176         { [ dup CHAR: ^ = ] [ 3drop "void*" ] }
177         { [ dup CHAR: { = ] [ drop objc-struct-type ] }
178         { [ dup CHAR: [ = ] [ 3drop "void*" ] }
179         [ 2nip 1string objc>alien-types get at ]
180     } cond ;
181
182 : parse-objc-type ( string -- ctype ) 0 swap (parse-objc-type) ;
183
184 : method-arg-type ( method i -- type )
185     method_copyArgumentType
186     [ ascii alien>string parse-objc-type ] keep
187     (free) ;
188
189 : method-arg-types ( method -- args )
190     dup method_getNumberOfArguments
191     [ method-arg-type ] with map ;
192
193 : method-return-type ( method -- ctype )
194     method_copyReturnType
195     [ ascii alien>string parse-objc-type ] keep
196     (free) ;
197
198 : register-objc-method ( method -- )
199     dup method-return-type over method-arg-types 2array
200     dup cache-stubs
201     swap method_getName sel_getName
202     objc-methods get set-at ;
203
204 : (register-objc-methods) ( methods count -- methods )
205     over [ void*-nth register-objc-method ] curry each ;
206
207 : register-objc-methods ( class -- )
208     0 <uint> [ class_copyMethodList ] keep *uint 
209     (register-objc-methods) (free) ;
210
211 : class-exists? ( string -- class ) objc_getClass >boolean ;
212
213 : unless-defined ( class quot -- )
214     >r class-exists? r> unless ; inline
215
216 : define-objc-class-word ( name quot -- )
217     [
218         over , , \ unless-defined , dup , \ objc-class ,
219     ] [ ] make >r "cocoa.classes" create r>
220     (( -- class )) define-declared ;
221
222 : import-objc-class ( name quot -- )
223     2dup unless-defined
224     dupd define-objc-class-word
225     [
226         dup
227         objc-class register-objc-methods
228         objc-meta-class register-objc-methods
229     ] curry try ;
230
231 : root-class ( class -- root )
232     dup class_getSuperclass [ root-class ] [ ] ?if ;