* procs.c (scm_setter): Converted to use generic dispatch.
[bpt/guile.git] / libguile / procs.c
1 /* Copyright (C) 1995,1996,1997 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program 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
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41 \f
42
43 #include <stdio.h>
44 #include "_scm.h"
45
46 #include "objects.h"
47
48 #include "procs.h"
49 \f
50
51
52 /* {Procedures}
53 */
54
55 scm_subr_entry *scm_subr_table;
56
57 /* libguile contained approx. 700 primitive procedures 990824. */
58
59 int scm_subr_table_size = 0;
60 int scm_subr_table_room = 750;
61
62 SCM
63 scm_make_subr_opt (name, type, fcn, set)
64 const char *name;
65 int type;
66 SCM (*fcn) ();
67 int set;
68 {
69 SCM symcell;
70 register SCM z;
71 int entry;
72
73 if (scm_subr_table_size == scm_subr_table_room)
74 {
75 scm_sizet new_size = scm_port_table_room * 3 / 2;
76 void *new_table = scm_must_realloc ((char *) scm_subr_table,
77 scm_subr_table_room,
78 new_size,
79 "scm_make_subr_opt");
80 scm_subr_table = new_table;
81 scm_subr_table_room = new_size;
82 }
83
84 SCM_NEWCELL (z);
85 symcell = set ? scm_sysintern0 (name) : scm_intern0 (name);
86
87 entry = scm_subr_table_size;
88 scm_subr_table[entry].handle = z;
89 scm_subr_table[entry].name = SCM_CAR (symcell);
90 scm_subr_table[entry].generic = 0;
91 scm_subr_table[entry].properties = SCM_EOL;
92 scm_subr_table[entry].documentation = SCM_BOOL_F;
93
94 SCM_SUBRF (z) = fcn;
95 SCM_SETCAR (z, (entry << 8) + type);
96 scm_subr_table_size++;
97
98 if (set)
99 SCM_SETCDR (symcell, z);
100
101 return z;
102 }
103
104 /* This function isn't currently used since subrs are never freed. */
105 /* *fixme* Need mutex here. */
106 void
107 scm_free_subr_entry (SCM subr)
108 {
109 int entry = SCM_SUBRNUM (subr);
110 /* Move last entry in table to the free position */
111 scm_subr_table[entry] = scm_subr_table[scm_subr_table_size - 1];
112 SCM_SET_SUBRNUM (scm_subr_table[entry].handle, entry);
113 scm_subr_table_size--;
114 }
115
116 SCM
117 scm_make_subr (name, type, fcn)
118 const char *name;
119 int type;
120 SCM (*fcn) ();
121 {
122 return scm_make_subr_opt (name, type, fcn, 1);
123 }
124
125 SCM
126 scm_make_subr_with_generic (const char *name, int type, SCM (*fcn) (), SCM *gf)
127 {
128 SCM subr = scm_make_subr_opt (name, type, fcn, 1);
129 scm_subr_table[scm_subr_table_size - 1].generic = gf;
130 return subr;
131 }
132
133 void
134 scm_mark_subr_table ()
135 {
136 int i;
137 for (i = 0; i < scm_subr_table_size; ++i)
138 {
139 SCM_SETGC8MARK (scm_subr_table[i].name);
140 if (scm_subr_table[i].generic && *scm_subr_table[i].generic)
141 scm_gc_mark (*scm_subr_table[i].generic);
142 if (SCM_NIMP (scm_subr_table[i].properties))
143 scm_gc_mark (scm_subr_table[i].properties);
144 if (SCM_NIMP (scm_subr_table[i].documentation))
145 scm_gc_mark (scm_subr_table[i].documentation);
146 }
147 }
148
149
150 #ifdef CCLO
151 SCM
152 scm_makcclo (proc, len)
153 SCM proc;
154 long len;
155 {
156 SCM s;
157 SCM_NEWCELL (s);
158 SCM_DEFER_INTS;
159 SCM_SETCHARS (s, scm_must_malloc (len * sizeof (SCM), "compiled-closure"));
160 SCM_SETLENGTH (s, len, scm_tc7_cclo);
161 while (--len)
162 SCM_VELTS (s)[len] = SCM_UNSPECIFIED;
163 SCM_CCLO_SUBR (s) = proc;
164 SCM_ALLOW_INTS;
165 return s;
166 }
167
168 /* Undocumented debugging procedure */
169 #ifdef GUILE_DEBUG
170 SCM_PROC (s_make_cclo, "make-cclo", 2, 0, 0, scm_make_cclo);
171
172 SCM
173 scm_make_cclo (proc, len)
174 SCM proc;
175 SCM len;
176 {
177 return scm_makcclo (proc, SCM_INUM (len));
178 }
179 #endif
180 #endif
181
182
183
184 SCM_PROC(s_procedure_p, "procedure?", 1, 0, 0, scm_procedure_p);
185
186 SCM
187 scm_procedure_p (obj)
188 SCM obj;
189 {
190 if (SCM_NIMP (obj))
191 switch (SCM_TYP7 (obj))
192 {
193 case scm_tcs_cons_gloc:
194 if (!SCM_I_OPERATORP (obj))
195 break;
196 case scm_tcs_closures:
197 case scm_tc7_contin:
198 case scm_tcs_subrs:
199 #ifdef CCLO
200 case scm_tc7_cclo:
201 #endif
202 case scm_tc7_pws:
203 return SCM_BOOL_T;
204 default:
205 return SCM_BOOL_F;
206 }
207 return SCM_BOOL_F;
208 }
209
210 SCM_PROC(s_closure_p, "closure?", 1, 0, 0, scm_closure_p);
211
212 SCM
213 scm_closure_p (obj)
214 SCM obj;
215 {
216 return SCM_NIMP (obj) && SCM_CLOSUREP (obj) ? SCM_BOOL_T : SCM_BOOL_F;
217 }
218
219 SCM_PROC(s_thunk_p, "thunk?", 1, 0, 0, scm_thunk_p);
220
221 #ifdef __STDC__
222 SCM
223 scm_thunk_p (SCM obj)
224 #else
225 SCM
226 scm_thunk_p (obj)
227 SCM obj;
228 #endif
229 {
230 if (SCM_NIMP (obj))
231 {
232 again:
233 switch (SCM_TYP7 (obj))
234 {
235 case scm_tcs_closures:
236 if (SCM_NULLP (SCM_CAR (SCM_CODE (obj))))
237 return SCM_BOOL_T;
238 case scm_tc7_subr_0:
239 case scm_tc7_subr_1o:
240 case scm_tc7_lsubr:
241 case scm_tc7_rpsubr:
242 case scm_tc7_asubr:
243 #ifdef CCLO
244 case scm_tc7_cclo:
245 #endif
246 return SCM_BOOL_T;
247 case scm_tc7_pws:
248 obj = SCM_PROCEDURE (obj);
249 goto again;
250 default:
251 ;
252 }
253 }
254 return SCM_BOOL_F;
255 }
256
257 /* Only used internally. */
258 int
259 scm_subr_p (SCM obj)
260 {
261 if (SCM_NIMP (obj))
262 switch (SCM_TYP7 (obj))
263 {
264 case scm_tcs_subrs:
265 return 1;
266 default:
267 ;
268 }
269 return 0;
270 }
271
272 SCM_PROC(s_procedure_documentation, "procedure-documentation", 1, 0, 0, scm_procedure_documentation);
273
274 SCM
275 scm_procedure_documentation (proc)
276 SCM proc;
277 {
278 SCM code;
279 SCM_ASSERT (SCM_BOOL_T == scm_procedure_p (proc) && SCM_NIMP (proc) && SCM_TYP7 (proc) != scm_tc7_contin,
280 proc, SCM_ARG1, s_procedure_documentation);
281 switch (SCM_TYP7 (proc))
282 {
283 case scm_tcs_closures:
284 code = SCM_CDR (SCM_CODE (proc));
285 if (SCM_IMP (SCM_CDR (code)))
286 return SCM_BOOL_F;
287 code = SCM_CAR (code);
288 if (SCM_IMP (code))
289 return SCM_BOOL_F;
290 if (SCM_STRINGP (code))
291 return code;
292 default:
293 return SCM_BOOL_F;
294 /*
295 case scm_tcs_subrs:
296 #ifdef CCLO
297 case scm_tc7_cclo:
298 #endif
299 */
300 }
301 }
302
303
304 /* Procedure-with-setter
305 */
306
307 SCM_PROC (s_procedure_with_setter_p, "procedure-with-setter?", 1, 0, 0, scm_procedure_with_setter_p);
308
309 SCM
310 scm_procedure_with_setter_p (SCM obj)
311 {
312 return (SCM_NIMP (obj) && SCM_PROCEDURE_WITH_SETTER_P (obj)
313 ? SCM_BOOL_T
314 : SCM_BOOL_F);
315 }
316
317 SCM_PROC (s_make_procedure_with_setter, "make-procedure-with-setter", 2, 0, 0, scm_make_procedure_with_setter);
318
319 SCM
320 scm_make_procedure_with_setter (SCM procedure, SCM setter)
321 {
322 SCM z;
323 SCM_ASSERT (SCM_NFALSEP (scm_procedure_p (procedure)),
324 procedure, SCM_ARG1, s_make_procedure_with_setter);
325 SCM_ASSERT (SCM_NFALSEP (scm_procedure_p (setter)),
326 setter, SCM_ARG2, s_make_procedure_with_setter);
327 SCM_NEWCELL (z);
328 SCM_ENTER_A_SECTION;
329 SCM_SETCDR (z, scm_cons (procedure, setter));
330 SCM_SETCAR (z, scm_tc7_pws);
331 SCM_EXIT_A_SECTION;
332 return z;
333 }
334
335 SCM_PROC (s_procedure, "procedure", 1, 0, 0, scm_procedure);
336
337 SCM
338 scm_procedure (SCM proc)
339 {
340 SCM_ASSERT (SCM_NIMP (proc), proc, SCM_ARG1, s_procedure);
341 if (SCM_PROCEDURE_WITH_SETTER_P (proc))
342 return SCM_PROCEDURE (proc);
343 else if (SCM_STRUCTP (proc))
344 {
345 SCM_ASSERT (SCM_I_OPERATORP (proc), proc, SCM_ARG1, s_procedure);
346 return proc;
347 }
348 scm_wrong_type_arg (s_procedure, SCM_ARG1, proc);
349 return 0; /* not reached */
350 }
351
352 SCM_GPROC (s_setter, "setter", 1, 0, 0, scm_setter, g_setter);
353
354 SCM
355 scm_setter (SCM proc)
356 {
357 SCM_GASSERT1 (SCM_NIMP (proc), g_setter, proc, SCM_ARG1, s_setter);
358 if (SCM_PROCEDURE_WITH_SETTER_P (proc))
359 return SCM_SETTER (proc);
360 else if (SCM_STRUCTP (proc))
361 {
362 SCM_GASSERT1 (SCM_I_OPERATORP (proc),
363 g_setter, proc, SCM_ARG1, s_setter);
364 return (SCM_I_ENTITYP (proc)
365 ? SCM_ENTITY_SETTER (proc)
366 : SCM_OPERATOR_SETTER (proc));
367 }
368 SCM_WTA_DISPATCH_1 (g_setter, proc, SCM_ARG1, s_setter);
369 return 0;
370 }
371
372
373 void
374 scm_init_iprocs(subra, type)
375 const scm_iproc *subra;
376 int type;
377 {
378 for(;subra->scm_string; subra++)
379 scm_make_subr(subra->scm_string,
380 type,
381 subra->cproc);
382 }
383
384
385 void
386 scm_init_subr_table ()
387 {
388 scm_subr_table
389 = ((scm_subr_entry *)
390 scm_must_malloc (sizeof (scm_subr_entry) * scm_subr_table_room,
391 "scm_subr_table"));
392 }
393
394 void
395 scm_init_procs ()
396 {
397 #include "procs.x"
398 }