17d4030eef01e649497624a4ca41aed42bfbc895
[mes.git] / scaffold / mini-mes.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
4  *
5  * This file is part of Mes.
6  *
7  * Mes is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or (at
10  * your option) any later version.
11  *
12  * Mes is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #define MES_MINI 1
22 #define FIXED_PRIMITIVES 1
23
24 #if __GNUC__
25 #define FIXME_NYACC 1
26 #define  __NYACC__ 0
27 #define NYACC_CAR
28 #define NYACC_CDR
29 #else
30 #define  __NYACC__ 1
31 #define NYACC_CAR nyacc_car
32 #define NYACC_CDR nyacc_cdr
33 #endif
34
35 int ARENA_SIZE = 200000;
36 char arena[200000];
37
38 int g_stdin = 0;
39
40 #if __GNUC__
41 typedef long size_t;
42 void *malloc (size_t i);
43 int open (char const *s, int mode);
44 int read (int fd, void* buf, size_t n);
45 void write (int fd, char const* s, int n);
46
47 void
48 exit (int code)
49 {
50   asm (
51        "movl %0,%%ebx\n\t"
52        "movl $1,%%eax\n\t"
53        "int  $0x80"
54        : // no outputs "=" (r)
55        : "" (code)
56        );
57   // not reached
58   exit (0);
59 }
60
61 char const*
62 getenv (char const* p)
63 {
64   return 0;
65 }
66
67 int
68 read (int fd, void* buf, size_t n)
69 {
70   int r;
71   //syscall (SYS_write, fd, s, n));
72   asm (
73        "movl %1,%%ebx\n\t"
74        "movl %2,%%ecx\n\t"
75        "movl %3,%%edx\n\t"
76        "movl $0x3,%%eax\n\t"
77        "int  $0x80\n\t"
78        "mov %%eax,%0\n\t"
79        : "=r" (r)
80        : "" (fd), "" (buf), "" (n)
81        : "eax", "ebx", "ecx", "edx"
82        );
83   return r;
84 }
85
86 int
87 open (char const *s, int mode)
88 {
89   int r;
90   //syscall (SYS_open, mode));
91   asm (
92        "mov %1,%%ebx\n\t"
93        "mov %2,%%ecx\n\t"
94        "mov $0x5,%%eax\n\t"
95        "int $0x80\n\t"
96        "mov %%eax,%0\n\t"
97        : "=r" (r)
98        : "" (s), "" (mode)
99        : "eax", "ebx", "ecx"
100        );
101   return r;
102 }
103
104 int puts (char const*);
105 char const* itoa (int);
106
107 int
108 getchar ()
109 {
110   char c;
111   int r = read (g_stdin, &c, 1);
112   if (r < 1) return -1;
113   int i = c;
114   if (i < 0) i += 256;
115   return i;
116 }
117
118 void
119 write (int fd, char const* s, int n)
120 {
121   int r;
122   //syscall (SYS_write, fd, s, n));
123   asm (
124        "mov %0,%%ebx\n\t"
125        "mov %1,%%ecx\n\t"
126        "mov %2,%%edx\n\t"
127
128        "mov $0x4, %%eax\n\t"
129        "int $0x80\n\t"
130        : // no outputs "=" (r)
131        : "" (fd), "" (s), "" (n)
132        : "eax", "ebx", "ecx", "edx"
133        );
134 }
135
136 int
137 putchar (int c)
138 {
139   //write (STDOUT, s, strlen (s));
140   //int i = write (STDOUT, s, strlen (s));
141   write (1, (char*)&c, 1);
142   return 0;
143 }
144
145 void *
146 malloc (size_t size)
147 {
148   int *n;
149   int len = size + sizeof (size);
150   //n = mmap (0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );
151   *n = len;
152   return (void*)(n+1);
153 }
154
155 void
156 free (void *p)
157 {
158   int *n = (int*)p-1;
159   //munmap ((void*)p, *n);
160 }
161
162 #define EOF -1
163 #define STDIN 0
164 #define STDOUT 1
165 #define STDERR 2
166
167 size_t
168 strlen (char const* s)
169 {
170   int i = 0;
171   while (s[i]) i++;
172   return i;
173 }
174
175 int
176 strcmp (char const* a, char const* b)
177 {
178   while (*a && *b && *a == *b) {a++;b++;}
179   return *a - *b;
180 }
181
182 int
183 puts (char const* s)
184 {
185   //write (STDOUT, s, strlen (s));
186   //int i = write (STDOUT, s, strlen (s));
187   int i = strlen (s);
188   write (1, s, i);
189   return 0;
190 }
191
192 int
193 eputs (char const* s)
194 {
195   //write (STDERR, s, strlen (s));
196   //int i = write (STDERR, s, strlen (s));
197   int i = strlen (s);
198   write (2, s, i);
199   return 0;
200 }
201
202 char const*
203 itoa (int x)
204 {
205   static char buf[10];
206   char *p = buf+9;
207   *p-- = 0;
208
209   int sign = x < 0;
210   if (sign)
211     x = -x;
212   
213   do
214     {
215       *p-- = '0' + (x % 10);
216       x = x / 10;
217     } while (x);
218
219   if (sign)
220     *p-- = '-';
221
222   return p+1;
223 }
224 #endif
225
226 void
227 assert_fail (char* s)
228 {
229   eputs ("assert fail:");
230 #if __GNUC__
231   eputs (s);
232 #endif
233   eputs ("\n");
234 #if __GNUC__
235   *((int*)0) = 0;
236 #endif
237 }
238
239 #if __GNUC__
240 #define assert(x) ((x) ? (void)0 : assert_fail ("boo:" #x))
241 #else
242 //#define assert(x) ((x) ? (void)0 : assert_fail ("boo:" #x))
243 #define assert(x) ((x) ? (void)0 : assert_fail (0))
244 #endif
245
246 typedef int SCM;
247
248 #if __GNUC__
249 int g_debug = 0;
250 #endif
251
252 int g_free = 0;
253
254 SCM g_continuations = 0;
255 SCM g_symbols = 0;
256 SCM g_stack = 0;
257 // a/env
258 SCM r0 = 0;
259 // param 1
260 SCM r1 = 0;
261 // save 2+load/dump
262 SCM r2 = 0;
263 // continuation
264 SCM r3 = 0;
265
266 #if __NYACC__ || FIXME_NYACC
267 enum type_t {CHAR, TCLOSURE, TCONTINUATION, TFUNCTION, KEYWORD, MACRO, NUMBER, PAIR, REF, SPECIAL, TSTRING, SYMBOL, VALUES, TVECTOR, BROKEN_HEART};
268 #else
269 enum type_t {CHAR, CLOSURE, CONTINUATION, FUNCTION, KEYWORD, MACRO, NUMBER, PAIR, REF, SPECIAL, STRING, SYMBOL, VALUES, VECTOR, BROKEN_HEART};
270 #endif
271
272 struct scm {
273   enum type_t type;
274   SCM car;
275   SCM cdr;
276 };
277
278 typedef int (*f_t) (void);
279 struct function {
280   int (*function) (void);
281   int arity;
282   char *name;
283 };
284
285 struct scm *g_cells = arena;
286
287 //scm *g_news = 0;
288
289 // struct scm scm_nil = {SPECIAL, "()"};
290 // struct scm scm_f = {SPECIAL, "#f"};
291 // struct scm scm_t = {SPECIAL, "#t"};
292 // struct scm_dot = {SPECIAL, "."};
293 // struct scm_arrow = {SPECIAL, "=>"};
294 // struct scm_undefined = {SPECIAL, "*undefined*"};
295 // struct scm_unspecified = {SPECIAL, "*unspecified*"};
296 // struct scm_closure = {SPECIAL, "*closure*"};
297 // struct scm_circular = {SPECIAL, "*circular*"};
298 // struct scm_begin = {SPECIAL, "*begin*"};
299
300 // struct scm_vm_apply = {SPECIAL, "core:apply"};
301 // struct scm_vm_apply2 = {SPECIAL, "*vm-apply2*"};
302
303 // struct scm_vm_eval = {SPECIAL, "core:eval"};
304
305 // struct scm_vm_begin = {SPECIAL, "*vm-begin*"};
306 // //scm scm_vm_begin_read_input_file = {SPECIAL, "*vm-begin-read-input-file*"};
307 // struct scm_vm_begin2 = {SPECIAL, "*vm-begin2*"};
308
309 // struct scm_vm_return = {SPECIAL, "*vm-return*"};
310
311 // //#include "mes.symbols.h"
312
313 #define cell_nil 1
314 #define cell_f 2
315 #define cell_t 3
316 #define cell_dot 4
317 // #define cell_arrow 5
318 #define cell_undefined 6
319 #define cell_unspecified 7
320 #define cell_closure 8
321 #define cell_circular 9
322 #define cell_begin 10
323 #define cell_symbol_dot 11
324 #define cell_symbol_lambda 12
325 #define cell_symbol_begin 13
326 #define cell_symbol_if 14
327 #define cell_symbol_quote 15
328 #define cell_symbol_set_x 16
329 #define cell_symbol_sc_expand 17
330 #define cell_symbol_macro_expand 18
331 #define cell_symbol_sc_expander_alist 19
332 #define cell_symbol_call_with_values 20
333 #define cell_call_with_current_continuation 21
334 #define cell_symbol_call_with_current_continuation 22
335 #define cell_symbol_current_module 23
336 #define cell_symbol_primitive_load 24
337 #define cell_symbol_read_input_file 25
338
339 #define cell_symbol_car 37
340 #define cell_symbol_cdr 38
341 #define cell_symbol_null_p 39
342 #define cell_symbol_eq_p 40
343 #define cell_symbol_cons 41
344
345 #define cell_vm_evlis 42
346 #define cell_vm_evlis2 43
347 #define cell_vm_evlis3 44
348 #define cell_vm_apply 45
349 #define cell_vm_apply2 46
350 #define cell_vm_eval 47
351 #define cell_vm_eval_car 48
352 #define cell_vm_eval_cdr 49
353 #define cell_vm_eval_cons 50
354 #define cell_vm_eval_null_p 51
355 #define cell_vm_eval_set_x 52
356 #define cell_vm_eval_macro 53
357 #define cell_vm_eval2 54
358 #define cell_vm_macro_expand 55
359 #define cell_vm_begin 56
360 #define cell_vm_begin_read_input_file 57
361 #define cell_vm_begin2 58
362 #define cell_vm_if 59
363 #define cell_vm_if_expr 60
364 #define cell_vm_call_with_values2 61
365 #define cell_vm_call_with_current_continuation2 62
366 #define cell_vm_return 63
367 #define cell_test 64
368
369
370
371 SCM tmp;
372 SCM tmp_num;
373 SCM tmp_num2;
374
375 struct function g_functions[5];
376 int g_function = 0;
377
378
379 #if __GNUC__
380 //FIXME
381 SCM make_cell (SCM type, SCM car, SCM cdr);
382 #endif
383 struct function fun_make_cell = {&make_cell,3,"make-cell"};
384 struct scm scm_make_cell = {TFUNCTION,0,0};
385 SCM cell_make_cell;
386
387 #if __GNUC__
388 //FIXME
389 SCM cons (SCM x, SCM y);
390 #endif
391 struct function fun_cons = {&cons,2,"cons"};
392 struct scm scm_cons = {TFUNCTION,0,0};
393 SCM cell_cons;
394
395 #if __GNUC__
396 //FIXME
397 SCM car (SCM x);
398 #endif
399 struct function fun_car = {&car,1,"car"};
400 struct scm scm_car = {TFUNCTION,0,0};
401 SCM cell_car;
402
403 #if __GNUC__
404 //FIXME
405 SCM cdr (SCM x);
406 #endif
407 struct function fun_cdr = {&cdr,1,"cdr"};
408 struct scm scm_cdr = {TFUNCTION,0,0};
409 SCM cell_cdr;
410
411 // SCM eq_p (SCM x, SCM y);
412 // struct function fun_eq_p = {&eq_p, 2};
413 // scm scm_eq_p = {TFUNCTION,0,0};// "eq?", 0};
414 // SCM cell_eq_p;
415
416 #define TYPE(x) (g_cells[x].type)
417
418 #define CAR(x) g_cells[x].car
419 #define LENGTH(x) g_cells[x].car
420 #define STRING(x) g_cells[x].car
421
422 #define CDR(x) g_cells[x].cdr
423 #define CLOSURE(x) g_cells[x].cdr
424 #define CONTINUATION(x) g_cells[x].cdr
425 #if __GNUC__
426 //#define FUNCTION(x) g_functions[g_cells[x].function]
427 #endif
428
429 #define FUNCTION(x) g_functions[g_cells[x].cdr]
430 #define VALUE(x) g_cells[x].cdr
431 #define VECTOR(x) g_cells[x].cdr
432
433 #define MAKE_CHAR(n) make_cell (tmp_num_ (CHAR), 0, tmp_num2_ (n))
434 #define MAKE_CONTINUATION(n) make_cell (tmp_num_ (TCONTINUATION), n, g_stack)
435 #define MAKE_NUMBER(n) make_cell (tmp_num_ (NUMBER), 0, tmp_num2_ (n))
436 //#define MAKE_REF(n) make_cell (tmp_num_ (REF), n, 0)
437
438
439 #define CAAR(x) CAR (CAR (x))
440 // #define CDAR(x) CDR (CAR (x))
441 #define CADAR(x) CAR (CDR (CAR (x)))
442 #define CADDR(x) CAR (CDR (CDR (x)))
443 // #define CDDDR(x) CDR (CDR (CDR (x)))
444 #define CDADAR(x) CAR (CDR (CAR (CDR (x))))
445 #define CADR(x) CAR (CDR (x))
446
447
448 #if __NYACC__ || FIXME_NYACC
449 #define MAKE_STRING(x) make_cell (tmp_num_ (TSTRING), x, 0)
450 // #else
451 // #define MAKE_STRING(x) make_cell (tmp_num_ (STRING), x, 0)
452 #endif
453
454 SCM
455 alloc (int n)
456 {
457   assert (g_free + n < ARENA_SIZE);
458   SCM x = g_free;
459   g_free += n;
460   return x;
461 }
462
463 #define DEBUG 0
464
465 SCM
466 make_cell (SCM type, SCM car, SCM cdr)
467 {
468   SCM x = alloc (1);
469   assert (TYPE (type) == NUMBER);
470   TYPE (x) = VALUE (type);
471   if (VALUE (type) == CHAR || VALUE (type) == NUMBER) {
472     if (car) CAR (x) = CAR (car);
473     if (cdr) CDR(x) = CDR(cdr);
474   }
475   else if (VALUE (type) == TFUNCTION) {
476     if (car) CAR (x) = car;
477     if (cdr) CDR(x) = CDR(cdr);
478   }
479   else {
480     CAR (x) = car;
481     CDR(x) = cdr;
482   }
483   return x;
484 }
485
486 SCM
487 tmp_num_ (int x)
488 {
489   VALUE (tmp_num) = x;
490   return tmp_num;
491 }
492
493 SCM
494 tmp_num2_ (int x)
495 {
496   VALUE (tmp_num2) = x;
497   return tmp_num2;
498 }
499
500 SCM
501 cons (SCM x, SCM y)
502 {
503   VALUE (tmp_num) = PAIR;
504   return make_cell (tmp_num, x, y);
505 }
506
507 SCM
508 car (SCM x)
509 {
510 #if MES_MINI
511   //Nyacc
512   //assert ("!car");
513 #else
514   if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_car));
515 #endif
516   return CAR (x);
517 }
518
519 SCM
520 cdr (SCM x)
521 {
522 #if MES_MINI
523   //Nyacc
524   //assert ("!cdr");
525 #else
526   if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_cdr));
527 #endif
528   return CDR(x);
529 }
530
531 SCM
532 null_p (SCM x)
533 {
534   return x == cell_nil ? cell_t : cell_f;
535 }
536
537 // SCM
538 // eq_p (SCM x, SCM y)
539 // {
540 //   return (x == y
541 //           || ((TYPE (x) == KEYWORD && TYPE (y) == KEYWORD
542 //                && STRING (x) == STRING (y)))
543 //           || (TYPE (x) == CHAR && TYPE (y) == CHAR
544 //               && VALUE (x) == VALUE (y))
545 //           || (TYPE (x) == NUMBER && TYPE (y) == NUMBER
546 //               && VALUE (x) == VALUE (y)))
547 //     ? cell_t : cell_f;
548 // }
549
550 SCM
551 assert_defined (SCM x, SCM e)
552 {
553   if (e != cell_undefined) return e;
554   // error (cell_symbol_unbound_variable, x);
555   puts ("unbound variable");
556   exit (33);
557   return e;
558 }
559
560 SCM
561 gc_push_frame ()
562 {
563   SCM frame = cons (r1, cons (r2, cons (r3, cons (r0, cell_nil))));
564   g_stack = cons (frame, g_stack);
565   return g_stack;
566 }
567
568 SCM
569 append2 (SCM x, SCM y)
570 {
571   if (x == cell_nil) return y;
572 #if __GNUC__
573   //FIXME GNUC
574   assert (TYPE (x) == PAIR);
575 #endif
576   return cons (car (x), append2 (cdr (x), y));
577 }
578
579 SCM
580 pairlis (SCM x, SCM y, SCM a)
581 {
582   if (x == cell_nil)
583     return a;
584   if (TYPE (x) != PAIR)
585     return cons (cons (x, y), a);
586   return cons (cons (car (x), car (y)),
587                pairlis (cdr (x), cdr (y), a));
588 }
589
590 SCM
591 assq (SCM x, SCM a)
592 {
593   //while (a != cell_nil && eq_p (x, CAAR (a)) == cell_f) a = CDR (a);
594   while (a != cell_nil && x == CAAR (a)) a = CDR (a);
595   return a != cell_nil ? car (a) : cell_f;
596 }
597
598 SCM
599 assq_ref_env (SCM x, SCM a)
600 {
601   x = assq (x, a);
602   if (x == cell_f) return cell_undefined;
603   return cdr (x);
604 }
605
606 SCM
607 set_car_x (SCM x, SCM e)
608 {
609   assert (TYPE (x) == PAIR);
610   CAR (x) = e;
611   return cell_unspecified;
612 }
613
614 SCM
615 set_cdr_x (SCM x, SCM e)
616 {
617   //if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_set_cdr_x));
618   CDR (x) = e;
619   return cell_unspecified;
620 }
621
622 SCM
623 set_env_x (SCM x, SCM e, SCM a)
624 {
625   SCM p = assert_defined (x, assq (x, a));
626   //if (TYPE (p) != PAIR)  error (cell_symbol_not_a_pair, cons (p, x));
627   return set_cdr_x (p, e);
628 }
629
630 SCM
631 call_lambda (SCM e, SCM x, SCM aa, SCM a) ///((internal))
632 {
633   SCM cl = cons (cons (cell_closure, x), x);
634   r1 = e;
635   r0 = cl;
636   return cell_unspecified;
637 }
638
639 SCM
640 push_cc (SCM p1, SCM p2, SCM a, SCM c) ///((internal))
641 {
642   SCM x = r3;
643   r3 = c;
644   r2 = p2;
645   gc_push_frame ();
646   r1 = p1;
647   r0 = a;
648   r3 = x;
649   return cell_unspecified;
650 }
651
652 SCM caar (SCM x) {return car (car (x));}
653 SCM cadr (SCM x) {return car (cdr (x));}
654 SCM cdar (SCM x) {return cdr (car (x));}
655 SCM cddr (SCM x) {return cdr (cdr (x));}
656
657 #if __GNUC__
658 //FIXME
659 SCM make_closure (SCM,SCM,SCM);
660 SCM call (SCM,SCM);
661 SCM gc_pop_frame ();
662 #endif
663
664 SCM
665 eval_apply ()
666 {
667  eval_apply:
668   // if (g_free + GC_SAFETY > ARENA_SIZE)
669   //   gc_pop_frame (gc (gc_push_frame ()));
670
671   switch (r3)
672     {
673     case cell_vm_evlis: goto evlis;
674     case cell_vm_evlis2: goto evlis2;
675     case cell_vm_evlis3: goto evlis3;
676     case cell_vm_apply: goto apply;
677     case cell_vm_apply2: goto apply2;
678     case cell_vm_eval: goto eval;
679 #if FIXED_PRIMITIVES
680     case cell_vm_eval_car: goto eval_car;
681     case cell_vm_eval_cdr: goto eval_cdr;
682     case cell_vm_eval_cons: goto eval_cons;
683     case cell_vm_eval_null_p: goto eval_null_p;
684 #endif
685     case cell_vm_eval_set_x: goto eval_set_x;
686     case cell_vm_eval_macro: goto eval_macro;
687     case cell_vm_eval2: goto eval2;
688     case cell_vm_macro_expand: goto macro_expand;
689     case cell_vm_begin: goto begin;
690       ///case cell_vm_begin_read_input_file: goto begin_read_input_file;
691     case cell_vm_begin2: goto begin2;
692     case cell_vm_if: goto vm_if;
693     case cell_vm_if_expr: goto if_expr;
694     case cell_vm_call_with_current_continuation2: goto call_with_current_continuation2;
695     case cell_vm_call_with_values2: goto call_with_values2;
696     case cell_vm_return: goto vm_return;
697     case cell_unspecified: return r1;
698     default: assert (0);
699     }
700
701   SCM x = cell_nil;
702   SCM y = cell_nil;
703  evlis:
704   if (r1 == cell_nil) goto vm_return;
705   if (TYPE (r1) != PAIR) goto eval;
706   push_cc (car (r1), r1, r0, cell_vm_evlis2);
707   goto eval;
708  evlis2:
709   push_cc (cdr (r2), r1, r0, cell_vm_evlis3);
710   goto evlis;
711  evlis3:
712   r1 = cons (r2, r1);
713   goto vm_return;
714
715  apply:
716   switch (TYPE (car (r1)))
717     {
718     case TFUNCTION: {
719       //check_formals (car (r1), MAKE_NUMBER (FUNCTION (car (r1)).arity), cdr (r1));
720       r1 = call (car (r1), cdr (r1)); /// FIXME: move into eval_apply
721       goto vm_return;
722     }
723     case TCLOSURE:
724       {
725         SCM cl = CLOSURE (car (r1));
726         SCM formals = cadr (cl);
727         SCM body = cddr (cl);
728         SCM aa = cdar (cl);
729         aa = cdr (aa);
730         //check_formals (car (r1), formals, cdr (r1));
731         SCM p = pairlis (formals, cdr (r1), aa);
732         call_lambda (body, p, aa, r0);
733         goto begin;
734       }
735       case TCONTINUATION:
736         {
737           x = r1;
738           g_stack = CONTINUATION (CAR (r1));
739           gc_pop_frame ();
740           r1 = cadr (x);
741           goto eval_apply;
742         }
743     case SPECIAL:
744       {
745         switch (car (r1))
746           {
747           case cell_vm_apply:
748             {
749               push_cc (cons (CADR (r1), CADDR (r1)), r1, r0, cell_vm_return);
750               goto apply;
751             }
752           case cell_vm_eval:
753             {
754               push_cc (CADR (r1), r1, CADDR (r1), cell_vm_return);
755               goto eval;
756             }
757           case cell_call_with_current_continuation:
758             {
759               r1 = cdr (r1);
760               goto call_with_current_continuation;
761             }
762             //default: check_apply (cell_f, car (r1));
763           }
764       }
765     case SYMBOL:
766       {
767         if (car (r1) == cell_symbol_call_with_values)
768           {
769             r1 = cdr (r1);
770             goto call_with_values;
771           }
772         if (car (r1) == cell_symbol_current_module)
773           {
774             r1 = r0;
775             goto vm_return;
776           }
777         break;
778       }
779     case PAIR:
780       {
781         switch (caar (r1))
782           {
783           case cell_symbol_lambda:
784             {
785               SCM formals = cadr (car (r1));
786               SCM body = cddr (car (r1));
787               SCM p = pairlis (formals, cdr (r1), r0);
788               //check_formals (r1, formals, cdr (r1));
789               call_lambda (body, p, p, r0);
790               goto begin;
791             }
792           }
793       }
794     }
795   push_cc (car (r1), r1, r0, cell_vm_apply2);
796   goto eval;
797  apply2:
798   //check_apply (r1, car (r2));
799   r1 = cons (r1, cdr (r2));
800   goto apply;
801
802  eval:
803   switch (TYPE (r1))
804     {
805     case PAIR:
806       {
807         switch (car (r1))
808           {
809 #if FIXED_PRIMITIVES
810           case cell_symbol_car:
811             {
812               push_cc (CADR (r1), r1, r0, cell_vm_eval_car); goto eval;
813             eval_car:
814               x = r1; gc_pop_frame (); r1 = car (x); goto eval_apply;
815             }
816           case cell_symbol_cdr:
817             {
818               push_cc (CADR (r1), r1, r0, cell_vm_eval_cdr); goto eval;
819             eval_cdr:
820               x = r1; gc_pop_frame (); r1 = cdr (x); goto eval_apply;
821             }
822           case cell_symbol_cons: {
823             push_cc (CDR (r1), r1, r0, cell_vm_eval_cons); goto evlis;
824             eval_cons:
825             x = r1;
826             gc_pop_frame ();
827             r1 = cons (CAR (x), CADR (x));
828             goto eval_apply;
829           }
830           case cell_symbol_null_p:
831             {
832               push_cc (CADR (r1), r1, r0, cell_vm_eval_null_p);
833               goto eval;
834             eval_null_p:
835               x = r1; gc_pop_frame (); r1 = null_p (x); goto eval_apply;
836             }
837 #endif // FIXED_PRIMITIVES
838           case cell_symbol_quote:
839             {
840               x = r1; gc_pop_frame (); r1 = cadr (x); goto eval_apply;
841             }
842           case cell_symbol_begin: goto begin;
843           case cell_symbol_lambda:
844             {
845               r1 = make_closure (cadr (r1), cddr (r1), assq (cell_closure, r0));
846               goto vm_return;
847             }
848           case cell_symbol_if: {r1=cdr (r1); goto vm_if;}
849           case cell_symbol_set_x:
850             {
851               push_cc (car (cddr (r1)), r1, r0, cell_vm_eval_set_x);
852               goto eval;
853             eval_set_x:
854               x = r2;
855               r1 = set_env_x (cadr (x), r1, r0);
856               goto vm_return;
857             }
858           case cell_vm_macro_expand:
859             {
860               push_cc (cadr (r1), r1, r0, cell_vm_return);
861               goto macro_expand;
862             }
863           default: {
864             push_cc (r1, r1, r0, cell_vm_eval_macro);
865             goto macro_expand;
866             eval_macro:
867             x = r2;
868             if (r1 != r2)
869               {
870                 if (TYPE (r1) == PAIR)
871                   {
872                     set_cdr_x (r2, cdr (r1));
873                     set_car_x (r2, car (r1));
874                   }
875                 goto eval;
876               }
877             push_cc (CDR (r1), r1, r0, cell_vm_eval2); goto evlis;
878             eval2:
879             r1 = cons (car (r2), r1);
880             goto apply;
881           }
882           }
883       }
884     case SYMBOL:
885       {
886         r1 = assert_defined (r1, assq_ref_env (r1, r0));
887         goto vm_return;
888       }
889     default: {goto vm_return;}
890     }
891
892   SCM macro;
893   SCM expanders;
894  macro_expand:
895 #if 0
896   if (TYPE (r1) == PAIR
897       && (macro = lookup_macro (car (r1), r0)) != cell_f) // FIXME GNUC
898     {
899       r1 = cons (macro, CDR (r1));
900       goto apply;
901     }
902   else if (TYPE (r1) == PAIR
903            && TYPE (CAR (r1)) == SYMBOL
904            && ((expanders = assq_ref_env (cell_symbol_sc_expander_alist, r0)) != cell_undefined)
905            && ((macro = assq (CAR (r1), expanders)) != cell_f))
906     {
907       SCM sc_expand = assq_ref_env (cell_symbol_macro_expand, r0);
908       if (sc_expand != cell_undefined && sc_expand != cell_f)
909         {
910           r1 = cons (sc_expand, cons (r1, cell_nil));
911           goto apply;
912         }
913     }
914   goto vm_return;
915 #endif
916  begin:
917   x = cell_unspecified;
918   while (r1 != cell_nil) {
919     if (TYPE (r1) == PAIR && TYPE (CAR (r1)) == PAIR)
920       {
921         if (caar (r1) == cell_symbol_begin)
922           r1 = append2 (cdar (r1), cdr (r1));
923         else if (caar (r1) == cell_symbol_primitive_load)
924           {
925             push_cc (cons (cell_symbol_read_input_file, cell_nil), r1, r0, cell_vm_begin_read_input_file);
926             goto apply;
927           begin_read_input_file:
928             r1 = append2 (r1, cdr (r2));
929           }
930       }
931     if (CDR (r1) == cell_nil)
932       {
933         r1 = car (r1);
934         goto eval;
935       }
936     push_cc (CAR (r1), r1, r0, cell_vm_begin2);
937     goto eval;
938   begin2:
939     x = r1;
940     r1 = CDR (r2);
941   }
942   r1 = x;
943   goto vm_return;
944
945  vm_if:
946   push_cc (car (r1), r1, r0, cell_vm_if_expr);
947   goto eval;
948  if_expr:
949   x = r1;
950   r1 = r2;
951   if (x != cell_f)
952     {
953       r1 = cadr (r1);
954       goto eval;
955     }
956   if (cddr (r1) != cell_nil)
957     {
958       r1 = car (cddr (r1));
959       goto eval;
960     }
961   r1 = cell_unspecified;
962   goto vm_return;
963
964  call_with_current_continuation:
965   gc_push_frame ();
966 #if __GNUC__
967   // FIXME GCC
968   x = MAKE_CONTINUATION (g_continuations++);
969 #else
970   x = MAKE_CONTINUATION (g_continuations);
971   g_continuations++;
972 #endif
973   gc_pop_frame ();
974   push_cc (cons (car (r1), cons (x, cell_nil)), x, r0, cell_vm_call_with_current_continuation2);
975   goto apply;
976  call_with_current_continuation2:
977   CONTINUATION (r2) = g_stack;
978   goto vm_return;
979
980  call_with_values:
981   push_cc (cons (car (r1), cell_nil), r1, r0, cell_vm_call_with_values2);
982   goto apply;
983  call_with_values2:
984   if (TYPE (r1) == VALUES)
985     r1 = CDR (r1);
986   r1 = cons (cadr (r2), r1);
987   goto apply;
988
989  vm_return:
990   x = r1;
991   gc_pop_frame ();
992   r1 = x;
993   goto eval_apply;
994 }
995
996 #if __GNUC__
997 SCM display_ (SCM);
998 #endif
999
1000 SCM
1001 call (SCM fn, SCM x)
1002 {
1003   if ((FUNCTION (fn).arity > 0 || FUNCTION (fn).arity == -1)
1004       && x != cell_nil && TYPE (CAR (x)) == VALUES)
1005     x = cons (CADAR (x), CDR (x));
1006   if ((FUNCTION (fn).arity > 1 || FUNCTION (fn).arity == -1)
1007       && x != cell_nil && TYPE (CDR (x)) == PAIR && TYPE (CADR (x)) == VALUES)
1008     x = cons (CAR (x), cons (CDADAR (x), CDR (x)));
1009
1010   switch (FUNCTION (fn).arity)
1011     {
1012     // case 0: return FUNCTION (fn).function0 ();
1013     // case 1: return FUNCTION (fn).function1 (car (x));
1014     // case 2: return FUNCTION (fn).function2 (car (x), cadr (x));
1015     // case 3: return FUNCTION (fn).function3 (car (x), cadr (x), car (cddr (x)));
1016     // case -1: return FUNCTION (fn).functionn (x);
1017     case 0: {return (FUNCTION (fn).function) ();}
1018     case 1: {return ((SCM(*)(SCM))(FUNCTION (fn).function)) (car (x));}
1019     case 2: {return ((SCM(*)(SCM,SCM))(FUNCTION (fn).function)) (car (x), cadr (x));}
1020     case 3: {return ((SCM(*)(SCM,SCM,SCM))(FUNCTION (fn).function)) (car (x), cadr (x), car (cddr (x)));}
1021 #if __GNUC__
1022       // FIXME GNUC
1023     case -1: {return ((SCM(*)(SCM))(FUNCTION (fn).function)) (x);}
1024 #endif
1025     default: {return ((SCM(*)(SCM))(FUNCTION (fn).function)) (x);}
1026     }
1027
1028   return cell_unspecified;
1029 }
1030
1031 SCM
1032 gc_peek_frame ()
1033 {
1034   SCM frame = car (g_stack);
1035   r1 = car (frame);
1036 #if 1
1037   //GNUC
1038   r2 = cadr (frame);
1039   r3 = car (cddr (frame));
1040   r0 = cadr (cddr (frame));
1041 #else
1042   r2 = cdr (frame);
1043   r2 = car (r2);
1044
1045   r3 = cdr (frame);
1046   r3 = cdr (r3);
1047   r3 = car (r3);
1048
1049   r0 = cdr (frame);
1050   r0 = cdr (r0);
1051   r0 = cdr (r0);
1052   r0 = cdr (r0);
1053   r0 = car (r0);
1054 #endif
1055   return frame;
1056 }
1057
1058 SCM
1059 gc_pop_frame ()
1060 {
1061   SCM frame = gc_peek_frame (g_stack);
1062   g_stack = cdr (g_stack);
1063   return frame;
1064 }
1065
1066 SCM
1067 mes_g_stack (SCM a) ///((internal))
1068 {
1069   r0 = a;
1070   r1 = MAKE_CHAR (0);
1071   r2 = MAKE_CHAR (0);
1072   r3 = MAKE_CHAR (0);
1073   g_stack = cons (cell_nil, cell_nil);
1074   return r0;
1075 }
1076
1077 //\f Environment setup
1078 SCM
1079 make_tmps (struct scm* cells)
1080 {
1081   tmp = g_free++;
1082   cells[tmp].type = CHAR;
1083   tmp_num = g_free++;
1084   cells[tmp_num].type = NUMBER;
1085   tmp_num2 = g_free++;
1086   cells[tmp_num2].type = NUMBER;
1087   return 0;
1088 }
1089
1090 SCM
1091 make_symbol_ (SCM s)
1092 {
1093   VALUE (tmp_num) = SYMBOL;
1094   SCM x = make_cell (tmp_num, s, 0);
1095   g_symbols = cons (x, g_symbols);
1096   return x;
1097 }
1098
1099 SCM
1100 make_symbol (SCM s)
1101 {
1102 #if MES_MINI
1103   SCM x = 0;
1104 #else
1105   SCM x = lookup_symbol_ (s);
1106 #endif
1107   return x ? x : make_symbol_ (s);
1108 }
1109
1110 SCM
1111 cstring_to_list (char const* s)
1112 {
1113   char *x = s;
1114   SCM p = cell_nil;
1115   int i = strlen (s);
1116   while (i--)
1117     {
1118 #if 0
1119       //FIXME
1120       p = cons (MAKE_CHAR (s[i]), p);
1121 #else
1122       p = cons (MAKE_CHAR (*x), p);
1123       x++;
1124 #endif
1125     }
1126   return p;
1127 }
1128
1129 SCM
1130 acons (SCM key, SCM value, SCM alist)
1131 {
1132   return cons (cons (key, value), alist);
1133 }
1134
1135 //\f Jam Collector
1136 SCM g_symbol_max;
1137
1138 SCM
1139 gc_init_cells ()
1140 {
1141   return 0;
1142 //   g_cells = (scm *)malloc (2*ARENA_SIZE*sizeof(scm));
1143
1144 // #if __NYACC__ || FIXME_NYACC
1145 //   TYPE (0) = TVECTOR;
1146 // // #else
1147 // //   TYPE (0) = VECTOR;
1148 // #endif
1149 //   LENGTH (0) = 1000;
1150 //   VECTOR (0) = 0;
1151 //   g_cells++;
1152 //   TYPE (0) = CHAR;
1153 //   VALUE (0) = 'c';
1154 }
1155
1156 // INIT NEWS
1157
1158 SCM
1159 mes_symbols () ///((internal))
1160 {
1161   gc_init_cells ();
1162   //  gc_init_news ();
1163
1164 #if __GNUC__ && 0
1165   //#include "mes.symbols.i"
1166 #else
1167 g_free++;
1168 // g_cells[cell_nil] = scm_nil;
1169
1170 g_free++;
1171 // g_cells[cell_f] = scm_f;
1172
1173 g_free++;
1174 // g_cells[cell_t] = scm_t;
1175
1176 g_free++;
1177 // g_cells[cell_dot] = scm_dot;
1178
1179 g_free++;
1180 // g_cells[cell_arrow] = scm_arrow;
1181
1182 g_free++;
1183 // g_cells[cell_undefined] = scm_undefined;
1184
1185 g_free++;
1186 // g_cells[cell_unspecified] = scm_unspecified;
1187
1188 g_free++;
1189 // g_cells[cell_closure] = scm_closure;
1190
1191 g_free++;
1192 // g_cells[cell_circular] = scm_circular;
1193
1194 g_free++;
1195 // g_cells[cell_begin] = scm_begin;
1196
1197 ///
1198 g_free = 44;
1199 g_free++;
1200 // g_cells[cell_vm_apply] = scm_vm_apply;
1201
1202 g_free++;
1203 // g_cells[cell_vm_apply2] = scm_vm_apply2;
1204
1205 g_free++;
1206 // g_cells[cell_vm_eval] = scm_vm_eval;
1207
1208 ///
1209 g_free = 55;
1210 g_free++;
1211 // g_cells[cell_vm_begin] = scm_vm_begin;
1212
1213 g_free++;
1214 // g_cells[cell_vm_begin_read_input_file] = scm_vm_begin_read_input_file;
1215
1216 g_free++;
1217 // g_cells[cell_vm_begin2] = scm_vm_begin2;
1218
1219 ///
1220 g_free = 62;
1221 g_free++;
1222 // g_cells[cell_vm_return] = scm_vm_return;
1223
1224 g_free = 63;
1225 g_free++;
1226 //g_cells[cell_test] = scm_test;
1227
1228 #endif
1229
1230   g_symbol_max = g_free;
1231   make_tmps (g_cells);
1232
1233   g_symbols = 0;
1234   for (int i=1; i<g_symbol_max; i++)
1235     g_symbols = cons (i, g_symbols);
1236
1237   SCM a = cell_nil;
1238
1239 #if __GNUC__ && 0
1240   //#include "mes.symbol-names.i"
1241 #else
1242 // g_cells[cell_nil].car = cstring_to_list (scm_nil.name);
1243 // g_cells[cell_f].car = cstring_to_list (scm_f.name);
1244 // g_cells[cell_t].car = cstring_to_list (scm_t.name);
1245 // g_cells[cell_dot].car = cstring_to_list (scm_dot.name);
1246 // g_cells[cell_arrow].car = cstring_to_list (scm_arrow.name);
1247 // g_cells[cell_undefined].car = cstring_to_list (scm_undefined.name);
1248 // g_cells[cell_unspecified].car = cstring_to_list (scm_unspecified.name);
1249 // g_cells[cell_closure].car = cstring_to_list (scm_closure.name);
1250 // g_cells[cell_circular].car = cstring_to_list (scm_circular.name);
1251 // g_cells[cell_begin].car = cstring_to_list (scm_begin.name);
1252 #endif
1253
1254   // a = acons (cell_symbol_mes_version, MAKE_STRING (cstring_to_list (VERSION)), a);
1255   // a = acons (cell_symbol_mes_prefix, MAKE_STRING (cstring_to_list (PREFIX)), a);
1256
1257   a = acons (cell_symbol_dot, cell_dot, a);
1258   a = acons (cell_symbol_begin, cell_begin, a);
1259   a = acons (cell_closure, a, a);
1260
1261   // a = acons (cell_symbol_call_with_current_continuation, cell_call_with_current_continuation, a);
1262   // a = acons (cell_symbol_sc_expand, cell_f, a);
1263
1264   return a;
1265 }
1266
1267 SCM
1268 make_closure (SCM args, SCM body, SCM a)
1269 {
1270   return make_cell (tmp_num_ (TCLOSURE), cell_f, cons (cons (cell_circular, a), cons (args, body)));
1271 }
1272
1273 SCM
1274 mes_environment () ///((internal))
1275 {
1276   SCM a = 0;
1277   a = mes_symbols ();
1278   a = mes_g_stack (a);
1279   return a;
1280 }
1281
1282 SCM
1283 mes_builtins (SCM a)
1284 {
1285 #if 0
1286   //__GNUC__
1287 //#include "mes.i"
1288
1289 // #include "lib.i"
1290 // #include "math.i"
1291 // #include "posix.i"
1292 // #include "reader.i"
1293
1294 // #include "lib.environment.i"
1295 // #include "math.environment.i"
1296 // #include "mes.environment.i"
1297 // #include "posix.environment.i"
1298 // #include "reader.environment.i"
1299 #else
1300
1301 scm_make_cell.cdr = g_function;
1302 g_functions[g_function++] = fun_make_cell;
1303 cell_make_cell = g_free++;
1304 g_cells[cell_make_cell] = scm_make_cell;
1305  
1306 scm_cons.cdr = g_function;
1307 g_functions[g_function++] = fun_cons;
1308 cell_cons = g_free++;
1309 g_cells[cell_cons] = scm_cons;
1310  
1311 scm_car.cdr = g_function;
1312 g_functions[g_function++] = fun_car;
1313 cell_car = g_free++;
1314 g_cells[cell_car] = scm_car;
1315  
1316 scm_cdr.cdr = g_function;
1317 g_functions[g_function++] = fun_cdr;
1318 cell_cdr = g_free++;
1319 g_cells[cell_cdr] = scm_cdr;
1320
1321 scm_make_cell.car = cstring_to_list (fun_make_cell.name);
1322 g_cells[cell_make_cell].car = MAKE_STRING (scm_make_cell.car);
1323 a = acons (make_symbol (scm_make_cell.car), cell_make_cell, a);
1324
1325 scm_cons.car = cstring_to_list (fun_cons.name);
1326 g_cells[cell_cons].car = MAKE_STRING (scm_cons.car);
1327 a = acons (make_symbol (scm_cons.car), cell_cons, a);
1328
1329 scm_car.car = cstring_to_list (fun_car.name);
1330 g_cells[cell_car].car = MAKE_STRING (scm_car.car);
1331 a = acons (make_symbol (scm_cons.car), cell_cons, a);
1332
1333 scm_cdr.car = cstring_to_list (fun_cdr.name);
1334 g_cells[cell_cdr].car = MAKE_STRING (scm_cdr.car);
1335 a = acons (make_symbol (scm_cdr.car), cell_cdr, a);
1336
1337 #endif
1338   return a;
1339 }
1340
1341 SCM
1342 bload_env (SCM a) ///((internal))
1343 {
1344   g_stdin = open ("module/mes/read-0.mo", 0);
1345 #if __GNUC__
1346   //FIXME GNUC
1347   //g_stdin = g_stdin ? g_stdin : fopen (PREFIX "module/mes/read-0.mo", "r");
1348 #endif
1349   char *p = (char*)g_cells;
1350   assert (getchar () == 'M');
1351   assert (getchar () == 'E');
1352   assert (getchar () == 'S');
1353   g_stack = getchar () << 8;
1354   g_stack += getchar ();
1355   int c = getchar ();
1356   while (c != EOF)
1357     {
1358       *p++ = c;
1359       c = getchar ();
1360     }
1361   g_free = (p-(char*)g_cells) / sizeof (struct scm);
1362   gc_peek_frame ();
1363   g_symbols = r1;
1364   g_stdin = STDIN;
1365   r0 = mes_builtins (r0);
1366   return r2;
1367 }
1368
1369 SCM
1370 display_ (SCM x)
1371 {
1372   //puts ("<display>\n");
1373   switch (TYPE (x))
1374     {
1375     case CHAR:
1376       {
1377         //puts ("<char>\n");
1378         puts ("#\\");
1379         putchar (VALUE (x));
1380         break;
1381       }
1382     case TFUNCTION:
1383       {
1384         //puts ("<function>\n");
1385         if (VALUE (x) == 0)
1386           puts ("make-cell");
1387         if (VALUE (x) == 1)
1388           puts ("cons");
1389         if (VALUE (x) == 2)
1390           puts ("car");
1391         if (VALUE (x) == 3)
1392           puts ("cdr");
1393         break;
1394       }
1395     case NUMBER:
1396       {
1397         //puts ("<number>\n");
1398 #if __GNUC__
1399         puts (itoa (VALUE (x)));
1400 #else
1401         int i;
1402         i = VALUE (x);
1403         i = i + 48;
1404         putchar (i);
1405 #endif
1406         break;
1407       }
1408     case PAIR:
1409       {
1410         //puts ("<pair>\n");
1411         //if (cont != cell_f) puts "(");
1412         puts ("(");
1413         if (x && x != cell_nil) display_ (CAR (x));
1414         if (CDR (x) && CDR (x) != cell_nil)
1415           {
1416 #if __GNUC__
1417             if (TYPE (CDR (x)) != PAIR)
1418               puts (" . ");
1419 #else
1420             int c;
1421             c = CDR (x);
1422             c = TYPE (c);
1423             if (c != PAIR)
1424               puts (" . ");
1425 #endif
1426             display_ (CDR (x));
1427           }
1428         //if (cont != cell_f) puts (")");
1429         puts (")");
1430         break;
1431       }
1432     case SPECIAL:
1433       {
1434         switch (x)
1435           {
1436           case 1: {puts ("()"); break;}
1437           case 2: {puts ("#f"); break;}
1438           case 3: {puts ("#t"); break;}
1439           default:
1440             {
1441 #if __GNUC__
1442         puts ("<x:");
1443         puts (itoa (x));
1444         puts (">");
1445 #else
1446         puts ("<x>");
1447 #endif
1448             }
1449           }
1450         break;
1451       }
1452     case SYMBOL:
1453       {
1454         switch (x)
1455           {
1456           case 11: {puts (" . "); break;}
1457           case 12: {puts ("lambda"); break;}
1458           case 13: {puts ("begin"); break;}
1459           case 14: {puts ("if"); break;}
1460           case 15: {puts ("quote"); break;}
1461           case 37: {puts ("car"); break;}
1462           case 38: {puts ("cdr"); break;}
1463           case 39: {puts ("null?"); break;}
1464           case 40: {puts ("eq?"); break;}
1465           case 41: {puts ("cons"); break;}
1466           default:
1467             {
1468 #if __GNUC__
1469         puts ("<s:");
1470         puts (itoa (x));
1471         puts (">");
1472 #else
1473         puts ("<s>");
1474 #endif
1475             }
1476           }
1477         break;
1478       }
1479     default:
1480       {
1481         //puts ("<default>\n");
1482 #if __GNUC__
1483         puts ("<");
1484         puts (itoa (TYPE (x)));
1485         puts (":");
1486         puts (itoa (x));
1487         puts (">");
1488 #else
1489         puts ("_");
1490 #endif
1491         break;
1492       }
1493     }
1494   return 0;
1495 }
1496
1497 SCM
1498 simple_bload_env (SCM a) ///((internal))
1499 {
1500   puts ("reading: ");
1501   char *mo = "mini-0-32.mo";
1502
1503   puts (mo);
1504   puts ("\n");
1505   g_stdin = open (mo, 0);
1506   if (g_stdin < 0) {eputs ("no such file: module/mes/read-0-32.mo\n");return 1;} 
1507
1508   char *p = (char*)g_cells;
1509   int c;
1510
1511 #if 0
1512   //__GNUC__
1513   puts ("fd: ");
1514   puts (itoa (g_stdin));
1515   puts ("\n");
1516 #endif
1517
1518   assert (getchar () == 'M');
1519   assert (getchar () == 'E');
1520   assert (getchar () == 'S');
1521   puts (" *GOT MES*\n");
1522   g_stack = getchar () << 8;
1523   g_stack += getchar ();
1524 #if __GNUC__
1525   puts ("stack: ");
1526   puts (itoa (g_stack));
1527   puts ("\n");
1528 #endif
1529
1530   c = getchar ();
1531   while (c != -1)
1532     {
1533       *p++ = c;
1534       c = getchar ();
1535     }
1536
1537   puts ("read done\n");
1538
1539   g_free = (p-(char*)g_cells) / sizeof (struct scm);
1540   gc_peek_frame ();
1541   g_symbols = r1;
1542
1543 #if __GNUC__
1544   puts ("XXcells read: ");
1545   puts (itoa (g_free));
1546   puts ("\n");
1547
1548   eputs ("r0=");
1549   eputs (itoa (r0));
1550   eputs ("\n");
1551
1552   eputs ("r1=");
1553   eputs (itoa (r1));
1554   eputs ("\n");
1555
1556   eputs ("r2=");
1557   eputs (itoa (r2));
1558   eputs ("\n");
1559
1560   eputs ("g_stack=");
1561   eputs (itoa (g_stack));
1562   eputs ("\n");
1563 #endif
1564   
1565   g_stdin = STDIN;
1566   r0 = mes_builtins (r0);
1567
1568 #if __GNUC__
1569   puts ("cells read: ");
1570   puts (itoa (g_free));
1571   puts ("\n");
1572
1573   puts ("symbols: ");
1574   puts (itoa (g_symbols));
1575   puts ("\n");
1576
1577   puts ("r2: ");
1578   puts (itoa (r2));
1579   puts ("\n");
1580 #endif
1581
1582   puts ("program[");
1583 #if __GNUC__
1584   puts (itoa (r2));
1585 #endif
1586   puts ("]: ");
1587
1588   display_ (r2);
1589   //stderr_ (r2);
1590   puts ("\n");
1591
1592   return r2;
1593 }
1594
1595 char const*
1596 string_to_cstring (SCM s)
1597 {
1598   static char buf[1024];
1599   char *p = buf;
1600   s = STRING(s);
1601   while (s != cell_nil)
1602     {
1603       *p++ = VALUE (car (s));
1604       s = cdr (s);
1605     }
1606   *p = 0;
1607   return buf;
1608 }
1609
1610 SCM
1611 stderr_ (SCM x)
1612 {
1613   //SCM write;
1614 #if __NYACC__ || FIXME_NYACC
1615   if (TYPE (x) == TSTRING)
1616 // #else
1617 //   if (TYPE (x) == STRING)
1618 #endif
1619     eputs (string_to_cstring (x));
1620   // else if ((write = assq_ref_env (cell_symbol_write, r0)) != cell_undefined)
1621   //   apply (assq_ref_env (cell_symbol_display, r0), cons (x, cons (MAKE_NUMBER (2), cell_nil)), r0);
1622 #if __NYACC__ || FIXME_NYACC
1623   else if (TYPE (x) == SPECIAL || TYPE (x) == TSTRING || TYPE (x) == SYMBOL)
1624 // #else
1625 //   else if (TYPE (x) == SPECIAL || TYPE (x) == STRING || TYPE (x) == SYMBOL)
1626 #endif
1627     eputs (string_to_cstring (x));
1628   else if (TYPE (x) == NUMBER)
1629     eputs (itoa (VALUE (x)));
1630   else
1631     eputs ("display: undefined\n");
1632   return cell_unspecified;
1633 }
1634
1635 int
1636 main (int argc, char *argv[])
1637 {
1638   puts ("Hello mini-mes!\n");
1639 #if __GNUC__
1640   //g_debug = getenv ("MES_DEBUG");
1641 #endif
1642   //if (getenv ("MES_ARENA")) ARENA_SIZE = atoi (getenv ("MES_ARENA"));
1643   if (argc > 1 && !strcmp (argv[1], "--help")) return eputs ("Usage: mes [--dump|--load] < FILE");
1644 #if __GNUC__
1645   if (argc > 1 && !strcmp (argv[1], "--version")) {eputs ("Mes ");return eputs (VERSION);};
1646 #else
1647   if (argc > 1 && !strcmp (argv[1], "--version")) {eputs ("Mes ");return eputs ("0.4");};
1648 #endif
1649   g_stdin = STDIN;
1650
1651   r0 = mes_environment ();
1652   
1653 #if MES_MINI
1654   SCM program = simple_bload_env (r0);
1655 #else  
1656   SCM program = (argc > 1 && !strcmp (argv[1], "--load"))
1657     ? bload_env (r0) : load_env (r0);
1658   if (argc > 1 && !strcmp (argv[1], "--dump")) return dump ();
1659 #endif
1660
1661   push_cc (r2, cell_unspecified, r0, cell_unspecified);
1662   r3 = cell_vm_begin;
1663   r1 = eval_apply ();
1664   display_ (r1);
1665   eputs ("\n");
1666
1667 #if !MES_MINI
1668   gc (g_stack);
1669 #endif
1670 #if __GNUC__
1671   if (g_debug)
1672     {
1673       eputs ("\nstats: [");
1674       eputs (itoa (g_free));
1675       eputs ("]\n");
1676     }
1677 #endif
1678   return 0;
1679 }
1680
1681 #if __GNUC__
1682 void
1683 _start ()
1684 {
1685   int r;
1686   asm (
1687        "mov %%ebp,%%eax\n\t"
1688        "addl $8,%%eax\n\t"
1689        "push %%eax\n\t"
1690
1691        "mov %%ebp,%%eax\n\t"
1692        "addl $4,%%eax\n\t"
1693        "movzbl (%%eax),%%eax\n\t"
1694        "push %%eax\n\t"
1695
1696        "call main\n\t"
1697        "movl %%eax,%0\n\t"
1698        : "=r" (r)
1699        : //no inputs "" (&main)
1700        );
1701   exit (r);
1702 }
1703 #endif