*** empty log message ***
[bpt/guile.git] / libguile / procprop.c
1 /* Copyright (C) 1995,1996,1998 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 "alist.h"
47 #include "eval.h"
48 #include "procs.h"
49 #include "gsubr.h"
50 #include "objects.h"
51
52 #include "procprop.h"
53 \f
54
55 SCM_GLOBAL_SYMBOL (scm_sym_system_procedure, "system-procedure");
56 SCM_GLOBAL_SYMBOL (scm_sym_arity, "arity");
57
58 SCM
59 scm_i_procedure_arity (SCM proc)
60 {
61 int a = 0, o = 0, r = 0;
62 if (SCM_IMP (proc))
63 return SCM_BOOL_F;
64 loop:
65 switch (SCM_TYP7 (proc))
66 {
67 case scm_tc7_subr_1o:
68 o = 1;
69 case scm_tc7_subr_0:
70 break;
71 case scm_tc7_subr_2o:
72 o = 1;
73 case scm_tc7_subr_1:
74 case scm_tc7_cxr:
75 case scm_tc7_contin:
76 a += 1;
77 break;
78 case scm_tc7_subr_2:
79 a += 2;
80 break;
81 case scm_tc7_subr_3:
82 a += 3;
83 break;
84 case scm_tc7_asubr:
85 case scm_tc7_rpsubr:
86 case scm_tc7_lsubr:
87 r = 1;
88 break;
89 case scm_tc7_lsubr_2:
90 a += 2;
91 r = 1;
92 break;
93 #ifdef CCLO
94 case scm_tc7_cclo:
95 if (SCM_CCLO_SUBR (proc) == scm_f_gsubr_apply)
96 {
97 int type = SCM_INUM (SCM_GSUBR_TYPE (proc));
98 a += SCM_GSUBR_REQ (type);
99 o = SCM_GSUBR_OPT (type);
100 r = SCM_GSUBR_REST (type);
101 break;
102 }
103 proc = SCM_CCLO_SUBR (proc);
104 a -= 1;
105 goto loop;
106 #endif
107 case scm_tc7_pws:
108 proc = SCM_PROCEDURE (proc);
109 goto loop;
110 case scm_tcs_closures:
111 proc = SCM_CAR (SCM_CODE (proc));
112 if (SCM_IMP (proc))
113 break;
114 while (SCM_NIMP (proc) && SCM_CONSP (proc))
115 {
116 ++a;
117 proc = SCM_CDR (proc);
118 }
119 if (SCM_NIMP (proc))
120 r = 1;
121 break;
122 case scm_tcs_cons_gloc:
123 if (!SCM_I_OPERATORP (proc))
124 return SCM_BOOL_F;
125 {
126 SCM *p = (SCM_I_ENTITYP (proc)
127 ? &SCM_ENTITY_PROC_0 (proc)
128 : &SCM_OPERATOR_PROC_0 (proc));
129 SCM arity;
130 int i, amin = -1, amax = 0;
131 for (i = 0; i < 4; ++i)
132 if (SCM_NFALSEP (arity = scm_i_procedure_arity (p[i])))
133 {
134 if (amin < 0)
135 amin = i;
136 amax = i;
137 }
138 if (amin < 0)
139 /* no procedures in the struct! */
140 return SCM_BOOL_F;
141 a += amin;
142 o = amax - amin;
143 r = SCM_NFALSEP (arity) && SCM_NFALSEP (SCM_CADDR (arity));
144 break;
145 }
146 default:
147 return SCM_BOOL_F;
148 }
149 return SCM_LIST3 (SCM_MAKINUM (a),
150 SCM_MAKINUM (o),
151 r ? SCM_BOOL_T : SCM_BOOL_F);
152 }
153
154 static SCM
155 scm_stand_in_scm_proc(proc)
156 SCM proc;
157 {
158 SCM answer;
159 answer = scm_assoc (proc, scm_stand_in_procs);
160 if (answer == SCM_BOOL_F)
161 {
162 answer = scm_closure (scm_listify (SCM_EOL, SCM_BOOL_F, SCM_UNDEFINED),
163 SCM_EOL);
164 scm_stand_in_procs = scm_cons (scm_cons (proc, answer),
165 scm_stand_in_procs);
166 }
167 else
168 answer = SCM_CDR (answer);
169 return answer;
170 }
171
172 SCM_PROC(s_procedure_properties, "procedure-properties", 1, 0, 0, scm_procedure_properties);
173
174 SCM
175 scm_procedure_properties (proc)
176 SCM proc;
177 {
178 SCM_ASSERT (SCM_NFALSEP (scm_procedure_p (proc)),
179 proc, SCM_ARG1, s_procedure_properties);
180 return scm_acons (scm_sym_arity, scm_i_procedure_arity (proc),
181 SCM_PROCPROPS (SCM_NIMP (proc) && SCM_CLOSUREP (proc)
182 ? proc
183 : scm_stand_in_scm_proc (proc)));
184 }
185
186 SCM_PROC(s_set_procedure_properties_x, "set-procedure-properties!", 2, 0, 0, scm_set_procedure_properties_x);
187
188 SCM
189 scm_set_procedure_properties_x (proc, new_val)
190 SCM proc;
191 SCM new_val;
192 {
193 if (!(SCM_NIMP (proc) && SCM_CLOSUREP (proc)))
194 proc = scm_stand_in_scm_proc(proc);
195 SCM_ASSERT (SCM_NIMP (proc) && SCM_CLOSUREP (proc), proc, SCM_ARG1, s_set_procedure_properties_x);
196 SCM_SETPROCPROPS (proc, new_val);
197 return SCM_UNSPECIFIED;
198 }
199
200 SCM_PROC(s_procedure_property, "procedure-property", 2, 0, 0, scm_procedure_property);
201
202 SCM
203 scm_procedure_property (p, k)
204 SCM p;
205 SCM k;
206 {
207 SCM assoc;
208 if (k == scm_sym_arity)
209 {
210 SCM arity;
211 SCM_ASSERT (SCM_NFALSEP (arity = scm_i_procedure_arity (p)),
212 p, SCM_ARG1, s_procedure_property);
213 return arity;
214 }
215 SCM_ASSERT (SCM_NFALSEP (scm_procedure_p (p)),
216 p, SCM_ARG1, s_procedure_property);
217 assoc = scm_sloppy_assq (k,
218 SCM_PROCPROPS (SCM_NIMP (p) && SCM_CLOSUREP (p)
219 ? p
220 : scm_stand_in_scm_proc (p)));
221 return (SCM_NIMP (assoc) ? SCM_CDR (assoc) : SCM_BOOL_F);
222 }
223
224 SCM_PROC(s_set_procedure_property_x, "set-procedure-property!", 3, 0, 0, scm_set_procedure_property_x);
225
226 SCM
227 scm_set_procedure_property_x (p, k, v)
228 SCM p;
229 SCM k;
230 SCM v;
231 {
232 SCM assoc;
233 if (!(SCM_NIMP (p) && SCM_CLOSUREP (p)))
234 p = scm_stand_in_scm_proc(p);
235 SCM_ASSERT (SCM_NIMP (p) && SCM_CLOSUREP (p), p, SCM_ARG1, s_set_procedure_property_x);
236 if (k == scm_sym_arity)
237 scm_misc_error (s_set_procedure_property_x,
238 "arity is a read-only property",
239 SCM_EOL);
240 assoc = scm_sloppy_assq (k, SCM_PROCPROPS (p));
241 if (SCM_NIMP (assoc))
242 SCM_SETCDR (assoc, v);
243 else
244 SCM_SETPROCPROPS (p, scm_acons (k, v, SCM_PROCPROPS (p)));
245 return SCM_UNSPECIFIED;
246 }
247
248 \f
249
250
251 void
252 scm_init_procprop ()
253 {
254 #include "procprop.x"
255 }
256