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