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