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