Generics with setters have <applicable-struct-with-setter> layout
[bpt/guile.git] / libguile / deprecated.c
1 /* This file contains definitions for deprecated features. When you
2 deprecate something, move it here when that is feasible.
3 */
4
5 /* Copyright (C) 2003, 2004, 2006, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #define SCM_BUILDING_DEPRECATED_CODE
28
29 #include "libguile/_scm.h"
30 #include "libguile/deprecation.h"
31
32 #if (SCM_ENABLE_DEPRECATED == 1)
33
34 \f
35
36 SCM
37 scm_internal_dynamic_wind (scm_t_guard before,
38 scm_t_inner inner,
39 scm_t_guard after,
40 void *inner_data,
41 void *guard_data)
42 {
43 SCM ans;
44
45 scm_c_issue_deprecation_warning
46 ("`scm_internal_dynamic_wind' is deprecated. "
47 "Use the `scm_dynwind_begin' / `scm_dynwind_end' API instead.");
48
49 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
50 scm_dynwind_rewind_handler (before, guard_data, SCM_F_WIND_EXPLICITLY);
51 scm_dynwind_unwind_handler (after, guard_data, SCM_F_WIND_EXPLICITLY);
52 ans = inner (inner_data);
53 scm_dynwind_end ();
54 return ans;
55 }
56
57 \f
58
59 SCM
60 scm_immutable_cell (scm_t_bits car, scm_t_bits cdr)
61 {
62 scm_c_issue_deprecation_warning
63 ("scm_immutable_cell is deprecated. Use scm_cell instead.");
64
65 return scm_cell (car, cdr);
66 }
67
68 SCM
69 scm_immutable_double_cell (scm_t_bits car, scm_t_bits cbr,
70 scm_t_bits ccr, scm_t_bits cdr)
71 {
72 scm_c_issue_deprecation_warning
73 ("scm_immutable_double_cell is deprecated. Use scm_double_cell instead.");
74
75 return scm_double_cell (car, cbr, ccr, cdr);
76 }
77
78
79 \f
80
81 SCM_GLOBAL_SYMBOL (scm_memory_alloc_key, "memory-allocation-error");
82 void
83 scm_memory_error (const char *subr)
84 {
85 scm_c_issue_deprecation_warning
86 ("scm_memory_error is deprecated. Use scm_report_out_of_memory to raise "
87 "an exception, or abort() to cause the program to exit.");
88
89 fprintf (stderr, "FATAL: memory error in %s\n", subr);
90 abort ();
91 }
92
93
94 \f
95
96 SCM scm_no_applicable_method = SCM_BOOL_F;
97
98 void
99 scm_init_deprecated_goops (void)
100 {
101 scm_no_applicable_method =
102 scm_variable_ref (scm_c_lookup ("no-applicable-method"));
103 }
104
105 #define BUFFSIZE 32 /* big enough for most uses */
106 #define SPEC_OF(x) \
107 (scm_slot_ref (x, scm_slot_ref (x, scm_from_latin1_symbol ("specializers"))))
108 #define CPL_OF(x) \
109 (scm_slot_ref (x, scm_slot_ref (x, scm_from_latin1_symbol ("cpl"))))
110
111 static SCM
112 scm_i_vector2list (SCM l, long len)
113 {
114 long j;
115 SCM z = scm_c_make_vector (len, SCM_UNDEFINED);
116
117 for (j = 0; j < len; j++, l = SCM_CDR (l)) {
118 SCM_SIMPLE_VECTOR_SET (z, j, SCM_CAR (l));
119 }
120 return z;
121 }
122
123 static int
124 applicablep (SCM actual, SCM formal)
125 {
126 /* We already know that the cpl is well formed. */
127 return scm_is_true (scm_c_memq (formal, CPL_OF (actual)));
128 }
129
130 static int
131 more_specificp (SCM m1, SCM m2, SCM const *targs)
132 {
133 register SCM s1, s2;
134 register long i;
135 /*
136 * Note:
137 * m1 and m2 can have != length (i.e. one can be one element longer than the
138 * other when we have a dotted parameter list). For instance, with the call
139 * (M 1)
140 * with
141 * (define-method M (a . l) ....)
142 * (define-method M (a) ....)
143 *
144 * we consider that the second method is more specific.
145 *
146 * BTW, targs is an array of types. We don't need it's size since
147 * we already know that m1 and m2 are applicable (no risk to go past
148 * the end of this array).
149 *
150 */
151 for (i=0, s1=SPEC_OF(m1), s2=SPEC_OF(m2); ; i++, s1=SCM_CDR(s1), s2=SCM_CDR(s2)) {
152 if (scm_is_null(s1)) return 1;
153 if (scm_is_null(s2)) return 0;
154 if (!scm_is_eq (SCM_CAR(s1), SCM_CAR(s2))) {
155 register SCM l, cs1 = SCM_CAR(s1), cs2 = SCM_CAR(s2);
156
157 for (l = CPL_OF (targs[i]); ; l = SCM_CDR(l)) {
158 if (scm_is_eq (cs1, SCM_CAR (l)))
159 return 1;
160 if (scm_is_eq (cs2, SCM_CAR (l)))
161 return 0;
162 }
163 return 0;/* should not occur! */
164 }
165 }
166 return 0; /* should not occur! */
167 }
168
169 static SCM
170 sort_applicable_methods (SCM method_list, long size, SCM const *targs)
171 {
172 long i, j, incr;
173 SCM *v, vector = SCM_EOL;
174 SCM buffer[BUFFSIZE];
175 SCM save = method_list;
176 scm_t_array_handle handle;
177
178 /* For reasonably sized method_lists we can try to avoid all the
179 * consing and reorder the list in place...
180 * This idea is due to David McClain <Dave_McClain@msn.com>
181 */
182 if (size <= BUFFSIZE)
183 {
184 for (i = 0; i < size; i++)
185 {
186 buffer[i] = SCM_CAR (method_list);
187 method_list = SCM_CDR (method_list);
188 }
189 v = buffer;
190 }
191 else
192 {
193 /* Too many elements in method_list to keep everything locally */
194 vector = scm_i_vector2list (save, size);
195 v = scm_vector_writable_elements (vector, &handle, NULL, NULL);
196 }
197
198 /* Use a simple shell sort since it is generally faster than qsort on
199 * small vectors (which is probably mostly the case when we have to
200 * sort a list of applicable methods).
201 */
202 for (incr = size / 2; incr; incr /= 2)
203 {
204 for (i = incr; i < size; i++)
205 {
206 for (j = i - incr; j >= 0; j -= incr)
207 {
208 if (more_specificp (v[j], v[j+incr], targs))
209 break;
210 else
211 {
212 SCM tmp = v[j + incr];
213 v[j + incr] = v[j];
214 v[j] = tmp;
215 }
216 }
217 }
218 }
219
220 if (size <= BUFFSIZE)
221 {
222 /* We did it in locally, so restore the original list (reordered) in-place */
223 for (i = 0, method_list = save; i < size; i++, v++)
224 {
225 SCM_SETCAR (method_list, *v);
226 method_list = SCM_CDR (method_list);
227 }
228 return save;
229 }
230
231 /* If we are here, that's that we did it the hard way... */
232 scm_array_handle_release (&handle);
233 return scm_vector_to_list (vector);
234 }
235
236 SCM
237 scm_compute_applicable_methods (SCM gf, SCM args, long len, int find_method_p)
238 {
239 register long i;
240 long count = 0;
241 SCM l, fl, applicable = SCM_EOL;
242 SCM save = args;
243 SCM buffer[BUFFSIZE];
244 SCM const *types;
245 SCM *p;
246 SCM tmp = SCM_EOL;
247 scm_t_array_handle handle;
248
249 scm_c_issue_deprecation_warning
250 ("scm_compute_applicable_methods is deprecated. Use "
251 "`compute-applicable-methods' from Scheme instead.");
252
253 /* Build the list of arguments types */
254 if (len >= BUFFSIZE)
255 {
256 tmp = scm_c_make_vector (len, SCM_UNDEFINED);
257 types = p = scm_vector_writable_elements (tmp, &handle, NULL, NULL);
258
259 /*
260 note that we don't have to work to reset the generation
261 count. TMP is a new vector anyway, and it is found
262 conservatively.
263 */
264 }
265 else
266 types = p = buffer;
267
268 for ( ; !scm_is_null (args); args = SCM_CDR (args))
269 *p++ = scm_class_of (SCM_CAR (args));
270
271 /* Build a list of all applicable methods */
272 for (l = scm_generic_function_methods (gf); !scm_is_null (l); l = SCM_CDR (l))
273 {
274 fl = SPEC_OF (SCM_CAR (l));
275 for (i = 0; ; i++, fl = SCM_CDR (fl))
276 {
277 if (SCM_INSTANCEP (fl)
278 /* We have a dotted argument list */
279 || (i >= len && scm_is_null (fl)))
280 { /* both list exhausted */
281 applicable = scm_cons (SCM_CAR (l), applicable);
282 count += 1;
283 break;
284 }
285 if (i >= len
286 || scm_is_null (fl)
287 || !applicablep (types[i], SCM_CAR (fl)))
288 break;
289 }
290 }
291
292 if (len >= BUFFSIZE)
293 scm_array_handle_release (&handle);
294
295 if (count == 0)
296 {
297 if (find_method_p)
298 return SCM_BOOL_F;
299 scm_call_2 (scm_no_applicable_method, gf, save);
300 /* if we are here, it's because no-applicable-method hasn't signaled an error */
301 return SCM_BOOL_F;
302 }
303
304 return (count == 1
305 ? applicable
306 : sort_applicable_methods (applicable, count, types));
307 }
308
309 SCM_SYMBOL (sym_compute_applicable_methods, "compute-applicable-methods");
310
311 SCM
312 scm_find_method (SCM l)
313 #define FUNC_NAME "find-method"
314 {
315 SCM gf;
316 long len = scm_ilength (l);
317
318 if (len == 0)
319 SCM_WRONG_NUM_ARGS ();
320
321 scm_c_issue_deprecation_warning
322 ("scm_find_method is deprecated. Use `compute-applicable-methods' "
323 "from Scheme instead.");
324
325 gf = SCM_CAR(l); l = SCM_CDR(l);
326 SCM_VALIDATE_GENERIC (1, gf);
327 if (scm_is_null (scm_slot_ref (gf, scm_from_latin1_symbol ("methods"))))
328 SCM_MISC_ERROR ("no methods for generic ~S", scm_list_1 (gf));
329
330 return scm_compute_applicable_methods (gf, l, len - 1, 1);
331 }
332 #undef FUNC_NAME
333
334 SCM
335 scm_basic_make_class (SCM meta, SCM name, SCM dsupers, SCM dslots)
336 {
337 scm_c_issue_deprecation_warning
338 ("scm_basic_make_class is deprecated. Use `define-class' in Scheme,"
339 "or use `(make META #:name NAME #:dsupers DSUPERS #:slots DSLOTS)' "
340 "in Scheme.");
341
342 return scm_make_standard_class (meta, name, dsupers, dslots);
343 }
344
345
346 \f
347
348 void
349 scm_i_init_deprecated ()
350 {
351 #include "libguile/deprecated.x"
352 }
353
354 #endif