Merge commit '5bb2d903b9e54fdd5858a16ba11fa91a9dc0c692' into vm-check
[bpt/guile.git] / libguile / procs.c
1 /* Copyright (C) 1995,1996,1997,1999,2000,2001, 2006, 2008 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18
19 \f
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "libguile/_scm.h"
25
26 #include "libguile/objects.h"
27 #include "libguile/strings.h"
28 #include "libguile/vectors.h"
29 #include "libguile/smob.h"
30 #include "libguile/deprecation.h"
31
32 #include "libguile/validate.h"
33 #include "libguile/procs.h"
34 #include "libguile/procprop.h"
35 #include "libguile/objcodes.h"
36 #include "libguile/programs.h"
37 \f
38
39
40 /* {Procedures}
41 */
42
43 scm_t_subr_entry *scm_subr_table;
44
45 /* libguile contained approx. 700 primitive procedures on 24 Aug 1999. */
46
47 /* Increased to 800 on 2001-05-07 -- Guile now has 779 primitives on
48 startup, 786 with guile-readline. 'martin */
49
50 static unsigned long scm_subr_table_size = 0;
51 static unsigned long scm_subr_table_room = 800;
52
53 SCM
54 scm_c_make_subr (const char *name, long type, SCM (*fcn) ())
55 {
56 register SCM z;
57 unsigned long entry;
58
59 if (scm_subr_table_size == scm_subr_table_room)
60 {
61 long new_size = scm_subr_table_room * 3 / 2;
62 void *new_table
63 = scm_realloc ((char *) scm_subr_table,
64 sizeof (scm_t_subr_entry) * new_size);
65 scm_subr_table = new_table;
66 scm_subr_table_room = new_size;
67 }
68
69 entry = scm_subr_table_size;
70 z = scm_cell ((entry << 8) + type, (scm_t_bits) fcn);
71 scm_subr_table[entry].handle = z;
72 scm_subr_table[entry].name = scm_from_locale_symbol (name);
73 scm_subr_table[entry].generic = 0;
74 scm_subr_table[entry].properties = SCM_EOL;
75 scm_subr_table_size++;
76
77 return z;
78 }
79
80 SCM
81 scm_c_define_subr (const char *name, long type, SCM (*fcn) ())
82 {
83 SCM subr = scm_c_make_subr (name, type, fcn);
84 scm_define (SCM_SUBR_ENTRY(subr).name, subr);
85 return subr;
86 }
87
88 /* This function isn't currently used since subrs are never freed. */
89 /* *fixme* Need mutex here. */
90 void
91 scm_free_subr_entry (SCM subr)
92 {
93 long entry = SCM_SUBRNUM (subr);
94 /* Move last entry in table to the free position */
95 scm_subr_table[entry] = scm_subr_table[scm_subr_table_size - 1];
96 SCM_SET_SUBRNUM (scm_subr_table[entry].handle, entry);
97 scm_subr_table_size--;
98 }
99
100 SCM
101 scm_c_make_subr_with_generic (const char *name,
102 long type, SCM (*fcn) (), SCM *gf)
103 {
104 SCM subr = scm_c_make_subr (name, type, fcn);
105 SCM_SUBR_ENTRY(subr).generic = gf;
106 return subr;
107 }
108
109 SCM
110 scm_c_define_subr_with_generic (const char *name,
111 long type, SCM (*fcn) (), SCM *gf)
112 {
113 SCM subr = scm_c_make_subr_with_generic (name, type, fcn, gf);
114 scm_define (SCM_SUBR_ENTRY(subr).name, subr);
115 return subr;
116 }
117
118 void
119 scm_mark_subr_table ()
120 {
121 long i;
122 for (i = 0; i < scm_subr_table_size; ++i)
123 {
124 scm_gc_mark (scm_subr_table[i].name);
125 if (scm_subr_table[i].generic && *scm_subr_table[i].generic)
126 scm_gc_mark (*scm_subr_table[i].generic);
127 if (SCM_NIMP (scm_subr_table[i].properties))
128 scm_gc_mark (scm_subr_table[i].properties);
129 }
130 }
131
132
133 #ifdef CCLO
134 SCM
135 scm_makcclo (SCM proc, size_t len)
136 {
137 scm_t_bits *base = scm_gc_malloc (len * sizeof (scm_t_bits),
138 "compiled closure");
139 unsigned long i;
140 SCM s;
141
142 for (i = 0; i < len; ++i)
143 base [i] = SCM_UNPACK (SCM_UNSPECIFIED);
144
145 s = scm_cell (SCM_MAKE_CCLO_TAG (len), (scm_t_bits) base);
146 SCM_SET_CCLO_SUBR (s, proc);
147 return s;
148 }
149
150 /* Undocumented debugging procedure */
151 #ifdef GUILE_DEBUG
152 SCM_DEFINE (scm_make_cclo, "make-cclo", 2, 0, 0,
153 (SCM proc, SCM len),
154 "Create a compiled closure for @var{proc}, which reserves\n"
155 "@var{len} objects for its usage.")
156 #define FUNC_NAME s_scm_make_cclo
157 {
158 return scm_makcclo (proc, scm_to_size_t (len));
159 }
160 #undef FUNC_NAME
161 #endif
162 #endif
163
164
165
166 SCM_DEFINE (scm_procedure_p, "procedure?", 1, 0, 0,
167 (SCM obj),
168 "Return @code{#t} if @var{obj} is a procedure.")
169 #define FUNC_NAME s_scm_procedure_p
170 {
171 if (SCM_NIMP (obj))
172 switch (SCM_TYP7 (obj))
173 {
174 case scm_tcs_struct:
175 if (!SCM_I_OPERATORP (obj))
176 break;
177 case scm_tcs_closures:
178 case scm_tcs_subrs:
179 #ifdef CCLO
180 case scm_tc7_cclo:
181 #endif
182 case scm_tc7_pws:
183 return SCM_BOOL_T;
184 case scm_tc7_smob:
185 return scm_from_bool (SCM_SMOB_DESCRIPTOR (obj).apply);
186 default:
187 return SCM_BOOL_F;
188 }
189 return SCM_BOOL_F;
190 }
191 #undef FUNC_NAME
192
193 SCM_DEFINE (scm_closure_p, "closure?", 1, 0, 0,
194 (SCM obj),
195 "Return @code{#t} if @var{obj} is a closure.")
196 #define FUNC_NAME s_scm_closure_p
197 {
198 return scm_from_bool (SCM_CLOSUREP (obj));
199 }
200 #undef FUNC_NAME
201
202 SCM_DEFINE (scm_thunk_p, "thunk?", 1, 0, 0,
203 (SCM obj),
204 "Return @code{#t} if @var{obj} is a thunk.")
205 #define FUNC_NAME s_scm_thunk_p
206 {
207 if (SCM_NIMP (obj))
208 {
209 again:
210 switch (SCM_TYP7 (obj))
211 {
212 case scm_tcs_closures:
213 return scm_from_bool (!scm_is_pair (SCM_CLOSURE_FORMALS (obj)));
214 case scm_tc7_subr_0:
215 case scm_tc7_subr_1o:
216 case scm_tc7_lsubr:
217 case scm_tc7_rpsubr:
218 case scm_tc7_asubr:
219 #ifdef CCLO
220 case scm_tc7_cclo:
221 #endif
222 return SCM_BOOL_T;
223 case scm_tc7_pws:
224 obj = SCM_PROCEDURE (obj);
225 goto again;
226 default:
227 if (SCM_PROGRAM_P (obj) && SCM_PROGRAM_DATA (obj)->nargs == 0)
228 return SCM_BOOL_T;
229 /* otherwise fall through */
230 }
231 }
232 return SCM_BOOL_F;
233 }
234 #undef FUNC_NAME
235
236 /* Only used internally. */
237 int
238 scm_subr_p (SCM obj)
239 {
240 if (SCM_NIMP (obj))
241 switch (SCM_TYP7 (obj))
242 {
243 case scm_tcs_subrs:
244 return 1;
245 default:
246 ;
247 }
248 return 0;
249 }
250
251 SCM_DEFINE (scm_procedure_documentation, "procedure-documentation", 1, 0, 0,
252 (SCM proc),
253 "Return the documentation string associated with @code{proc}. By\n"
254 "convention, if a procedure contains more than one expression and the\n"
255 "first expression is a string constant, that string is assumed to contain\n"
256 "documentation for that procedure.")
257 #define FUNC_NAME s_scm_procedure_documentation
258 {
259 SCM code;
260 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
261 proc, SCM_ARG1, FUNC_NAME);
262 switch (SCM_TYP7 (proc))
263 {
264 case scm_tcs_closures:
265 code = SCM_CLOSURE_BODY (proc);
266 if (scm_is_null (SCM_CDR (code)))
267 return SCM_BOOL_F;
268 code = SCM_CAR (code);
269 if (scm_is_string (code))
270 return code;
271 else
272 return SCM_BOOL_F;
273 default:
274 return SCM_BOOL_F;
275 /*
276 case scm_tcs_subrs:
277 #ifdef CCLO
278 case scm_tc7_cclo:
279 #endif
280 */
281 }
282 }
283 #undef FUNC_NAME
284
285
286 /* Procedure-with-setter
287 */
288
289 SCM_DEFINE (scm_procedure_with_setter_p, "procedure-with-setter?", 1, 0, 0,
290 (SCM obj),
291 "Return @code{#t} if @var{obj} is a procedure with an\n"
292 "associated setter procedure.")
293 #define FUNC_NAME s_scm_procedure_with_setter_p
294 {
295 return scm_from_bool(SCM_PROCEDURE_WITH_SETTER_P (obj));
296 }
297 #undef FUNC_NAME
298
299 SCM_DEFINE (scm_make_procedure_with_setter, "make-procedure-with-setter", 2, 0, 0,
300 (SCM procedure, SCM setter),
301 "Create a new procedure which behaves like @var{procedure}, but\n"
302 "with the associated setter @var{setter}.")
303 #define FUNC_NAME s_scm_make_procedure_with_setter
304 {
305 SCM name, ret;
306 SCM_VALIDATE_PROC (1, procedure);
307 SCM_VALIDATE_PROC (2, setter);
308 ret = scm_double_cell (scm_tc7_pws,
309 SCM_UNPACK (procedure),
310 SCM_UNPACK (setter), 0);
311 /* don't use procedure_name, because don't care enough to do a reverse
312 lookup */
313 switch (SCM_TYP7 (procedure)) {
314 case scm_tcs_subrs:
315 name = SCM_SNAME (procedure);
316 break;
317 default:
318 name = scm_procedure_property (procedure, scm_sym_name);
319 break;
320 }
321 if (scm_is_true (name))
322 scm_set_procedure_property_x (ret, scm_sym_name, name);
323 return ret;
324 }
325 #undef FUNC_NAME
326
327 SCM_DEFINE (scm_procedure, "procedure", 1, 0, 0,
328 (SCM proc),
329 "Return the procedure of @var{proc}, which must be either a\n"
330 "procedure with setter, or an operator struct.")
331 #define FUNC_NAME s_scm_procedure
332 {
333 SCM_VALIDATE_NIM (1, proc);
334 if (SCM_PROCEDURE_WITH_SETTER_P (proc))
335 return SCM_PROCEDURE (proc);
336 else if (SCM_STRUCTP (proc))
337 {
338 SCM_ASSERT (SCM_I_OPERATORP (proc), proc, SCM_ARG1, FUNC_NAME);
339 return proc;
340 }
341 SCM_WRONG_TYPE_ARG (1, proc);
342 return SCM_BOOL_F; /* not reached */
343 }
344 #undef FUNC_NAME
345
346 SCM_GPROC (s_setter, "setter", 1, 0, 0, scm_setter, g_setter);
347
348 SCM
349 scm_setter (SCM proc)
350 {
351 SCM_GASSERT1 (SCM_NIMP (proc), g_setter, proc, SCM_ARG1, s_setter);
352 if (SCM_PROCEDURE_WITH_SETTER_P (proc))
353 return SCM_SETTER (proc);
354 else if (SCM_STRUCTP (proc))
355 {
356 SCM setter;
357 SCM_GASSERT1 (SCM_I_OPERATORP (proc),
358 g_setter, proc, SCM_ARG1, s_setter);
359 setter = (SCM_I_ENTITYP (proc)
360 ? SCM_ENTITY_SETTER (proc)
361 : SCM_OPERATOR_SETTER (proc));
362 if (SCM_NIMP (setter))
363 return setter;
364 /* fall through */
365 }
366 SCM_WTA_DISPATCH_1 (g_setter, proc, SCM_ARG1, s_setter);
367 return SCM_BOOL_F; /* not reached */
368 }
369
370
371 void
372 scm_init_subr_table ()
373 {
374 scm_subr_table
375 = ((scm_t_subr_entry *)
376 scm_malloc (sizeof (scm_t_subr_entry) * scm_subr_table_room));
377 }
378
379 void
380 scm_init_procs ()
381 {
382 #include "libguile/procs.x"
383 }
384
385 /*
386 Local Variables:
387 c-file-style: "gnu"
388 End:
389 */