map and for-each in scheme
[bpt/guile.git] / libguile / vm-i-system.c
CommitLineData
dce0252b 1/* Copyright (C) 2001,2008,2009,2010,2011 Free Software Foundation, Inc.
a98cef7e 2 *
53e28ed9 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
a98cef7e 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
53e28ed9
AW
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
a98cef7e 12 *
53e28ed9
AW
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
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
53e28ed9
AW
17 */
18
a98cef7e
KN
19
20/* This file is included in vm_engine.c */
21
a98cef7e
KN
22\f
23/*
24 * Basic operations
25 */
26
53e28ed9 27VM_DEFINE_INSTRUCTION (0, nop, "nop", 0, 0, 0)
a98cef7e
KN
28{
29 NEXT;
30}
31
53e28ed9 32VM_DEFINE_INSTRUCTION (1, halt, "halt", 0, 0, 0)
a98cef7e 33{
a222b0fa 34 nvalues = SCM_I_INUM (*sp--);
11ea1aba 35 NULLSTACK (1);
a222b0fa 36 if (nvalues == 1)
e06e857c 37 POP (finish_args);
a222b0fa
AW
38 else
39 {
40 POP_LIST (nvalues);
e06e857c 41 POP (finish_args);
877ffa3f 42 SYNC_REGISTER ();
e06e857c 43 finish_args = scm_values (finish_args);
a222b0fa
AW
44 }
45
1dc8f851 46 {
6c6a4439
AW
47#ifdef VM_ENABLE_STACK_NULLING
48 SCM *old_sp = sp;
49#endif
1dc8f851
AW
50
51 /* Restore registers */
52 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
6c6a4439
AW
53 /* Setting the ip here doesn't actually affect control flow, as the calling
54 code will restore its own registers, but it does help when walking the
55 stack */
56 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1dc8f851 57 fp = SCM_FRAME_DYNAMIC_LINK (fp);
6c6a4439 58 NULLSTACK (old_sp - sp);
1dc8f851 59 }
e06e857c
AW
60
61 goto vm_done;
a98cef7e
KN
62}
63
cf45ff03 64VM_DEFINE_INSTRUCTION (2, drop, "drop", 0, 1, 0)
a98cef7e 65{
17e90c5e 66 DROP ();
a98cef7e
KN
67 NEXT;
68}
69
cf45ff03 70VM_DEFINE_INSTRUCTION (3, dup, "dup", 0, 0, 1)
26403690 71{
f349065e
KN
72 SCM x = *sp;
73 PUSH (x);
26403690
KN
74 NEXT;
75}
76
17e90c5e
KN
77\f
78/*
79 * Object creation
80 */
a98cef7e 81
cf45ff03 82VM_DEFINE_INSTRUCTION (4, void, "void", 0, 0, 1)
a98cef7e 83{
17e90c5e 84 PUSH (SCM_UNSPECIFIED);
a98cef7e
KN
85 NEXT;
86}
87
cf45ff03 88VM_DEFINE_INSTRUCTION (5, make_true, "make-true", 0, 0, 1)
a98cef7e 89{
17e90c5e 90 PUSH (SCM_BOOL_T);
a98cef7e
KN
91 NEXT;
92}
93
cf45ff03 94VM_DEFINE_INSTRUCTION (6, make_false, "make-false", 0, 0, 1)
a98cef7e 95{
17e90c5e 96 PUSH (SCM_BOOL_F);
a98cef7e
KN
97 NEXT;
98}
99
cf45ff03 100VM_DEFINE_INSTRUCTION (7, make_nil, "make-nil", 0, 0, 1)
4530432e
DK
101{
102 PUSH (SCM_ELISP_NIL);
103 NEXT;
104}
105
cf45ff03 106VM_DEFINE_INSTRUCTION (8, make_eol, "make-eol", 0, 0, 1)
a98cef7e 107{
17e90c5e 108 PUSH (SCM_EOL);
a98cef7e
KN
109 NEXT;
110}
111
cf45ff03 112VM_DEFINE_INSTRUCTION (9, make_int8, "make-int8", 1, 0, 1)
a98cef7e 113{
2d80426a 114 PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
a98cef7e
KN
115 NEXT;
116}
117
cf45ff03 118VM_DEFINE_INSTRUCTION (10, make_int8_0, "make-int8:0", 0, 0, 1)
a98cef7e 119{
238e7a11 120 PUSH (SCM_INUM0);
a98cef7e
KN
121 NEXT;
122}
123
cf45ff03 124VM_DEFINE_INSTRUCTION (11, make_int8_1, "make-int8:1", 0, 0, 1)
a98cef7e 125{
238e7a11 126 PUSH (SCM_I_MAKINUM (1));
a98cef7e
KN
127 NEXT;
128}
129
cf45ff03 130VM_DEFINE_INSTRUCTION (12, make_int16, "make-int16", 2, 0, 1)
a98cef7e 131{
ea9b4b29
KN
132 int h = FETCH ();
133 int l = FETCH ();
2d80426a 134 PUSH (SCM_I_MAKINUM ((signed short) (h << 8) + l));
a98cef7e
KN
135 NEXT;
136}
137
cf45ff03 138VM_DEFINE_INSTRUCTION (13, make_int64, "make-int64", 8, 0, 1)
586cfdec
AW
139{
140 scm_t_uint64 v = 0;
141 v += FETCH ();
142 v <<= 8; v += FETCH ();
143 v <<= 8; v += FETCH ();
144 v <<= 8; v += FETCH ();
145 v <<= 8; v += FETCH ();
146 v <<= 8; v += FETCH ();
147 v <<= 8; v += FETCH ();
148 v <<= 8; v += FETCH ();
149 PUSH (scm_from_int64 ((scm_t_int64) v));
150 NEXT;
151}
152
cf45ff03 153VM_DEFINE_INSTRUCTION (14, make_uint64, "make-uint64", 8, 0, 1)
586cfdec
AW
154{
155 scm_t_uint64 v = 0;
156 v += FETCH ();
157 v <<= 8; v += FETCH ();
158 v <<= 8; v += FETCH ();
159 v <<= 8; v += FETCH ();
160 v <<= 8; v += FETCH ();
161 v <<= 8; v += FETCH ();
162 v <<= 8; v += FETCH ();
163 v <<= 8; v += FETCH ();
164 PUSH (scm_from_uint64 (v));
165 NEXT;
166}
167
cf45ff03 168VM_DEFINE_INSTRUCTION (15, make_char8, "make-char8", 1, 0, 1)
a98cef7e 169{
4c402b88
MG
170 scm_t_uint8 v = 0;
171 v = FETCH ();
172
173 PUSH (SCM_MAKE_CHAR (v));
174 /* Don't simplify this to PUSH (SCM_MAKE_CHAR (FETCH ())). The
175 contents of SCM_MAKE_CHAR may be evaluated more than once,
176 resulting in a double fetch. */
a98cef7e
KN
177 NEXT;
178}
179
cf45ff03 180VM_DEFINE_INSTRUCTION (16, make_char32, "make-char32", 4, 0, 1)
904a78f1
MG
181{
182 scm_t_wchar v = 0;
183 v += FETCH ();
184 v <<= 8; v += FETCH ();
185 v <<= 8; v += FETCH ();
186 v <<= 8; v += FETCH ();
187 PUSH (SCM_MAKE_CHAR (v));
188 NEXT;
189}
190
191
192
cf45ff03 193VM_DEFINE_INSTRUCTION (17, list, "list", 2, -1, 1)
cb4cca12 194{
23b587b0
LC
195 unsigned h = FETCH ();
196 unsigned l = FETCH ();
197 unsigned len = ((h << 8) + l);
198 POP_LIST (len);
cb4cca12
KN
199 NEXT;
200}
201
cf45ff03 202VM_DEFINE_INSTRUCTION (18, vector, "vector", 2, -1, 1)
cb4cca12 203{
23b587b0
LC
204 unsigned h = FETCH ();
205 unsigned l = FETCH ();
206 unsigned len = ((h << 8) + l);
5338b62b
AW
207 SCM vect;
208
877ffa3f 209 SYNC_REGISTER ();
5338b62b
AW
210 sp++; sp -= len;
211 CHECK_UNDERFLOW ();
212 vect = scm_make_vector (scm_from_uint (len), SCM_BOOL_F);
213 memcpy (SCM_I_VECTOR_WELTS(vect), sp, sizeof(SCM) * len);
214 NULLSTACK (len);
215 *sp = vect;
216
cb4cca12
KN
217 NEXT;
218}
219
a98cef7e
KN
220\f
221/*
17e90c5e 222 * Variable access
a98cef7e
KN
223 */
224
17e90c5e
KN
225#define OBJECT_REF(i) objects[i]
226#define OBJECT_SET(i,o) objects[i] = o
a98cef7e 227
af988bbf
KN
228#define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
229#define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
a98cef7e 230
2d80426a
LC
231/* For the variable operations, we _must_ obviously avoid function calls to
232 `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
233 nothing more than the corresponding macros. */
234#define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
235#define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
236#define VARIABLE_BOUNDP(v) (VARIABLE_REF (v) != SCM_UNDEFINED)
a98cef7e 237
6f16379e 238#define FREE_VARIABLE_REF(i) SCM_PROGRAM_FREE_VARIABLE_REF (program, i)
8d90b356 239
17e90c5e 240/* ref */
a98cef7e 241
cf45ff03 242VM_DEFINE_INSTRUCTION (19, object_ref, "object-ref", 1, 0, 1)
a98cef7e 243{
a52b2d3d 244 register unsigned objnum = FETCH ();
0b5f0e49
LC
245 CHECK_OBJECT (objnum);
246 PUSH (OBJECT_REF (objnum));
17e90c5e 247 NEXT;
a98cef7e
KN
248}
249
a5cfddd5 250/* FIXME: necessary? elt 255 of the vector could be a vector... */
cf45ff03 251VM_DEFINE_INSTRUCTION (20, long_object_ref, "long-object-ref", 2, 0, 1)
a5cfddd5
AW
252{
253 unsigned int objnum = FETCH ();
254 objnum <<= 8;
255 objnum += FETCH ();
256 CHECK_OBJECT (objnum);
257 PUSH (OBJECT_REF (objnum));
258 NEXT;
259}
260
cf45ff03 261VM_DEFINE_INSTRUCTION (21, local_ref, "local-ref", 1, 0, 1)
a98cef7e 262{
17e90c5e 263 PUSH (LOCAL_REF (FETCH ()));
a1a482e0 264 ASSERT_BOUND (*sp);
17e90c5e 265 NEXT;
a98cef7e
KN
266}
267
cf45ff03 268VM_DEFINE_INSTRUCTION (22, long_local_ref, "long-local-ref", 2, 0, 1)
a98cef7e 269{
80545853
AW
270 unsigned int i = FETCH ();
271 i <<= 8;
272 i += FETCH ();
28b119ee 273 PUSH (LOCAL_REF (i));
a1a482e0 274 ASSERT_BOUND (*sp);
a98cef7e
KN
275 NEXT;
276}
277
cf45ff03 278VM_DEFINE_INSTRUCTION (23, local_bound, "local-bound?", 1, 0, 1)
3092a14d
AW
279{
280 if (LOCAL_REF (FETCH ()) == SCM_UNDEFINED)
281 PUSH (SCM_BOOL_F);
282 else
283 PUSH (SCM_BOOL_T);
284 NEXT;
285}
286
cf45ff03 287VM_DEFINE_INSTRUCTION (24, long_local_bound, "long-local-bound?", 2, 0, 1)
3092a14d
AW
288{
289 unsigned int i = FETCH ();
290 i <<= 8;
291 i += FETCH ();
292 if (LOCAL_REF (i) == SCM_UNDEFINED)
293 PUSH (SCM_BOOL_F);
294 else
295 PUSH (SCM_BOOL_T);
296 NEXT;
297}
298
cf45ff03 299VM_DEFINE_INSTRUCTION (25, variable_ref, "variable-ref", 0, 1, 1)
a98cef7e 300{
17e90c5e 301 SCM x = *sp;
238e7a11 302
dce0252b
AW
303 /* We don't use ASSERT_VARIABLE or ASSERT_BOUND_VARIABLE here because,
304 unlike in top-variable-ref, it really isn't an internal assertion
305 that can be optimized out -- the variable could be coming directly
306 from the user. */
307 if (SCM_UNLIKELY (!SCM_VARIABLEP (x)))
308 {
309 func_name = "variable-ref";
310 finish_args = x;
311 goto vm_error_not_a_variable;
312 }
313 else if (SCM_UNLIKELY (!VARIABLE_BOUNDP (x)))
17e90c5e 314 {
1af77230
LC
315 SCM var_name;
316
317 /* Attempt to provide the variable name in the error message. */
318 var_name = scm_module_reverse_lookup (scm_current_module (), x);
d1079217 319 finish_args = scm_is_true (var_name) ? var_name : x;
17e90c5e
KN
320 goto vm_error_unbound;
321 }
238e7a11
LC
322 else
323 {
2d80426a 324 SCM o = VARIABLE_REF (x);
238e7a11
LC
325 *sp = o;
326 }
327
a98cef7e
KN
328 NEXT;
329}
330
cf45ff03 331VM_DEFINE_INSTRUCTION (26, variable_bound, "variable-bound?", 0, 1, 1)
3092a14d 332{
dce0252b
AW
333 SCM x = *sp;
334
335 if (SCM_UNLIKELY (!SCM_VARIABLEP (x)))
336 {
337 func_name = "variable-bound?";
338 finish_args = x;
339 goto vm_error_not_a_variable;
340 }
3092a14d 341 else
dce0252b 342 *sp = scm_from_bool (VARIABLE_BOUNDP (x));
3092a14d
AW
343 NEXT;
344}
345
cf45ff03 346VM_DEFINE_INSTRUCTION (27, toplevel_ref, "toplevel-ref", 1, 0, 1)
9cc649b8 347{
6297d229 348 unsigned objnum = FETCH ();
45dc6b34 349 SCM what, resolved;
9cc649b8 350 CHECK_OBJECT (objnum);
fd358575 351 what = OBJECT_REF (objnum);
9cc649b8 352
45dc6b34 353 if (!SCM_VARIABLEP (what))
9cc649b8 354 {
d0168f3d 355 SYNC_REGISTER ();
45dc6b34
MG
356 resolved = resolve_variable (what, scm_program_module (program));
357 if (!VARIABLE_BOUNDP (resolved))
9cc649b8 358 {
d1079217 359 finish_args = what;
9cc649b8
AW
360 goto vm_error_unbound;
361 }
45dc6b34 362 what = resolved;
fd358575 363 OBJECT_SET (objnum, what);
9cc649b8
AW
364 }
365
fd358575 366 PUSH (VARIABLE_REF (what));
9cc649b8
AW
367 NEXT;
368}
369
cf45ff03 370VM_DEFINE_INSTRUCTION (28, long_toplevel_ref, "long-toplevel-ref", 2, 0, 1)
a5cfddd5 371{
45dc6b34 372 SCM what, resolved;
a5cfddd5
AW
373 unsigned int objnum = FETCH ();
374 objnum <<= 8;
375 objnum += FETCH ();
376 CHECK_OBJECT (objnum);
377 what = OBJECT_REF (objnum);
378
45dc6b34 379 if (!SCM_VARIABLEP (what))
a5cfddd5
AW
380 {
381 SYNC_REGISTER ();
45dc6b34
MG
382 resolved = resolve_variable (what, scm_program_module (program));
383 if (!VARIABLE_BOUNDP (resolved))
a5cfddd5 384 {
d1079217 385 finish_args = what;
a5cfddd5
AW
386 goto vm_error_unbound;
387 }
45dc6b34 388 what = resolved;
a5cfddd5
AW
389 OBJECT_SET (objnum, what);
390 }
391
392 PUSH (VARIABLE_REF (what));
393 NEXT;
394}
395
17e90c5e
KN
396/* set */
397
cf45ff03 398VM_DEFINE_INSTRUCTION (29, local_set, "local-set", 1, 1, 0)
a98cef7e 399{
eae2438d
AW
400 SCM x;
401 POP (x);
402 LOCAL_SET (FETCH (), x);
a98cef7e
KN
403 NEXT;
404}
405
cf45ff03 406VM_DEFINE_INSTRUCTION (30, long_local_set, "long-local-set", 2, 1, 0)
a98cef7e 407{
eae2438d 408 SCM x;
80545853
AW
409 unsigned int i = FETCH ();
410 i <<= 8;
411 i += FETCH ();
eae2438d
AW
412 POP (x);
413 LOCAL_SET (i, x);
a98cef7e
KN
414 NEXT;
415}
416
cf45ff03 417VM_DEFINE_INSTRUCTION (31, variable_set, "variable-set", 0, 2, 0)
a98cef7e 418{
dce0252b
AW
419 if (SCM_UNLIKELY (!SCM_VARIABLEP (sp[0])))
420 {
421 func_name = "variable-set!";
422 finish_args = sp[0];
423 goto vm_error_not_a_variable;
424 }
2d80426a 425 VARIABLE_SET (sp[0], sp[-1]);
11ea1aba 426 DROPN (2);
a98cef7e
KN
427 NEXT;
428}
429
cf45ff03 430VM_DEFINE_INSTRUCTION (32, toplevel_set, "toplevel-set", 1, 1, 0)
9cc649b8 431{
6297d229 432 unsigned objnum = FETCH ();
fd358575 433 SCM what;
9cc649b8 434 CHECK_OBJECT (objnum);
fd358575 435 what = OBJECT_REF (objnum);
9cc649b8 436
fd358575 437 if (!SCM_VARIABLEP (what))
9cc649b8 438 {
6287726a 439 SYNC_BEFORE_GC ();
b7393ea1 440 what = resolve_variable (what, scm_program_module (program));
fd358575 441 OBJECT_SET (objnum, what);
9cc649b8
AW
442 }
443
fd358575 444 VARIABLE_SET (what, *sp);
9cc649b8
AW
445 DROP ();
446 NEXT;
447}
448
cf45ff03 449VM_DEFINE_INSTRUCTION (33, long_toplevel_set, "long-toplevel-set", 2, 1, 0)
a5cfddd5
AW
450{
451 SCM what;
452 unsigned int objnum = FETCH ();
453 objnum <<= 8;
454 objnum += FETCH ();
455 CHECK_OBJECT (objnum);
456 what = OBJECT_REF (objnum);
457
458 if (!SCM_VARIABLEP (what))
459 {
460 SYNC_BEFORE_GC ();
461 what = resolve_variable (what, scm_program_module (program));
462 OBJECT_SET (objnum, what);
463 }
464
465 VARIABLE_SET (what, *sp);
466 DROP ();
467 NEXT;
468}
469
a98cef7e
KN
470\f
471/*
472 * branch and jump
473 */
474
97fcf583 475/* offset must be at least 24 bits wide, and signed */
efbd5892 476#define FETCH_OFFSET(offset) \
17e90c5e 477{ \
97fcf583
AW
478 offset = FETCH () << 16; \
479 offset += FETCH () << 8; \
480 offset += FETCH (); \
481 offset -= (offset & (1<<23)) << 1; \
efbd5892
AW
482}
483
eae2438d 484#define BR(p) \
efbd5892 485{ \
97fcf583 486 scm_t_int32 offset; \
efbd5892 487 FETCH_OFFSET (offset); \
17e90c5e 488 if (p) \
97fcf583 489 ip += offset; \
5b09b37f
AW
490 if (offset < 0) \
491 VM_HANDLE_INTERRUPTS; \
17e90c5e
KN
492 NEXT; \
493}
494
cf45ff03 495VM_DEFINE_INSTRUCTION (34, br, "br", 3, 0, 0)
41f248a8 496{
97fcf583 497 scm_t_int32 offset;
e5dc27b8 498 FETCH_OFFSET (offset);
97fcf583 499 ip += offset;
5b09b37f
AW
500 if (offset < 0)
501 VM_HANDLE_INTERRUPTS;
41f248a8
KN
502 NEXT;
503}
504
cf45ff03 505VM_DEFINE_INSTRUCTION (35, br_if, "br-if", 3, 0, 0)
a98cef7e 506{
eae2438d
AW
507 SCM x;
508 POP (x);
509 BR (scm_is_true (x));
a98cef7e
KN
510}
511
cf45ff03 512VM_DEFINE_INSTRUCTION (36, br_if_not, "br-if-not", 3, 0, 0)
a98cef7e 513{
eae2438d
AW
514 SCM x;
515 POP (x);
516 BR (scm_is_false (x));
a98cef7e
KN
517}
518
cf45ff03 519VM_DEFINE_INSTRUCTION (37, br_if_eq, "br-if-eq", 3, 0, 0)
a98cef7e 520{
eae2438d
AW
521 SCM x, y;
522 POP2 (y, x);
523 BR (scm_is_eq (x, y));
a98cef7e
KN
524}
525
cf45ff03 526VM_DEFINE_INSTRUCTION (38, br_if_not_eq, "br-if-not-eq", 3, 0, 0)
a98cef7e 527{
eae2438d
AW
528 SCM x, y;
529 POP2 (y, x);
530 BR (!scm_is_eq (x, y));
17e90c5e
KN
531}
532
cf45ff03 533VM_DEFINE_INSTRUCTION (39, br_if_null, "br-if-null", 3, 0, 0)
17e90c5e 534{
eae2438d
AW
535 SCM x;
536 POP (x);
537 BR (scm_is_null (x));
17e90c5e
KN
538}
539
cf45ff03 540VM_DEFINE_INSTRUCTION (40, br_if_not_null, "br-if-not-null", 3, 0, 0)
17e90c5e 541{
eae2438d
AW
542 SCM x;
543 POP (x);
544 BR (!scm_is_null (x));
a98cef7e
KN
545}
546
a98cef7e
KN
547\f
548/*
549 * Subprogram call
550 */
551
cf45ff03 552VM_DEFINE_INSTRUCTION (41, br_if_nargs_ne, "br-if-nargs-ne", 5, 0, 0)
7e01997e
AW
553{
554 scm_t_ptrdiff n;
7f991c7d 555 scm_t_int32 offset;
7e01997e
AW
556 n = FETCH () << 8;
557 n += FETCH ();
7e01997e
AW
558 FETCH_OFFSET (offset);
559 if (sp - (fp - 1) != n)
560 ip += offset;
561 NEXT;
562}
563
cf45ff03 564VM_DEFINE_INSTRUCTION (42, br_if_nargs_lt, "br-if-nargs-lt", 5, 0, 0)
7e01997e
AW
565{
566 scm_t_ptrdiff n;
7f991c7d 567 scm_t_int32 offset;
7e01997e
AW
568 n = FETCH () << 8;
569 n += FETCH ();
7e01997e
AW
570 FETCH_OFFSET (offset);
571 if (sp - (fp - 1) < n)
572 ip += offset;
573 NEXT;
574}
575
cf45ff03 576VM_DEFINE_INSTRUCTION (43, br_if_nargs_gt, "br-if-nargs-gt", 5, 0, 0)
7e01997e
AW
577{
578 scm_t_ptrdiff n;
ff74e44e
AW
579 scm_t_int32 offset;
580
7e01997e
AW
581 n = FETCH () << 8;
582 n += FETCH ();
7e01997e
AW
583 FETCH_OFFSET (offset);
584 if (sp - (fp - 1) > n)
585 ip += offset;
586 NEXT;
587}
588
cf45ff03 589VM_DEFINE_INSTRUCTION (44, assert_nargs_ee, "assert-nargs-ee", 2, 0, 0)
1e2a8c26
AW
590{
591 scm_t_ptrdiff n;
592 n = FETCH () << 8;
593 n += FETCH ();
a6f15a1e 594 if (sp - (fp - 1) != n)
1e2a8c26 595 goto vm_error_wrong_num_args;
1e2a8c26
AW
596 NEXT;
597}
598
cf45ff03 599VM_DEFINE_INSTRUCTION (45, assert_nargs_ge, "assert-nargs-ge", 2, 0, 0)
1e2a8c26
AW
600{
601 scm_t_ptrdiff n;
602 n = FETCH () << 8;
603 n += FETCH ();
a6f15a1e 604 if (sp - (fp - 1) < n)
1e2a8c26 605 goto vm_error_wrong_num_args;
1e2a8c26
AW
606 NEXT;
607}
608
cf45ff03 609VM_DEFINE_INSTRUCTION (46, bind_optionals, "bind-optionals", 2, -1, -1)
7e01997e
AW
610{
611 scm_t_ptrdiff n;
612 n = FETCH () << 8;
613 n += FETCH ();
614 while (sp - (fp - 1) < n)
615 PUSH (SCM_UNDEFINED);
616 NEXT;
617}
618
cf45ff03 619VM_DEFINE_INSTRUCTION (47, bind_optionals_shuffle, "bind-optionals/shuffle", 6, -1, -1)
7e01997e
AW
620{
621 SCM *walk;
622 scm_t_ptrdiff nreq, nreq_and_opt, ntotal;
623 nreq = FETCH () << 8;
624 nreq += FETCH ();
625 nreq_and_opt = FETCH () << 8;
626 nreq_and_opt += FETCH ();
627 ntotal = FETCH () << 8;
628 ntotal += FETCH ();
629
630 /* look in optionals for first keyword or last positional */
631 /* starting after the last required positional arg */
3092a14d 632 walk = fp + nreq;
7e01997e
AW
633 while (/* while we have args */
634 walk <= sp
635 /* and we still have positionals to fill */
3092a14d 636 && walk - fp < nreq_and_opt
7e01997e
AW
637 /* and we haven't reached a keyword yet */
638 && !scm_is_keyword (*walk))
639 /* bind this optional arg (by leaving it in place) */
640 walk++;
641 /* now shuffle up, from walk to ntotal */
642 {
3092a14d 643 scm_t_ptrdiff nshuf = sp - walk + 1, i;
7e01997e
AW
644 sp = (fp - 1) + ntotal + nshuf;
645 CHECK_OVERFLOW ();
3092a14d
AW
646 for (i = 0; i < nshuf; i++)
647 sp[-i] = walk[nshuf-i-1];
7e01997e
AW
648 }
649 /* and fill optionals & keyword args with SCM_UNDEFINED */
3092a14d 650 while (walk <= (fp - 1) + ntotal)
7e01997e
AW
651 *walk++ = SCM_UNDEFINED;
652
653 NEXT;
654}
655
ff74e44e
AW
656/* Flags that determine whether other keywords are allowed, and whether a
657 rest argument is expected. These values must match those used by the
658 glil->assembly compiler. */
659#define F_ALLOW_OTHER_KEYS 1
660#define F_REST 2
661
cf45ff03 662VM_DEFINE_INSTRUCTION (48, bind_kwargs, "bind-kwargs", 5, 0, 0)
7e01997e
AW
663{
664 scm_t_uint16 idx;
665 scm_t_ptrdiff nkw;
ff74e44e 666 int kw_and_rest_flags;
7e01997e
AW
667 SCM kw;
668 idx = FETCH () << 8;
669 idx += FETCH ();
ff74e44e 670 /* XXX: We don't actually use NKW. */
7e01997e
AW
671 nkw = FETCH () << 8;
672 nkw += FETCH ();
ff74e44e 673 kw_and_rest_flags = FETCH ();
7e01997e 674
ff74e44e
AW
675 if (!(kw_and_rest_flags & F_REST)
676 && ((sp - (fp - 1) - nkw) % 2))
7e01997e
AW
677 goto vm_error_kwargs_length_not_even;
678
679 CHECK_OBJECT (idx);
680 kw = OBJECT_REF (idx);
ff74e44e
AW
681
682 /* Switch NKW to be a negative index below SP. */
683 for (nkw = -(sp - (fp - 1) - nkw) + 1; nkw < 0; nkw++)
7e01997e
AW
684 {
685 SCM walk;
ff74e44e
AW
686
687 if (scm_is_keyword (sp[nkw]))
688 {
689 for (walk = kw; scm_is_pair (walk); walk = SCM_CDR (walk))
690 {
691 if (scm_is_eq (SCM_CAAR (walk), sp[nkw]))
692 {
693 SCM si = SCM_CDAR (walk);
694 LOCAL_SET (SCM_I_INUMP (si) ? SCM_I_INUM (si) : scm_to_long (si),
695 sp[nkw + 1]);
696 break;
697 }
698 }
699 if (!(kw_and_rest_flags & F_ALLOW_OTHER_KEYS) && !scm_is_pair (walk))
700 goto vm_error_kwargs_unrecognized_keyword;
701
702 nkw++;
703 }
704 else if (!(kw_and_rest_flags & F_REST))
705 goto vm_error_kwargs_invalid_keyword;
7e01997e
AW
706 }
707
708 NEXT;
709}
710
ff74e44e
AW
711#undef F_ALLOW_OTHER_KEYS
712#undef F_REST
713
714
cf45ff03 715VM_DEFINE_INSTRUCTION (49, push_rest, "push-rest", 2, -1, -1)
1e2a8c26
AW
716{
717 scm_t_ptrdiff n;
a6f15a1e 718 SCM rest = SCM_EOL;
1e2a8c26
AW
719 n = FETCH () << 8;
720 n += FETCH ();
a6f15a1e 721 while (sp - (fp - 1) > n)
1e2a8c26
AW
722 /* No need to check for underflow. */
723 CONS (rest, *sp--, rest);
724 PUSH (rest);
1e2a8c26
AW
725 NEXT;
726}
727
cf45ff03 728VM_DEFINE_INSTRUCTION (50, bind_rest, "bind-rest", 4, -1, -1)
899d37a6
AW
729{
730 scm_t_ptrdiff n;
731 scm_t_uint32 i;
732 SCM rest = SCM_EOL;
733 n = FETCH () << 8;
734 n += FETCH ();
735 i = FETCH () << 8;
736 i += FETCH ();
737 while (sp - (fp - 1) > n)
738 /* No need to check for underflow. */
739 CONS (rest, *sp--, rest);
740 LOCAL_SET (i, rest);
741 NEXT;
742}
743
cf45ff03 744VM_DEFINE_INSTRUCTION (51, reserve_locals, "reserve-locals", 2, -1, -1)
b7946e9e 745{
258344b4 746 SCM *old_sp;
55d9bc94
AW
747 scm_t_int32 n;
748 n = FETCH () << 8;
749 n += FETCH ();
258344b4
AW
750 old_sp = sp;
751 sp = (fp - 1) + n;
752
753 if (old_sp < sp)
754 {
755 CHECK_OVERFLOW ();
756 while (old_sp < sp)
757 *++old_sp = SCM_UNDEFINED;
758 }
759 else
760 NULLSTACK (old_sp - sp);
761
55d9bc94
AW
762 NEXT;
763}
764
cf45ff03 765VM_DEFINE_INSTRUCTION (52, new_frame, "new-frame", 0, 0, 3)
b7946e9e 766{
6c6a4439
AW
767 /* NB: if you change this, see frames.c:vm-frame-num-locals */
768 /* and frames.h, vm-engine.c, etc of course */
9b709b0f
AW
769
770 /* We don't initialize the dynamic link here because we don't actually
771 know that this frame will point to the current fp: it could be
772 placed elsewhere on the stack if captured in a partial
773 continuation, and invoked from some other context. */
774 PUSH (0); /* dynamic link */
775 PUSH (0); /* mvra */
776 PUSH (0); /* ra */
b7946e9e
AW
777 NEXT;
778}
779
cf45ff03 780VM_DEFINE_INSTRUCTION (53, call, "call", 1, -1, 1)
a98cef7e 781{
17e90c5e 782 nargs = FETCH ();
a98cef7e
KN
783
784 vm_call:
75c3ed28 785 program = sp[-nargs];
c8b9df71 786
e8c37772 787 VM_HANDLE_INTERRUPTS;
e311f5fa 788
75c3ed28 789 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
a98cef7e 790 {
75c3ed28 791 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
42906d74 792 {
75c3ed28
AW
793 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
794 goto vm_call;
795 }
796 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
797 && SCM_SMOB_APPLICABLE_P (program))
798 {
799 SYNC_REGISTER ();
800 sp[-nargs] = scm_i_smob_apply_trampoline (program);
801 goto vm_call;
42906d74 802 }
23f276de 803 else
75c3ed28 804 goto vm_error_wrong_type_apply;
a98cef7e 805 }
a98cef7e 806
75c3ed28 807 CACHE_PROGRAM ();
9b709b0f
AW
808
809 {
810 SCM *old_fp = fp;
811
812 fp = sp - nargs + 1;
813
814 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp) == 0);
815 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
816 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
817 SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
818 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
819 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, 0);
820 }
821
75c3ed28 822 ip = SCM_C_OBJCODE_BASE (bp);
c45d4d77 823 PUSH_CONTINUATION_HOOK ();
75c3ed28
AW
824 APPLY_HOOK ();
825 NEXT;
a98cef7e
KN
826}
827
cf45ff03 828VM_DEFINE_INSTRUCTION (54, tail_call, "tail-call", 1, -1, 1)
a98cef7e 829{
17e90c5e 830 nargs = FETCH ();
75c3ed28 831
a5bbb22e 832 vm_tail_call:
75c3ed28 833 program = sp[-nargs];
17e90c5e 834
e8c37772 835 VM_HANDLE_INTERRUPTS;
a98cef7e 836
75c3ed28
AW
837 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
838 {
839 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
840 {
841 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
842 goto vm_tail_call;
843 }
844 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
845 && SCM_SMOB_APPLICABLE_P (program))
846 {
847 SYNC_REGISTER ();
848 sp[-nargs] = scm_i_smob_apply_trampoline (program);
849 goto vm_tail_call;
850 }
851 else
852 goto vm_error_wrong_type_apply;
853 }
854 else
17e90c5e 855 {
28106f54 856 int i;
11ea1aba 857#ifdef VM_ENABLE_STACK_NULLING
a6f15a1e
AW
858 SCM *old_sp = sp;
859 CHECK_STACK_LEAK ();
11ea1aba 860#endif
28106f54 861
28106f54 862 /* switch programs */
28106f54 863 CACHE_PROGRAM ();
a6f15a1e
AW
864 /* shuffle down the program and the arguments */
865 for (i = -1, sp = sp - nargs + 1; i < nargs; i++)
866 SCM_FRAME_STACK_ADDRESS (fp)[i] = sp[i];
11ea1aba 867
03e6c165 868 sp = fp + i - 1;
28106f54 869
11ea1aba
AW
870 NULLSTACK (old_sp - sp);
871
3dbbe28d 872 ip = SCM_C_OBJCODE_BASE (bp);
11ea1aba 873
28106f54
AW
874 APPLY_HOOK ();
875 NEXT;
17e90c5e 876 }
17e90c5e
KN
877}
878
cf45ff03 879VM_DEFINE_INSTRUCTION (55, subr_call, "subr-call", 1, -1, -1)
fd629322 880{
5b46a8c2 881 SCM pointer, ret;
fd629322 882 SCM (*subr)();
5b46a8c2 883
fd629322 884 nargs = FETCH ();
5b46a8c2 885 POP (pointer);
fd629322 886
5b46a8c2 887 subr = SCM_POINTER_VALUE (pointer);
fd629322
AW
888
889 VM_HANDLE_INTERRUPTS;
890 SYNC_REGISTER ();
891
892 switch (nargs)
893 {
894 case 0:
895 ret = subr ();
896 break;
897 case 1:
898 ret = subr (sp[0]);
899 break;
900 case 2:
901 ret = subr (sp[-1], sp[0]);
902 break;
903 case 3:
904 ret = subr (sp[-2], sp[-1], sp[0]);
905 break;
906 case 4:
907 ret = subr (sp[-3], sp[-2], sp[-1], sp[0]);
908 break;
909 case 5:
910 ret = subr (sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
911 break;
912 case 6:
913 ret = subr (sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
914 break;
915 case 7:
916 ret = subr (sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
917 break;
918 case 8:
919 ret = subr (sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
920 break;
921 case 9:
922 ret = subr (sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
923 break;
924 case 10:
925 ret = subr (sp[-9], sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
926 break;
927 default:
928 abort ();
929 }
930
931 NULLSTACK_FOR_NONLOCAL_EXIT ();
fd629322
AW
932
933 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
934 {
935 /* multiple values returned to continuation */
936 ret = scm_struct_ref (ret, SCM_INUM0);
937 nvalues = scm_ilength (ret);
938 PUSH_LIST (ret, scm_is_null);
939 goto vm_return_values;
940 }
941 else
942 {
943 PUSH (ret);
944 goto vm_return;
945 }
946}
947
cf45ff03 948VM_DEFINE_INSTRUCTION (56, smob_call, "smob-call", 1, -1, -1)
75c3ed28
AW
949{
950 SCM smob, ret;
951 SCM (*subr)();
952 nargs = FETCH ();
953 POP (smob);
954
955 subr = SCM_SMOB_DESCRIPTOR (smob).apply;
956
957 VM_HANDLE_INTERRUPTS;
958 SYNC_REGISTER ();
959
960 switch (nargs)
961 {
962 case 0:
963 ret = subr (smob);
964 break;
965 case 1:
966 ret = subr (smob, sp[0]);
967 break;
968 case 2:
969 ret = subr (smob, sp[-1], sp[0]);
970 break;
971 case 3:
972 ret = subr (smob, sp[-2], sp[-1], sp[0]);
973 break;
974 default:
975 abort ();
976 }
977
978 NULLSTACK_FOR_NONLOCAL_EXIT ();
75c3ed28
AW
979
980 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
981 {
982 /* multiple values returned to continuation */
983 ret = scm_struct_ref (ret, SCM_INUM0);
984 nvalues = scm_ilength (ret);
985 PUSH_LIST (ret, scm_is_null);
986 goto vm_return_values;
987 }
988 else
989 {
990 PUSH (ret);
991 goto vm_return;
992 }
993}
994
cf45ff03 995VM_DEFINE_INSTRUCTION (57, foreign_call, "foreign-call", 1, -1, -1)
827dc8dc
AW
996{
997 SCM foreign, ret;
998 nargs = FETCH ();
999 POP (foreign);
1000
1001 VM_HANDLE_INTERRUPTS;
1002 SYNC_REGISTER ();
1003
4d9130a5 1004 ret = scm_i_foreign_call (foreign, sp - nargs + 1);
827dc8dc
AW
1005
1006 NULLSTACK_FOR_NONLOCAL_EXIT ();
1007
1008 if (SCM_UNLIKELY (SCM_VALUESP (ret)))
1009 {
1010 /* multiple values returned to continuation */
1011 ret = scm_struct_ref (ret, SCM_INUM0);
1012 nvalues = scm_ilength (ret);
1013 PUSH_LIST (ret, scm_is_null);
1014 goto vm_return_values;
1015 }
1016 else
1017 {
1018 PUSH (ret);
1019 goto vm_return;
1020 }
1021}
1022
cf45ff03 1023VM_DEFINE_INSTRUCTION (58, continuation_call, "continuation-call", 0, -1, 0)
1d1cae0e
AW
1024{
1025 SCM contregs;
1026 POP (contregs);
d8873dfe 1027
f7cea645 1028 SYNC_ALL ();
d8873dfe
AW
1029 scm_i_check_continuation (contregs);
1030 vm_return_to_continuation (scm_i_contregs_vm (contregs),
1031 scm_i_contregs_vm_cont (contregs),
1032 sp - (fp - 1), fp);
1033 scm_i_reinstate_continuation (contregs);
1034
1d1cae0e
AW
1035 /* no NEXT */
1036 abort ();
1037}
1038
cf45ff03 1039VM_DEFINE_INSTRUCTION (59, partial_cont_call, "partial-cont-call", 0, -1, 0)
cee1d22c 1040{
adbdfd6d 1041 SCM vmcont, intwinds, prevwinds;
eae2438d 1042 POP2 (intwinds, vmcont);
07801437 1043 SYNC_REGISTER ();
b3950ad6
AW
1044 if (SCM_UNLIKELY (!SCM_VM_CONT_REWINDABLE_P (vmcont)))
1045 { finish_args = vmcont;
1046 goto vm_error_continuation_not_rewindable;
1047 }
adbdfd6d
AW
1048 prevwinds = scm_i_dynwinds ();
1049 vm_reinstate_partial_continuation (vm, vmcont, intwinds, sp + 1 - fp, fp,
1050 vm_cookie);
1051
1052 /* Rewind prompt jmpbuffers, if any. */
1053 {
1054 SCM winds = scm_i_dynwinds ();
1055 for (; !scm_is_eq (winds, prevwinds); winds = scm_cdr (winds))
1056 if (SCM_PROMPT_P (scm_car (winds)) && SCM_PROMPT_SETJMP (scm_car (winds)))
1057 break;
1058 }
1059
07801437
AW
1060 CACHE_REGISTER ();
1061 program = SCM_FRAME_PROGRAM (fp);
1062 CACHE_PROGRAM ();
cee1d22c
AW
1063 NEXT;
1064}
1065
cf45ff03 1066VM_DEFINE_INSTRUCTION (60, tail_call_nargs, "tail-call/nargs", 0, 0, 1)
efbd5892
AW
1067{
1068 SCM x;
1069 POP (x);
1070 nargs = scm_to_int (x);
d51406fe 1071 /* FIXME: should truncate values? */
a5bbb22e 1072 goto vm_tail_call;
efbd5892
AW
1073}
1074
cf45ff03 1075VM_DEFINE_INSTRUCTION (61, call_nargs, "call/nargs", 0, 0, 1)
efbd5892
AW
1076{
1077 SCM x;
1078 POP (x);
1079 nargs = scm_to_int (x);
d51406fe 1080 /* FIXME: should truncate values? */
efbd5892
AW
1081 goto vm_call;
1082}
1083
cf45ff03 1084VM_DEFINE_INSTRUCTION (62, mv_call, "mv-call", 4, -1, 1)
a222b0fa 1085{
97fcf583 1086 scm_t_int32 offset;
e5dc27b8 1087 scm_t_uint8 *mvra;
a222b0fa
AW
1088
1089 nargs = FETCH ();
efbd5892 1090 FETCH_OFFSET (offset);
97fcf583 1091 mvra = ip + offset;
a222b0fa 1092
352c87d7 1093 vm_mv_call:
75c3ed28 1094 program = sp[-nargs];
a222b0fa 1095
7d94e4af
AW
1096 VM_HANDLE_INTERRUPTS;
1097
75c3ed28 1098 if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
a222b0fa 1099 {
75c3ed28
AW
1100 if (SCM_STRUCTP (program) && SCM_STRUCT_APPLICABLE_P (program))
1101 {
1102 sp[-nargs] = SCM_STRUCT_PROCEDURE (program);
1103 goto vm_mv_call;
1104 }
1105 else if (SCM_NIMP (program) && SCM_TYP7 (program) == scm_tc7_smob
1106 && SCM_SMOB_APPLICABLE_P (program))
a222b0fa 1107 {
75c3ed28
AW
1108 SYNC_REGISTER ();
1109 sp[-nargs] = scm_i_smob_apply_trampoline (program);
1110 goto vm_mv_call;
a222b0fa 1111 }
cc8d1f5f 1112 else
75c3ed28 1113 goto vm_error_wrong_type_apply;
a222b0fa 1114 }
a222b0fa 1115
75c3ed28 1116 CACHE_PROGRAM ();
9b709b0f
AW
1117
1118 {
1119 SCM *old_fp = fp;
1120
1121 fp = sp - nargs + 1;
1122
1123 ASSERT (SCM_FRAME_DYNAMIC_LINK (fp) == 0);
1124 ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
1125 ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
1126 SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
1127 SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
1128 SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, mvra);
1129 }
1130
75c3ed28 1131 ip = SCM_C_OBJCODE_BASE (bp);
c45d4d77 1132 PUSH_CONTINUATION_HOOK ();
75c3ed28
AW
1133 APPLY_HOOK ();
1134 NEXT;
a222b0fa
AW
1135}
1136
cf45ff03 1137VM_DEFINE_INSTRUCTION (63, apply, "apply", 1, -1, 1)
3616e9e9 1138{
c8b9df71
KN
1139 int len;
1140 SCM ls;
1141 POP (ls);
1142
1143 nargs = FETCH ();
9a8cc8e7 1144 ASSERT (nargs >= 2);
c8b9df71
KN
1145
1146 len = scm_ilength (ls);
41e49280
AW
1147 if (SCM_UNLIKELY (len < 0))
1148 {
1149 finish_args = ls;
1150 goto vm_error_apply_to_non_list;
1151 }
c8b9df71 1152
fb10a008 1153 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
c8b9df71
KN
1154
1155 nargs += len - 2;
1156 goto vm_call;
3616e9e9
KN
1157}
1158
cf45ff03 1159VM_DEFINE_INSTRUCTION (64, tail_apply, "tail-apply", 1, -1, 1)
f03c31db
AW
1160{
1161 int len;
1162 SCM ls;
1163 POP (ls);
1164
1165 nargs = FETCH ();
9a8cc8e7 1166 ASSERT (nargs >= 2);
f03c31db
AW
1167
1168 len = scm_ilength (ls);
41e49280
AW
1169 if (SCM_UNLIKELY (len < 0))
1170 {
1171 finish_args = ls;
1172 goto vm_error_apply_to_non_list;
1173 }
f03c31db 1174
fb10a008 1175 PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
f03c31db
AW
1176
1177 nargs += len - 2;
a5bbb22e 1178 goto vm_tail_call;
f03c31db
AW
1179}
1180
cf45ff03 1181VM_DEFINE_INSTRUCTION (65, call_cc, "call/cc", 0, 1, 1)
17e90c5e 1182{
76282387 1183 int first;
d8873dfe 1184 SCM proc, vm_cont, cont;
76282387
AW
1185 POP (proc);
1186 SYNC_ALL ();
cee1d22c 1187 vm_cont = scm_i_vm_capture_stack (vp->stack_base, fp, sp, ip, NULL, 0);
d8873dfe 1188 cont = scm_i_make_continuation (&first, vm, vm_cont);
76282387
AW
1189 if (first)
1190 {
6f2ff782 1191 PUSH (0); /* dynamic link */
b7946e9e
AW
1192 PUSH (0); /* mvra */
1193 PUSH (0); /* ra */
76282387
AW
1194 PUSH (proc);
1195 PUSH (cont);
1196 nargs = 1;
1197 goto vm_call;
1198 }
d8873dfe 1199 else
76282387 1200 {
f3120251
AW
1201 /* Otherwise, the vm continuation was reinstated, and
1202 vm_return_to_continuation pushed on one value. We know only one
1203 value was returned because we are in value context -- the
1204 previous block jumped to vm_call, not vm_mv_call, after all.
1205
1206 So, pull our regs back down from the vp, and march on to the
1207 next instruction. */
d8873dfe
AW
1208 CACHE_REGISTER ();
1209 program = SCM_FRAME_PROGRAM (fp);
1210 CACHE_PROGRAM ();
f3120251 1211 RESTORE_CONTINUATION_HOOK ();
76282387
AW
1212 NEXT;
1213 }
a98cef7e
KN
1214}
1215
cf45ff03 1216VM_DEFINE_INSTRUCTION (66, tail_call_cc, "tail-call/cc", 0, 1, 1)
f03c31db 1217{
76282387 1218 int first;
d8873dfe 1219 SCM proc, vm_cont, cont;
76282387
AW
1220 POP (proc);
1221 SYNC_ALL ();
d8873dfe
AW
1222 /* In contrast to call/cc, tail-call/cc captures the continuation without the
1223 stack frame. */
cee1d22c
AW
1224 vm_cont = scm_i_vm_capture_stack (vp->stack_base,
1225 SCM_FRAME_DYNAMIC_LINK (fp),
1226 SCM_FRAME_LOWER_ADDRESS (fp) - 1,
1227 SCM_FRAME_RETURN_ADDRESS (fp),
1228 SCM_FRAME_MV_RETURN_ADDRESS (fp),
1229 0);
d8873dfe 1230 cont = scm_i_make_continuation (&first, vm, vm_cont);
76282387
AW
1231 if (first)
1232 {
1233 PUSH (proc);
1234 PUSH (cont);
1235 nargs = 1;
a5bbb22e 1236 goto vm_tail_call;
76282387 1237 }
76282387
AW
1238 else
1239 {
d8873dfe 1240 /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
f3120251
AW
1241 does a return from the frame, either to the RA or
1242 MVRA. */
d8873dfe
AW
1243 CACHE_REGISTER ();
1244 program = SCM_FRAME_PROGRAM (fp);
1245 CACHE_PROGRAM ();
f3120251
AW
1246 /* Unfortunately we don't know whether we are at the RA, and thus
1247 have one value without an nvalues marker, or we are at the
1248 MVRA and thus have multiple values and the nvalues
1249 marker. Instead of adding heuristics here, we will let hook
1250 client code do that. */
1251 RESTORE_CONTINUATION_HOOK ();
d8873dfe 1252 NEXT;
76282387 1253 }
f03c31db
AW
1254}
1255
cf45ff03 1256VM_DEFINE_INSTRUCTION (67, return, "return", 0, 1, 1)
a98cef7e 1257{
a98cef7e 1258 vm_return:
c45d4d77 1259 POP_CONTINUATION_HOOK (1);
e8c37772
AW
1260
1261 VM_HANDLE_INTERRUPTS;
1262
f13c269b 1263 {
03e6c165 1264 SCM ret;
f13c269b
AW
1265
1266 POP (ret);
6c6a4439
AW
1267
1268#ifdef VM_ENABLE_STACK_NULLING
1269 SCM *old_sp = sp;
1270#endif
f13c269b
AW
1271
1272 /* Restore registers */
1273 sp = SCM_FRAME_LOWER_ADDRESS (fp);
03e6c165
AW
1274 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1275 fp = SCM_FRAME_DYNAMIC_LINK (fp);
6c6a4439 1276
11ea1aba 1277#ifdef VM_ENABLE_STACK_NULLING
6c6a4439 1278 NULLSTACK (old_sp - sp);
11ea1aba 1279#endif
f13c269b
AW
1280
1281 /* Set return value (sp is already pushed) */
1282 *sp = ret;
1283 }
17e90c5e 1284
15df3447 1285 /* Restore the last program */
af988bbf 1286 program = SCM_FRAME_PROGRAM (fp);
499a4c07 1287 CACHE_PROGRAM ();
7e4760e4 1288 CHECK_IP ();
a98cef7e
KN
1289 NEXT;
1290}
17e90c5e 1291
cf45ff03 1292VM_DEFINE_INSTRUCTION (68, return_values, "return/values", 1, -1, -1)
a222b0fa 1293{
ef24c01b
AW
1294 /* nvalues declared at top level, because for some reason gcc seems to think
1295 that perhaps it might be used without declaration. Fooey to that, I say. */
ef24c01b
AW
1296 nvalues = FETCH ();
1297 vm_return_values:
c45d4d77 1298 POP_CONTINUATION_HOOK (nvalues);
ef24c01b 1299
7d94e4af
AW
1300 VM_HANDLE_INTERRUPTS;
1301
03e6c165 1302 if (nvalues != 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp))
ef24c01b 1303 {
6c6a4439
AW
1304 /* A multiply-valued continuation */
1305 SCM *vals = sp - nvalues;
ef24c01b
AW
1306 int i;
1307 /* Restore registers */
1308 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
03e6c165
AW
1309 ip = SCM_FRAME_MV_RETURN_ADDRESS (fp);
1310 fp = SCM_FRAME_DYNAMIC_LINK (fp);
a222b0fa 1311
ef24c01b
AW
1312 /* Push return values, and the number of values */
1313 for (i = 0; i < nvalues; i++)
6c6a4439 1314 *++sp = vals[i+1];
ef24c01b 1315 *++sp = SCM_I_MAKINUM (nvalues);
a222b0fa 1316
6c6a4439
AW
1317 /* Finally null the end of the stack */
1318 NULLSTACK (vals + nvalues - sp);
ef24c01b
AW
1319 }
1320 else if (nvalues >= 1)
1321 {
1322 /* Multiple values for a single-valued continuation -- here's where I
1323 break with guile tradition and try and do something sensible. (Also,
1324 this block handles the single-valued return to an mv
1325 continuation.) */
6c6a4439 1326 SCM *vals = sp - nvalues;
ef24c01b
AW
1327 /* Restore registers */
1328 sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
03e6c165
AW
1329 ip = SCM_FRAME_RETURN_ADDRESS (fp);
1330 fp = SCM_FRAME_DYNAMIC_LINK (fp);
a222b0fa 1331
ef24c01b 1332 /* Push first value */
6c6a4439 1333 *++sp = vals[1];
a222b0fa 1334
6c6a4439
AW
1335 /* Finally null the end of the stack */
1336 NULLSTACK (vals + nvalues - sp);
ef24c01b
AW
1337 }
1338 else
1339 goto vm_error_no_values;
a222b0fa
AW
1340
1341 /* Restore the last program */
1342 program = SCM_FRAME_PROGRAM (fp);
1343 CACHE_PROGRAM ();
a222b0fa
AW
1344 CHECK_IP ();
1345 NEXT;
1346}
1347
cf45ff03 1348VM_DEFINE_INSTRUCTION (69, return_values_star, "return/values*", 1, -1, -1)
ef24c01b
AW
1349{
1350 SCM l;
1351
1352 nvalues = FETCH ();
11ea1aba 1353 ASSERT (nvalues >= 1);
ef24c01b
AW
1354
1355 nvalues--;
1356 POP (l);
9bd48cb1 1357 while (scm_is_pair (l))
ef24c01b
AW
1358 {
1359 PUSH (SCM_CAR (l));
1360 l = SCM_CDR (l);
1361 nvalues++;
1362 }
fb10a008 1363 if (SCM_UNLIKELY (!SCM_NULL_OR_NIL_P (l))) {
e06e857c 1364 finish_args = scm_list_1 (l);
fb10a008
AW
1365 goto vm_error_improper_list;
1366 }
ef24c01b
AW
1367
1368 goto vm_return_values;
1369}
1370
cf45ff03 1371VM_DEFINE_INSTRUCTION (70, return_nvalues, "return/nvalues", 0, 1, -1)
2d9260d1
AW
1372{
1373 SCM n;
1374 POP (n);
1375 nvalues = scm_to_int (n);
1376 ASSERT (nvalues >= 0);
1377 goto vm_return_values;
1378}
1379
cf45ff03 1380VM_DEFINE_INSTRUCTION (71, truncate_values, "truncate-values", 2, -1, -1)
d51406fe
AW
1381{
1382 SCM x;
1383 int nbinds, rest;
1384 POP (x);
1385 nvalues = scm_to_int (x);
1386 nbinds = FETCH ();
1387 rest = FETCH ();
1388
1389 if (rest)
1390 nbinds--;
1391
1392 if (nvalues < nbinds)
1393 goto vm_error_not_enough_values;
1394
1395 if (rest)
1396 POP_LIST (nvalues - nbinds);
1397 else
1398 DROPN (nvalues - nbinds);
1399
1400 NEXT;
1401}
1402
cf45ff03 1403VM_DEFINE_INSTRUCTION (72, box, "box", 1, 1, 0)
a9b0f876 1404{
8d90b356
AW
1405 SCM val;
1406 POP (val);
1407 SYNC_BEFORE_GC ();
1408 LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable, SCM_UNPACK (val)));
a9b0f876
AW
1409 NEXT;
1410}
1411
8d90b356
AW
1412/* for letrec:
1413 (let ((a *undef*) (b *undef*) ...)
1414 (set! a (lambda () (b ...)))
1415 ...)
1416 */
cf45ff03 1417VM_DEFINE_INSTRUCTION (73, empty_box, "empty-box", 1, 0, 0)
a9b0f876 1418{
8d90b356
AW
1419 SYNC_BEFORE_GC ();
1420 LOCAL_SET (FETCH (),
1421 scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1422 NEXT;
1423}
a9b0f876 1424
cf45ff03 1425VM_DEFINE_INSTRUCTION (74, local_boxed_ref, "local-boxed-ref", 1, 0, 1)
8d90b356
AW
1426{
1427 SCM v = LOCAL_REF (FETCH ());
1428 ASSERT_BOUND_VARIABLE (v);
1429 PUSH (VARIABLE_REF (v));
1430 NEXT;
1431}
a9b0f876 1432
cf45ff03 1433VM_DEFINE_INSTRUCTION (75, local_boxed_set, "local-boxed-set", 1, 1, 0)
8d90b356
AW
1434{
1435 SCM v, val;
1436 v = LOCAL_REF (FETCH ());
1437 POP (val);
1438 ASSERT_VARIABLE (v);
1439 VARIABLE_SET (v, val);
a9b0f876
AW
1440 NEXT;
1441}
1442
cf45ff03 1443VM_DEFINE_INSTRUCTION (76, free_ref, "free-ref", 1, 0, 1)
a9b0f876 1444{
8d90b356
AW
1445 scm_t_uint8 idx = FETCH ();
1446
57ab0671
AW
1447 CHECK_FREE_VARIABLE (idx);
1448 PUSH (FREE_VARIABLE_REF (idx));
8d90b356
AW
1449 NEXT;
1450}
a9b0f876 1451
57ab0671 1452/* no free-set -- if a var is assigned, it should be in a box */
a9b0f876 1453
cf45ff03 1454VM_DEFINE_INSTRUCTION (77, free_boxed_ref, "free-boxed-ref", 1, 0, 1)
8d90b356
AW
1455{
1456 SCM v;
1457 scm_t_uint8 idx = FETCH ();
57ab0671
AW
1458 CHECK_FREE_VARIABLE (idx);
1459 v = FREE_VARIABLE_REF (idx);
8d90b356
AW
1460 ASSERT_BOUND_VARIABLE (v);
1461 PUSH (VARIABLE_REF (v));
1462 NEXT;
1463}
1464
cf45ff03 1465VM_DEFINE_INSTRUCTION (78, free_boxed_set, "free-boxed-set", 1, 1, 0)
8d90b356
AW
1466{
1467 SCM v, val;
1468 scm_t_uint8 idx = FETCH ();
1469 POP (val);
57ab0671
AW
1470 CHECK_FREE_VARIABLE (idx);
1471 v = FREE_VARIABLE_REF (idx);
8d90b356
AW
1472 ASSERT_BOUND_VARIABLE (v);
1473 VARIABLE_SET (v, val);
1474 NEXT;
1475}
1476
cf45ff03 1477VM_DEFINE_INSTRUCTION (79, make_closure, "make-closure", 2, -1, 1)
8d90b356 1478{
6f16379e
AW
1479 size_t n, len;
1480 SCM closure;
1481
1482 len = FETCH ();
1483 len <<= 8;
1484 len += FETCH ();
8d90b356 1485 SYNC_BEFORE_GC ();
6f16379e
AW
1486 closure = scm_words (scm_tc7_program | (len<<16), len + 3);
1487 SCM_SET_CELL_OBJECT_1 (closure, SCM_PROGRAM_OBJCODE (sp[-len]));
1488 SCM_SET_CELL_OBJECT_2 (closure, SCM_PROGRAM_OBJTABLE (sp[-len]));
1489 sp[-len] = closure;
1490 for (n = 0; n < len; n++)
1491 SCM_PROGRAM_FREE_VARIABLE_SET (closure, n, sp[-len + 1 + n]);
1492 DROPN (len);
a9b0f876
AW
1493 NEXT;
1494}
1495
cf45ff03 1496VM_DEFINE_INSTRUCTION (80, make_variable, "make-variable", 0, 0, 1)
80545853
AW
1497{
1498 SYNC_BEFORE_GC ();
1499 /* fixme underflow */
1500 PUSH (scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
1501 NEXT;
1502}
1503
cf45ff03 1504VM_DEFINE_INSTRUCTION (81, fix_closure, "fix-closure", 2, -1, 0)
c21c89b1 1505{
6f16379e 1506 SCM x;
c21c89b1 1507 unsigned int i = FETCH ();
6f16379e 1508 size_t n, len;
c21c89b1
AW
1509 i <<= 8;
1510 i += FETCH ();
c21c89b1
AW
1511 /* FIXME CHECK_LOCAL (i) */
1512 x = LOCAL_REF (i);
1513 /* FIXME ASSERT_PROGRAM (x); */
6f16379e
AW
1514 len = SCM_PROGRAM_NUM_FREE_VARIABLES (x);
1515 for (n = 0; n < len; n++)
1516 SCM_PROGRAM_FREE_VARIABLE_SET (x, n, sp[-len + 1 + n]);
1517 DROPN (len);
c21c89b1
AW
1518 NEXT;
1519}
1520
cf45ff03 1521VM_DEFINE_INSTRUCTION (82, define, "define", 0, 0, 2)
94ff26b9
AW
1522{
1523 SCM sym, val;
eae2438d 1524 POP2 (sym, val);
94ff26b9
AW
1525 SYNC_REGISTER ();
1526 VARIABLE_SET (scm_sym2var (sym, scm_current_module_lookup_closure (),
1527 SCM_BOOL_T),
1528 val);
1529 NEXT;
1530}
1531
cf45ff03 1532VM_DEFINE_INSTRUCTION (83, make_keyword, "make-keyword", 0, 1, 1)
94ff26b9
AW
1533{
1534 CHECK_UNDERFLOW ();
1535 SYNC_REGISTER ();
1536 *sp = scm_symbol_to_keyword (*sp);
1537 NEXT;
1538}
1539
cf45ff03 1540VM_DEFINE_INSTRUCTION (84, make_symbol, "make-symbol", 0, 1, 1)
94ff26b9
AW
1541{
1542 CHECK_UNDERFLOW ();
1543 SYNC_REGISTER ();
1544 *sp = scm_string_to_symbol (*sp);
1545 NEXT;
1546}
1547
cf45ff03 1548VM_DEFINE_INSTRUCTION (85, prompt, "prompt", 4, 2, 0)
4f66bcde
AW
1549{
1550 scm_t_int32 offset;
ea6b18e8 1551 scm_t_uint8 escape_only_p;
747022e4 1552 SCM k, prompt;
4f66bcde 1553
4f66bcde
AW
1554 escape_only_p = FETCH ();
1555 FETCH_OFFSET (offset);
4f66bcde
AW
1556 POP (k);
1557
1558 SYNC_REGISTER ();
d2964315 1559 /* Push the prompt onto the dynamic stack. */
adbdfd6d
AW
1560 prompt = scm_c_make_prompt (k, fp, sp, ip + offset, escape_only_p, vm_cookie,
1561 scm_i_dynwinds ());
1562 scm_i_set_dynwinds (scm_cons (prompt, SCM_PROMPT_DYNWINDS (prompt)));
adaf86ec 1563 if (SCM_PROMPT_SETJMP (prompt))
4f66bcde
AW
1564 {
1565 /* The prompt exited nonlocally. Cache the regs back from the vp, and go
ea6b18e8 1566 to the handler.
d2964315
AW
1567
1568 Note, at this point, we must assume that any variable local to
1569 vm_engine that can be assigned *has* been assigned. So we need to pull
1570 all our state back from the ip/fp/sp.
ea6b18e8 1571 */
d2964315
AW
1572 CACHE_REGISTER ();
1573 program = SCM_FRAME_PROGRAM (fp);
1574 CACHE_PROGRAM ();
f3120251
AW
1575 /* The stack contains the values returned to this prompt, along
1576 with a number-of-values marker -- like an MV return. */
1577 ABORT_CONTINUATION_HOOK ();
4f66bcde
AW
1578 NEXT;
1579 }
1580
1581 /* Otherwise setjmp returned for the first time, so we go to execute the
1582 prompt's body. */
1583 NEXT;
1584}
1585
cf45ff03 1586VM_DEFINE_INSTRUCTION (86, wind, "wind", 0, 2, 0)
4f66bcde
AW
1587{
1588 SCM wind, unwind;
eae2438d 1589 POP2 (unwind, wind);
4f66bcde
AW
1590 SYNC_REGISTER ();
1591 /* Push wind and unwind procedures onto the dynamic stack. Note that neither
1592 are actually called; the compiler should emit calls to wind and unwind for
1593 the normal dynamic-wind control flow. */
1594 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (wind))))
1595 {
1596 finish_args = wind;
1597 goto vm_error_not_a_thunk;
1598 }
1599 if (SCM_UNLIKELY (scm_is_false (scm_thunk_p (unwind))))
1600 {
1601 finish_args = unwind;
1602 goto vm_error_not_a_thunk;
1603 }
1604 scm_i_set_dynwinds (scm_cons (scm_cons (wind, unwind), scm_i_dynwinds ()));
1605 NEXT;
1606}
1607
cf45ff03 1608VM_DEFINE_INSTRUCTION (87, abort, "abort", 1, -1, -1)
4f66bcde
AW
1609{
1610 unsigned n = FETCH ();
4f66bcde 1611 SYNC_REGISTER ();
2d026f04 1612 if (sp - n - 2 <= SCM_FRAME_UPPER_ADDRESS (fp))
eaefabee 1613 goto vm_error_stack_underflow;
cee1d22c 1614 vm_abort (vm, n, vm_cookie);
6e84cb95 1615 /* vm_abort should not return */
4f66bcde
AW
1616 abort ();
1617}
1618
cf45ff03 1619VM_DEFINE_INSTRUCTION (88, unwind, "unwind", 0, 0, 0)
4f66bcde
AW
1620{
1621 /* A normal exit from the dynamic extent of an expression. Pop the top entry
1622 off of the dynamic stack. */
1623 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
1624 NEXT;
1625}
1626
cf45ff03 1627VM_DEFINE_INSTRUCTION (89, wind_fluids, "wind-fluids", 1, -1, 0)
e084b27e
AW
1628{
1629 unsigned n = FETCH ();
1630 SCM wf;
1631
f7cea645 1632 SYNC_REGISTER ();
2b41a37b
AW
1633 sp -= 2 * n;
1634 CHECK_UNDERFLOW ();
1635 wf = scm_i_make_with_fluids (n, sp + 1, sp + 1 + n);
1636 NULLSTACK (2 * n);
1637
26e6f99f 1638 scm_i_swap_with_fluids (wf, dynstate);
e084b27e
AW
1639 scm_i_set_dynwinds (scm_cons (wf, scm_i_dynwinds ()));
1640 NEXT;
1641}
1642
cf45ff03 1643VM_DEFINE_INSTRUCTION (90, unwind_fluids, "unwind-fluids", 0, 0, 0)
e084b27e
AW
1644{
1645 SCM wf;
1646 wf = scm_car (scm_i_dynwinds ());
1647 scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
26e6f99f 1648 scm_i_swap_with_fluids (wf, dynstate);
e084b27e
AW
1649 NEXT;
1650}
4f66bcde 1651
cf45ff03 1652VM_DEFINE_INSTRUCTION (91, fluid_ref, "fluid-ref", 0, 1, 1)
1e7a0337
AW
1653{
1654 size_t num;
1655 SCM fluids;
1656
1657 CHECK_UNDERFLOW ();
1658 fluids = SCM_I_DYNAMIC_STATE_FLUIDS (dynstate);
6f8d7b12 1659 if (SCM_UNLIKELY (!SCM_FLUID_P (*sp))
1e7a0337
AW
1660 || ((num = SCM_I_FLUID_NUM (*sp)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
1661 {
1662 /* Punt dynstate expansion and error handling to the C proc. */
1663 SYNC_REGISTER ();
1664 *sp = scm_fluid_ref (*sp);
1665 }
1666 else
ef94624e
BT
1667 {
1668 SCM val = SCM_SIMPLE_VECTOR_REF (fluids, num);
1669 if (SCM_UNLIKELY (val == SCM_UNDEFINED))
1670 {
1671 finish_args = *sp;
1672 goto vm_error_unbound_fluid;
1673 }
1674 *sp = val;
1675 }
1e7a0337
AW
1676
1677 NEXT;
1678}
1679
cf45ff03 1680VM_DEFINE_INSTRUCTION (92, fluid_set, "fluid-set", 0, 2, 0)
1e7a0337
AW
1681{
1682 size_t num;
1683 SCM val, fluid, fluids;
1684
eae2438d 1685 POP2 (val, fluid);
1e7a0337 1686 fluids = SCM_I_DYNAMIC_STATE_FLUIDS (dynstate);
6f8d7b12 1687 if (SCM_UNLIKELY (!SCM_FLUID_P (fluid))
1e7a0337
AW
1688 || ((num = SCM_I_FLUID_NUM (fluid)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
1689 {
1690 /* Punt dynstate expansion and error handling to the C proc. */
1691 SYNC_REGISTER ();
1692 scm_fluid_set_x (fluid, val);
1693 }
1694 else
1695 SCM_SIMPLE_VECTOR_SET (fluids, num, val);
1696
1697 NEXT;
1698}
1699
cf45ff03 1700VM_DEFINE_INSTRUCTION (93, assert_nargs_ee_locals, "assert-nargs-ee/locals", 1, 0, 0)
de45d8ee
AW
1701{
1702 scm_t_ptrdiff n;
1703 SCM *old_sp;
1704
1705 /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
1706 n = FETCH ();
1707
1708 if (SCM_UNLIKELY (sp - (fp - 1) != (n & 0x7)))
1709 goto vm_error_wrong_num_args;
1710
1711 old_sp = sp;
1712 sp += (n >> 3);
1713 CHECK_OVERFLOW ();
1714 while (old_sp < sp)
1715 *++old_sp = SCM_UNDEFINED;
1716
1717 NEXT;
1718}
1719
8d90b356 1720
53e28ed9
AW
1721/*
1722(defun renumber-ops ()
1723 "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
1724 (interactive "")
1725 (save-excursion
1726 (let ((counter -1)) (goto-char (point-min))
1727 (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
1728 (replace-match
1729 (number-to-string (setq counter (1+ counter)))
1730 t t nil 1)))))
ff810079 1731(renumber-ops)
53e28ed9 1732*/
17e90c5e
KN
1733/*
1734 Local Variables:
1735 c-file-style: "gnu"
1736 End:
1737*/