The FSF has a new address.
[bpt/guile.git] / libguile / procprop.c
CommitLineData
82c76fd3 1/* Copyright (C) 1995,1996,1998,2000,2001,2003,2004 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
JB
19\f
20
a0599745
MD
21#include "libguile/_scm.h"
22
23#include "libguile/alist.h"
24#include "libguile/eval.h"
25#include "libguile/procs.h"
26#include "libguile/gsubr.h"
27#include "libguile/objects.h"
5540e847 28#include "libguile/smob.h"
a0599745
MD
29#include "libguile/root.h"
30#include "libguile/vectors.h"
82c76fd3 31#include "libguile/hashtab.h"
a0599745
MD
32
33#include "libguile/validate.h"
34#include "libguile/procprop.h"
0f2d19dd
JB
35\f
36
c083a529 37SCM_GLOBAL_SYMBOL (scm_sym_system_procedure, "system-procedure");
67e60655
MD
38SCM_GLOBAL_SYMBOL (scm_sym_arity, "arity");
39
08906709
MD
40SCM
41scm_i_procedure_arity (SCM proc)
67e60655
MD
42{
43 int a = 0, o = 0, r = 0;
08906709
MD
44 if (SCM_IMP (proc))
45 return SCM_BOOL_F;
67e60655
MD
46 loop:
47 switch (SCM_TYP7 (proc))
48 {
49 case scm_tc7_subr_1o:
50 o = 1;
51 case scm_tc7_subr_0:
52 break;
53 case scm_tc7_subr_2o:
54 o = 1;
55 case scm_tc7_subr_1:
14b18ed6 56 case scm_tc7_dsubr:
67e60655 57 case scm_tc7_cxr:
67e60655
MD
58 a += 1;
59 break;
60 case scm_tc7_subr_2:
61 a += 2;
62 break;
63 case scm_tc7_subr_3:
64 a += 3;
65 break;
66 case scm_tc7_asubr:
67 case scm_tc7_rpsubr:
68 case scm_tc7_lsubr:
69 r = 1;
91517e28 70 break;
67e60655
MD
71 case scm_tc7_lsubr_2:
72 a += 2;
91517e28 73 r = 1;
67e60655 74 break;
5540e847 75 case scm_tc7_smob:
68b06924 76 if (SCM_SMOB_APPLICABLE_P (proc))
362306b9
DH
77 {
78 int type = SCM_SMOB_DESCRIPTOR (proc).gsubr_type;
79 a += SCM_GSUBR_REQ (type);
80 o = SCM_GSUBR_OPT (type);
81 r = SCM_GSUBR_REST (type);
82 break;
83 }
84 else
85 {
5540e847 86 return SCM_BOOL_F;
362306b9
DH
87 }
88 case scm_tc7_cclo:
bc36d050 89 if (scm_is_eq (SCM_CCLO_SUBR (proc), scm_f_gsubr_apply))
67e60655 90 {
e11e83f3 91 int type = scm_to_int (SCM_GSUBR_TYPE (proc));
08906709 92 a += SCM_GSUBR_REQ (type);
67e60655
MD
93 o = SCM_GSUBR_OPT (type);
94 r = SCM_GSUBR_REST (type);
95 break;
96 }
362306b9
DH
97 else
98 {
99 proc = SCM_CCLO_SUBR (proc);
100 a -= 1;
101 goto loop;
102 }
dec118c8
MD
103 case scm_tc7_pws:
104 proc = SCM_PROCEDURE (proc);
105 goto loop;
67e60655 106 case scm_tcs_closures:
726d810a 107 proc = SCM_CLOSURE_FORMALS (proc);
d2e53ed6 108 if (scm_is_null (proc))
67e60655 109 break;
d2e53ed6 110 while (scm_is_pair (proc))
67e60655
MD
111 {
112 ++a;
113 proc = SCM_CDR (proc);
114 }
d2e53ed6 115 if (!scm_is_null (proc))
67e60655
MD
116 r = 1;
117 break;
904a077d 118 case scm_tcs_struct:
815ce8d5
MD
119 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
120 {
121 r = 1;
122 break;
123 }
124 else if (!SCM_I_OPERATORP (proc))
08906709 125 return SCM_BOOL_F;
815ce8d5
MD
126 proc = (SCM_I_ENTITYP (proc)
127 ? SCM_ENTITY_PROCEDURE (proc)
128 : SCM_OPERATOR_PROCEDURE (proc));
129 a -= 1;
130 goto loop;
08906709
MD
131 default:
132 return SCM_BOOL_F;
67e60655 133 }
e11e83f3 134 return scm_list_3 (scm_from_int (a), scm_from_int (o), scm_from_bool(r));
67e60655
MD
135}
136
ece721f0
MV
137/* XXX - instead of using a stand-in value for everything except
138 closures, we should find other ways to store the procedure
139 properties for those other kinds of procedures. For example, subrs
140 have their own property slot, which is unused at present.
141*/
142
0f2d19dd 143static SCM
1bbd0b84 144scm_stand_in_scm_proc(SCM proc)
0f2d19dd 145{
82c76fd3
MV
146 SCM handle, answer;
147 handle = scm_hashq_get_handle (scm_stand_in_procs, proc);
148 if (scm_is_false (handle))
0f2d19dd 149 {
1afff620 150 answer = scm_closure (scm_list_2 (SCM_EOL, SCM_BOOL_F), SCM_EOL);
82c76fd3 151 scm_hashq_set_x (scm_stand_in_procs, proc, answer);
0f2d19dd
JB
152 }
153 else
82c76fd3 154 answer = SCM_CDR (handle);
0f2d19dd
JB
155 return answer;
156}
157
3b3b36dd 158SCM_DEFINE (scm_procedure_properties, "procedure-properties", 1, 0, 0,
1bbd0b84 159 (SCM proc),
b380b885 160 "Return @var{obj}'s property list.")
1bbd0b84 161#define FUNC_NAME s_scm_procedure_properties
0f2d19dd 162{
34d19ef6 163 SCM_VALIDATE_PROC (1, proc);
67e60655 164 return scm_acons (scm_sym_arity, scm_i_procedure_arity (proc),
0c95b57d 165 SCM_PROCPROPS (SCM_CLOSUREP (proc)
67e60655
MD
166 ? proc
167 : scm_stand_in_scm_proc (proc)));
0f2d19dd 168}
1bbd0b84 169#undef FUNC_NAME
0f2d19dd 170
3b3b36dd 171SCM_DEFINE (scm_set_procedure_properties_x, "set-procedure-properties!", 2, 0, 0,
1bbd0b84 172 (SCM proc, SCM new_val),
b380b885 173 "Set @var{obj}'s property list to @var{alist}.")
1bbd0b84 174#define FUNC_NAME s_scm_set_procedure_properties_x
0f2d19dd 175{
0c95b57d 176 if (!SCM_CLOSUREP (proc))
0f2d19dd 177 proc = scm_stand_in_scm_proc(proc);
34d19ef6 178 SCM_VALIDATE_CLOSURE (1, proc);
a6c64c3c 179 SCM_SETPROCPROPS (proc, new_val);
0f2d19dd
JB
180 return SCM_UNSPECIFIED;
181}
1bbd0b84 182#undef FUNC_NAME
0f2d19dd 183
3b3b36dd 184SCM_DEFINE (scm_procedure_property, "procedure-property", 2, 0, 0,
1bbd0b84 185 (SCM p, SCM k),
b380b885 186 "Return the property of @var{obj} with name @var{key}.")
1bbd0b84 187#define FUNC_NAME s_scm_procedure_property
0f2d19dd
JB
188{
189 SCM assoc;
bc36d050 190 if (scm_is_eq (k, scm_sym_arity))
08906709
MD
191 {
192 SCM arity;
7888309b 193 SCM_ASSERT (scm_is_true (arity = scm_i_procedure_arity (p)),
1bbd0b84 194 p, SCM_ARG1, FUNC_NAME);
08906709
MD
195 return arity;
196 }
34d19ef6 197 SCM_VALIDATE_PROC (1, p);
67e60655 198 assoc = scm_sloppy_assq (k,
0c95b57d 199 SCM_PROCPROPS (SCM_CLOSUREP (p)
67e60655
MD
200 ? p
201 : scm_stand_in_scm_proc (p)));
0f2d19dd
JB
202 return (SCM_NIMP (assoc) ? SCM_CDR (assoc) : SCM_BOOL_F);
203}
1bbd0b84 204#undef FUNC_NAME
0f2d19dd 205
3b3b36dd 206SCM_DEFINE (scm_set_procedure_property_x, "set-procedure-property!", 3, 0, 0,
1bbd0b84 207 (SCM p, SCM k, SCM v),
b380b885
MD
208 "In @var{obj}'s property list, set the property named @var{key} to\n"
209 "@var{value}.")
1bbd0b84 210#define FUNC_NAME s_scm_set_procedure_property_x
0f2d19dd
JB
211{
212 SCM assoc;
0c95b57d 213 if (!SCM_CLOSUREP (p))
0f2d19dd 214 p = scm_stand_in_scm_proc(p);
34d19ef6 215 SCM_VALIDATE_CLOSURE (1, p);
bc36d050 216 if (scm_is_eq (k, scm_sym_arity))
1bbd0b84 217 SCM_MISC_ERROR ("arity is a read-only property", SCM_EOL);
0f2d19dd
JB
218 assoc = scm_sloppy_assq (k, SCM_PROCPROPS (p));
219 if (SCM_NIMP (assoc))
220 SCM_SETCDR (assoc, v);
221 else
a6c64c3c 222 SCM_SETPROCPROPS (p, scm_acons (k, v, SCM_PROCPROPS (p)));
0f2d19dd
JB
223 return SCM_UNSPECIFIED;
224}
1bbd0b84 225#undef FUNC_NAME
0f2d19dd
JB
226
227\f
228
1cc91f1b 229
0f2d19dd
JB
230void
231scm_init_procprop ()
0f2d19dd 232{
a0599745 233#include "libguile/procprop.x"
0f2d19dd
JB
234}
235
89e00824
ML
236
237/*
238 Local Variables:
239 c-file-style: "gnu"
240 End:
241*/