* objects.c, objects.h (scm_entity_p): New procedure. Together
[bpt/guile.git] / libguile / objects.c
1 /* Copyright (C) 1995,1996 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 /* This file and objects.h contains those minimal pieces of the Guile
44 * Object Oriented Programming System which need to be included in
45 * libguile. See the comments in objects.h.
46 */
47
48 #include "_scm.h"
49
50 #include "struct.h"
51 #include "procprop.h"
52
53 #include "objects.h"
54 \f
55
56 SCM scm_metaclass_standard;
57 SCM scm_metaclass_operator;
58
59 SCM_PROC (s_entity_p, "entity?", 1, 0, 0, scm_entity_p);
60
61 SCM
62 scm_entity_p (SCM obj)
63 {
64 return (SCM_NIMP (obj) && SCM_STRUCTP (obj) && SCM_I_ENTITYP (obj)
65 ? SCM_BOOL_T
66 : SCM_BOOL_F);
67 }
68
69 SCM_PROC (s_set_object_procedure_x, "set-object-procedure!", 1, 0, 1, scm_set_object_procedure_x);
70
71 SCM
72 scm_set_object_procedure_x (SCM obj, SCM procs)
73 {
74 SCM proc[4], *pp, p, setp, arity;
75 int i, a, r;
76 SCM_ASSERT (SCM_NIMP (obj) && SCM_STRUCTP (obj)
77 && ((SCM_CLASS_FLAGS (obj) & SCM_CLASSF_OPERATOR)
78 || SCM_I_ENTITYP (obj)),
79 obj,
80 SCM_ARG1,
81 s_set_object_procedure_x);
82 for (i = 0; i < 4; ++i)
83 proc[i] = SCM_BOOL_F;
84 i = 0;
85 while (SCM_NIMP (procs))
86 {
87 if (i == 4)
88 scm_wrong_num_args (scm_makfrom0str (s_set_object_procedure_x));
89 p = SCM_CAR (procs);
90 setp = 0;
91 SCM_ASSERT (SCM_NIMP (p), p, SCM_ARG2 + i, s_set_object_procedure_x);
92 if (SCM_CLOSUREP (p))
93 {
94 arity = scm_procedure_property (p, scm_sym_arity);
95 a = SCM_INUM (SCM_CAR (arity));
96 /* Closures have zero optional args */
97 r = SCM_NFALSEP (SCM_CADDR (arity));
98 if (a == 1 || (a <= 1 && r))
99 {
100 if (SCM_NFALSEP (proc[0]))
101 goto ambiguous;
102 proc[0] = setp = p;
103 }
104 if (a == 2 || (a <= 2 && r))
105 {
106 if (SCM_NFALSEP (proc[1]))
107 goto ambiguous;
108 proc[1] = setp = p;
109 }
110 if (a == 3 || (a <= 3 && r))
111 {
112 if (SCM_NFALSEP (proc[2]))
113 goto ambiguous;
114 proc[2] = setp = p;
115 }
116 if (a <= 4 && r)
117 {
118 if (SCM_NFALSEP (proc[3]))
119 goto ambiguous;
120 proc[3] = setp = p;
121 }
122 }
123 else if (SCM_TYP7 (p) == scm_tc7_subr_1)
124 {
125 if (SCM_NFALSEP (proc[0]))
126 goto ambiguous;
127 proc[0] = setp = p;
128 }
129 else if (SCM_TYP7 (p) == scm_tc7_subr_2)
130 {
131 if (SCM_NFALSEP (proc[1]))
132 goto ambiguous;
133 proc[1] = setp = p;
134 }
135 else if (SCM_TYP7 (p) == scm_tc7_subr_3)
136 {
137 if (SCM_NFALSEP (proc[2]))
138 goto ambiguous;
139 proc[2] = setp = p;
140 }
141 else if (SCM_TYP7 (p) == scm_tc7_lsubr_2)
142 {
143 if (SCM_NFALSEP (proc[3]))
144 {
145 ambiguous:
146 SCM_ASSERT (0, p, "Ambiguous procedure arities",
147 s_set_object_procedure_x);
148 }
149 proc[3] = setp = p;
150 }
151 SCM_ASSERT (setp, p, SCM_ARG2 + i, s_set_object_procedure_x);
152 ++i;
153 procs = SCM_CDR (procs);
154 }
155 pp = (SCM_I_ENTITYP (obj)
156 ? &SCM_ENTITY_PROC_0 (obj)
157 : &SCM_OPERATOR_CLASS (obj)->proc0);
158 for (i = 0; i < 4; ++i)
159 *pp++ = proc[i];
160 return SCM_UNSPECIFIED;
161 }
162
163 SCM
164 scm_i_make_class_object (SCM meta,
165 SCM layout_string,
166 unsigned long flags)
167 {
168 SCM c;
169 SCM layout = scm_make_struct_layout (layout_string);
170 c = scm_make_struct (meta,
171 SCM_INUM0,
172 SCM_LIST4 (layout, SCM_BOOL_F, SCM_EOL, SCM_EOL));
173 SCM_SET_CLASS_FLAGS (c, flags);
174 return c;
175 }
176
177 SCM_PROC (s_make_class_object, "make-class-object", 2, 0, 0, scm_make_class_object);
178
179 SCM
180 scm_make_class_object (SCM metaclass, SCM layout)
181 {
182 unsigned long flags = 0;
183 SCM_ASSERT (SCM_NIMP (metaclass) && SCM_STRUCTP (metaclass),
184 metaclass, SCM_ARG1, s_make_class_object);
185 SCM_ASSERT (SCM_NIMP (layout) && SCM_STRINGP (layout),
186 layout, SCM_ARG2, s_make_class_object);
187 if (metaclass == scm_metaclass_operator)
188 flags = SCM_CLASSF_OPERATOR;
189 return scm_i_make_class_object (metaclass, layout, flags);
190 }
191
192 SCM_PROC (s_make_subclass_object, "make-subclass-object", 2, 0, 0, scm_make_subclass_object);
193
194 SCM
195 scm_make_subclass_object (SCM class, SCM layout)
196 {
197 SCM pl;
198 SCM_ASSERT (SCM_NIMP (class) && SCM_STRUCTP (class),
199 class,
200 SCM_ARG1,
201 s_make_subclass_object);
202 SCM_ASSERT (SCM_NIMP (layout) && SCM_STRINGP (layout),
203 layout,
204 SCM_ARG2,
205 s_make_subclass_object);
206 pl = SCM_STRUCT_DATA (class)[scm_vtable_index_layout];
207 /* Convert symbol->string */
208 pl = scm_makfromstr (SCM_CHARS (pl), (scm_sizet) SCM_LENGTH (pl), 0);
209 return scm_i_make_class_object (SCM_STRUCT_VTABLE (class),
210 scm_string_append (SCM_LIST2 (pl, layout)),
211 SCM_CLASS_FLAGS (class));
212 }
213
214 void
215 scm_init_objects ()
216 {
217 SCM ms = scm_makfrom0str (SCM_METACLASS_STANDARD_LAYOUT);
218 SCM ml = scm_make_struct_layout (ms);
219 SCM mt = scm_make_vtable_vtable (ml, SCM_INUM0,
220 SCM_LIST3 (SCM_BOOL_F, SCM_EOL, SCM_EOL));
221
222 SCM os = scm_makfrom0str (SCM_METACLASS_OPERATOR_LAYOUT);
223 SCM ol = scm_make_struct_layout (os);
224 SCM ot = scm_make_vtable_vtable (ol, SCM_INUM0,
225 SCM_LIST3 (SCM_BOOL_F, SCM_EOL, SCM_EOL));
226
227 SCM es = scm_makfrom0str (SCM_ENTITY_LAYOUT);
228 SCM el = scm_make_struct_layout (es);
229 SCM et = scm_make_struct (mt, SCM_INUM0,
230 SCM_LIST4 (el, SCM_BOOL_F, SCM_EOL, SCM_EOL));
231
232 scm_sysintern ("<class>", mt);
233 scm_metaclass_standard = mt;
234 scm_sysintern ("<operator-class>", ot);
235 scm_metaclass_operator = ot;
236 SCM_SET_CLASS_FLAGS (et, SCM_CLASSF_OPERATOR | SCM_CLASSF_ENTITY);
237 scm_sysintern ("<entity>", et);
238
239 #include "objects.x"
240 }