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