make-procedure-with-setter inherits name from getter
[bpt/guile.git] / libguile / procs.c
CommitLineData
dbb605f5 1/* Copyright (C) 1995,1996,1997,1999,2000,2001, 2006, 2008 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
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.
0f2d19dd 7 *
73be1d9e
MV
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.
0f2d19dd 12 *
73be1d9e
MV
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
92205699 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73be1d9e 16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd 19\f
dbb605f5
LC
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
0f2d19dd 23
a0599745 24#include "libguile/_scm.h"
0f2d19dd 25
a0599745
MD
26#include "libguile/objects.h"
27#include "libguile/strings.h"
28#include "libguile/vectors.h"
0717dfd8 29#include "libguile/smob.h"
c88a8162 30#include "libguile/deprecation.h"
bdc88419 31
a0599745
MD
32#include "libguile/validate.h"
33#include "libguile/procs.h"
3fd8807e 34#include "libguile/procprop.h"
7e580328 35#include "libguile/programs.h"
0f2d19dd
JB
36\f
37
38
39/* {Procedures}
40 */
41
92c2555f 42scm_t_subr_entry *scm_subr_table;
9de33deb 43
98f9c984 44/* libguile contained approx. 700 primitive procedures on 24 Aug 1999. */
9de33deb 45
7c582ec9
MG
46/* Increased to 800 on 2001-05-07 -- Guile now has 779 primitives on
47 startup, 786 with guile-readline. 'martin */
48
c014a02e
ML
49long scm_subr_table_size = 0;
50long scm_subr_table_room = 800;
1cc91f1b 51
0f2d19dd 52SCM
c014a02e 53scm_c_make_subr (const char *name, long type, SCM (*fcn) ())
0f2d19dd 54{
0f2d19dd 55 register SCM z;
c014a02e 56 long entry;
9de33deb
MD
57
58 if (scm_subr_table_size == scm_subr_table_room)
59 {
c014a02e 60 long new_size = scm_subr_table_room * 3 / 2;
98f9c984 61 void *new_table
4c9419ac
MV
62 = scm_realloc ((char *) scm_subr_table,
63 sizeof (scm_t_subr_entry) * new_size);
9de33deb
MD
64 scm_subr_table = new_table;
65 scm_subr_table_room = new_size;
66 }
67
9de33deb 68 entry = scm_subr_table_size;
228a24ef 69 z = scm_cell ((entry << 8) + type, (scm_t_bits) fcn);
9de33deb 70 scm_subr_table[entry].handle = z;
cc95e00a 71 scm_subr_table[entry].name = scm_from_locale_symbol (name);
9de33deb 72 scm_subr_table[entry].generic = 0;
23a62df4 73 scm_subr_table[entry].properties = SCM_EOL;
9de33deb
MD
74 scm_subr_table_size++;
75
0f2d19dd
JB
76 return z;
77}
78
c88a8162 79SCM
c014a02e 80scm_c_define_subr (const char *name, long type, SCM (*fcn) ())
c88a8162
MV
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
9de33deb
MD
87/* This function isn't currently used since subrs are never freed. */
88/* *fixme* Need mutex here. */
89void
90scm_free_subr_entry (SCM subr)
91{
c014a02e 92 long entry = SCM_SUBRNUM (subr);
9de33deb
MD
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}
1cc91f1b 98
c88a8162
MV
99SCM
100scm_c_make_subr_with_generic (const char *name,
c014a02e 101 long type, SCM (*fcn) (), SCM *gf)
0f2d19dd 102{
c88a8162
MV
103 SCM subr = scm_c_make_subr (name, type, fcn);
104 SCM_SUBR_ENTRY(subr).generic = gf;
105 return subr;
0f2d19dd
JB
106}
107
9de33deb 108SCM
c88a8162 109scm_c_define_subr_with_generic (const char *name,
c014a02e 110 long type, SCM (*fcn) (), SCM *gf)
9de33deb 111{
c88a8162
MV
112 SCM subr = scm_c_make_subr_with_generic (name, type, fcn, gf);
113 scm_define (SCM_SUBR_ENTRY(subr).name, subr);
9de33deb
MD
114 return subr;
115}
116
117void
118scm_mark_subr_table ()
119{
c014a02e 120 long i;
9de33deb
MD
121 for (i = 0; i < scm_subr_table_size; ++i)
122 {
eab1b259 123 scm_gc_mark (scm_subr_table[i].name);
9de33deb
MD
124 if (scm_subr_table[i].generic && *scm_subr_table[i].generic)
125 scm_gc_mark (*scm_subr_table[i].generic);
23a62df4
DH
126 if (SCM_NIMP (scm_subr_table[i].properties))
127 scm_gc_mark (scm_subr_table[i].properties);
9de33deb
MD
128 }
129}
1cc91f1b 130
9de33deb
MD
131
132#ifdef CCLO
0f2d19dd 133SCM
1be6b49c 134scm_makcclo (SCM proc, size_t len)
0f2d19dd 135{
4c9419ac
MV
136 scm_t_bits *base = scm_gc_malloc (len * sizeof (scm_t_bits),
137 "compiled closure");
74cc8503 138 unsigned long i;
0f2d19dd 139 SCM s;
74cc8503
DH
140
141 for (i = 0; i < len; ++i)
142 base [i] = SCM_UNPACK (SCM_UNSPECIFIED);
143
228a24ef 144 s = scm_cell (SCM_MAKE_CCLO_TAG (len), (scm_t_bits) base);
74cc8503 145 SCM_SET_CCLO_SUBR (s, proc);
0f2d19dd
JB
146 return s;
147}
d88094f9
MD
148
149/* Undocumented debugging procedure */
150#ifdef GUILE_DEBUG
a1ec6916 151SCM_DEFINE (scm_make_cclo, "make-cclo", 2, 0, 0,
1bbd0b84 152 (SCM proc, SCM len),
8cf97abf
MG
153 "Create a compiled closure for @var{proc}, which reserves\n"
154 "@var{len} objects for its usage.")
1bbd0b84 155#define FUNC_NAME s_scm_make_cclo
d88094f9 156{
e11e83f3 157 return scm_makcclo (proc, scm_to_size_t (len));
d88094f9 158}
1bbd0b84 159#undef FUNC_NAME
d88094f9 160#endif
0f2d19dd
JB
161#endif
162
163
164
3b3b36dd 165SCM_DEFINE (scm_procedure_p, "procedure?", 1, 0, 0,
8cf97abf
MG
166 (SCM obj),
167 "Return @code{#t} if @var{obj} is a procedure.")
1bbd0b84 168#define FUNC_NAME s_scm_procedure_p
0f2d19dd
JB
169{
170 if (SCM_NIMP (obj))
171 switch (SCM_TYP7 (obj))
172 {
904a077d 173 case scm_tcs_struct:
bdc88419
MD
174 if (!SCM_I_OPERATORP (obj))
175 break;
0f2d19dd 176 case scm_tcs_closures:
0f2d19dd
JB
177 case scm_tcs_subrs:
178#ifdef CCLO
179 case scm_tc7_cclo:
180#endif
b4cd6492 181 case scm_tc7_pws:
0f2d19dd 182 return SCM_BOOL_T;
0717dfd8 183 case scm_tc7_smob:
7888309b 184 return scm_from_bool (SCM_SMOB_DESCRIPTOR (obj).apply);
0f2d19dd
JB
185 default:
186 return SCM_BOOL_F;
187 }
188 return SCM_BOOL_F;
189}
1bbd0b84 190#undef FUNC_NAME
0f2d19dd 191
3b3b36dd 192SCM_DEFINE (scm_closure_p, "closure?", 1, 0, 0,
1bbd0b84 193 (SCM obj),
8cf97abf 194 "Return @code{#t} if @var{obj} is a closure.")
1bbd0b84 195#define FUNC_NAME s_scm_closure_p
ecdb5eb2 196{
7888309b 197 return scm_from_bool (SCM_CLOSUREP (obj));
ecdb5eb2 198}
1bbd0b84 199#undef FUNC_NAME
ecdb5eb2 200
3b3b36dd 201SCM_DEFINE (scm_thunk_p, "thunk?", 1, 0, 0,
8cf97abf
MG
202 (SCM obj),
203 "Return @code{#t} if @var{obj} is a thunk.")
1bbd0b84 204#define FUNC_NAME s_scm_thunk_p
44bd53b9
MD
205{
206 if (SCM_NIMP (obj))
b4cd6492
MD
207 {
208 again:
209 switch (SCM_TYP7 (obj))
210 {
211 case scm_tcs_closures:
d2e53ed6 212 return scm_from_bool (!scm_is_pair (SCM_CLOSURE_FORMALS (obj)));
b4cd6492
MD
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:
44bd53b9 218#ifdef CCLO
b4cd6492 219 case scm_tc7_cclo:
44bd53b9 220#endif
b4cd6492
MD
221 return SCM_BOOL_T;
222 case scm_tc7_pws:
223 obj = SCM_PROCEDURE (obj);
224 goto again;
225 default:
7e580328
AW
226 if (SCM_PROGRAM_P (obj) && SCM_PROGRAM_DATA (obj)->nargs == 0)
227 return SCM_BOOL_T;
228 /* otherwise fall through */
b4cd6492
MD
229 }
230 }
44bd53b9
MD
231 return SCM_BOOL_F;
232}
1bbd0b84 233#undef FUNC_NAME
44bd53b9 234
9de33deb
MD
235/* Only used internally. */
236int
237scm_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
3b3b36dd 250SCM_DEFINE (scm_procedure_documentation, "procedure-documentation", 1, 0, 0,
1bbd0b84 251 (SCM proc),
b380b885
MD
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.")
1bbd0b84 256#define FUNC_NAME s_scm_procedure_documentation
c2c82fba
MD
257{
258 SCM code;
bc36d050 259 SCM_ASSERT (scm_is_true (scm_procedure_p (proc)),
9a09deb1 260 proc, SCM_ARG1, FUNC_NAME);
c2c82fba
MD
261 switch (SCM_TYP7 (proc))
262 {
263 case scm_tcs_closures:
f9450cdb 264 code = SCM_CLOSURE_BODY (proc);
d2e53ed6 265 if (scm_is_null (SCM_CDR (code)))
c2c82fba
MD
266 return SCM_BOOL_F;
267 code = SCM_CAR (code);
7f9994d9 268 if (scm_is_string (code))
c2c82fba 269 return code;
5c9e7dad
DH
270 else
271 return SCM_BOOL_F;
c2c82fba
MD
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}
1bbd0b84 282#undef FUNC_NAME
c2c82fba 283
0f2d19dd 284
b4cd6492
MD
285/* Procedure-with-setter
286 */
287
a1ec6916 288SCM_DEFINE (scm_procedure_with_setter_p, "procedure-with-setter?", 1, 0, 0,
1bbd0b84 289 (SCM obj),
8cf97abf
MG
290 "Return @code{#t} if @var{obj} is a procedure with an\n"
291 "associated setter procedure.")
1bbd0b84 292#define FUNC_NAME s_scm_procedure_with_setter_p
b4cd6492 293{
7888309b 294 return scm_from_bool(SCM_PROCEDURE_WITH_SETTER_P (obj));
b4cd6492 295}
1bbd0b84 296#undef FUNC_NAME
b4cd6492 297
a1ec6916 298SCM_DEFINE (scm_make_procedure_with_setter, "make-procedure-with-setter", 2, 0, 0,
1bbd0b84 299 (SCM procedure, SCM setter),
8cf97abf
MG
300 "Create a new procedure which behaves like @var{procedure}, but\n"
301 "with the associated setter @var{setter}.")
1bbd0b84 302#define FUNC_NAME s_scm_make_procedure_with_setter
b4cd6492 303{
3fd8807e 304 SCM name, ret;
e1f8eb2b
MD
305 SCM_VALIDATE_PROC (1, procedure);
306 SCM_VALIDATE_PROC (2, setter);
3fd8807e
AW
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;
b4cd6492 323}
1bbd0b84 324#undef FUNC_NAME
b4cd6492 325
a1ec6916 326SCM_DEFINE (scm_procedure, "procedure", 1, 0, 0,
1bbd0b84 327 (SCM proc),
8cf97abf
MG
328 "Return the procedure of @var{proc}, which must be either a\n"
329 "procedure with setter, or an operator struct.")
1bbd0b84 330#define FUNC_NAME s_scm_procedure
b4cd6492 331{
e1f8eb2b 332 SCM_VALIDATE_NIM (1, proc);
b4cd6492
MD
333 if (SCM_PROCEDURE_WITH_SETTER_P (proc))
334 return SCM_PROCEDURE (proc);
335 else if (SCM_STRUCTP (proc))
336 {
1bbd0b84 337 SCM_ASSERT (SCM_I_OPERATORP (proc), proc, SCM_ARG1, FUNC_NAME);
b4cd6492
MD
338 return proc;
339 }
1bbd0b84 340 SCM_WRONG_TYPE_ARG (1, proc);
4260a7fc 341 return SCM_BOOL_F; /* not reached */
b4cd6492 342}
1bbd0b84 343#undef FUNC_NAME
b4cd6492 344
f5267231 345SCM_GPROC (s_setter, "setter", 1, 0, 0, scm_setter, g_setter);
b4cd6492
MD
346
347SCM
348scm_setter (SCM proc)
349{
f5267231 350 SCM_GASSERT1 (SCM_NIMP (proc), g_setter, proc, SCM_ARG1, s_setter);
b4cd6492
MD
351 if (SCM_PROCEDURE_WITH_SETTER_P (proc))
352 return SCM_SETTER (proc);
353 else if (SCM_STRUCTP (proc))
354 {
c72a774a 355 SCM setter;
f5267231
MD
356 SCM_GASSERT1 (SCM_I_OPERATORP (proc),
357 g_setter, proc, SCM_ARG1, s_setter);
c72a774a
MD
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 */
b4cd6492 364 }
f5267231 365 SCM_WTA_DISPATCH_1 (g_setter, proc, SCM_ARG1, s_setter);
b038d983 366 return SCM_BOOL_F; /* not reached */
b4cd6492 367}
1cc91f1b 368
9de33deb 369
9de33deb
MD
370void
371scm_init_subr_table ()
372{
373 scm_subr_table
92c2555f 374 = ((scm_t_subr_entry *)
4c9419ac 375 scm_malloc (sizeof (scm_t_subr_entry) * scm_subr_table_room));
9de33deb 376}
1cc91f1b 377
0f2d19dd
JB
378void
379scm_init_procs ()
0f2d19dd 380{
a0599745 381#include "libguile/procs.x"
0f2d19dd 382}
89e00824
ML
383
384/*
385 Local Variables:
386 c-file-style: "gnu"
387 End:
388*/