34
35:- module(pce_realise,
36 [ pce_register_class/1, 37 pce_extended_class/1, 38 pce_realise_class/1, 39 pce_begin_class_definition/4, 40 pce_prolog_class/1, 41 pce_prolog_class/2 42 ]). 43
44:- use_module(pce_boot(pce_principal)). 45:- use_module(pce_boot(pce_global)). 46:- require([ ignore/1
47 , pce_error/1
48 , call/3
49 , last/2
50 ]). 51
52:- pce_global(@class, new(var(class, class, @nil))).
53
54 57
58pce_register_class(ClassName) :-
59 check_loaded_class(ClassName).
60
61
62 65
66pce_extended_class(ClassName) :-
67 get(@classes, member, ClassName, Class),
68 !,
69 attach_class_attributes(ClassName),
70 send(Class, clear_cache),
71 resolve_method_message(Msg),
72 send(Class, resolve_method_message, Msg).
73pce_extended_class(_).
81pce_begin_class_definition(_,_,_,_).
82
83
84
93check_loaded_class(ClassName) :-
94 get(@classes, member, ClassName, _),
95 !,
96 pce_realise_class(ClassName).
97check_loaded_class(_).
98
99
100
107pce_realise_class(ClassName) :-
108 pce_class(ClassName, MetaClassName, SuperName, _, _, _),
109 MetaClassName \== (-),
110 create_class(ClassName, MetaClassName, SuperName, Class),
111 !,
112 resolve_method_message(Msg),
113 send(Class, resolve_method_message, Msg),
114 attach_class_attributes(ClassName),
115 ( cache_table(TableName),
116 get(Class, slot, TableName, Table),
117 get(Table, size, Size),
118 Size > 0
119 -> delete_prolog_methods(Class)
120 ; true
121 ),
122 ignore(get(Class, send_method, in_event_area, _)). 123
124cache_table(send_table).
125cache_table(get_table).
126cache_table(send_methods).
127cache_table(get_methods).
128
129attach_class_attributes(ClassName) :-
130 get(@classes, member, ClassName, Class),
131 pce_class(ClassName, _, _,
132 Variables,
133 ClassVariables,
134 Directives),
135 attach_variables(Variables, Class),
136 attach_class_variables(ClassVariables, Class),
137 run_directives(Directives, Class),
138 fail ; true.
147pce_prolog_class(ClassName) :-
148 pce_prolog_class(ClassName, _SuperName).
149pce_prolog_class(ClassName, SuperName) :-
150 pce_class(ClassName, _MetaClassName, SuperName,
151 _Variables,
152 _ClassVariables,
153 _Directives),
154 SuperName \== '-'.
163create_class(ClassName, MetaClassName, Super, Class) :-
164 get(@classes, member, ClassName, Class),
165 send(Class, instance_of, class),
166 !,
167 get(Class, super_class, SuperClass),
168 ( ( Super == @nil,
169 SuperClass == @nil
170 ; SuperClass \== @nil,
171 get(SuperClass, name, Super)
172 )
173 -> true
174 ; pce_error(superclass_not_changed(ClassName))
175 ),
176 ( ( MetaClassName == @default
177 ; get(Class, class, MetaClass),
178 get(MetaClass, name, MetaClassName)
179 )
180 -> true
181 ; pce_error(metaclass_not_changed(ClassName))
182 ),
183 send(Class, clear_cache).
184create_class(ClassName, MetaClassName, SuperName, Class) :-
185 ( get(@pce, convert, SuperName, class, Super)
186 -> true
187 ; pce_error(superclass_not_exist(SuperName, ClassName))
188 ),
189 ( MetaClassName == @default
190 -> get(Super, sub_class, ClassName, Class)
191 ; Term =.. [MetaClassName, ClassName, Super],
192 new(Class, Term)
193 ).
201attach_variables([], _).
202attach_variables([V|T], Class) :-
203 catch(send(Class, instance_variable, V), E,
204 pce_error(E)),
205 attach_variables(T, Class).
211attach_class_variables([], _).
212attach_class_variables([R|T], Class) :-
213 attach_class_variable(Class, R),
214 attach_class_variables(T, Class).
215
216attach_class_variable(Class, M:class_variable(Name, Def, Type, Summary)) :-
217 !,
218 classvar_default(Def, PceDef),
219 new(_, M:class_variable(Class, Name, PceDef, Type, Summary)).
220attach_class_variable(Class, ClassVar) :-
221 attach_class_variable(Class, user:ClassVar).
232classvar_default(List, Default) :-
233 is_list(List),
234 !,
235 ( get(@pce, window_system, 'X'),
236 get(@pce, operating_system, OS),
237 sub_atom(OS, _, _, _, darwin),
238 memberchk(apple(AppleDefault), List)
239 -> Default = AppleDefault
240 ; get(@pce, window_system, WS),
241 Term =.. [WS,Default],
242 memberchk(Term, List)
243 -> true
244 ; List = [H|_],
245 compound(H),
246 H =.. [_, Default]
247 -> true
248 ; throw(error(type_error(class_variable_default, List), _))
249 ).
250classvar_default(Default, Default).
251
252
253run_directives([], _).
254run_directives(Directives, Class) :-
255 send(@class, assign, Class),
256 run_directives(Directives).
257
258run_directives([]).
259run_directives([H|T]) :-
260 H,
261 run_directives(T).
262
263delete_prolog_methods(Class) :-
264 get(Class, name, ClassName),
265 ( pce_lazy_send_method(Selector, ClassName, _Binder1),
266 send(Class, delete_send_method, Selector),
267 fail
268 ; pce_lazy_get_method(Selector, ClassName, _Binder2),
269 send(Class, delete_get_method, Selector),
270 fail
271 ; true
272 ).
273
274
275
284resolve_method_message(X) :-
285 X = @pce_resolve_method_message,
286 ( object(X)
287 -> true
288 ; new(X, message(@prolog, call, '_bind_lazy', @arg1, @arg2, @arg3))
289 ).
290
291pce_ifhostproperty(prolog(swi),
292 (:- '$hide'('_bind_lazy'/3))).
293
294pce_ifhostproperty(prolog(swi),
295('_bind_lazy'(Type, ClassName, Selector) :-
297 notrace(do_bind_lazy(Type, ClassName, Selector))),
298('_bind_lazy'(Type, ClassName, Selector) :-
299 do_bind_lazy(Type, ClassName, Selector))).
300
301do_bind_lazy(send, ClassName, @default) :-
302 !,
303 get(@pce, convert, ClassName, class, Class),
304 ( send_binder(Selector, ClassName, Binder),
305 \+ send(Class, bound_send_method, Selector),
306 call_binder(ClassName, Selector, Binder),
307 fail ; true
308 ).
309do_bind_lazy(send, ClassName, Selector) :-
310 send_binder(Selector, ClassName, Binder),
311 call_binder(ClassName, Selector, Binder).
312do_bind_lazy(get, ClassName, @default) :-
313 !,
314 get(@pce, convert, ClassName, class, Class),
315 ( get_binder(Selector, ClassName, Binder),
316 \+ send(Class, bound_get_method, Selector),
317 call_binder(ClassName, Selector, Binder),
318 fail ; true
319 ).
320do_bind_lazy(get, ClassName, Selector) :-
321 get_binder(Selector, ClassName, Binder),
322 call_binder(ClassName, Selector, Binder).
323
331
332send_binder(Sel, Class, Binder) :-
333 bagof(B, pce_lazy_send_method(Sel, Class, B), Binders),
334 last(Binders, Binder).
335get_binder(Sel, Class, Binder) :-
336 bagof(B, pce_lazy_get_method(Sel, Class, B), Binders),
337 last(Binders, Binder).
338
339call_binder(ClassName, Selector, Binder) :-
340 build_in_binder(Binder, ClassName, Selector),
341 !.
342call_binder(ClassName, Selector, Binder) :-
343 call(Binder, ClassName, Selector).
344
345build_in_binder(bind_send(Id, T, D, L, G), C, S) :-
346 !,
347 pce_bind_send(Id, T, D, L, G, C, S).
348build_in_binder(bind_send(Id, T, D, L), C, S) :-
349 !,
350 pce_bind_send(Id, T, D, L, @default, C, S).
351build_in_binder(bind_send(Id, T, D), C, S) :-
352 !,
353 pce_bind_send(Id, T, D, @default, @default, C, S).
354build_in_binder(bind_send(Id, T), C, S) :-
355 !,
356 pce_bind_send(Id, T, @default, @default, @default, C, S).
357
358build_in_binder(bind_get(Id, R, T, D, L, G), C, S) :-
359 !,
360 pce_bind_get(Id, R, T, D, L, G, C, S).
361build_in_binder(bind_get(Id, R, T, D, L), C, S) :-
362 !,
363 pce_bind_get(Id, R, T, D, L, @default, C, S).
364build_in_binder(bind_get(Id, R, T, D), C, S) :-
365 !,
366 pce_bind_get(Id, R, T, D, @default, @default, C, S).
367build_in_binder(bind_get(Id, R, T), C, S) :-
368 !,
369 pce_bind_get(Id, R, T, @default, @default, @default, C, S).
370
371
372pce_bind_send(Id, Types, Doc, Loc, Group, ClassName, Selector) :-
373 get(@pce, convert, ClassName, class, Class),
374 pce_method_implementation(Id, Message),
375 send(Class, send_method,
376 send_method(Selector, Types, Message, Doc, Loc, Group)).
377
378pce_bind_get(Id, RType, Types, Doc, Loc, Group, ClassName, Selector) :-
379 get(@pce, convert, ClassName, class, Class),
380 pce_method_implementation(Id, Message),
381 send(Class, get_method,
382 get_method(Selector, RType, Types, Message, Doc, Loc, Group))