move module and meta inside programs' object tables
[bpt/guile.git] / libguile / programs.c
1 /* Copyright (C) 2001 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
42 #if HAVE_CONFIG_H
43 # include <config.h>
44 #endif
45
46 #include <string.h>
47 #include "vm-bootstrap.h"
48 #include "instructions.h"
49 #include "modules.h"
50 #include "programs.h"
51 #include "vm.h"
52
53 \f
54 scm_t_bits scm_tc16_program;
55
56 static SCM zero_vector;
57 static SCM write_program = SCM_BOOL_F;
58
59 SCM
60 scm_c_make_program (void *addr, size_t size, SCM objs, SCM holder)
61 #define FUNC_NAME "scm_c_make_program"
62 {
63 struct scm_program *p = scm_gc_malloc (sizeof (struct scm_program),
64 "program");
65 p->size = size;
66 p->nargs = 0;
67 p->nrest = 0;
68 p->nlocs = 0;
69 p->nexts = 0;
70 p->objs = objs;
71 p->external = SCM_EOL;
72 p->holder = holder;
73
74 /* If nobody holds bytecode's address, then allocate a new memory */
75 if (SCM_FALSEP (holder))
76 {
77 p->base = scm_gc_malloc (size, "program-base");
78 memcpy (p->base, addr, size);
79 }
80 else
81 p->base = addr;
82
83 SCM_RETURN_NEWSMOB (scm_tc16_program, p);
84 }
85 #undef FUNC_NAME
86
87 SCM
88 scm_c_make_closure (SCM program, SCM external)
89 {
90 struct scm_program *p = scm_gc_malloc (sizeof (struct scm_program),
91 "program");
92 *p = *SCM_PROGRAM_DATA (program);
93 p->holder = program;
94 p->external = external;
95 SCM_RETURN_NEWSMOB (scm_tc16_program, p);
96 }
97
98 static SCM
99 program_mark (SCM obj)
100 {
101 struct scm_program *p = SCM_PROGRAM_DATA (obj);
102 if (scm_is_true (p->objs))
103 scm_gc_mark (p->objs);
104 if (!scm_is_null (p->external))
105 scm_gc_mark (p->external);
106 return p->holder;
107 }
108
109 static scm_sizet
110 program_free (SCM obj)
111 {
112 struct scm_program *p = SCM_PROGRAM_DATA (obj);
113 scm_sizet size = (sizeof (struct scm_program));
114
115 if (SCM_FALSEP (p->holder))
116 scm_gc_free (p->base, p->size, "program-base");
117
118 scm_gc_free (p, size, "program");
119
120 return 0;
121 }
122
123 static SCM
124 program_apply (SCM program, SCM args)
125 {
126 return scm_vm_apply (scm_the_vm (), program, args);
127 }
128
129 static int
130 program_print (SCM program, SCM port, scm_print_state *pstate)
131 {
132 static int print_error = 0;
133
134 if (SCM_FALSEP (write_program) && scm_module_system_booted_p)
135 write_program = scm_module_local_variable
136 (scm_c_resolve_module ("system vm program"),
137 scm_from_locale_symbol ("write-program"));
138
139 if (SCM_FALSEP (write_program) || print_error)
140 return scm_smob_print (program, port, pstate);
141
142 print_error = 1;
143 scm_call_2 (SCM_VARIABLE_REF (write_program), program, port);
144 print_error = 0;
145 return 1;
146 }
147
148 \f
149 /*
150 * Scheme interface
151 */
152
153 SCM_DEFINE (scm_program_p, "program?", 1, 0, 0,
154 (SCM obj),
155 "")
156 #define FUNC_NAME s_scm_program_p
157 {
158 return SCM_BOOL (SCM_PROGRAM_P (obj));
159 }
160 #undef FUNC_NAME
161
162 SCM_DEFINE (scm_program_base, "program-base", 1, 0, 0,
163 (SCM program),
164 "")
165 #define FUNC_NAME s_scm_program_base
166 {
167 SCM_VALIDATE_PROGRAM (1, program);
168
169 return scm_from_ulong ((unsigned long) SCM_PROGRAM_DATA (program)->base);
170 }
171 #undef FUNC_NAME
172
173 SCM_DEFINE (scm_program_arity, "program-arity", 1, 0, 0,
174 (SCM program),
175 "")
176 #define FUNC_NAME s_scm_program_arity
177 {
178 struct scm_program *p;
179
180 SCM_VALIDATE_PROGRAM (1, program);
181
182 p = SCM_PROGRAM_DATA (program);
183 return SCM_LIST4 (SCM_I_MAKINUM (p->nargs),
184 SCM_I_MAKINUM (p->nrest),
185 SCM_I_MAKINUM (p->nlocs),
186 SCM_I_MAKINUM (p->nexts));
187 }
188 #undef FUNC_NAME
189
190 SCM_DEFINE (scm_program_meta, "program-meta", 1, 0, 0,
191 (SCM program),
192 "")
193 #define FUNC_NAME s_scm_program_meta
194 {
195 SCM objs;
196 SCM_VALIDATE_PROGRAM (1, program);
197 objs = SCM_PROGRAM_DATA (program)->objs;
198 return scm_is_true (objs) ? scm_c_vector_ref (objs, 1) : SCM_BOOL_F;
199 }
200 #undef FUNC_NAME
201
202 extern SCM
203 scm_c_program_source (struct scm_program *p, size_t ip)
204 {
205 SCM meta, sources, source;
206
207 if (scm_is_false (p->objs))
208 return SCM_BOOL_F;
209 meta = scm_c_vector_ref (p->objs, 1);
210 if (scm_is_false (meta))
211 return SCM_BOOL_F;
212 meta = scm_call_0 (meta);
213 if (scm_is_false (meta))
214 return SCM_BOOL_F;
215 sources = scm_cadr (meta);
216 source = scm_assv (scm_from_size_t (ip), sources);
217 if (scm_is_false (source))
218 return SCM_BOOL_F;
219
220 return scm_cdr (source); /* a #(line column file) vector */
221 }
222
223 SCM_DEFINE (scm_program_objects, "program-objects", 1, 0, 0,
224 (SCM program),
225 "")
226 #define FUNC_NAME s_scm_program_objects
227 {
228 SCM_VALIDATE_PROGRAM (1, program);
229 return SCM_PROGRAM_DATA (program)->objs;
230 }
231 #undef FUNC_NAME
232
233 SCM_DEFINE (scm_program_module, "program-module", 1, 0, 0,
234 (SCM program),
235 "")
236 #define FUNC_NAME s_scm_program_module
237 {
238 SCM objs;
239 SCM_VALIDATE_PROGRAM (1, program);
240 objs = SCM_PROGRAM_DATA (program)->objs;
241 return scm_is_true (objs) ? scm_c_vector_ref (objs, 0) : SCM_BOOL_F;
242 }
243 #undef FUNC_NAME
244
245 SCM_DEFINE (scm_program_external, "program-external", 1, 0, 0,
246 (SCM program),
247 "")
248 #define FUNC_NAME s_scm_program_external
249 {
250 SCM_VALIDATE_PROGRAM (1, program);
251 return SCM_PROGRAM_DATA (program)->external;
252 }
253 #undef FUNC_NAME
254
255 SCM_DEFINE (scm_program_external_set_x, "program-external-set!", 2, 0, 0,
256 (SCM program, SCM external),
257 "Modify the list of closure variables of @var{program} (for "
258 "debugging purposes).")
259 #define FUNC_NAME s_scm_program_external_set_x
260 {
261 SCM_VALIDATE_PROGRAM (1, program);
262 SCM_VALIDATE_LIST (2, external);
263 SCM_PROGRAM_DATA (program)->external = external;
264 return SCM_UNSPECIFIED;
265 }
266 #undef FUNC_NAME
267
268 SCM_DEFINE (scm_program_bytecode, "program-bytecode", 1, 0, 0,
269 (SCM program),
270 "Return a u8vector containing @var{program}'s bytecode.")
271 #define FUNC_NAME s_scm_program_bytecode
272 {
273 size_t size;
274 scm_t_uint8 *c_bytecode;
275
276 SCM_VALIDATE_PROGRAM (1, program);
277
278 size = SCM_PROGRAM_DATA (program)->size;
279 c_bytecode = malloc (size);
280 if (!c_bytecode)
281 return SCM_BOOL_F;
282
283 memcpy (c_bytecode, SCM_PROGRAM_DATA (program)->base, size);
284
285 return scm_take_u8vector (c_bytecode, size);
286 }
287 #undef FUNC_NAME
288
289
290 \f
291 void
292 scm_bootstrap_programs (void)
293 {
294 zero_vector = scm_permanent_object (scm_c_make_vector (0, SCM_BOOL_F));
295
296 scm_tc16_program = scm_make_smob_type ("program", 0);
297 scm_set_smob_mark (scm_tc16_program, program_mark);
298 scm_set_smob_free (scm_tc16_program, program_free);
299 scm_set_smob_apply (scm_tc16_program, program_apply, 0, 0, 1);
300 scm_set_smob_print (scm_tc16_program, program_print);
301 }
302
303 void
304 scm_init_programs (void)
305 {
306 scm_bootstrap_vm ();
307
308 #ifndef SCM_MAGIC_SNARFER
309 #include "programs.x"
310 #endif
311 }
312
313 /*
314 Local Variables:
315 c-file-style: "gnu"
316 End:
317 */