1 /* -*- tab-width:4; -*- */
2
3 #include "s.h"
4 #include "vm2.h"
5 #include "stack.h"
6 #include "asm.h"
7
8 /* #define DEBUG_ASM */
9
10
11 /* Max number of successive pushes:
12 * Note: this measure is important for threads. With correct vm it
13 * gives the maximum depth. VM must ensure to sync the stack before
14 * calls. So that we have good checkpoints. */
15
16 int scm_push_seq_max;
17
18 /*-- local const */
19
20 static SOBJ scm_atom_local, scm_atom_rest, scm_atom_optionnal;
21
22 static int
23 warn_unbound_func = FALSE,
24 warn_unbound_symbol = FALSE;
25
26
27 /*-- forward decl */
28 static SOBJ scm_asm_internal(SOBJ pcode, SOBJ icode);
29 static SOBJ scm_optimize1(SOBJ icode);
30 static SOBJ scm_compile_funcall2(SOBJ icode, SOBJ func, SOBJ argl, SOBJ env);
31 static SOBJ scm_compile_letrec(SOBJ icode, SOBJ argl, SOBJ env);
32
33 /****************************************************************
34 * helper functions
35 ****************************************************************/
36
37 /* search atom in current environment and in the current module
38 * chain.
39 *
40 * Returns:
41 * NULL if symbol is not found
42 * a LSYM if it's a local symbol. in this case the depth is set.
43 * a SYM if it's a global symbol.
44 *
45 * If create_flag is TRUE, the symbol is created and the functions
46 * never returns NULL. */
47
48
lookup_atom(SOBJ atom,SOBJ env,int * depth,int create_flag)49 static SOBJ lookup_atom(SOBJ atom, SOBJ env, int *depth, int create_flag)
50 {
51 SOBJ sym;
52
53 if (env != NULL) {
54 if ((sym = scm_env_search(env, atom, depth)) != NULL)
55 return(sym);
56 }
57 return(scm_module_find_symbol(scm_current_module, atom, create_flag));
58 }
59
60
61 /*-- convert icode to proc: Used when assembling (mkclosure) */
icode_to_proc(SOBJ icode,SOBJ env,int nargs,int optargs)62 static SOBJ icode_to_proc(SOBJ icode, SOBJ env, int nargs, int optargs)
63 {
64 SOBJ proc;
65 SCM_Code *code;
66 long size;
67
68 size = SCM_ASIZE(icode);
69 code = scm_must_alloc(offsetof(SCM_Code, code[size]));
70 code->envlist = NULL;
71 code->nargs = nargs;
72 code->optargs = optargs;
73 code->nlocals = 0;
74 code->size = size;
75 memcpy(code->code, SCM_ARRAY(icode), size * sizeof(SOBJ*));
76
77 proc = scm_newcell(SOBJ_T_PROC);
78
79 SCM_PROC_CODE(proc) = code;
80 SCM_PROC_ENV(proc) = NULL;
81 return(proc);
82 }
83
mkproc(SOBJ icode,SOBJ env)84 static SOBJ mkproc(SOBJ icode, SOBJ env)
85 {
86 return(icode_to_proc(icode, env, 0, FALSE));
87 }
88
mkcode(SOBJ icode)89 static SOBJ mkcode(SOBJ icode)
90 {
91 return(scm_mkcode(SCM_ARRAY(icode), SCM_ASIZE(icode)));
92 }
93
94
95 /* search for local vars in the body of the expr */
search_local(SOBJ list,SOBJ body)96 static SOBJ search_local(SOBJ list, SOBJ body)
97 {
98 SOBJ expr, var;
99 while(body) {
100 expr = SCM_CAR(body);
101 if (SCM_PAIRP(expr)) {
102 if (SCM_CAR(expr) == SCM_SYM_NAME(scm_sym_define)) {
103 var = SCM_CADR(expr);
104 if (SCM_ATOMP(var)) {
105 list = scm_cons(var, list);
106 } else if (SCM_PAIRP(var)) {
107 list = scm_cons(SCM_CAR(var), list);
108 } else {
109 scm_puts("; strange construct: "); scm_cprint(var);
110 }
111 }
112 }
113 body = SCM_CDR(body);
114 }
115 return(list);
116 }
117
118 /****************************************************************
119 * function to generate and manipulate SCM_ASM_CODE structure
120 ****************************************************************/
121 static int scm_asm_last_label = 1;
122
123 static SOBJ scm_asm_known_labels; /* array of resolved labels */
124 static SOBJ scm_asm_unknown_labels; /* array to store unresolved labels */
125
126
next_label()127 static SOBJ next_label()
128 {
129 ++scm_asm_last_label;
130 return(SCM_MKINUM(scm_asm_last_label));
131 }
132
scm_asm_new_code()133 static SOBJ scm_asm_new_code()
134 {
135 SOBJ code = scm_mkarray(0, NULL);
136 return(code);
137 }
138
scm_array_resize(SOBJ array,int newsize)139 SOBJ scm_array_resize(SOBJ array, int newsize)
140 {
141 SCM_Array *p;
142 if (newsize > SCM_AMAX(array)) {
143 p = scm_must_realloc(SCM_ADESCR(array),
144 sizeof(SCM_Array) + (newsize * sizeof(SOBJ)));
145 SCM_ADESCR(array) = p;
146 p->alloced = newsize + 1;
147 }
148 return(array);
149 }
150
scm_asm_put_opc(SOBJ c,int opcode)151 static void scm_asm_put_opc(SOBJ c, int opcode)
152 {
153 if (SCM_ASIZE(c) >= SCM_AMAX(c))
154 scm_array_resize(c, 2 * SCM_ASIZE(c));
155
156 SCM_AREF(c, SCM_ASIZE(c)++) = SCM_OPCODE(opcode);
157 }
158
scm_asm_put_lit(SOBJ c,SOBJ obj)159 static void scm_asm_put_lit(SOBJ c, SOBJ obj)
160 {
161 if (SCM_ASIZE(c) >= SCM_AMAX(c))
162 scm_array_resize(c, 2 * SCM_ASIZE(c));
163
164 SCM_AREF(c, SCM_ASIZE(c)++) = obj;
165 }
166
scm_asm_defined_label(SOBJ lab)167 static int scm_asm_defined_label(SOBJ lab)
168 {
169 int i;
170
171 for (i = 0; i < SCM_ASIZE(scm_asm_known_labels); i += 2) {
172 if (SCM_AREF(scm_asm_known_labels, i) == lab) {
173 return(i);
174 }
175 }
176 return(-1);
177 }
178
scm_asm_put_lab_ref(SOBJ c,SOBJ lab)179 static void scm_asm_put_lab_ref(SOBJ c, SOBJ lab)
180 {
181 int lab_index;
182 if ((lab_index = scm_asm_defined_label(lab)) >= 0) {
183 scm_asm_put_lit(c, SCM_MKINUM(SCM_INUM(SCM_AREF(scm_asm_known_labels,
184 lab_index+1)) -
185 SCM_ASIZE(c)));
186 } else {
187 scm_vector_append(scm_asm_unknown_labels, lab);
188 scm_vector_append(scm_asm_unknown_labels, SCM_MKINUM(SCM_ASIZE(c)));
189 scm_asm_put_lit(c, SCM_MKINUM(0));
190 }
191 }
192
scm_asm_put2(SOBJ c,int opcode,SOBJ obj)193 static void scm_asm_put2(SOBJ c, int opcode, SOBJ obj)
194 {
195 scm_asm_put_opc(c, opcode);
196 scm_asm_put_lit(c, obj);
197 }
198
199 /*-- opcode assembly */
200
scm_asm_nop(SOBJ c,SOBJ arglist)201 static void scm_asm_nop(SOBJ c, SOBJ arglist)
202 {
203 }
204
scm_asm_end(SOBJ c,SOBJ arglist)205 static void scm_asm_end(SOBJ c, SOBJ arglist)
206 {
207 scm_asm_put_opc(c, SCM_OP_END);
208 }
209
scm_asm_dolet(SOBJ c,SOBJ arglist)210 static void scm_asm_dolet(SOBJ c, SOBJ arglist)
211 {
212 scm_asm_put_opc(c, SCM_OP_DOLET);
213 }
214
scm_asm_doletstar(SOBJ c,SOBJ arglist)215 static void scm_asm_doletstar(SOBJ c, SOBJ arglist)
216 {
217 scm_asm_put2(c, SCM_OP_DOLETSTAR, SCM_CAR(arglist));
218 }
219
scm_asm_drop(SOBJ c,SOBJ arglist)220 static void scm_asm_drop(SOBJ c, SOBJ arglist)
221 {
222 scm_asm_put_opc(c, SCM_OP_DROP);
223 }
224
scm_asm_pushq(SOBJ c,SOBJ arglist)225 static void scm_asm_pushq(SOBJ c, SOBJ arglist)
226 {
227 scm_asm_put2(c, SCM_OP_PUSH, SCM_CAR(arglist));
228 }
229
scm_asm_pushv(SOBJ c,SOBJ arglist)230 static void scm_asm_pushv(SOBJ c, SOBJ arglist)
231 {
232 scm_asm_put2(c, SCM_OP_PUSHV, SCM_CAR(arglist));
233 }
234
235 /*I* (pushl <varnum> <depth>) */
scm_asm_pushl(SOBJ c,SOBJ arglist)236 static void scm_asm_pushl(SOBJ c, SOBJ arglist)
237 {
238 SOBJ n, d;
239 int depth, varnum;
240
241 n = SCM_CAR(arglist);
242 d = SCM_CADR(arglist);
243 depth = SCM_INUM(d);
244 if (depth < 4) {
245 scm_asm_put2(c, SCM_OP_PUSHL0 + depth, n);
246 } else {
247 varnum = SCM_INUM(n);
248 scm_asm_put2(c, SCM_OP_PUSHL, SCM_MKINUM(depth << 16 | varnum));
249 }
250 }
251
252 /*I* (store) */
scm_asm_store(SOBJ c,SOBJ arglist)253 static void scm_asm_store(SOBJ c, SOBJ arglist)
254 {
255 scm_asm_put_opc(c, SCM_OP_STORE);
256 }
257
258 /* syntax: (setl var-number depth) */
scm_asm_setl(SOBJ c,SOBJ arglist)259 static void scm_asm_setl(SOBJ c, SOBJ arglist)
260 {
261 SOBJ varnum;
262 int n, d;
263 varnum = SCM_CAR(arglist);
264 d = SCM_INUM(SCM_CADR(arglist));
265
266 if (d == 0) {
267 scm_asm_put2(c, SCM_OP_SETL0, varnum);
268 } else {
269 n = SCM_INUM(varnum);
270 scm_asm_put2(c, SCM_OP_SETL, SCM_MKINUM( ((d << 16) | n) ));
271 }
272 }
273
274 /* syntax: (setl0drop var-number) */
scm_asm_setl0drop(SOBJ c,SOBJ arglist)275 static void scm_asm_setl0drop(SOBJ c, SOBJ arglist)
276 {
277 SOBJ varnum;
278 varnum = SCM_CAR(arglist);
279 scm_asm_put2(c, SCM_OP_SETL0DROP, varnum);
280 }
281
282 /*I* (getvar) */
scm_asm_getvar(SOBJ c,SOBJ arglist)283 static void scm_asm_getvar(SOBJ c, SOBJ arglist)
284 {
285 scm_asm_put_opc(c, SCM_OP_GETVAR);
286 }
287
288 /*I* (setvar) */
scm_asm_setvar(SOBJ c,SOBJ arglist)289 static void scm_asm_setvar(SOBJ c, SOBJ arglist)
290 {
291 scm_asm_put_opc(c, SCM_OP_SETVAR);
292 }
293
294
scm_asm_mark(SOBJ c,SOBJ arglist)295 static void scm_asm_mark(SOBJ c, SOBJ arglist)
296 {
297 scm_asm_put_opc(c, SCM_OP_MARK);
298 }
299
300 /* (mkclosure nvars nopts code) */
scm_asm_mkclosure(SOBJ c,SOBJ arglist)301 static void scm_asm_mkclosure(SOBJ c, SOBJ arglist)
302 {
303 scm_asm_put_opc(c, SCM_OP_MKCLOSURE);
304 }
305
306 /*I* (mkproc varlist nargs nlocals optargs asmcode) */
scm_asm_mkproc(SOBJ c,SOBJ argl)307 static void scm_asm_mkproc(SOBJ c, SOBJ argl)
308 {
309 SOBJ varlist, optargs, asmcode, icode;
310 SOBJ proc;
311 SCM_Code *code;
312 int size, nargs, nlocals;
313
314 varlist = SCM_CAR(argl); argl = SCM_CDR(argl);
315 nargs = SCM_INUM(SCM_CAR(argl)); argl = SCM_CDR(argl);
316 nlocals = SCM_INUM(SCM_CAR(argl)); argl = SCM_CDR(argl);
317 optargs = SCM_CAR(argl); argl = SCM_CDR(argl);
318 icode = SCM_CAR(argl); argl = SCM_CDR(argl);
319
320 if (argl) SCM_ERR("mkproc: to much args, rest", argl);
321
322 asmcode = scm_asm_internal(scm_asm_new_code(), icode);
323
324 size = SCM_ASIZE(asmcode);
325
326 code = scm_must_alloc(offsetof(SCM_Code, code[size]));
327 code->envlist = varlist;
328 code->nargs = nargs;
329 code->nlocals = nlocals;
330 code->optargs = (optargs != scm_false);
331 code->size = size;
332 memcpy(code->code, SCM_ARRAY(asmcode), size * sizeof(SOBJ*));
333
334 proc = scm_newcell(SOBJ_T_PROC);
335 SCM_PROC_CODE(proc) = code;
336 SCM_PROC_ENV(proc) = NULL;
337
338 scm_asm_put2(c, SCM_OP_PUSH, proc);
339 }
340
scm_asm_mkcode(SOBJ c,SOBJ arglist)341 static void scm_asm_mkcode(SOBJ c, SOBJ arglist)
342 {
343 SCM_ERR("scm_asm_mkcode: not implemented", arglist);
344 }
345
346
scm_asm_endlet(SOBJ c,SOBJ arglist)347 static void scm_asm_endlet(SOBJ c, SOBJ arglist)
348 {
349 scm_asm_put_opc(c, SCM_OP_ENDLET);
350 }
351
scm_asm_return(SOBJ c,SOBJ arglist)352 static void scm_asm_return(SOBJ c, SOBJ arglist)
353 {
354 scm_asm_put_opc(c, SCM_OP_RETURN);
355 }
356
scm_asm_call_jump(SOBJ c,SOBJ arglist,int op_to_compile)357 static void scm_asm_call_jump(SOBJ c, SOBJ arglist, int op_to_compile)
358 {
359 SOBJ f, sym, val;
360 /*int depth;*/
361
362 if (arglist == NULL) { /* no arguments */
363 scm_asm_put_opc(c, op_to_compile);
364 return;
365 }
366 f = SCM_CAR(arglist);
367 if (SCM_ATOMP(f)) SCM_ERR("scm_asm_call_jump: got atom", f);
368
369 sym = f;
370
371 if (sym == NULL) SCM_ERR("scm_asm_call_jump: undefined symbol for function", f);
372
373 switch(SCM_OBJTYPE(sym)) {
374 case SOBJ_T_LSYMBOL:
375 SCM_ERR("scm_asm_call_jump: shoud not have lsymbol here", sym);
376 /*
377 scm_asm_push_local(c, sym, depth);
378 scm_asm_put_opc(c, op_to_compile);
379 */
380 break;
381
382 case SOBJ_T_SYMBOL:
383 val = SCM_SYM_VALUE(sym);
384 if (val == NULL) val = scm_unbound;
385 switch(SCM_OBJTYPE(val)) {
386 case SOBJ_T_CPRIM:
387 {
388 int nargs = SCM_CPRIM_NARGS(val);
389 if (nargs > 5)
390 SCM_ERR("scm_asm_call_jump: cprim with more than 5 arguments", sym);
391
392 scm_asm_put2(c, SCM_OP_PUSH, val);
393 scm_asm_put_opc(c, (nargs < 0) ? SCM_OP_CALLS : SCM_OP_CALLC0 + nargs);
394 }
395 break;
396 case SOBJ_T_PRIM:
397 scm_asm_put_lit(c, SCM_PRIM(val)->address);
398 if (op_to_compile == SCM_OP_ENDLET_JUMP) {
399 scm_asm_put_opc(c, SCM_OP_ENDLET);
400 }
401 break;
402
403 default:
404 scm_asm_put2(c, SCM_OP_PUSHV, sym);
405 scm_asm_put_opc(c, op_to_compile);
406 }
407 break;
408
409 default:
410 SCM_ERR("call: don't know how to compile", f);
411 }
412 }
413
scm_asm_callp(SOBJ c,SOBJ argl)414 static void scm_asm_callp(SOBJ c, SOBJ argl)
415 {
416 scm_asm_put_lit(c, SCM_PRIM(SCM_CAR(argl))->address);
417 }
418
scm_asm_callc(SOBJ c,SOBJ argl)419 static void scm_asm_callc(SOBJ c, SOBJ argl)
420 {
421 SOBJ cfunc = SCM_CAR(argl);
422 int nargs = SCM_CPRIM_NARGS(cfunc);
423 scm_asm_put2(c, SCM_OP_PUSH, cfunc);
424 if (nargs >= 0) {
425 scm_asm_put_opc(c, SCM_OP_CALLC0 + nargs);
426 } else {
427 scm_asm_put_opc(c, SCM_OP_CALLS);
428 }
429 }
430
scm_asm_call(SOBJ c,SOBJ argl)431 static void scm_asm_call(SOBJ c, SOBJ argl)
432 {
433 scm_asm_call_jump(c, argl, SCM_OP_CALL);
434 }
435
scm_asm_jump(SOBJ c,SOBJ argl)436 static void scm_asm_jump(SOBJ c, SOBJ argl)
437 {
438 scm_asm_call_jump(c, argl, SCM_OP_JUMP);
439 }
440
scm_asm_endlet_jump(SOBJ c,SOBJ argl)441 static void scm_asm_endlet_jump(SOBJ c, SOBJ argl)
442 {
443 scm_asm_call_jump(c, argl, SCM_OP_ENDLET_JUMP);
444 }
445
scm_asm_endlet_return(SOBJ c,SOBJ argl)446 static void scm_asm_endlet_return(SOBJ c, SOBJ argl)
447 {
448 scm_asm_put_opc(c, SCM_OP_ENDLET);
449 scm_asm_put_opc(c, SCM_OP_RETURN);
450 }
451
452
scm_asm_label(SOBJ c,SOBJ argl)453 static void scm_asm_label(SOBJ c, SOBJ argl)
454 {
455 int i, loc;
456 SOBJ lab;
457
458 lab = SCM_CAR(argl);
459 scm_vector_append(scm_asm_known_labels, lab);
460 scm_vector_append(scm_asm_known_labels, SCM_MKINUM(SCM_ASIZE(c)));
461
462 /*-- resolv labels now */
463 for (i = 0; i < SCM_ASIZE(scm_asm_unknown_labels); i += 2) {
464 if (SCM_AREF(scm_asm_unknown_labels, i) == lab) {
465 loc = SCM_INUM(SCM_AREF(scm_asm_unknown_labels, i+1));
466 SCM_AREF(c, loc) = SCM_MKINUM(SCM_ASIZE(c) - loc);
467 SCM_AREF(scm_asm_unknown_labels, i) = SCM_MKINUM(0);
468 }
469 }
470 }
471
scm_asm_br_and(SOBJ c,SOBJ argl)472 static void scm_asm_br_and(SOBJ c, SOBJ argl)
473 {
474 scm_asm_put_opc(c, SCM_OP_BR_AND);
475 scm_asm_put_lab_ref(c, SCM_CAR(argl));
476 }
477
scm_asm_br_or(SOBJ c,SOBJ argl)478 static void scm_asm_br_or(SOBJ c, SOBJ argl)
479 {
480 scm_asm_put_opc(c, SCM_OP_BR_OR);
481 scm_asm_put_lab_ref(c, SCM_CAR(argl));
482 }
483
scm_asm_br_cond(SOBJ c,SOBJ argl)484 static void scm_asm_br_cond(SOBJ c, SOBJ argl)
485 {
486 scm_asm_put_opc(c, SCM_OP_BR_COND);
487 scm_asm_put_lab_ref(c, SCM_CAR(argl));
488 }
489
scm_asm_br_while(SOBJ c,SOBJ argl)490 static void scm_asm_br_while(SOBJ c, SOBJ argl)
491 {
492 scm_asm_put_opc(c, SCM_OP_BR_WHILE);
493 scm_asm_put_lab_ref(c, SCM_CAR(argl));
494 }
495
scm_asm_brf(SOBJ c,SOBJ argl)496 static void scm_asm_brf(SOBJ c, SOBJ argl)
497 {
498 SOBJ lab = SCM_CAR(argl);
499
500 scm_asm_put_opc(c, SCM_OP_BRF);
501 scm_asm_put_lab_ref(c, lab);
502 }
503
scm_asm_brt(SOBJ c,SOBJ argl)504 static void scm_asm_brt(SOBJ c, SOBJ argl)
505 {
506 SOBJ lab = SCM_CAR(argl);
507
508 scm_asm_put_opc(c, SCM_OP_BRT);
509 scm_asm_put_lab_ref(c, lab);
510 }
511
512 /*I* (bra <label>) */
scm_asm_bra(SOBJ c,SOBJ argl)513 static void scm_asm_bra(SOBJ c, SOBJ argl)
514 {
515 SOBJ lab = SCM_CAR(argl);
516
517 scm_asm_put_opc(c, SCM_OP_BRA);
518 scm_asm_put_lab_ref(c, lab);
519 }
520
521 /*I* (catch <label>) */
scm_asm_catch(SOBJ c,SOBJ argl)522 static void scm_asm_catch(SOBJ c, SOBJ argl)
523 {
524 SOBJ lab = SCM_CAR(argl);
525 scm_asm_put_opc(c, SCM_OP_CATCH);
526 scm_asm_put_lab_ref(c, lab);
527 }
528
529 /*I* (uncatch) */
scm_asm_uncatch(SOBJ c,SOBJ argl)530 static void scm_asm_uncatch(SOBJ c, SOBJ argl)
531 {
532 scm_asm_put_opc(c, SCM_OP_UNCATCH);
533 }
534
535 /*I* (load-r0) */
scm_asm_load_r0(SOBJ c,SOBJ argl)536 static void scm_asm_load_r0(SOBJ c, SOBJ argl)
537 {
538 scm_asm_put_opc(c, SCM_OP_LOAD_R0);
539 }
540
541 /*I* (save-r0) */
scm_asm_save_r0(SOBJ c,SOBJ argl)542 static void scm_asm_save_r0(SOBJ c, SOBJ argl)
543 {
544 scm_asm_put_opc(c, SCM_OP_SAVE_R0);
545 }
546
547 /*-- table to dispatch assembly */
548
549 static SOBJ
550 op_nop, op_end, op_dolet, op_doletstar, op_endlet_jump, op_drop,
551 op_pushq, op_pushv, op_pushl,
552 op_store,
553 op_setl, op_setl0drop,
554 op_getvar, op_setvar,
555 op_mark, op_mkclosure, op_mkproc, op_mkcode,
556 op_endlet, op_return, op_endlet_return,
557 op_callp, op_callc, op_call, op_jump,
558 op_br_and, op_br_or, op_br_cond, op_br_while, op_bra, op_brf, op_brt,
559 op_catch, op_uncatch,
560 op_label,
561 op_save_r0,
562 op_load_r0;
563
564
565 static SCM_ASM_INSTR scm_asm_table[] = {
566 { "nop", &op_nop, scm_asm_nop },
567 { "end", &op_end, scm_asm_end },
568 { "dolet", &op_dolet, scm_asm_dolet },
569 { "dolet*", &op_doletstar, scm_asm_doletstar },
570 { "endlet-jump", &op_endlet_jump,scm_asm_endlet_jump },
571 { "endlet-return",&op_endlet_return,scm_asm_endlet_return },
572 { "drop", &op_drop, scm_asm_drop },
573 { "pushq", &op_pushq, scm_asm_pushq, }, /* push quoted */
574 { "pushv", &op_pushv, scm_asm_pushv, }, /* push global */
575 { "pushl", &op_pushl, scm_asm_pushl }, /* push local val*/
576 { "store", &op_store, scm_asm_store },
577 { "setl", &op_setl, scm_asm_setl },
578 { "setl0drop", &op_setl0drop, scm_asm_setl0drop },
579
580 { "getvar", &op_getvar, scm_asm_getvar },
581 { "setvar", &op_setvar, scm_asm_setvar },
582
583 { "mark", &op_mark, scm_asm_mark }, /* push a mark */
584 { "mkclosure", &op_mkclosure, scm_asm_mkclosure },
585 { "mkproc", &op_mkproc, scm_asm_mkproc }, /* make a proc */
586 { "mkcode", &op_mkcode, scm_asm_mkcode }, /* create a code */
587
588 { "endlet", &op_endlet, scm_asm_endlet }, /* push a mark */
589 { "return", &op_return, scm_asm_return }, /* push a mark */
590 { "callp", &op_callp, scm_asm_callp }, /* call prim */
591 { "callc", &op_callc, scm_asm_callc }, /* call c func */
592 { "call", &op_call, scm_asm_call }, /* general call */
593 { "jump", &op_jump, scm_asm_jump },
594
595 { "br-and", &op_br_and, scm_asm_br_and },
596 { "br-or", &op_br_or, scm_asm_br_or },
597 { "br-cond", &op_br_cond, scm_asm_br_cond },
598 { "br-while", &op_br_while, scm_asm_br_while },
599 { "bra", &op_bra, scm_asm_bra },
600 { "brf", &op_brf, scm_asm_brf },
601 { "brt", &op_brt, scm_asm_brt },
602
603 { "catch", &op_catch, scm_asm_catch }, /* catch */
604 { "uncatch", &op_uncatch, scm_asm_uncatch }, /* uncatch */
605
606 { "label", &op_label, scm_asm_label },
607 { "save-r0", &op_save_r0, scm_asm_save_r0 },
608 { "load-r0", &op_load_r0, scm_asm_load_r0 },
609 { NULL, NULL, NULL }
610 };
611
612
scm_asm_make_table()613 static void scm_asm_make_table()
614 {
615 SCM_ASM_INSTR *p = scm_asm_table;
616
617 while(p->name) {
618 *p->atom = scm_mkatom(p->name);
619 p++;
620 }
621 }
622
scm_asm_search(SOBJ atom)623 static SCM_ASM_INSTR *scm_asm_search(SOBJ atom)
624 {
625 SCM_ASM_INSTR *p;
626 for (p = scm_asm_table; p->name != NULL; p++) {
627 if (*p->atom == atom) return(p);
628 }
629 return(NULL);
630 }
631
scm_asm_dispatch(SOBJ c,SOBJ opcode,SOBJ arglist)632 static SOBJ scm_asm_dispatch(SOBJ c, SOBJ opcode, SOBJ arglist)
633 {
634 SCM_ASM_INSTR *p;
635
636 if ((p = scm_asm_search(opcode)) == NULL)
637 SCM_ERR("scm_asm_dispatch: bad instruction", opcode);
638
639 if (arglist != NULL && !SCM_PAIRP(arglist))
640 SCM_ERR("scm_asm_dispatch: bad argument list", scm_cons(opcode, arglist));
641
642 (*p->func)(c, arglist);
643
644 return(NULL);
645 }
646
647
648 /* assemble an instruction
649 *
650 * Instruction has form: (<opcode> [<arg>]*)
651 */
scm_asm_instr(SOBJ c,SOBJ expr)652 SOBJ scm_asm_instr(SOBJ c, SOBJ expr)
653 {
654 SOBJ op, arg;
655
656 if (!SCM_PAIRP(expr)) SCM_ERR("asm: bad instruction format", expr);
657
658 op = SCM_CAR(expr);
659 arg = SCM_CDR(expr);
660
661 scm_asm_dispatch(c, op, arg);
662
663 return(NULL);
664 }
665
scm_syntax_asm(SOBJ expr)666 SOBJ scm_syntax_asm(SOBJ expr)
667 {
668 SOBJ c = scm_asm_new_code();
669
670 while(expr) {
671 if (!SCM_PAIRP(expr)) SCM_ERR("asm: bad list", expr);
672 scm_asm_instr(c, SCM_CAR(expr));
673 expr = SCM_CDR(expr);
674 }
675 #ifdef DEBUG_ASM
676 scm_disassemble(SCM_ARRAY(c), SCM_ASIZE(c));
677 #endif
678 return(NULL);
679 }
680
scm_asm_internal(SOBJ pcode,SOBJ icode)681 static SOBJ scm_asm_internal(SOBJ pcode, SOBJ icode)
682 {
683 int i;
684
685 for (i = 0; i < SCM_ASIZE(icode); i++) {
686 scm_asm_instr(pcode, SCM_AREF(icode, i));
687 }
688 return(pcode);
689 }
690
scm_assemble(SOBJ icode)691 static SOBJ scm_assemble(SOBJ icode)
692 {
693 int i;
694 SOBJ c;
695
696 if (!SCM_ARRAYP(icode)) SCM_ERR("scm_assemble: bad icode", icode);
697
698 c = scm_asm_new_code();
699 scm_asm_known_labels = scm_mkarray(0, NULL);
700 scm_asm_unknown_labels = scm_mkarray(0, NULL);
701
702 scm_asm_internal(c, icode);
703
704 #ifdef DEBUG_ASM
705 for (i = 0; i < SCM_ASIZE(scm_asm_known_labels); i += 2) {
706 scm_puts("label ");
707 scm_cdisplay(SCM_AREF(scm_asm_known_labels, i));
708 scm_puts(" at offset ");
709 scm_cdisplay(SCM_AREF(scm_asm_known_labels, i+1));
710 scm_puts("\n");
711 }
712 #endif
713
714 for (i = 0; i < SCM_ASIZE(scm_asm_unknown_labels); i += 2) {
715 if (SCM_AREF(scm_asm_unknown_labels, i) != SCM_MKINUM(0)) {
716 scm_puts("OUPS: label ");
717 scm_cdisplay(SCM_AREF(scm_asm_unknown_labels, i));
718 scm_puts(" used in code at offset ");
719 scm_cdisplay(SCM_AREF(scm_asm_unknown_labels, i+1));
720 scm_puts(" has not been resolved\n");
721 }
722 }
723 #ifdef DEBUG_ASM
724 scm_disassemble(SCM_ARRAY(c), SCM_ASIZE(c));
725 #endif
726 return(c);
727 }
728
729
730 /*
731 * Compiler
732 */
733
scm_asm_gen(SOBJ a,SOBJ list)734 static void scm_asm_gen(SOBJ a, SOBJ list)
735 {
736 SCM_Array *p = SCM_ADESCR(a);
737
738 if (p->size >= p->alloced) {
739 p = scm_must_realloc(p,(p->alloced *2*sizeof(SOBJ)) + sizeof(SCM_Array));
740 p->alloced = p->alloced * 2;
741 SCM_ADESCR(a) = p;
742 }
743 p->item[p->size++] = list;
744 }
745
scm_asm_gen1(SOBJ a,SOBJ item)746 static void scm_asm_gen1(SOBJ a, SOBJ item)
747 {
748 scm_asm_gen(a, scm_cons(item, NULL));
749 }
750
scm_asm_gen2(SOBJ a,SOBJ n1,SOBJ n2)751 static void scm_asm_gen2(SOBJ a, SOBJ n1, SOBJ n2)
752 {
753 scm_asm_gen(a, SCM_LIST2(n1, n2));
754 }
755
scm_asm_gen3(SOBJ a,SOBJ n1,SOBJ n2,SOBJ n3)756 static void scm_asm_gen3(SOBJ a, SOBJ n1, SOBJ n2, SOBJ n3)
757 {
758 scm_asm_gen(a, SCM_LIST3(n1, n2, n3));
759 }
760
scm_asm_gen6(SOBJ a,SOBJ n1,SOBJ n2,SOBJ n3,SOBJ n4,SOBJ n5,SOBJ n6)761 static void scm_asm_gen6(SOBJ a, SOBJ n1, SOBJ n2, SOBJ n3, SOBJ n4, SOBJ n5, SOBJ n6)
762 {
763 scm_asm_gen(a, SCM_LIST6(n1, n2, n3, n4, n5, n6));
764 }
765
766 static SOBJ scm_compile_obj(SOBJ icode, SOBJ obj, SOBJ env);
767
scm_asm_gen_push_args(SOBJ icode,SOBJ argl,SOBJ env)768 static void scm_asm_gen_push_args(SOBJ icode, SOBJ argl, SOBJ env)
769 {
770 int l;
771
772 if (argl == NULL) return;
773
774 if (SCM_CDR(argl)) scm_asm_gen_push_args(icode, SCM_CDR(argl), env);
775
776 l = scm_list_length(argl);
777 if (l > scm_push_seq_max) scm_push_seq_max = l;
778 /* printf("; push seq length=%d max=%d\n", l, scm_push_seq_max); */
779 scm_compile_obj(icode, SCM_CAR(argl), env);
780 }
781
scm_asm_gen_mark(SOBJ ic)782 static void scm_asm_gen_mark(SOBJ ic)
783 {
784 scm_asm_gen1(ic, op_mark);
785 }
786
scm_asm_gen_call(SOBJ ic,int needmark,SOBJ sym,SOBJ argl,SOBJ env)787 static void scm_asm_gen_call(SOBJ ic, int needmark, SOBJ sym, SOBJ argl, SOBJ env)
788 {
789 if (needmark) scm_asm_gen_mark(ic);
790 scm_asm_gen_push_args(ic, argl, env);
791 scm_asm_gen2(ic, op_call, sym);
792 }
793
scm_asm_gen_callp(SOBJ ic,int needmark,SOBJ prim,SOBJ argl,SOBJ env)794 static void scm_asm_gen_callp(SOBJ ic, int needmark, SOBJ prim, SOBJ argl, SOBJ env)
795 {
796 if (needmark) scm_asm_gen_mark(ic);
797 scm_asm_gen_push_args(ic, argl, env);
798 scm_asm_gen2(ic, op_callp, prim);
799 }
800
scm_asm_gen_callc(SOBJ ic,int needmark,SOBJ cprim,SOBJ argl,SOBJ env)801 static void scm_asm_gen_callc(SOBJ ic, int needmark, SOBJ cprim, SOBJ argl, SOBJ env)
802 {
803 if (needmark) scm_asm_gen_mark(ic);
804 scm_asm_gen_push_args(ic, argl, env);
805 scm_asm_gen2(ic, op_callc, cprim);
806 }
807
808
809 /************************************************************************
810 * Compiler: common parts
811 ************************************************************************/
812 /*F* (begin EXPR...) => ANY */
813 /*D* Evaluates EXPR sequencially from left to right. The value the last
814 expression is returned */
815 /* NOTE: compile_begin is public, because it is needed by the module
816 syntax */
817
scm_compile_begin(SOBJ icode,SOBJ argl,SOBJ env)818 SOBJ scm_compile_begin(SOBJ icode, SOBJ argl, SOBJ env)
819 {
820 while(argl) {
821 scm_compile_obj(icode, SCM_CAR(argl), env);
822 argl = SCM_CDR(argl);
823 if (argl != NULL) scm_asm_gen1(icode, op_drop);
824 }
825 return(icode);
826 }
827
828 /*-- lambda compiler -- itself */
scm_compile_lambda2(SOBJ icode,SOBJ formal,SOBJ body,SOBJ env)829 static SOBJ scm_compile_lambda2(SOBJ icode, SOBJ formal, SOBJ body, SOBJ env)
830 {
831 SOBJ newenv, code;
832 int varnum, optargs;
833 int nargs, nlocals;
834 SOBJ l, sym, vlist;
835
836 /* parse lambda arguments and create matching environement */
837 varnum = 0;
838 nargs = 0; nlocals = 0;
839 optargs = FALSE;
840 newenv = scm_env_add_level(env);
841
842 vlist = search_local(NULL, body);
843 #ifdef DEBUG
844 if (vlist) { /* local defines */
845 scm_puts("; local define: "); scm_cprint(vlist);
846 }
847 #endif
848
849 for (l = vlist; l; l = SCM_CDR(l)) {
850 #ifdef DEBUG
851 scm_puts("; local def: "); scm_cprint(SCM_CAR(l));
852 #endif
853 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(l), varnum++));
854 nlocals++;
855 }
856
857 /* add local definitions to the env */
858 l = formal;
859 while(l && SCM_PAIRP(l)) {
860 sym = SCM_CAR(l); l = SCM_CDR(l);
861 if (SCM_KEYWORDP(sym) && SCM_KEYW_NAME(sym) == scm_atom_local) {
862 while(l && SCM_PAIRP(l) && !SCM_KEYWORDP(SCM_CAR(l))) {
863 scm_puts("local def: "); scm_cprint(SCM_CAR(l));
864 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(l), varnum++));
865 nlocals++;
866 l = SCM_CDR(l);
867 }
868 }
869 }
870
871 /* add formal fixed arguments to the env */
872 l = formal;
873 while (l && SCM_PAIRP(l) && !SCM_KEYWORDP(SCM_CAR(l))) {
874 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(l), varnum++));
875 nargs++;
876 l = SCM_CDR(l);
877 }
878
879 /* handle optionnal parameters */
880 if (l && SCM_ATOMP(l)) { /* formal like (a b c . x) */
881 newenv = scm_env_add(newenv, scm_mklsymbol(l, varnum++));
882 optargs = TRUE;
883 nargs++;
884 } else {
885 while(l && SCM_PAIRP(l) && SCM_KEYWORDP(SCM_CAR(l))) { /* (:keyw ...) */
886 sym = SCM_CAR(l); l = SCM_CDR(l);
887
888 if (SCM_KEYW_NAME(sym) == scm_atom_rest) {
889 /* register optionnal var */
890 if (l && SCM_PAIRP(l)) {
891 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(l), varnum++));
892 optargs = TRUE;
893 nargs++;
894 l = SCM_CDR(l);
895 continue;
896 }
897 }
898
899 if (SCM_KEYW_NAME(sym) == scm_atom_local) {
900 /* ignore local var, because they are already defined */
901 while(l && SCM_PAIRP(l) && !SCM_KEYWORDP(SCM_CAR(l))) {
902 l = SCM_CDR(l);
903 }
904 continue;
905 }
906 }
907 if (l != NULL) SCM_ERR("bad formal syntax", formal);
908 }
909 code = scm_compile_begin(scm_mkarray(0,NULL), body, newenv);
910 scm_asm_gen1(code, op_return);
911 scm_optimize1(code);
912 scm_asm_gen6(icode, op_mkproc, newenv,
913 SCM_MKINUM(nargs), SCM_MKINUM(nlocals), SCM_MKBOOL(optargs),
914 code);
915 scm_asm_gen1(icode, op_mkclosure);
916 return(icode);
917 }
918
919 /*-- compile a set! -- scm_asm_generic */
scm_compile_set2(SOBJ icode,SOBJ var,SOBJ expr,SOBJ env)920 static SOBJ scm_compile_set2(SOBJ icode, SOBJ var, SOBJ expr, SOBJ env)
921 {
922 SOBJ sym;
923 int depth;
924
925 sym = lookup_atom(var, env, &depth, FALSE);
926 if (sym == NULL) SCM_ERR("set! needs an existing symbol", var);
927 switch(SCM_OBJTYPE(sym)) {
928 case SOBJ_T_SYMBOL:
929 if (SCM_VARP(SCM_SYM_VALUE(sym))) {
930 scm_compile_obj(icode, expr, env); /* compile the value */
931 scm_asm_gen2(icode, op_pushq, SCM_SYM_VALUE(sym));
932 scm_asm_gen1(icode, op_setvar);
933 break;
934 }
935 scm_compile_obj(icode, expr, env);
936 scm_asm_gen2(icode, op_pushq, sym);
937 scm_asm_gen1(icode, op_store);
938 break;
939
940 case SOBJ_T_LSYMBOL:
941 scm_compile_obj(icode, expr, env);
942 scm_asm_gen3(icode, op_setl, SCM_MKINUM(SCM_LSYM_OFS(sym)), SCM_MKINUM(depth));
943 break;
944
945 default:
946 SCM_ERR("set!: bad symbol", var);
947 }
948 return(icode);
949 }
950
951 /*F* (if TEST CONSEQUENT [ALTERNATE]) => OBJ */
952 /*D* Evaluates CONSEQUENT if the TEST expression evaluates to
953 #t. Otherwise evaluates ALTERNATE. */
scm_compile_if(SOBJ icode,SOBJ argl,SOBJ env)954 static SOBJ scm_compile_if(SOBJ icode, SOBJ argl, SOBJ env)
955 {
956 int len = scm_list_length(argl);
957 SOBJ l1, l2; /* labels */
958
959 if (len != 2 && len != 3)
960 SCM_ERR("scm_compile_if: (if <expr> <true> [ <false> ])", argl);
961
962 if (len == 2) { /* (if <expr> <true>) */
963 l1 = next_label();
964 scm_compile_obj(icode, SCM_CAR(argl), env);
965 scm_asm_gen2(icode, op_br_and, l1);
966 scm_compile_obj(icode, SCM_CADR(argl), env);
967 scm_asm_gen2(icode, op_label, l1);
968 return(icode);
969 }
970 l1 = next_label(); l2 = next_label();
971 scm_compile_obj(icode, SCM_CAR(argl), env);
972 scm_asm_gen2(icode, op_brf, l1);
973 scm_compile_obj(icode, SCM_CADR(argl), env);
974 scm_asm_gen2(icode, op_bra, l2);
975 scm_asm_gen2(icode, op_label, l1);
976 scm_compile_obj(icode, SCM_CADDR(argl), env);
977 scm_asm_gen2(icode, op_label, l2);
978 return(icode);
979 }
980
981 /*F* (define VAR [EXPR]) => EXPR */
982 /*D* Create a new variable VAR, bind it to a fresh location and store
983 the value of EXPR. If EXPR is not given, #unbound is assigned */
984
985 /*F* (define (VAR FORMAL) BODY) => PROC */
986 /*D* Create a variable VAR and assign the procedure equivalent to
987 (lambda (FORMAL) BODY). */
988
989 /*E* (define (VAR ARG [:local LOC] [:rest SYM]) BODY) => PROC */
990 /*D* Same as define but also creates local variables and a binding for
991 the rest of arguments */
992
scm_compile_define(SOBJ icode,SOBJ argl,SOBJ env)993 static SOBJ scm_compile_define(SOBJ icode, SOBJ argl, SOBJ env)
994 {
995 SOBJ var, sym;
996 int depth;
997
998 var = SCM_CAR(argl);
999
1000 if (SCM_SYMBOLP(var)) /* obtain atom from symbol */
1001 var = SCM_SYM_NAME(var);
1002
1003 if (SCM_ATOMP(var)) {
1004
1005 /* force creation of symbol in case it does not exist */
1006 sym = lookup_atom(var, env, &depth, TRUE);
1007
1008
1009 /* compile the code scm_asm_generating the value of the symbol */
1010 if (!SCM_PAIRP(SCM_CDR(argl))) {
1011 /* (define x) => (define x #unbound) */
1012 scm_asm_gen2(icode, op_pushq, scm_unbound);
1013 } else {
1014 scm_compile_obj(icode, SCM_CADR(argl), env);
1015 }
1016
1017 if (SCM_LSYMBOLP(sym)) { /* local symbol */
1018 scm_asm_gen3(icode, op_setl, SCM_MKINUM(SCM_LSYM_OFS(sym)), SCM_MKINUM(depth));
1019 } else { /* global symbol */
1020 if (SCM_SYNTAXP(SCM_SYM_VALUE(sym))) SCM_ERR("syntax redefinition:", sym);
1021 scm_asm_gen2(icode, op_pushq, sym); scm_asm_gen1(icode, op_store);
1022 }
1023 return(icode);
1024 }
1025
1026 if (SCM_PAIRP(var)) { /* (define (var formals) body) */
1027 SOBJ body, formal;
1028
1029 formal = SCM_CDR(var); /* need check */
1030 var = SCM_CAR(var);
1031 body = SCM_CDR(argl); /* need check */
1032 #ifdef OLD
1033 vlist = search_local(NULL, body);
1034 if (vlist) { /* local definitions */
1035 scm_puts("; localy defined variables: "); scm_cprint(vlist);
1036 scm_puts("; have to create environment for this variables\n");
1037 formal = scm_append2(formal,
1038 scm_cons(scm_mkkeyword2(scm_atom_local,
1039 scm_unbound),
1040 vlist));
1041 scm_puts("; new formal: "); scm_cprint(formal);
1042 }
1043 #endif
1044 /* force creation of symbol in case it does not exist */
1045 sym = lookup_atom(var, env, &depth, TRUE);
1046
1047 scm_compile_lambda2(icode, formal, body, env);
1048
1049 if (SCM_LSYMBOLP(sym)) { /* local symbol here */
1050 scm_asm_gen3(icode, op_setl, SCM_MKINUM(SCM_LSYM_OFS(sym)), SCM_MKINUM(depth));
1051 } else {
1052 scm_asm_gen2(icode, op_pushq, sym);
1053 scm_asm_gen1(icode, op_store);
1054 }
1055 return(icode);
1056
1057 }
1058 SCM_ERR("scm_compile_define: cannot compile", argl);
1059 return(NULL); /* keep compiler silent */
1060 }
1061
1062 /*-- compile a set expr */
1063 /*F* (set! VAR EXPR) => VALUE */
1064 /*D* Evaluates EXPR and stores the resulting value in the location to
1065 which VAR is bound. */
scm_compile_set(SOBJ icode,SOBJ argl,SOBJ env)1066 static SOBJ scm_compile_set(SOBJ icode, SOBJ argl, SOBJ env)
1067 {
1068 SOBJ var, expr;
1069
1070 var = SCM_CAR(argl);
1071 expr = SCM_CADR(argl);
1072 return(scm_compile_set2(icode, var, expr, env));
1073 }
1074
scm_compile_named_let(SOBJ icode,SOBJ name,SOBJ argl,SOBJ env)1075 static SOBJ scm_compile_named_let(SOBJ icode, SOBJ name, SOBJ argl, SOBJ env)
1076 {
1077 SOBJ bind, body, newenv, obj, pair;
1078 SOBJ larg, vals, *pn;
1079
1080 bind = SCM_CAR(argl);
1081 body = SCM_CDR(argl);
1082
1083 /* make the binding for the lambda code */
1084 newenv = scm_env_add_level(env);
1085 newenv = scm_env_add(newenv, scm_mklsymbol(name, 0));
1086 scm_asm_gen2(icode, op_doletstar, SCM_MKINUM(1));
1087
1088 /* build a list of arg for the lambda */
1089 larg = NULL;
1090 pn = &larg;
1091 for (obj = bind; obj; obj = SCM_CDR(obj)) {
1092 pair = SCM_CAR(obj);
1093 if (!SCM_PAIRP(obj)) SCM_ERR("let: incorrect binding", obj);
1094 *pn = scm_cons(SCM_CAR(pair), NULL);
1095 pn = &SCM_CDR(*pn);
1096 }
1097 /* scm_puts("named-let: lambda args="); scm_cprint(larg); */
1098 scm_compile_lambda2(icode, larg, body, newenv);
1099 scm_asm_gen3(icode, op_setl0drop, SCM_MKINUM(0), SCM_MKINUM(0));
1100
1101 /* push the argument for the lambda call */
1102 scm_asm_gen_mark(icode);
1103 vals = NULL;
1104 for (obj = bind; obj; obj = SCM_CDR(obj)) {
1105 pair = SCM_CAR(obj);
1106 if (!SCM_PAIRP(obj)) SCM_ERR("let: incorrect binding", obj);
1107 vals = scm_cons(SCM_CDR(pair) ? SCM_CADR(pair) : scm_unbound, vals);
1108 }
1109
1110 for (obj = vals; obj; obj = SCM_CDR(obj)) {
1111 scm_compile_obj(icode, SCM_CAR(obj), newenv);
1112 }
1113 scm_asm_gen3(icode, op_pushl, SCM_MKINUM(0), SCM_MKINUM(0));
1114
1115 /* call this lambda */
1116 scm_asm_gen1(icode, op_call);
1117
1118 scm_asm_gen1(icode, op_endlet);
1119 return(icode);
1120 }
1121
1122
1123 /*-- (let BINDING EXPR...)
1124 * or (let NAME BINDING EXPR)
1125 */
1126 /*F* (let BINDING EXPR...) => OBJ */
1127 /*D* Creates local variables as described in BINDING and evaluates in
1128 the new environemnent the expressions. Returns the value of last
1129 EXPR. The BINDING are evaluated using the enclosing environment */
1130
1131 /*F* (let NAME BINDING EXPR...) => OBJ */
1132 /*D* Does the same as LET except that it binds NAME to the body of the
1133 let construct. Thus the execution of the body EXPRs may be repeated
1134 by invoking the procedure named NAME. */
scm_compile_let(SOBJ icode,SOBJ argl,SOBJ env)1135 static SOBJ scm_compile_let(SOBJ icode, SOBJ argl, SOBJ env)
1136 {
1137 SOBJ bind, expr, newenv, obj, pair;
1138 int varnum;
1139 SOBJ atom;
1140
1141 if (SCM_ATOMP(SCM_CAR(argl))) { /* named let?*/
1142 return(scm_compile_named_let(icode, SCM_CAR(argl), SCM_CDR(argl), env));
1143 }
1144 bind = SCM_CAR(argl);
1145 expr = SCM_CDR(argl);
1146
1147 if (search_local(NULL, expr) != NULL) {
1148 return(scm_compile_letrec(icode, argl, env));
1149 }
1150
1151 newenv = scm_env_add_level(env); /* add a new level of env */
1152 varnum = 0;
1153 atom = NULL;
1154
1155 /* create the new environment */
1156 for (obj = bind; obj; obj = SCM_CDR(obj)) {
1157 pair = SCM_CAR(obj);
1158 if (!SCM_PAIRP(pair)) SCM_ERR("let: incorrect binding", obj);
1159 if (SCM_ATOMP(SCM_CAR(pair)))
1160 atom = SCM_CAR(pair);
1161 else if (SCM_SYMBOLP(SCM_CAR(pair)))
1162 atom = SCM_SYM_NAME(SCM_CAR(pair));
1163 else
1164 SCM_ERR("let: bad local var", SCM_CAR(pair));
1165 newenv = scm_env_add(newenv, scm_mklsymbol(atom, varnum++));
1166 }
1167
1168 /* compile initialisation code */
1169 scm_asm_gen1(icode, op_mark);
1170 for (obj = scm_reverse(bind); obj; obj = SCM_CDR(obj)) {
1171 pair = SCM_CAR(obj);
1172 if (SCM_CDR(pair)) {
1173 scm_compile_obj(icode, SCM_CADR(pair), env);
1174 } else {
1175 scm_asm_gen2(icode, op_pushq, scm_unbound);
1176 }
1177 }
1178 scm_asm_gen1(icode, op_dolet);
1179 scm_compile_begin(icode, expr, newenv);
1180 scm_asm_gen1(icode, op_endlet);
1181 /* scm_optimize1(icode); */
1182 return(icode);
1183 }
1184
1185 /*-- (let* BINDING EXPR) */
1186 /*F* (let* ((VAR INIT) ...) BODY) => OBJ */
1187 /*D* Let* is similar to let, but the bindings are performed
1188 sequentially from left to right, and the region of a binding
1189 indicated by (VAR INIT) is that part of the let* expression to the
1190 right of the binding. Thus the second binding is done in an
1191 environment in which the first binding is visible, and so on. */
scm_compile_letstar(SOBJ icode,SOBJ argl,SOBJ env)1192 static SOBJ scm_compile_letstar(SOBJ icode, SOBJ argl, SOBJ env)
1193 {
1194 SOBJ bind, expr, newenv, obj, pair;
1195 SOBJ vlist;
1196 int varnum;
1197
1198 bind = SCM_CAR(argl);
1199 expr = SCM_CDR(argl);
1200
1201 newenv = scm_env_add_level(env); /* add a new level of env */
1202 varnum = 0;
1203
1204 /* create the new environment */
1205 for (obj = bind; obj; obj = SCM_CDR(obj)) {
1206 pair = SCM_CAR(obj);
1207 if (!SCM_PAIRP(pair)) SCM_ERR("let: incorrect binding", obj);
1208 if (!SCM_ATOMP(SCM_CAR(pair))) SCM_ERR("let: bad local var", SCM_CAR(pair));
1209 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(pair), varnum++));
1210 }
1211 /* add local defs to env */
1212 vlist = search_local(NULL, expr);
1213 for (obj = vlist; obj; obj = SCM_CDR(obj)) {
1214 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(obj), varnum++));
1215 }
1216
1217 /* header of let* */
1218 scm_asm_gen2(icode, op_doletstar, SCM_MKINUM(varnum));
1219
1220 /* compile initialisation code */
1221 varnum = 0;
1222 for (obj = bind; obj; obj = SCM_CDR(obj)) {
1223 pair = SCM_CAR(obj);
1224 if (SCM_CDR(pair)) {
1225 scm_compile_obj(icode, SCM_CADR(pair), newenv);
1226 } else {
1227 scm_asm_gen2(icode, op_pushq, scm_unbound);
1228 }
1229 scm_asm_gen2(icode, op_setl0drop, SCM_MKINUM(varnum++));
1230 }
1231 /* set unbound in local defs */
1232 for (obj = vlist; obj; obj = SCM_CDR(obj)) {
1233 scm_asm_gen2(icode, op_pushq, scm_unbound);
1234 scm_asm_gen2(icode, op_setl0drop, SCM_MKINUM(varnum++));
1235 }
1236
1237 /* compile the body */
1238 scm_compile_begin(icode, expr, newenv);
1239 scm_asm_gen1(icode, op_endlet);
1240 /* scm_optimize1(icode); */
1241 return(icode);
1242 }
1243
1244 /*F* (letrec ((VAR INIT) ...) BODY) => OBJ */
1245 /*D* The VARs are bound to fresh locations holding undefined values,
1246 the INITs are evaluated in the resulting environment (in some
1247 unspecified order), each VAR is assigned to the result of the
1248 corresponding INIT, the BODY is evaluated in the resulting
1249 environment, and the value of the last expression in BODY is
1250 returned. Each binding of a VAR has the entire letrec expression as
1251 its region, making it possible to define mutually recursive
1252 procedures. */
1253
scm_compile_letrec(SOBJ icode,SOBJ argl,SOBJ env)1254 static SOBJ scm_compile_letrec(SOBJ icode, SOBJ argl, SOBJ env)
1255 {
1256 SOBJ bind, expr, newenv, obj, pair;
1257 int varnum;
1258 SOBJ vlist;
1259
1260 bind = SCM_CAR(argl);
1261 expr = SCM_CDR(argl);
1262
1263 newenv = scm_env_add_level(env); /* add a new level of env */
1264 varnum = 0;
1265
1266 /*-- add variable to the new env */
1267 for (obj = bind; obj; obj = SCM_CDR(obj)) {
1268 pair = SCM_CAR(obj);
1269 if (!SCM_PAIRP(pair)) SCM_ERR("letrec: incorrect binding", obj);
1270 if (!SCM_ATOMP(SCM_CAR(pair))) SCM_ERR("letrec: bad local var", SCM_CAR(pair));
1271 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(pair), varnum++));
1272 }
1273 /* add local defs to env */
1274 vlist = search_local(NULL, expr);
1275 for (obj = vlist; obj; obj = SCM_CDR(obj)) {
1276 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(obj), varnum++));
1277 }
1278
1279 /*-- compile code to alloc space for the new variables */
1280 scm_asm_gen2(icode, op_doletstar, SCM_MKINUM(varnum));
1281
1282 /*-- compile code to scm_asm_generate */
1283 varnum = 0;
1284 for (obj = bind; obj; obj = SCM_CDR(obj)) {
1285 pair = SCM_CAR(obj);
1286 if (SCM_CDR(pair)) {
1287 scm_compile_obj(icode, SCM_CADR(pair), newenv);
1288 } else {
1289 scm_asm_gen2(icode, op_pushq, scm_unbound);
1290 }
1291 scm_asm_gen2(icode, op_setl0drop, SCM_MKINUM(varnum++));
1292 }
1293 /* set unbound in local defs */
1294 for (obj = vlist; obj; obj = SCM_CDR(obj)) {
1295 scm_asm_gen2(icode, op_pushq, scm_unbound);
1296 scm_asm_gen2(icode, op_setl0drop, SCM_MKINUM(varnum++));
1297 }
1298 /* compile the body */
1299 scm_compile_begin(icode, expr, newenv);
1300 scm_asm_gen1(icode, op_endlet);
1301 /* scm_optimize1(icode); */
1302 return(icode);
1303 }
1304
1305 /*-- lambda compiler -- front end */
1306 /*F* (lambda FORMALS BODY) => PROCEDURE */
1307 /*D* Returns a new procedure. The environment in effect when the
1308 lambda expression was evaluated is remembered as part of the
1309 procedure. When the procedure is later called with some actual
1310 arguments, the environment in which the lambda expression was
1311 evaluated will be extended by binding the variables in the FORMAL
1312 argument list to fresh locations, the corresponding actual argument
1313 values will be stored in those locations, and the expressions in the
1314 BODY of the lambda expression will be evaluated sequentially in the
1315 extended environment. The result of the last expression in the
1316 BODY will be returned as the result of the procedure call. */
1317
scm_compile_lambda(SOBJ icode,SOBJ argl,SOBJ env)1318 static SOBJ scm_compile_lambda(SOBJ icode, SOBJ argl, SOBJ env)
1319 {
1320 SOBJ formal, body;
1321
1322 formal = SCM_CAR(argl);
1323 body = SCM_CDR(argl);
1324 return(scm_compile_lambda2(icode, formal, body, env));
1325 }
1326
1327 /*-- compiler for quote */
1328 /*F* (quote X) => X */
1329 /*D* Return X, unevaluated */
1330
scm_compile_quote(SOBJ icode,SOBJ argl,SOBJ env)1331 static SOBJ scm_compile_quote(SOBJ icode, SOBJ argl, SOBJ env)
1332 {
1333 scm_asm_gen2(icode, op_pushq, SCM_CAR(argl));
1334 return(icode);
1335 }
1336
prim(char * x)1337 static SOBJ prim(char *x) {
1338 int dummy;
1339 return(SCM_SYM_VALUE(lookup_atom(scm_mkatom(x),NULL,&dummy,FALSE)));
1340 }
1341
1342 /*-- KKK: should try to compile parial constant list */
backquotify(SOBJ ic,SOBJ l,SOBJ env,int level)1343 SOBJ backquotify(SOBJ ic, SOBJ l, SOBJ env, int level)
1344 {
1345 static SOBJ sym_cons, sym_append, sym_list2, sym_list2vec;
1346
1347 if (sym_cons == NULL) {
1348 sym_cons = prim("cons");
1349 sym_list2 = prim("list2");
1350 sym_append = prim("qq-append2");
1351 sym_list2vec = prim("list->vector");
1352 }
1353
1354 if (SCM_ARRAYP(l)) {
1355 backquotify(ic, scm_vector_to_list(l), env, level);
1356 scm_asm_gen2(ic, op_callc, sym_list2vec);
1357 return(ic);
1358 }
1359
1360 if (!SCM_PAIRP(l)) {
1361 scm_asm_gen2(ic, op_pushq, l);
1362 return(ic);
1363 }
1364
1365 if (scm_eqv(SCM_CAR(l), scm_sym_qquote) != scm_false) {
1366 backquotify(ic, SCM_CADR(l), env, level+1);
1367 scm_asm_gen2(ic, op_pushq, scm_sym_qquote);
1368 scm_asm_gen2(ic, op_callp, sym_list2);
1369 return(ic);
1370 }
1371
1372 if (scm_eqv(SCM_CAR(l), scm_sym_unquote) != scm_false) {
1373 if (level == 1) {
1374 scm_compile_obj(ic, SCM_CADR(l), env);
1375 } else {
1376 backquotify(ic, SCM_CADR(l), env, level-1);
1377 scm_asm_gen2(ic, op_pushq, scm_sym_unquote);
1378 scm_asm_gen2(ic, op_callp, sym_list2);
1379 }
1380 return(ic);
1381 }
1382
1383 if (SCM_PAIRP(SCM_CAR(l)) &&
1384 scm_eqv(SCM_CAAR(l), scm_sym_unquote_splicing) != scm_false) {
1385
1386 if (SCM_CDR(l)) backquotify(ic, SCM_CDR(l), env, level);
1387 scm_compile_obj(ic, SCM_CAR(SCM_CDAR(l)), env);
1388 if (SCM_CDR(l)) scm_asm_gen2(ic, op_callp, sym_append);
1389 return(ic);
1390 }
1391 backquotify(ic, SCM_CDR(l), env, level);
1392 backquotify(ic, SCM_CAR(l), env, level);
1393 scm_asm_gen2(ic, op_callp, sym_cons);
1394 return(ic);
1395 }
1396
1397
1398 /*-- compiler for quasiquote */
1399 /*F* (quasiquote TEMPLATE) => LIST */
1400 /*D* If no comma appears in the TEMPLATE, just behaves like
1401 quote. Otherwise the values following the comma are evaluated and
1402 the result is inserted in place. */
1403
scm_compile_qquote(SOBJ icode,SOBJ argl,SOBJ env)1404 static SOBJ scm_compile_qquote(SOBJ icode, SOBJ argl, SOBJ env)
1405 {
1406 /* scm_asm_gen2(icode, op_pushq, SCM_CAR(argl)); */
1407 backquotify(icode, SCM_CAR(argl), env, 1);
1408 /* scm_cprint(backquotify(icode, SCM_CAR(argl), env, 1)); */
1409 return(icode);
1410 }
1411
1412 /*-- compiler for the-env */
1413 /*F* (the-env) => ENV */
1414 /*D* Returns the current compilation environment */
scm_compile_the_env(SOBJ icode,SOBJ argl,SOBJ env)1415 static SOBJ scm_compile_the_env(SOBJ icode, SOBJ argl, SOBJ env)
1416 {
1417 scm_asm_gen2(icode, op_pushq, env);
1418 return(icode);
1419 }
1420
1421
1422 /*-- compiler for and */
1423 /*F* (and TEST1 ...) => OBJ */
1424 /*D* Expressions are evaluated from left to right, and the value of
1425 the first expression that evaluates to a false is returned. Any
1426 remaining expressions are not evaluated. If all the expressions
1427 evaluate to true values, the value of the last expression is
1428 returned. If there are no expressions then #t is returned.*/
1429
scm_compile_and(SOBJ icode,SOBJ argl,SOBJ env)1430 static SOBJ scm_compile_and(SOBJ icode, SOBJ argl, SOBJ env)
1431 {
1432 SOBJ lab;
1433
1434 if (argl == NULL) {
1435 scm_asm_gen2(icode, op_pushq, scm_true);
1436 } else {
1437 lab = next_label();
1438 while(1) {
1439 scm_compile_obj(icode, SCM_CAR(argl), env);
1440 if ((argl = SCM_CDR(argl)) == NULL) break;
1441 scm_asm_gen2(icode, op_br_and, lab);
1442 }
1443 scm_asm_gen2(icode, op_label, lab);
1444 }
1445 return(icode);
1446 }
1447
1448 /*F* (or TEST1 ...) => OBJ */
1449 /*D* expressions are evaluated from left to right, and the value of
1450 the first expression that evaluates to a true is returned. Any
1451 remaining expressions are not evaluated. If all expressions
1452 evaluate to false values, the value of the last expression is
1453 returned. If there are no expressions then #f is returned. */
1454
1455 /*-- compiler for or */
scm_compile_or(SOBJ icode,SOBJ argl,SOBJ env)1456 static SOBJ scm_compile_or(SOBJ icode, SOBJ argl, SOBJ env)
1457 {
1458 SOBJ lab;
1459
1460 if (argl == NULL) {
1461 scm_asm_gen2(icode, op_pushq, scm_false);
1462 } else {
1463 lab = next_label();
1464 while(1) {
1465 scm_compile_obj(icode, SCM_CAR(argl), env);
1466 if ((argl = SCM_CDR(argl)) == NULL) break;
1467 scm_asm_gen2(icode, op_br_or, lab);
1468 }
1469 scm_asm_gen2(icode, op_label, lab);
1470 }
1471 return(icode);
1472 }
1473
1474 /*-- compiler for cond */
1475 /*F* (cond (TEST EXPR...) ... [(else EXPR...)] ) => OBJ */
1476 /*D* Each TEST is evaluated until one evaluates to true or the final
1477 else is reached. When TEST is true, the rest of EXPR is evaluated
1478 and the result of last is returned. */
1479
scm_compile_cond(SOBJ icode,SOBJ argl,SOBJ env)1480 static SOBJ scm_compile_cond(SOBJ icode, SOBJ argl, SOBJ env)
1481 {
1482 static SOBJ sym_else, sym_impl;
1483 SOBJ clause, exitlab, lab;
1484
1485 if (sym_else == NULL) { sym_else = scm_mkatom("else"); }
1486 if (sym_impl == NULL) { sym_impl = scm_mkatom("=>"); }
1487
1488 if (argl == NULL) {
1489 scm_asm_gen2(icode, op_pushq, scm_undefined);
1490 } else {
1491 exitlab = next_label();
1492 lab = NULL;
1493 while(argl) {
1494 clause = SCM_CAR(argl); argl = SCM_CDR(argl);
1495
1496 if (SCM_CAR(clause) == sym_else) { /* else clause */
1497 if (argl) SCM_ERR("cond: else clause must be the last:", argl);
1498 if (lab) scm_asm_gen2(icode, op_label, lab);
1499 lab = NULL; /* disable generation of default case */
1500 scm_compile_begin(icode, SCM_CDR(clause), env);
1501
1502 } else { /* regular clause */
1503 if (lab) scm_asm_gen2(icode, op_label, lab);
1504 scm_compile_obj(icode, SCM_CAR(clause), env); /* compile test */
1505 lab = next_label();
1506 if (SCM_CDR(clause) != NULL) {
1507 if (SCM_CADR(clause) == sym_impl) {
1508 SOBJ sym = SCM_CADDR(clause);
1509
1510 /* this is a little tricky:
1511 * - compile save-r0
1512 * - compile funcall: (sym '())
1513 * - replace code for argument pushing with load-r0
1514 * Note: optimizer will strip sequences like (save-r0) (load-r0)
1515 */
1516 scm_asm_gen2(icode, op_br_cond, lab);
1517 scm_asm_gen1(icode, op_save_r0);
1518 scm_compile_funcall2(icode, sym, scm_cons(NULL, NULL), env);
1519 SCM_AREF(icode, SCM_ASIZE(icode) - 2) = scm_cons(op_load_r0, NULL);
1520 } else {
1521 /* compile exprlist */
1522 scm_asm_gen2(icode, op_brf, lab);
1523 scm_compile_begin(icode, SCM_CDR(clause), env);
1524 }
1525 } else {
1526 scm_asm_gen2(icode, op_br_cond, lab);
1527 }
1528 scm_asm_gen2(icode, op_bra, exitlab);
1529 }
1530 }
1531 if (lab) { /* generate default */
1532 scm_asm_gen2(icode, op_label, lab);
1533 scm_asm_gen2(icode, op_pushq, scm_false);
1534 }
1535 scm_asm_gen2(icode, op_label, exitlab);
1536 }
1537 return(icode);
1538 }
1539
1540 /*-- compile helper for while and until */
scm_compile_loop(SOBJ icode,SOBJ argl,SOBJ env,SOBJ branch_op)1541 static SOBJ scm_compile_loop(SOBJ icode, SOBJ argl, SOBJ env, SOBJ branch_op)
1542 {
1543 SOBJ test_lab = next_label();
1544 SOBJ loop_lab = next_label();
1545
1546 scm_asm_gen2(icode, op_pushq, scm_undefined);
1547 scm_asm_gen2(icode, op_bra, test_lab);
1548 scm_asm_gen2(icode, op_label, loop_lab);
1549 scm_asm_gen1(icode, op_drop);
1550 scm_compile_begin(icode, SCM_CDR(argl), env);
1551 scm_asm_gen2(icode, op_label, test_lab);
1552 scm_compile_obj(icode, SCM_CAR(argl), env);
1553 scm_asm_gen2(icode, branch_op, loop_lab);
1554
1555 return(icode);
1556 }
1557
1558 /*E* (while TEST EXPR ...) => OBJ */
1559 /*D* Evaluates the EXPR while TEST evaluates to TRUE. */
1560
scm_compile_while(SOBJ icode,SOBJ argl,SOBJ env)1561 static SOBJ scm_compile_while(SOBJ icode, SOBJ argl, SOBJ env)
1562 {
1563 if (scm_list_length(argl) < 2)
1564 SCM_ERR("while: syntax <test> [<expr>]+", argl);
1565
1566 return(scm_compile_loop(icode, argl, env, op_brt));
1567 }
1568
1569 /*E* (until TEST EXPR ...) => OBJ */
1570 /*D* Evaluates the EXPR until TEST evaluates to TRUE. */
1571
scm_compile_until(SOBJ icode,SOBJ argl,SOBJ env)1572 static SOBJ scm_compile_until(SOBJ icode, SOBJ argl, SOBJ env)
1573 {
1574 if (scm_list_length(argl) < 2)
1575 SCM_ERR("until: syntax <test> [<expr>]+", argl);
1576
1577 return(scm_compile_loop(icode, argl, env, op_brf));
1578 }
1579
1580 /*-- compiler for do expressions */
1581 /*F* (do ((VAR INIT STEP)...)(TST EXPR...) CMD...) => OBJ */
1582 /*D* Binds VAR to INIT and start iterate. First evaluate TEST. If TEST
1583 is true, then EXPR are evaluated and the result of last EXPR is
1584 returned. If TST is false then CMD are evaluated and the iteration
1585 restarts by evaluating the STEP expr and binding the result to VAR
1586 again. */
1587
scm_compile_do(SOBJ icode,SOBJ argl,SOBJ env)1588 static SOBJ scm_compile_do(SOBJ icode, SOBJ argl, SOBJ env)
1589 {
1590 SOBJ i_list, t_list, newenv, obj, decl; SOBJ loop_label, exit_label;
1591 SOBJ v_list; SOBJ enclosing_env; int varnum;
1592
1593 if (scm_list_length(argl) < 2)
1594 SCM_ERR("do: syntax (do (<iteration spec>*) (<test> <do result>) <command>*)",
1595 argl);
1596
1597 i_list = SCM_CAR(argl);
1598 t_list = SCM_CADR(argl);
1599
1600 #ifdef DEBUG
1601 scm_puts("iteration list="); scm_cdisplay(i_list);
1602 scm_puts(", test list="); scm_cprint(t_list);
1603 #endif
1604
1605 /* build the new environement for the body */
1606 newenv = scm_env_add_level(env);
1607 varnum = 0;
1608 for (obj = i_list; obj; obj = SCM_CDR(obj)) {
1609 decl = SCM_CAR(obj);
1610 if (!SCM_PAIRP(decl)) SCM_ERR("do: incorrect iterator list", decl);
1611 newenv = scm_env_add(newenv, scm_mklsymbol(SCM_CAR(decl), varnum++));
1612 }
1613 #ifdef DEBUG
1614 scm_puts("newenv="); scm_cprint(newenv);
1615 #endif
1616
1617 /* alloc space for loop variables */
1618 scm_asm_gen2(icode, op_doletstar, SCM_MKINUM(varnum));
1619
1620 /* generate initialisation code for each variable */
1621 enclosing_env = scm_env_add_level(env);
1622 varnum = 0;
1623 for (obj = i_list; obj; obj = SCM_CDR(obj)) {
1624 decl = SCM_CAR(obj);
1625 if (SCM_CDR(decl) == NULL) SCM_ERR("do: bad iterator init", decl);
1626 /* init code is runned in the enclosing env */
1627 scm_compile_obj(icode, SCM_CADR(decl), enclosing_env);
1628 scm_asm_gen2(icode, op_setl0drop, SCM_MKINUM(varnum++));
1629 }
1630 /* get 2 labels: one for the loop, one for the exit */
1631 loop_label = next_label();
1632 exit_label = next_label();
1633
1634 /* the test part */
1635 scm_asm_gen2(icode, op_label, loop_label);
1636 scm_compile_obj(icode, SCM_CAR(t_list), newenv);
1637 scm_asm_gen2(icode, op_brt, exit_label);
1638
1639 /* the loop body */
1640 if (SCM_CDDR(argl) != NULL) {
1641 scm_compile_begin(icode, SCM_CDDR(argl), newenv);
1642 scm_asm_gen1(icode, op_drop);
1643 }
1644
1645 #ifdef OLD_DO
1646 varnum = 0;
1647 for (obj = i_list; obj; obj = SCM_CDR(obj)) {
1648 decl = SCM_CAR(obj);
1649 if (SCM_CDDR(decl)) {
1650 scm_compile_obj(icode, SCM_CADDR(decl), newenv);
1651 scm_asm_gen2(icode, op_setl0drop, SCM_MKINUM(varnum));
1652 }
1653 varnum++;
1654 }
1655 #else
1656 v_list = NULL;
1657 varnum = 0;
1658 for (obj = i_list; obj; obj = SCM_CDR(obj)) {
1659 decl = SCM_CAR(obj);
1660 if (SCM_CDDR(decl)) {
1661 scm_compile_obj(icode, SCM_CADDR(decl), newenv);
1662 v_list = scm_cons(SCM_MKINUM(varnum), v_list);
1663 }
1664 varnum++;
1665 }
1666 for (obj = v_list; obj; obj = SCM_CDR(obj)) {
1667 scm_asm_gen2(icode, op_setl0drop, SCM_CAR(obj));
1668 }
1669 #endif
1670 scm_asm_gen2(icode, op_bra, loop_label);
1671
1672 /* generate the return code here */
1673 scm_asm_gen2(icode, op_label, exit_label);
1674 if (SCM_CDR(t_list)) {
1675 scm_compile_obj(icode, SCM_CADR(t_list), newenv);
1676 } else {
1677 scm_asm_gen2(icode, op_pushq, scm_true);
1678 }
1679 scm_asm_gen1(icode, op_endlet);
1680 return (icode);
1681 }
1682
1683
1684 /*-- compiler for catch */
1685 /*F* (catch TAG HANDLER EXPR...) => OBJ */
1686 /*D* Catch exceptions occuring during evaluation of the EXPR. TAG is
1687 either a list of symbol or #t or #f. HANDLER is a function to handle
1688 the exception. When an execption occurs, the TAG list is search for
1689 a matching symbol and the HANDLER procedure is called. */
scm_compile_catch(SOBJ icode,SOBJ argl,SOBJ env)1690 static SOBJ scm_compile_catch(SOBJ icode, SOBJ argl, SOBJ env)
1691 {
1692 SOBJ tag, thunk, expr, lab;
1693
1694 tag = SCM_CAR(argl);
1695 thunk = SCM_CADR(argl);
1696 expr = SCM_CDDR(argl);
1697 scm_compile_obj(icode, thunk, env);
1698 scm_asm_gen2(icode, op_pushq, tag);
1699 lab = next_label();
1700 scm_asm_gen2(icode, op_catch, lab);
1701 scm_compile_begin(icode, expr, env);
1702 scm_asm_gen1(icode, op_uncatch);
1703 scm_asm_gen2(icode, op_label, lab);
1704 return(icode);
1705 }
1706
1707 #ifdef COMMENT
1708 /*-- compiler for xxx */
scm_compile_xxx(SOBJ icode,SOBJ argl,SOBJ env)1709 static SOBJ scm_compile_xxx(SOBJ icode, SOBJ argl, SOBJ env)
1710 {
1711 return(icode);
1712 }
1713 #endif
1714 /*KKK: end of the scm_compile_xxx section */
1715
1716 /*-- icode */
err_bad_arg_count(SOBJ sym,int wanted,int got)1717 static void err_bad_arg_count(SOBJ sym, int wanted, int got)
1718 {
1719 char buf[128];
1720 sprintf(buf, "bad argument count (expected %d, got %d) for", wanted, got);
1721 SCM_ERR(buf, sym);
1722 }
1723
check_prim_arg_count(SOBJ sym,SOBJ argl)1724 static void check_prim_arg_count(SOBJ sym, SOBJ argl)
1725 {
1726 SOBJ prim = SCM_SYM_VALUE(sym);
1727 int nargs = SCM_PRIM(prim)->nargs;
1728 int got_args;
1729
1730 if (nargs < 0) return;
1731
1732 got_args = scm_list_length(argl);
1733
1734 if (nargs != got_args)
1735 err_bad_arg_count(sym, SCM_PRIM(prim)->nargs, got_args);
1736 }
1737
check_cprim_arg_count(SOBJ sym,SOBJ argl)1738 static void check_cprim_arg_count(SOBJ sym, SOBJ argl)
1739 {
1740 SOBJ cprim = SCM_SYM_VALUE(sym);
1741 int nargs = SCM_CPRIM_NARGS(cprim);
1742 int got_args;
1743
1744 if (nargs < 0) return;
1745 if (nargs > SCM_OP_CALLC_MAX)
1746 SCM_ERR("callc does not support all this args", sym);
1747
1748 got_args = scm_list_length(argl);
1749 if (nargs != got_args)
1750 err_bad_arg_count(sym, nargs, got_args);
1751 }
1752
1753 /*E* (execute-macro MACRO FORM ENV) => OBJ */
execute_macro(SOBJ macro,SOBJ form,SOBJ env)1754 static SOBJ execute_macro(SOBJ macro, SOBJ form, SOBJ env)
1755 {
1756 SOBJ code = SCM_MACRO_CODE(macro);
1757 SOBJ vmcode[] = {
1758 SCM_OPCODE(SCM_OP_MARK),
1759 SCM_OPCODE(SCM_OP_PUSH), form,
1760 SCM_OPCODE(SCM_OP_PUSH), code,
1761 SCM_OPCODE(SCM_OP_CALL),
1762 SCM_OPCODE(SCM_OP_END)
1763 };
1764 return(scm_run_engine(vmcode));
1765 }
1766
1767 /*E* (macro-expand EXPR ENV) => OBJ */
macroexpand(SOBJ expr,SOBJ env)1768 static SOBJ macroexpand(SOBJ expr, SOBJ env)
1769 {
1770 if (SCM_PAIRP(expr) && SCM_MACROP(SCM_CAR(expr))) {
1771 return(execute_macro(SCM_CAR(expr), expr, env));
1772 }
1773 return(expr);
1774 }
1775
scm_compile_funcall2(SOBJ icode,SOBJ func,SOBJ argl,SOBJ env)1776 static SOBJ scm_compile_funcall2(SOBJ icode, SOBJ func, SOBJ argl, SOBJ env)
1777 {
1778 int depth;
1779 SOBJ v, sym;
1780
1781 sym = SCM_SYMBOLP(func) ? func : lookup_atom(func, env, &depth, TRUE);
1782
1783 if (!SCM_SYMBOLP(sym) && !SCM_LSYMBOLP(sym))
1784 SCM_ERR("scm_compile_funcall: not a symbol, don't know what to compile", sym);
1785
1786 if (SCM_LSYMBOLP(sym)) {
1787 /* fetch value and call */
1788 scm_asm_gen_mark(icode);
1789 scm_asm_gen_push_args(icode, argl, env);
1790 scm_asm_gen3(icode, op_pushl, SCM_MKINUM(SCM_LSYM_OFS(sym)),SCM_MKINUM(depth));
1791 scm_asm_gen1(icode, op_call);
1792 return(icode);
1793 }
1794
1795 /* ok, it's a global symbol.
1796 try to scm_asm_generate better code based upon the fact that some symbol
1797 are bound to primitive, cprim, macros, syntax */
1798
1799 v = SCM_SYM_VALUE(sym); /* load binding */
1800
1801 switch(SCM_OBJTYPE(v)) { /* test it's binding */
1802 case SOBJ_T_PRIM: /* vm primitive */
1803 check_prim_arg_count(sym, argl);
1804 scm_asm_gen_callp(icode, (SCM_PRIM(v)->nargs < 0), v, argl, env);
1805 return(icode);
1806
1807 case SOBJ_T_CPRIM:
1808 check_cprim_arg_count(sym, argl);
1809 scm_asm_gen_callc(icode, (SCM_CPRIM_NARGS(v) < 0), v, argl, env);
1810 return(icode);
1811
1812 case SOBJ_T_MACRO:
1813 /*
1814 scm_puts("; before execute_macro: "); scm_cprint(form);
1815 l = execute_macro(v, form, env);
1816 scm_puts("; execute_macro returns: "); scm_cprint(l);
1817 return(scm_compile_obj(icode, l, env));
1818 */
1819 return(scm_compile_obj(icode,
1820 execute_macro(v, scm_cons(sym, argl), env), env));
1821
1822 case SOBJ_T_SYNTAX:
1823 return( (*SCM_SYNTAX_FUNC(v))(icode, argl, env) );
1824 }
1825
1826 /* Nothing special. Sorry. Compiling default code */
1827 if (warn_unbound_func && (v == NULL || v == scm_unbound)) {
1828 scm_puts("Warning: function "); scm_cdisplay(sym);
1829 scm_puts(" was not bound to "); scm_cdisplay(v);
1830 scm_puts(" at compile-time\n");
1831 }
1832 scm_asm_gen_call(icode, TRUE, sym, argl, env);
1833 return(icode);
1834 }
1835
scm_compile_funcall(SOBJ icode,SOBJ form,SOBJ env)1836 static SOBJ scm_compile_funcall(SOBJ icode, SOBJ form, SOBJ env)
1837 {
1838 SOBJ func, argl;
1839
1840 func = SCM_CAR(form);
1841 argl = SCM_CDR(form);
1842
1843 return(scm_compile_funcall2(icode, func, argl, env));
1844 }
1845
scm_compile_pair(SOBJ icode,SOBJ form,SOBJ env)1846 static SOBJ scm_compile_pair(SOBJ icode, SOBJ form, SOBJ env)
1847 {
1848 SOBJ f;
1849
1850 f = SCM_CAR(form);
1851
1852 switch(SCM_OBJTYPE(f)) {
1853 case SOBJ_T_PAIR:
1854 scm_asm_gen_mark(icode);
1855 scm_asm_gen_push_args(icode, SCM_CDR(form), env);
1856 scm_compile_pair(icode, f, env);
1857 scm_asm_gen1(icode, op_call);
1858 break;
1859
1860 SCM_ERR("scm_compile_pair: don't know how to compile pair function", f);
1861
1862 case SOBJ_T_INUM:
1863 case SOBJ_T_BNUM:
1864 case SOBJ_T_FNUM:
1865 SCM_ERR("scm_compile_pair: illegal expr (number ..)", form);
1866
1867 case SOBJ_T_SYMBOL:
1868 case SOBJ_T_ATOM:
1869 return(scm_compile_funcall(icode, form, env));
1870
1871 case SOBJ_T_MACRO:
1872 {
1873 SOBJ l = execute_macro(f, form, env);
1874 /* scm_puts("; execute_macro returns: "); scm_cprint(l); */
1875 return(scm_compile_obj(icode, l, env));
1876 }
1877
1878 default:
1879 if (f != NULL) {
1880 scm_puts("func type is ");
1881 scm_puts(scm_type_hook[SCM_OBJTYPE(f)].name);
1882 scm_puts("\n");
1883 }
1884 SCM_ERR("scm_compile_pair: unsupported func", f);
1885 }
1886 return(icode);
1887 }
1888
scm_compile_obj(SOBJ icode,SOBJ obj,SOBJ env)1889 static SOBJ scm_compile_obj(SOBJ icode, SOBJ obj, SOBJ env)
1890 {
1891 SOBJ sym;
1892 int depth;
1893
1894 switch(SCM_OBJTYPE(obj)) {
1895 case SOBJ_T_PAIR: /* ( PROC | SYNTAX ARG... ) */
1896 scm_compile_pair(icode, obj, env);
1897 break;
1898
1899 case SOBJ_T_SYMBOL:
1900
1901 /* Coming here either for generated symbol or for modules symbols.
1902 Generated symbols should be looked up in the env: trying to
1903 find sym in env */
1904
1905 #ifdef DEBUG
1906 scm_puts("; compile_obj: got symbol "); scm_cprint(obj);
1907 scm_puts("; could be a generated symbol or a module symbol\n");
1908 #endif
1909 sym = lookup_atom(SCM_SYM_NAME(obj), env, &depth, FALSE);
1910 if (sym == NULL) {
1911 /* not found in current env: should be a module symbol */
1912 #ifdef DEBUG
1913 scm_puts("; seems to be a module symbol\n");
1914 #endif
1915 sym = obj; depth = 0;
1916 #ifdef DEBUG
1917 } else {
1918 scm_puts("; seems to be a generated symbol\n");
1919 #endif
1920 }
1921 goto sym_found;
1922
1923 case SOBJ_T_ATOM:
1924 sym = lookup_atom(obj, env, &depth, FALSE);
1925 if (sym == NULL) { /* oops. symbol not found */
1926 /* Assuming forward decl, create an unbound symbol. */
1927 scm_hash_set(scm_symbol_hash, obj, scm_unbound);
1928 sym = scm_hash_search(scm_symbol_hash, obj);
1929 }
1930 /* Here we have either a new symbol or an existing symbol. */
1931
1932 sym_found:
1933 switch(SCM_OBJTYPE(sym)) {
1934 case SOBJ_T_SYMBOL:
1935 if (SCM_VARP(SCM_SYM_VALUE(sym))) {
1936 scm_asm_gen2(icode, op_pushq, SCM_SYM_VALUE(sym));
1937 scm_asm_gen1(icode, op_getvar);
1938 } else if (SCM_MACROP(SCM_SYM_VALUE(sym)) &&
1939 SCM_MACRO_FUNC(SCM_SYM_VALUE(sym)) != NULL) {
1940 scm_asm_gen2(icode, op_pushq, SCM_MACRO_FUNC(SCM_SYM_VALUE(sym)));
1941 } else {
1942 if (warn_unbound_symbol) {
1943 scm_puts("Warning: symbol "); scm_cdisplay(sym);
1944 scm_puts(" is unbound during compilation\n");
1945 }
1946 scm_asm_gen2(icode, op_pushv, sym);
1947 }
1948 break;
1949
1950 case SOBJ_T_LSYMBOL:
1951 scm_asm_gen3(icode, op_pushl,
1952 SCM_MKINUM(SCM_LSYM_OFS(sym)), SCM_MKINUM(depth));
1953 break;
1954
1955 default:
1956 SCM_ERR("scm_compile_obj: strange atom binding", sym);
1957 }
1958
1959 break;
1960 default:
1961 scm_asm_gen2(icode, op_pushq, obj); break;
1962
1963 SCM_ERR("scm_compile_expr: unexpected symbol", obj);
1964 SCM_ERR("scm_compile_obj: don't know how to compile", obj);
1965 }
1966 return(icode);
1967 }
1968
scm_compile_expr(SOBJ obj,SOBJ env)1969 static SOBJ scm_compile_expr(SOBJ obj, SOBJ env)
1970 {
1971 SOBJ code;
1972 code = scm_compile_obj(scm_mkarray(0, NULL), obj, env);
1973 scm_asm_gen1(code, op_return);
1974 return(scm_optimize1(code));
1975 }
1976
1977 /*************************************************************************
1978 * optimizer
1979 *************************************************************************/
opt_search_label(SOBJ icode,SOBJ lab)1980 static int opt_search_label(SOBJ icode, SOBJ lab)
1981 {
1982 int i;
1983 SOBJ l;
1984 for (i = 0; i < SCM_ASIZE(icode); i++) {
1985 l = SCM_AREF(icode, i);
1986 if (SCM_CAR(l) == op_label && SCM_CADR(l) == lab)
1987 return(i);
1988 }
1989 return(-1);
1990 }
1991
1992 /*** KKK: should use reference counting instead of this slow full scan */
opt_used_label(SOBJ icode,SOBJ l)1993 static int opt_used_label(SOBJ icode, SOBJ l)
1994 {
1995 int i;
1996 SOBJ opc;
1997 for (i = 0; i < SCM_ASIZE(icode); i++) {
1998 opc = SCM_CAR(SCM_AREF(icode, i));
1999
2000 if ( (opc == op_bra || opc == op_brf || opc == op_brt ||
2001 opc == op_br_and || opc == op_br_or ||
2002 opc == op_br_cond || opc == op_br_while) &&
2003 SCM_CADR(SCM_AREF(icode, i)) == l)
2004 return(TRUE);
2005 }
2006 return(FALSE);
2007 }
2008
opt_branch(SOBJ icode,int i)2009 static int opt_branch(SOBJ icode, int i)
2010 {
2011 SOBJ expr = SCM_AREF(icode, i);
2012 int j, li;
2013
2014 li = opt_search_label(icode, SCM_CADR(expr));
2015 if (li < 0) {
2016 scm_puts("optimize: oops: label "); scm_cdisplay(SCM_CADR(expr));
2017 scm_puts(" not known. Current code is:\n");
2018 scm_cprint(icode);
2019 return(FALSE);
2020 }
2021 #ifdef DEBUG_ASM
2022 scm_puts("; branch to "); scm_cprint(SCM_CADR(expr));
2023 #endif
2024
2025 /* Found bra and matching label. Try to see if next opc is a return */
2026 for (j = li; j < SCM_ASIZE(icode); j++) {
2027 SOBJ o = SCM_CAR(SCM_AREF(icode, j));
2028 if (o != op_label && o != op_nop) {
2029 if (o == op_return) { /* yeah */
2030 #ifdef DEBUG_ASM
2031 scm_puts("; points to a return - replacing\n");
2032 #endif
2033 SCM_AREF(icode, i) = scm_cons(op_return, NULL);
2034
2035 if (!opt_used_label(icode, SCM_CADR(SCM_AREF(icode, li))))
2036 SCM_CAR(SCM_AREF(icode, li)) = op_nop;
2037
2038 return(TRUE);
2039 } else if (o == op_endlet_return) {
2040 #ifdef DEBUG_ASM
2041 scm_puts("; points to an endlet_return - replacing\n");
2042 #endif
2043 SCM_AREF(icode, i) = scm_cons(op_endlet_return, NULL);
2044
2045 if (!opt_used_label(icode, SCM_CADR(SCM_AREF(icode, li))))
2046 SCM_CAR(SCM_AREF(icode, li)) = op_nop;
2047
2048 return(TRUE);
2049 } else {
2050 #ifdef DEBUG_ASM
2051 scm_puts("; does not point to return\n");
2052 #endif
2053 }
2054 break;
2055 }
2056 }
2057 return(FALSE);
2058 }
2059
next_instr(SOBJ icode,int i,int * label_between)2060 static SOBJ next_instr(SOBJ icode, int i, int *label_between)
2061 {
2062 SOBJ *p = &SCM_AREF(icode, ++i);
2063 SOBJ *l = &SCM_AREF(icode, SCM_ASIZE(icode));
2064
2065 *label_between = FALSE;
2066 while(p < l) {
2067 if (SCM_CAR(*p) == op_label) {
2068 *label_between = TRUE;
2069 } else {
2070 if(SCM_CAR(*p) != op_nop) return(*p);
2071 }
2072 p++;
2073 }
2074 return(NULL);
2075 }
2076
opt_endlet_return(SOBJ icode,int i)2077 static int opt_endlet_return(SOBJ icode, int i)
2078 {
2079 int label_between;
2080 SOBJ next;
2081
2082 next = next_instr(icode, i, &label_between);
2083
2084 if (next == NULL || SCM_CAR(next) != op_return) return(FALSE);
2085
2086 #ifdef DEBUG_ASM
2087 scm_puts("; scm_optimize1: endlet ... return -> endlet-return\n");
2088 #endif
2089 SCM_CAR(SCM_AREF(icode, i)) = op_endlet_return;
2090
2091 if (!label_between) SCM_CAR(next) = op_nop;
2092 return(TRUE);
2093 }
2094
opt_call_endlet_return(SOBJ icode,int i)2095 static int opt_call_endlet_return(SOBJ icode, int i)
2096 {
2097 int label_between;
2098 SOBJ next;
2099
2100 next = next_instr(icode, i, &label_between);
2101 if (next == NULL || SCM_CAR(next) != op_endlet_return) return(FALSE);
2102 #ifdef DEBUG_ASM
2103 scm_puts("; scm_optimize1: call ... endlet_return -> endlet-jump\n");
2104 #endif
2105
2106 SCM_CAR(SCM_AREF(icode, i)) = op_endlet_jump;
2107
2108 /* if they are no label between the call and the endlet_return, we
2109 can safely remove the endlet_return bcz it can't be reached */
2110
2111 if (!label_between) SCM_CAR(next) = op_nop;
2112 return(TRUE);
2113 }
2114
opt_call_return(SOBJ icode,int i)2115 static int opt_call_return(SOBJ icode, int i)
2116 {
2117 int label_between;
2118 SOBJ next;
2119
2120 next = next_instr(icode, i, &label_between);
2121
2122 if (next == NULL || SCM_CAR(next) != op_return) return(FALSE);
2123
2124 #ifdef DEBUG_ASM
2125 scm_puts("; scm_optimize1: call ... return -> jump\n");
2126 #endif
2127 SCM_CAR(SCM_AREF(icode, i)) = op_jump;
2128
2129 if (!label_between) SCM_CAR(next) = op_nop;
2130 return(TRUE);
2131 }
2132
opt_save_load(SOBJ icode,int i)2133 static int opt_save_load(SOBJ icode, int i)
2134 {
2135 SOBJ next;
2136 int label_between;
2137 next = next_instr(icode, i, &label_between);
2138 if (next == NULL || SCM_CAR(next) != op_load_r0) return(FALSE);
2139 if (label_between) return(FALSE);
2140 SCM_CAR(SCM_AREF(icode, i)) = op_nop;
2141 SCM_CAR(next) = op_nop;
2142 return(TRUE);
2143 }
2144
scm_optimize1(SOBJ icode)2145 static SOBJ scm_optimize1(SOBJ icode)
2146 {
2147 int i, changed;
2148
2149 /* optimization game */
2150
2151 /* first optimization:
2152 * ... (bra 10) ... (label 10) (return)
2153 * =>
2154 * ... (return) ... (label 10) (return)
2155 */
2156 #ifdef DEBUG_ASM
2157 scm_puts("; optimize phase I\n");
2158 scm_puts("; before optimization:\n"); scm_cprint(icode);
2159 #endif
2160 do {
2161 changed = FALSE;
2162 for (i = 0; i < SCM_ASIZE(icode); i++) {
2163 if (SCM_CAR(SCM_AREF(icode,i)) == op_bra) { /* got a branch */
2164 #ifdef DEBUG_ASM
2165 scm_puts("; scm_optimize1: branch ... return -> return\n");
2166 #endif
2167 if ((changed = opt_branch(icode, i))) break;
2168 }
2169 if (SCM_CAR(SCM_AREF(icode,i)) == op_endlet) {
2170 if ((changed = opt_endlet_return(icode, i))) break;
2171 }
2172 if (SCM_CAR(SCM_AREF(icode,i)) == op_call) {
2173 if ((changed = opt_call_endlet_return(icode, i))) break;
2174 if ((changed = opt_call_return(icode, i))) break;
2175 }
2176 if (SCM_CAR(SCM_AREF(icode,i)) == op_save_r0) {
2177 if ((changed = opt_save_load(icode, i))) break;
2178 }
2179 }
2180 } while(changed);
2181 return(icode);
2182 }
2183
2184 /************************************************************************
2185 * execute the icode
2186 ************************************************************************/
scm_compile(SOBJ form,SOBJ env)2187 SOBJ scm_compile(SOBJ form, SOBJ env)
2188 {
2189 return(mkcode(scm_assemble(scm_compile_expr(form, env))));
2190 }
2191
scm_compile2(SOBJ form,SOBJ env)2192 SOBJ scm_compile2(SOBJ form, SOBJ env)
2193 {
2194 return(scm_compile(form, env));
2195 }
2196
scm_init_asm()2197 void scm_init_asm()
2198 {
2199 scm_asm_make_table();
2200
2201 scm_gc_protect(&scm_asm_unknown_labels);
2202 scm_gc_protect(&scm_asm_known_labels);
2203
2204 /*-- syntax expressions */
2205
2206 /* obsolete features */
2207 /* scm_sym_code = scm_add_syntax("code", scm_compile_code); */
2208 /* scm_sym_immediate = scm_add_syntax("immediate",scm_compile_immediate); */
2209
2210 scm_sym_set = scm_add_syntax("set!", scm_compile_set);
2211 scm_sym_quote = scm_add_syntax("quote", scm_compile_quote);
2212 scm_sym_qquote = scm_add_syntax("quasiquote", scm_compile_qquote);
2213 scm_sym_if = scm_add_syntax("if", scm_compile_if);
2214 scm_sym_begin = scm_add_syntax("begin", scm_compile_begin);
2215 scm_sym_lambda = scm_add_syntax("lambda", scm_compile_lambda);
2216 scm_sym_define = scm_add_syntax("define", scm_compile_define);
2217 scm_sym_let = scm_add_syntax("let", scm_compile_let);
2218 scm_sym_letstar = scm_add_syntax("let*", scm_compile_letstar);
2219 scm_sym_letrec = scm_add_syntax("letrec", scm_compile_letrec);
2220 scm_sym_env = scm_add_syntax("the-env", scm_compile_the_env);
2221 scm_sym_and = scm_add_syntax("and", scm_compile_and);
2222 scm_sym_or = scm_add_syntax("or", scm_compile_or);
2223 scm_sym_cond = scm_add_syntax("cond", scm_compile_cond);
2224 scm_sym_catch = scm_add_syntax("catch", scm_compile_catch);
2225 scm_sym_while = scm_add_syntax("while", scm_compile_while);
2226 scm_sym_until = scm_add_syntax("until", scm_compile_until);
2227 scm_sym_do = scm_add_syntax("do", scm_compile_do);
2228
2229 scm_sym_else = scm_symadd("else", scm_unbound);
2230
2231 scm_add_syntax("asm", scm_syntax_asm);
2232
2233 scm_add_cprim("execute-macro", execute_macro, 3);
2234 scm_add_cprim("macroexpand", macroexpand, 2);
2235 scm_add_cprim("assemble", scm_assemble, 1);
2236 scm_add_cprim("ncomp", scm_compile_expr, 2);
2237 scm_add_cprim("nopt", scm_optimize1, 1);
2238 scm_add_cprim("make-proc", mkproc, 2);
2239 scm_add_cprim("make-code", mkcode, 1);
2240 scm_add_cprim("ncompile", scm_compile2, 2);
2241
2242 scm_atom_local = scm_mkatom("local");
2243 scm_atom_rest = scm_mkatom("rest");
2244 scm_atom_optionnal = scm_mkatom("optionnal");
2245
2246 /* ??? don't need this because it should be protect by atom-list */
2247 /* scm_gc_protect(&scm_atom_local); */
2248 /* scm_gc_protect(&scm_atom_rest); */
2249 /* scm_gc_protect(&scm_atom_optionnal); */
2250 }
2251
2252