Remove "compiled closures" ("cclos") in favor of a simpler mechanism.
[bpt/guile.git] / libguile / gsubr.c
CommitLineData
cce8b2ce 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2006, 2008, 2009 Free Software Foundation, Inc.
c0fa6561 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.
c0fa6561 7 *
73be1d9e 8 * This library is distributed in the hope that it will be useful,
0f2d19dd 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
c0fa6561 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
0f2d19dd 18\f
dbb605f5
LC
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
0f2d19dd
JB
22
23#include <stdio.h>
a0599745
MD
24#include "libguile/_scm.h"
25#include "libguile/procprop.h"
26#include "libguile/root.h"
0f2d19dd 27
a0599745 28#include "libguile/gsubr.h"
1be6b49c 29#include "libguile/deprecation.h"
22fc179a
HWN
30
31#include "libguile/private-options.h"
0f2d19dd
JB
32\f
33/*
34 * gsubr.c
35 * Provide `gsubrs' -- subrs taking a prescribed number of required, optional,
36 * and rest arguments.
37 */
38
952bedad 39/* #define GSUBR_TEST */
0f2d19dd 40
85db4a2c
DH
41SCM_GLOBAL_SYMBOL (scm_sym_name, "name");
42
9d78586f 43static SCM
c0fa6561 44create_gsubr (int define, const char *name,
e20d7001
LC
45 unsigned int req, unsigned int opt, unsigned int rst,
46 SCM (*fcn) ())
0f2d19dd 47{
9d78586f
MV
48 SCM subr;
49
50 switch (SCM_GSUBR_MAKTYPE (req, opt, rst))
0f2d19dd 51 {
9d78586f
MV
52 case SCM_GSUBR_MAKTYPE(0, 0, 0):
53 subr = scm_c_make_subr (name, scm_tc7_subr_0, fcn);
e20d7001 54 break;
9d78586f
MV
55 case SCM_GSUBR_MAKTYPE(1, 0, 0):
56 subr = scm_c_make_subr (name, scm_tc7_subr_1, fcn);
e20d7001 57 break;
9d78586f
MV
58 case SCM_GSUBR_MAKTYPE(0, 1, 0):
59 subr = scm_c_make_subr (name, scm_tc7_subr_1o, fcn);
e20d7001 60 break;
9d78586f
MV
61 case SCM_GSUBR_MAKTYPE(1, 1, 0):
62 subr = scm_c_make_subr (name, scm_tc7_subr_2o, fcn);
e20d7001 63 break;
9d78586f
MV
64 case SCM_GSUBR_MAKTYPE(2, 0, 0):
65 subr = scm_c_make_subr (name, scm_tc7_subr_2, fcn);
e20d7001 66 break;
9d78586f
MV
67 case SCM_GSUBR_MAKTYPE(3, 0, 0):
68 subr = scm_c_make_subr (name, scm_tc7_subr_3, fcn);
e20d7001 69 break;
9d78586f
MV
70 case SCM_GSUBR_MAKTYPE(0, 0, 1):
71 subr = scm_c_make_subr (name, scm_tc7_lsubr, fcn);
e20d7001 72 break;
9d78586f
MV
73 case SCM_GSUBR_MAKTYPE(2, 0, 1):
74 subr = scm_c_make_subr (name, scm_tc7_lsubr_2, fcn);
e20d7001 75 break;
9d78586f
MV
76 default:
77 {
e20d7001
LC
78 unsigned type;
79
80 type = SCM_GSUBR_MAKTYPE (req, opt, rst);
81 if (SCM_GSUBR_REQ (type) != req
82 || SCM_GSUBR_OPT (type) != opt
83 || SCM_GSUBR_REST (type) != rst)
84 scm_out_of_range ("create_gsubr", scm_from_uint (req + opt + rst));
85
86 subr = scm_c_make_subr (name, scm_tc7_gsubr | (type << 8U),
87 fcn);
9d78586f 88 }
0f2d19dd 89 }
e20d7001
LC
90
91 if (define)
92 scm_define (SCM_SNAME (subr), subr);
93
94 return subr;
0f2d19dd
JB
95}
96
9de33deb 97SCM
9d78586f 98scm_c_make_gsubr (const char *name, int req, int opt, int rst, SCM (*fcn)())
9de33deb 99{
9d78586f
MV
100 return create_gsubr (0, name, req, opt, rst, fcn);
101}
102
103SCM
104scm_c_define_gsubr (const char *name, int req, int opt, int rst, SCM (*fcn)())
105{
106 return create_gsubr (1, name, req, opt, rst, fcn);
107}
108
109static SCM
110create_gsubr_with_generic (int define,
111 const char *name,
112 int req,
113 int opt,
114 int rst,
115 SCM (*fcn)(),
116 SCM *gf)
117{
118 SCM subr;
119
120 switch (SCM_GSUBR_MAKTYPE(req, opt, rst))
121 {
122 case SCM_GSUBR_MAKTYPE(0, 0, 0):
123 subr = scm_c_make_subr_with_generic (name, scm_tc7_subr_0, fcn, gf);
124 goto create_subr;
125 case SCM_GSUBR_MAKTYPE(1, 0, 0):
126 subr = scm_c_make_subr_with_generic (name, scm_tc7_subr_1, fcn, gf);
127 goto create_subr;
128 case SCM_GSUBR_MAKTYPE(0, 1, 0):
129 subr = scm_c_make_subr_with_generic (name, scm_tc7_subr_1o, fcn, gf);
130 goto create_subr;
131 case SCM_GSUBR_MAKTYPE(1, 1, 0):
132 subr = scm_c_make_subr_with_generic (name, scm_tc7_subr_2o, fcn, gf);
133 goto create_subr;
134 case SCM_GSUBR_MAKTYPE(2, 0, 0):
135 subr = scm_c_make_subr_with_generic (name, scm_tc7_subr_2, fcn, gf);
136 goto create_subr;
137 case SCM_GSUBR_MAKTYPE(3, 0, 0):
138 subr = scm_c_make_subr_with_generic (name, scm_tc7_subr_3, fcn, gf);
139 goto create_subr;
140 case SCM_GSUBR_MAKTYPE(0, 0, 1):
141 subr = scm_c_make_subr_with_generic (name, scm_tc7_lsubr, fcn, gf);
142 goto create_subr;
143 case SCM_GSUBR_MAKTYPE(2, 0, 1):
144 subr = scm_c_make_subr_with_generic (name, scm_tc7_lsubr_2, fcn, gf);
145 create_subr:
146 if (define)
cce8b2ce 147 scm_define (SCM_SNAME (subr), subr);
9d78586f
MV
148 return subr;
149 default:
150 ;
151 }
152 scm_misc_error ("scm_c_make_gsubr_with_generic",
9de33deb
MD
153 "can't make primitive-generic with this arity",
154 SCM_EOL);
4260a7fc 155 return SCM_BOOL_F; /* never reached */
9de33deb
MD
156}
157
9d78586f
MV
158SCM
159scm_c_make_gsubr_with_generic (const char *name,
160 int req,
161 int opt,
162 int rst,
163 SCM (*fcn)(),
164 SCM *gf)
165{
166 return create_gsubr_with_generic (0, name, req, opt, rst, fcn, gf);
167}
168
169SCM
170scm_c_define_gsubr_with_generic (const char *name,
171 int req,
172 int opt,
173 int rst,
174 SCM (*fcn)(),
175 SCM *gf)
176{
177 return create_gsubr_with_generic (1, name, req, opt, rst, fcn, gf);
178}
179
0f2d19dd 180
6fa73e72
GB
181SCM
182scm_gsubr_apply (SCM args)
a4bb4e6d 183#define FUNC_NAME "scm_gsubr_apply"
0f2d19dd 184{
1be6b49c 185 SCM self = SCM_CAR (args);
e20d7001 186 SCM (*fcn)() = SCM_SUBRF (self);
a4bb4e6d 187 SCM v[SCM_GSUBR_MAX];
e20d7001 188 unsigned int typ = SCM_GSUBR_TYPE (self);
c014a02e 189 long i, n = SCM_GSUBR_REQ (typ) + SCM_GSUBR_OPT (typ) + SCM_GSUBR_REST (typ);
e20d7001 190
1be6b49c
ML
191 args = SCM_CDR (args);
192 for (i = 0; i < SCM_GSUBR_REQ (typ); i++) {
d2e53ed6 193 if (scm_is_null (args))
e20d7001 194 scm_wrong_num_args (SCM_SNAME (self));
0f2d19dd
JB
195 v[i] = SCM_CAR(args);
196 args = SCM_CDR(args);
197 }
1be6b49c
ML
198 for (; i < SCM_GSUBR_REQ (typ) + SCM_GSUBR_OPT (typ); i++) {
199 if (SCM_NIMP (args)) {
200 v[i] = SCM_CAR (args);
0f2d19dd
JB
201 args = SCM_CDR(args);
202 }
203 else
204 v[i] = SCM_UNDEFINED;
205 }
dc0938d8 206 if (SCM_GSUBR_REST(typ))
0f2d19dd 207 v[i] = args;
d2e53ed6 208 else if (!scm_is_null (args))
e20d7001 209 scm_wrong_num_args (SCM_SNAME (self));
0f2d19dd 210 switch (n) {
0f2d19dd
JB
211 case 2: return (*fcn)(v[0], v[1]);
212 case 3: return (*fcn)(v[0], v[1], v[2]);
213 case 4: return (*fcn)(v[0], v[1], v[2], v[3]);
214 case 5: return (*fcn)(v[0], v[1], v[2], v[3], v[4]);
215 case 6: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5]);
216 case 7: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6]);
217 case 8: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
218 case 9: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
219 case 10: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]);
e20d7001
LC
220 default:
221 scm_misc_error ((char *) SCM_SNAME (self),
222 "gsubr invocation with more than 10 arguments not implemented",
223 SCM_EOL);
0f2d19dd 224 }
4260a7fc 225 return SCM_BOOL_F; /* Never reached. */
0f2d19dd 226}
a4bb4e6d 227#undef FUNC_NAME
0f2d19dd
JB
228
229
230#ifdef GSUBR_TEST
231/* A silly example, taking 2 required args, 1 optional, and
c0fa6561 232 a scm_list of rest args
0f2d19dd
JB
233 */
234SCM
1bbd0b84 235gsubr_21l(SCM req1, SCM req2, SCM opt, SCM rst)
0f2d19dd 236{
b7f3516f 237 scm_puts ("gsubr-2-1-l:\n req1: ", scm_cur_outp);
0f2d19dd 238 scm_display(req1, scm_cur_outp);
b7f3516f 239 scm_puts ("\n req2: ", scm_cur_outp);
0f2d19dd 240 scm_display(req2, scm_cur_outp);
b7f3516f 241 scm_puts ("\n opt: ", scm_cur_outp);
0f2d19dd 242 scm_display(opt, scm_cur_outp);
b7f3516f 243 scm_puts ("\n rest: ", scm_cur_outp);
0f2d19dd
JB
244 scm_display(rst, scm_cur_outp);
245 scm_newline(scm_cur_outp);
246 return SCM_UNSPECIFIED;
247}
248#endif
249
250
0f2d19dd
JB
251void
252scm_init_gsubr()
0f2d19dd 253{
0f2d19dd 254#ifdef GSUBR_TEST
9d78586f 255 scm_c_define_gsubr ("gsubr-2-1-l", 2, 1, 1, gsubr_21l); /* example */
0f2d19dd 256#endif
85db4a2c 257
85db4a2c 258#include "libguile/gsubr.x"
0f2d19dd 259}
89e00824
ML
260
261/*
262 Local Variables:
263 c-file-style: "gnu"
264 End:
265*/