bf8d990b5d331db218645b486633fd624f63af82
[bpt/guile.git] / src / vm_system.c
1 /* Copyright (C) 2000 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 /* This file is included in vm_engine.c */
43
44 \f
45 /*
46 * Basic operations
47 */
48
49 /* This must be the first instruction! */
50 VM_DEFINE_INSTRUCTION (nop, "nop", 0, 0, 0)
51 {
52 NEXT;
53 }
54
55 VM_DEFINE_INSTRUCTION (halt, "halt", 0, 0, 0)
56 {
57 SCM ret = *sp;
58 vp->time += scm_c_get_internal_run_time () - start_time;
59 HALT_HOOK ();
60 FREE_FRAME ();
61 SYNC_ALL ();
62 return ret;
63 }
64
65 VM_DEFINE_INSTRUCTION (drop, "drop", 0, 0, 0)
66 {
67 DROP ();
68 NEXT;
69 }
70
71 VM_DEFINE_INSTRUCTION (dup, "dup", 0, 0, 1)
72 {
73 PUSH (*sp);
74 NEXT;
75 }
76
77 \f
78 /*
79 * Object creation
80 */
81
82 VM_DEFINE_INSTRUCTION (void, "void", 0, 0, 1)
83 {
84 PUSH (SCM_UNSPECIFIED);
85 NEXT;
86 }
87
88 VM_DEFINE_INSTRUCTION (mark, "mark", 0, 0, 1)
89 {
90 PUSH (SCM_UNDEFINED);
91 NEXT;
92 }
93
94 VM_DEFINE_INSTRUCTION (make_true, "make-true", 0, 0, 1)
95 {
96 PUSH (SCM_BOOL_T);
97 NEXT;
98 }
99
100 VM_DEFINE_INSTRUCTION (make_false, "make-false", 0, 0, 1)
101 {
102 PUSH (SCM_BOOL_F);
103 NEXT;
104 }
105
106 VM_DEFINE_INSTRUCTION (make_eol, "make-eol", 0, 0, 1)
107 {
108 PUSH (SCM_EOL);
109 NEXT;
110 }
111
112 VM_DEFINE_INSTRUCTION (make_int8, "make-int8", 1, 0, 1)
113 {
114 PUSH (SCM_MAKINUM ((signed char) FETCH ()));
115 NEXT;
116 }
117
118 VM_DEFINE_INSTRUCTION (make_int8_0, "make-int8:0", 0, 0, 1)
119 {
120 PUSH (SCM_MAKINUM (0));
121 NEXT;
122 }
123
124 VM_DEFINE_INSTRUCTION (make_int8_1, "make-int8:1", 0, 0, 1)
125 {
126 PUSH (SCM_MAKINUM (1));
127 NEXT;
128 }
129
130 VM_DEFINE_INSTRUCTION (make_int16, "make-int16", 2, 0, 1)
131 {
132 int h = FETCH ();
133 int l = FETCH ();
134 PUSH (SCM_MAKINUM ((signed short) (h << 8) + l));
135 NEXT;
136 }
137
138 VM_DEFINE_INSTRUCTION (make_char8, "make-char8", 1, 0, 1)
139 {
140 PUSH (SCM_MAKE_CHAR (FETCH ()));
141 NEXT;
142 }
143
144 \f
145 /*
146 * Variable access
147 */
148
149 #define OBJECT_REF(i) objects[i]
150 #define OBJECT_SET(i,o) objects[i] = o
151
152 #define LOCAL_REF(i) SCM_VM_FRAME_VARIABLE (fp, i)
153 #define LOCAL_SET(i,o) SCM_VM_FRAME_VARIABLE (fp, i) = o
154
155 #define VARIABLE_REF(v) SCM_CDR (v)
156 #define VARIABLE_SET(v,o) SCM_SETCDR (v, o)
157
158 /* ref */
159
160 VM_DEFINE_INSTRUCTION (object_ref, "object-ref", 1, 0, 1)
161 {
162 PUSH (OBJECT_REF (FETCH ()));
163 NEXT;
164 }
165
166 VM_DEFINE_INSTRUCTION (local_ref, "local-ref", 1, 0, 1)
167 {
168 PUSH (LOCAL_REF (FETCH ()));
169 NEXT;
170 }
171
172 VM_DEFINE_INSTRUCTION (external_ref, "external-ref", 1, 0, 1)
173 {
174 unsigned int i;
175 SCM e = external;
176 for (i = FETCH (); i; i--)
177 e = SCM_CDR (e);
178 PUSH (SCM_CAR (e));
179 NEXT;
180 }
181
182 VM_DEFINE_INSTRUCTION (variable_ref, "variable-ref", 0, 0, 1)
183 {
184 SCM x = *sp;
185 SCM o = VARIABLE_REF (x);
186 if (SCM_UNBNDP (o))
187 {
188 /* Try autoload here */
189 err_args = SCM_LIST1 (SCM_CAR (x));
190 goto vm_error_unbound;
191 }
192 *sp = o;
193 NEXT;
194 }
195
196 /* set */
197
198 VM_DEFINE_INSTRUCTION (local_set, "local-set", 1, 1, 0)
199 {
200 LOCAL_SET (FETCH (), *sp);
201 DROP ();
202 NEXT;
203 }
204
205 VM_DEFINE_INSTRUCTION (external_set, "external-set", 1, 1, 0)
206 {
207 unsigned int i;
208 SCM e = external;
209 for (i = FETCH (); i; i--)
210 e = SCM_CDR (e);
211 SCM_SETCAR (e, *sp);
212 DROP ();
213 NEXT;
214 }
215
216 VM_DEFINE_INSTRUCTION (variable_set, "variable-set", 0, 1, 0)
217 {
218 VARIABLE_SET (sp[0], sp[1]);
219 scm_set_object_property_x (sp[1], scm_sym_name, SCM_CAR (sp[0]));
220 sp += 2;
221 NEXT;
222 }
223
224 \f
225 /*
226 * branch and jump
227 */
228
229 #define BR(p) \
230 { \
231 signed char offset = FETCH (); \
232 if (p) \
233 ip += offset; \
234 DROP (); \
235 NEXT; \
236 }
237
238 VM_DEFINE_INSTRUCTION (br_if, "br-if", 1, 0, 0)
239 {
240 BR (!SCM_FALSEP (*sp));
241 }
242
243 VM_DEFINE_INSTRUCTION (br_if_not, "br-if-not", 1, 0, 0)
244 {
245 BR (SCM_FALSEP (*sp));
246 }
247
248 VM_DEFINE_INSTRUCTION (br_if_eq, "br-if-eq", 1, 0, 0)
249 {
250 BR (SCM_EQ_P (sp[0], sp--[1]));
251 }
252
253 VM_DEFINE_INSTRUCTION (br_if_not_eq, "br-if-not-eq", 1, 0, 0)
254 {
255 BR (!SCM_EQ_P (sp[0], sp--[1]));
256 }
257
258 VM_DEFINE_INSTRUCTION (br_if_null, "br-if-null", 1, 0, 0)
259 {
260 BR (SCM_NULLP (*sp));
261 }
262
263 VM_DEFINE_INSTRUCTION (br_if_not_null, "br-if-not-null", 1, 0, 0)
264 {
265 BR (!SCM_NULLP (*sp));
266 }
267
268 VM_DEFINE_INSTRUCTION (jump, "jump", 1, 0, 0)
269 {
270 ip += (signed char) FETCH ();
271 NEXT;
272 }
273
274 \f
275 /*
276 * Subprogram call
277 */
278
279 VM_DEFINE_INSTRUCTION (make_closure, "make-closure", 0, 1, 1)
280 {
281 SYNC_BEFORE_GC ();
282 *sp = scm_c_make_closure (*sp, external);
283 NEXT;
284 }
285
286 VM_DEFINE_INSTRUCTION (call, "call", 1, -1, 1)
287 {
288 POP (program);
289 nargs = FETCH ();
290
291 vm_call:
292 /*
293 * Subprogram call
294 */
295 if (SCM_PROGRAM_P (program))
296 {
297 int i;
298 vm_call_program:
299 CACHE_PROGRAM ();
300 INIT_ARGS ();
301 NEW_FRAME ();
302
303 /* Init local variables */
304 for (i = 0; i < bp->nlocs; i++)
305 LOCAL_SET (i, SCM_UNDEFINED);
306
307 /* Create external variables */
308 for (i = 0; i < bp->nexts; i++)
309 CONS (external, SCM_UNDEFINED, external);
310
311 ENTER_HOOK ();
312 APPLY_HOOK ();
313 NEXT;
314 }
315 /*
316 * Function call
317 */
318 if (!SCM_FALSEP (scm_procedure_p (program)))
319 {
320 POP_LIST (nargs);
321 SYNC_BEFORE_GC ();
322 *sp = scm_apply (program, *sp, SCM_EOL);
323 program = SCM_VM_FRAME_PROGRAM (fp);
324 NEXT;
325 }
326 /*
327 * Continuation call
328 */
329 if (SCM_VM_CONT_P (program))
330 {
331 vm_call_cc:
332 /* Check the number of arguments */
333 if (nargs != 1)
334 scm_wrong_num_args (program);
335
336 /* Reinstate the continuation */
337 EXIT_HOOK ();
338 reinstate_vm_cont (vp, program);
339 CACHE_REGISTER ();
340 /* We don't need to set the return value here
341 because it is already on the top of the stack. */
342 NEXT;
343 }
344
345 goto vm_error_wrong_type_apply;
346 }
347
348 VM_DEFINE_INSTRUCTION (tail_call, "tail-call", 1, -1, 1)
349 {
350 SCM x;
351 POP (x);
352 nargs = FETCH ();
353
354 SCM_TICK; /* allow interrupt here */
355
356 /*
357 * Tail recursive call
358 */
359 if (SCM_EQ_P (x, program))
360 {
361 INIT_ARGS ();
362
363 /* Move arguments */
364 if (bp->nargs)
365 {
366 int i;
367 SCM *base = fp + bp->nlocs;
368 for (i = 0; i < bp->nargs; i++)
369 base[i] = sp[i];
370 }
371
372 ip = bp->base;
373 sp = SCM_VM_FRAME_LOWER_ADDRESS (fp);
374 APPLY_HOOK ();
375 NEXT;
376 }
377 program = x;
378 /*
379 * Proper tail call
380 */
381 if (SCM_PROGRAM_P (program))
382 {
383 int i;
384 SCM *base = sp;
385
386 /* Exit the current frame */
387 EXIT_HOOK ();
388 FREE_FRAME ();
389
390 /* Move arguments */
391 sp -= nargs;
392 for (i = 0; i < nargs; i++)
393 sp[i] = base[i];
394
395 /* Call the program */
396 goto vm_call_program;
397 }
398 /*
399 * Function call
400 */
401 if (!SCM_FALSEP (scm_procedure_p (program)))
402 {
403 POP_LIST (nargs);
404 SYNC_BEFORE_GC ();
405 *sp = scm_apply (program, *sp, SCM_EOL);
406 program = SCM_VM_FRAME_PROGRAM (fp);
407 goto vm_return;
408 }
409 /*
410 * Continuation call
411 */
412 if (SCM_VM_CONT_P (program))
413 goto vm_call_cc;
414
415 goto vm_error_wrong_type_apply;
416 }
417
418 VM_DEFINE_INSTRUCTION (call_cc, "call/cc", 1, 1, 1)
419 {
420 SYNC_BEFORE_GC ();
421 PUSH (capture_vm_cont (vp));
422 POP (program);
423 nargs = 1;
424 goto vm_call;
425 }
426
427 VM_DEFINE_INSTRUCTION (return, "return", 0, 0, 1)
428 {
429 SCM ret;
430 vm_return:
431 ret = *sp;
432 EXIT_HOOK ();
433 RETURN_HOOK ();
434 FREE_FRAME ();
435
436 /* Cache the last program */
437 program = SCM_VM_FRAME_PROGRAM (fp);
438 CACHE_PROGRAM ();
439 PUSH (ret);
440 NEXT;
441 }
442
443 /*
444 Local Variables:
445 c-file-style: "gnu"
446 End:
447 */