9d0a389d0220e627e3e0602bcbb1923de30e723d
[mes.git] / scaffold / cons-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 0
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 char arena[2000];
36 //char buf0[400];
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
105 getchar ()
106 {
107   char c;
108   int r = read (g_stdin, &c, 1);
109   if (r < 1) return -1;
110   return c;
111 }
112
113 void
114 write (int fd, char const* s, int n)
115 {
116   int r;
117   //syscall (SYS_write, fd, s, n));
118   asm (
119        "mov %0,%%ebx\n\t"
120        "mov %1,%%ecx\n\t"
121        "mov %2,%%edx\n\t"
122
123        "mov $0x4, %%eax\n\t"
124        "int $0x80\n\t"
125        : // no outputs "=" (r)
126        : "" (fd), "" (s), "" (n)
127        : "eax", "ebx", "ecx", "edx"
128        );
129 }
130
131 int
132 putchar (int c)
133 {
134   //write (STDOUT, s, strlen (s));
135   //int i = write (STDOUT, s, strlen (s));
136   write (1, (char*)&c, 1);
137   return 0;
138 }
139
140 void *
141 malloc (size_t size)
142 {
143   int *n;
144   int len = size + sizeof (size);
145   //n = mmap (0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );
146   *n = len;
147   return (void*)(n+1);
148 }
149
150 void
151 free (void *p)
152 {
153   int *n = (int*)p-1;
154   //munmap ((void*)p, *n);
155 }
156
157 #define EOF -1
158 #define STDIN 0
159 #define STDOUT 1
160 #define STDERR 2
161
162 size_t
163 strlen (char const* s)
164 {
165   int i = 0;
166   while (s[i]) i++;
167   return i;
168 }
169
170 int
171 strcmp (char const* a, char const* b)
172 {
173   while (*a && *b && *a == *b) {a++;b++;}
174   return *a - *b;
175 }
176
177 int
178 puts (char const* s)
179 {
180   //write (STDOUT, s, strlen (s));
181   //int i = write (STDOUT, s, strlen (s));
182   int i = strlen (s);
183   write (1, s, i);
184   return 0;
185 }
186
187 int
188 eputs (char const* s)
189 {
190   //write (STDERR, s, strlen (s));
191   //int i = write (STDERR, s, strlen (s));
192   int i = strlen (s);
193   write (2, s, i);
194   return 0;
195 }
196
197 char const*
198 itoa (int x)
199 {
200   static char buf[10];
201   char *p = buf+9;
202   *p-- = 0;
203
204   int sign = x < 0;
205   if (sign)
206     x = -x;
207   
208   do
209     {
210       *p-- = '0' + (x % 10);
211       x = x / 10;
212     } while (x);
213
214   if (sign)
215     *p-- = '-';
216
217   return p+1;
218 }
219 #endif
220
221 void
222 assert_fail (char* s)
223 {
224   eputs ("assert fail:");
225 #if __GNUC__
226   eputs (s);
227 #endif
228   eputs ("\n");
229 #if __GNUC__
230   *((int*)0) = 0;
231 #endif
232 }
233
234 #if __GNUC__
235 #define assert(x) ((x) ? (void)0 : assert_fail ("boo:" #x))
236 #else
237 //#define assert(x) ((x) ? (void)0 : assert_fail ("boo:" #x))
238 #define assert(x) ((x) ? (void)0 : assert_fail (0))
239 #endif
240
241 typedef int SCM;
242
243 #if __GNUC__
244 int g_debug = 0;
245 #endif
246
247 int g_free = 0;
248
249 SCM g_symbols = 0;
250 SCM g_stack = 0;
251 // a/env
252 SCM r0 = 0;
253 // param 1
254 SCM r1 = 0;
255 // save 2+load/dump
256 SCM r2 = 0;
257 // continuation
258 SCM r3 = 0;
259
260 #if __NYACC__ || FIXME_NYACC
261 enum type_t {CHAR, CLOSURE, CONTINUATION, TFUNCTION, KEYWORD, MACRO, NUMBER, PAIR, REF, SPECIAL, TSTRING, SYMBOL, VALUES, TVECTOR, BROKEN_HEART};
262 #else
263 enum type_t {CHAR, CLOSURE, CONTINUATION, FUNCTION, KEYWORD, MACRO, NUMBER, PAIR, REF, SPECIAL, STRING, SYMBOL, VALUES, VECTOR, BROKEN_HEART};
264 #endif
265
266 struct scm {
267   enum type_t type;
268   SCM car;
269   SCM cdr;
270 };
271
272 typedef int (*f_t) (void);
273 struct function {
274   int (*function) (void);
275   int arity;
276   char *name;
277 };
278
279 struct scm *g_cells = arena;
280
281 //scm *g_news = 0;
282
283 // struct scm scm_nil = {SPECIAL, "()"};
284 // struct scm scm_f = {SPECIAL, "#f"};
285 // struct scm scm_t = {SPECIAL, "#t"};
286 // struct scm_dot = {SPECIAL, "."};
287 // struct scm_arrow = {SPECIAL, "=>"};
288 // struct scm_undefined = {SPECIAL, "*undefined*"};
289 // struct scm_unspecified = {SPECIAL, "*unspecified*"};
290 // struct scm_closure = {SPECIAL, "*closure*"};
291 // struct scm_circular = {SPECIAL, "*circular*"};
292 // struct scm_begin = {SPECIAL, "*begin*"};
293
294 // struct scm_vm_apply = {SPECIAL, "core:apply"};
295 // struct scm_vm_apply2 = {SPECIAL, "*vm-apply2*"};
296
297 // struct scm_vm_eval = {SPECIAL, "core:eval"};
298
299 // struct scm_vm_begin = {SPECIAL, "*vm-begin*"};
300 // //scm scm_vm_begin_read_input_file = {SPECIAL, "*vm-begin-read-input-file*"};
301 // struct scm_vm_begin2 = {SPECIAL, "*vm-begin2*"};
302
303 // struct scm_vm_return = {SPECIAL, "*vm-return*"};
304
305 // //#include "mes.symbols.h"
306
307 #define cell_nil 1
308 #define cell_f 2
309 #define cell_t 3
310 #define cell_dot 4
311 // #define cell_arrow 5
312 #define cell_undefined 6
313 #define cell_unspecified 7
314 #define cell_closure 8
315 #define cell_circular 9
316 #define cell_begin 10
317 #define cell_symbol_dot 11
318 #define cell_symbol_lambda 12
319 #define cell_symbol_begin 13
320 #define cell_symbol_if 14
321 #define cell_symbol_quote 15
322 #define cell_symbol_set_x 16
323
324 #define cell_vm_apply 45
325 #define cell_vm_apply2 46
326
327 #define cell_vm_eval 47
328
329 #define cell_vm_begin 56
330 //#define cell_vm_begin_read_input_file 57
331 #define cell_vm_begin2 58
332
333 #define cell_vm_return 63
334
335 SCM tmp;
336 SCM tmp_num;
337 SCM tmp_num2;
338
339 int ARENA_SIZE = 200;
340 struct function g_functions[5];
341 int g_function = 0;
342
343
344 #if __GNUC__
345 //FIXME
346 SCM make_cell (SCM type, SCM car, SCM cdr);
347 #endif
348 struct function fun_make_cell = {&make_cell,3,"make-cell"};
349 struct scm scm_make_cell = {TFUNCTION,0,0};
350    //, "make-cell", 0};
351 SCM cell_make_cell;
352
353 #if __GNUC__
354 //FIXME
355 SCM cons (SCM x, SCM y);
356 #endif
357 struct function fun_cons = {&cons,2,"cons"};
358 struct scm scm_cons = {TFUNCTION,0,0};
359   // "cons", 0};
360 SCM cell_cons;
361
362 #if __GNUC__
363 //FIXME
364 SCM car (SCM x);
365 #endif
366 struct function fun_car = {&car,1,"car"};
367 struct scm scm_car = {TFUNCTION,0,0};
368   // "car", 0};
369 SCM cell_car;
370
371 #if __GNUC__
372 //FIXME
373 SCM cdr (SCM x);
374 #endif
375 struct function fun_cdr = {&cdr,1,"cdr"};
376 struct scm scm_cdr = {TFUNCTION,0,0};
377 // "cdr", 0};
378 SCM cell_cdr;
379
380 // SCM eq_p (SCM x, SCM y);
381 // struct function fun_eq_p = {&eq_p,2,"eq?"};
382 // scm scm_eq_p = {TFUNCTION,0,0};
383 // SCM cell_eq_p;
384
385 #define TYPE(x) (g_cells[x].type)
386
387 #define CAR(x) g_cells[x].car
388 #define LENGTH(x) g_cells[x].car
389 #define STRING(x) g_cells[x].car
390
391 #define CDR(x) g_cells[x].cdr
392 #if __GNUC__
393 //#define CLOSURE(x) g_cells[x].closure
394 #endif
395 #define CONTINUATION(x) g_cells[x].cdr
396 #if __GNUC__
397 //#define FUNCTION(x) g_functions[g_cells[x].function]
398 #endif
399
400 #define FUNCTION(x) g_functions[g_cells[x].cdr]
401 #define VALUE(x) g_cells[x].cdr
402 #define VECTOR(x) g_cells[x].cdr
403
404 #define MAKE_CHAR(n) make_cell (tmp_num_ (CHAR), 0, tmp_num2_ (n))
405 //#define MAKE_CONTINUATION(n) make_cell (tmp_num_ (CONTINUATION), n, g_stack)
406 #define MAKE_NUMBER(n) make_cell (tmp_num_ (NUMBER), 0, tmp_num2_ (n))
407 //#define MAKE_REF(n) make_cell (tmp_num_ (REF), n, 0)
408
409
410 #define CAAR(x) CAR (CAR (x))
411 // #define CDAR(x) CDR (CAR (x))
412 #define CADAR(x) CAR (CDR (CAR (x)))
413 // #define CADDR(x) CAR (CDR (CDR (x)))
414 // #define CDDDR(x) CDR (CDR (CDR (x)))
415 #define CDADAR(x) CAR (CDR (CAR (CDR (x))))
416 #define CADR(x) CAR (CDR (x))
417
418
419 #if __NYACC__ || FIXME_NYACC
420 #define MAKE_STRING(x) make_cell (tmp_num_ (TSTRING), x, 0)
421 // #else
422 // #define MAKE_STRING(x) make_cell (tmp_num_ (STRING), x, 0)
423 #endif
424
425 SCM
426 alloc (int n)
427 {
428   assert (g_free + n < ARENA_SIZE);
429   SCM x = g_free;
430   g_free += n;
431   return x;
432 }
433
434 SCM
435 make_cell (SCM type, SCM car, SCM cdr)
436 {
437   SCM x = alloc (1);
438   assert (TYPE (type) == NUMBER);
439   TYPE (x) = VALUE (type);
440   if (VALUE (type) == CHAR || VALUE (type) == NUMBER) {
441     if (car) CAR (x) = CAR (car);
442     if (cdr) CDR(x) = CDR(cdr);
443   }
444   else if (VALUE (type) == TFUNCTION) {
445     if (car) CAR (x) = car;
446     if (cdr) CDR(x) = CDR(cdr);
447   }
448   else {
449     CAR (x) = car;
450     CDR(x) = cdr;
451   }
452   return x;
453 }
454
455 SCM
456 tmp_num_ (int x)
457 {
458   VALUE (tmp_num) = x;
459   return tmp_num;
460 }
461
462 SCM
463 tmp_num2_ (int x)
464 {
465   VALUE (tmp_num2) = x;
466   return tmp_num2;
467 }
468
469 SCM
470 cons (SCM x, SCM y)
471 {
472   puts ("cons x=");
473 #if __GNUC__
474   puts (itoa (x));
475 #endif
476   puts ("\n");
477   VALUE (tmp_num) = PAIR;
478   return make_cell (tmp_num, x, y);
479 }
480
481 SCM
482 car (SCM x)
483 {
484   puts ("car x=");
485 #if __GNUC__
486   puts (itoa (x));
487 #endif
488   puts ("\n");
489 #if MES_MINI
490   //Nyacc
491   //assert ("!car");
492 #else
493   if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_car));
494 #endif
495   return CAR (x);
496 }
497
498 SCM
499 cdr (SCM x)
500 {
501   puts ("cdr x=");
502 #if __GNUC__
503   puts (itoa (x));
504 #endif
505   puts ("\n");
506 #if MES_MINI
507   //Nyacc
508   //assert ("!cdr");
509 #else
510   if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_cdr));
511 #endif
512   return CDR(x);
513 }
514
515 SCM
516 gc_push_frame ()
517 {
518   SCM frame = cons (r1, cons (r2, cons (r3, cons (r0, cell_nil))));
519   g_stack = cons (frame, g_stack);
520   return g_stack;
521 }
522
523 SCM
524 append2 (SCM x, SCM y)
525 {
526   if (x == cell_nil) return y;
527 #if __GNUC__
528   //FIXME GNUC
529   assert (TYPE (x) == PAIR);
530 #endif
531   return cons (car (x), append2 (cdr (x), y));
532 }
533
534 SCM
535 pairlis (SCM x, SCM y, SCM a)
536 {
537   if (x == cell_nil)
538     return a;
539   if (TYPE (x) != PAIR)
540     return cons (cons (x, y), a);
541   return cons (cons (car (x), car (y)),
542                pairlis (cdr (x), cdr (y), a));
543 }
544
545 SCM
546 assq (SCM x, SCM a)
547 {
548   //while (a != cell_nil && eq_p (x, CAAR (a)) == cell_f) a = CDR (a);
549   while (a != cell_nil && x == CAAR (a)) a = CDR (a);
550   return a != cell_nil ? car (a) : cell_f;
551 }
552
553 SCM
554 push_cc (SCM p1, SCM p2, SCM a, SCM c) ///((internal))
555 {
556   puts ("push cc\n");
557   SCM x = r3;
558   r3 = c;
559   r2 = p2;
560   gc_push_frame ();
561   r1 = p1;
562   r0 = a;
563   r3 = x;
564   return cell_unspecified;
565 }
566
567 SCM caar (SCM x) {return car (car (x));}
568 SCM cadr (SCM x) {return car (cdr (x));}
569 SCM cdar (SCM x) {return cdr (car (x));}
570 SCM cddr (SCM x) {return cdr (cdr (x));}
571
572 #if __GNUC__
573 //FIXME
574 SCM call (SCM,SCM);
575 SCM gc_pop_frame ();
576 #endif
577
578 SCM
579 eval_apply ()
580 {
581  eval_apply:
582   // if (g_free + GC_SAFETY > ARENA_SIZE)
583   //   gc_pop_frame (gc (gc_push_frame ()));
584
585   switch (r3)
586     {
587     case cell_vm_apply: {goto apply;}
588     case cell_unspecified: {return r1;}
589     }
590
591   SCM x = cell_nil;
592   SCM y = cell_nil;
593
594  apply:
595   switch (TYPE (car (r1)))
596     {
597     case TFUNCTION: {
598       puts ("apply.function\n");
599       //check_formals (car (r1), MAKE_NUMBER (FUNCTION (car (r1)).arity), cdr (r1));
600       r1 = call (car (r1), cdr (r1));
601       goto vm_return;
602     }
603     }
604  vm_return:
605   x = r1;
606   gc_pop_frame ();
607   r1 = x;
608   goto eval_apply;
609 }
610
611 SCM
612 call (SCM fn, SCM x)
613 {
614   puts ("call\n");
615   if ((FUNCTION (fn).arity > 0 || FUNCTION (fn).arity == -1)
616       && x != cell_nil && TYPE (CAR (x)) == VALUES)
617     x = cons (CADAR (x), CDR (x));
618   if ((FUNCTION (fn).arity > 1 || FUNCTION (fn).arity == -1)
619       && x != cell_nil && TYPE (CDR (x)) == PAIR && TYPE (CADR (x)) == VALUES)
620     x = cons (CAR (x), cons (CDADAR (x), CDR (x)));
621   switch (FUNCTION (fn).arity)
622     {
623     // case 0: return FUNCTION (fn).function0 ();
624     // case 1: return FUNCTION (fn).function1 (car (x));
625     // case 2: return FUNCTION (fn).function2 (car (x), cadr (x));
626     // case 3: return FUNCTION (fn).function3 (car (x), cadr (x), car (cddr (x)));
627     // case -1: return FUNCTION (fn).functionn (x);
628     case 0: {return (FUNCTION (fn).function) ();}
629     case 1: {return ((SCM(*)(SCM))(FUNCTION (fn).function)) (car (x));}
630     case 2: {return ((SCM(*)(SCM,SCM))(FUNCTION (fn).function)) (car (x), cadr (x));}
631     case 3: {return ((SCM(*)(SCM,SCM,SCM))(FUNCTION (fn).function)) (car (x), cadr (x), car (cddr (x)));}
632 #if __GNUC__
633       // FIXME GNUC
634     case -1: {return ((SCM(*)(SCM))(FUNCTION (fn).function)) (x);}
635 #endif
636     default: {return ((SCM(*)(SCM))(FUNCTION (fn).function)) (x);}
637     }
638   return cell_unspecified;
639 }
640
641 SCM
642 gc_peek_frame ()
643 {
644   SCM frame = car (g_stack);
645   r1 = car (frame);
646 #if __GNUC__
647   r2 = cadr (frame);
648   r3 = car (cddr (frame));
649   r0 = cadr (cddr (frame));
650 #else
651   r2 = cdr (frame);
652   r2 = car (r2);
653
654   r3 = cdr (frame);
655   r3 = cdr (r3);
656   r3 = car (r3);
657
658   r0 = cdr (frame);
659   r0 = cdr (r0);
660   r0 = cdr (r0);
661   r0 = cdr (r0);
662   r0 = car (r0);
663 #endif
664   return frame;
665 }
666
667 SCM
668 gc_pop_frame ()
669 {
670   SCM frame = gc_peek_frame (g_stack);
671   g_stack = cdr (g_stack);
672   return frame;
673 }
674
675 SCM
676 mes_g_stack (SCM a) ///((internal))
677 {
678   r0 = a;
679   r1 = MAKE_CHAR (0);
680   r2 = MAKE_CHAR (0);
681   r3 = MAKE_CHAR (0);
682   g_stack = cons (cell_nil, cell_nil);
683   return r0;
684 }
685
686 //\f Environment setup
687 SCM
688 make_tmps (struct scm* cells)
689 {
690   tmp = g_free++;
691   cells[tmp].type = CHAR;
692   tmp_num = g_free++;
693   cells[tmp_num].type = NUMBER;
694   tmp_num2 = g_free++;
695   cells[tmp_num2].type = NUMBER;
696   return 0;
697 }
698
699 SCM
700 make_symbol_ (SCM s)
701 {
702   VALUE (tmp_num) = SYMBOL;
703   SCM x = make_cell (tmp_num, s, 0);
704   g_symbols = cons (x, g_symbols);
705   return x;
706 }
707
708 SCM
709 make_symbol (SCM s)
710 {
711 #if MES_MINI
712   SCM x = 0;
713 #else
714   SCM x = lookup_symbol_ (s);
715 #endif
716   return x ? x : make_symbol_ (s);
717 }
718
719 SCM
720 acons (SCM key, SCM value, SCM alist)
721 {
722   return cons (cons (key, value), alist);
723 }
724
725 //\f Jam Collector
726 SCM g_symbol_max;
727
728 SCM
729 gc_init_cells ()
730 {
731   return 0;
732 }
733
734 // INIT NEWS
735
736 SCM
737 mes_symbols () ///((internal))
738 {
739   gc_init_cells ();
740   //  gc_init_news ();
741
742 #if __GNUC__ && 0
743   //#include "mes.symbols.i"
744 #else
745 g_free++;
746 // g_cells[cell_nil] = scm_nil;
747
748 g_free++;
749 // g_cells[cell_f] = scm_f;
750
751 g_free++;
752 // g_cells[cell_t] = scm_t;
753
754 g_free++;
755 // g_cells[cell_dot] = scm_dot;
756
757 g_free++;
758 // g_cells[cell_arrow] = scm_arrow;
759
760 g_free++;
761 // g_cells[cell_undefined] = scm_undefined;
762
763 g_free++;
764 // g_cells[cell_unspecified] = scm_unspecified;
765
766 g_free++;
767 // g_cells[cell_closure] = scm_closure;
768
769 g_free++;
770 // g_cells[cell_circular] = scm_circular;
771
772 g_free++;
773 // g_cells[cell_begin] = scm_begin;
774
775 ///
776 g_free = 44;
777 g_free++;
778 // g_cells[cell_vm_apply] = scm_vm_apply;
779
780 g_free++;
781 // g_cells[cell_vm_apply2] = scm_vm_apply2;
782
783 g_free++;
784 // g_cells[cell_vm_eval] = scm_vm_eval;
785
786 ///
787 g_free = 55;
788 g_free++;
789 // g_cells[cell_vm_begin] = scm_vm_begin;
790
791 g_free++;
792 // g_cells[cell_vm_begin_read_input_file] = scm_vm_begin_read_input_file;
793
794 g_free++;
795 // g_cells[cell_vm_begin2] = scm_vm_begin2;
796
797 ///
798 g_free = 62;
799 g_free++;
800 // g_cells[cell_vm_return] = scm_vm_return;
801
802 #endif
803
804   g_symbol_max = g_free;
805   make_tmps (g_cells);
806
807   g_symbols = 0;
808   for (int i=1; i<g_symbol_max; i++)
809     g_symbols = cons (i, g_symbols);
810
811   SCM a = cell_nil;
812
813   a = acons (cell_symbol_dot, cell_dot, a);
814   a = acons (cell_symbol_begin, cell_begin, a);
815   a = acons (cell_closure, a, a);
816
817   return a;
818 }
819
820 SCM
821 make_closure (SCM args, SCM body, SCM a)
822 {
823   return make_cell (tmp_num_ (CLOSURE), cell_f, cons (cons (cell_circular, a), cons (args, body)));
824 }
825
826 SCM
827 mes_environment () ///((internal))
828 {
829   SCM a = 0;
830   a = mes_symbols ();
831   a = mes_g_stack (a);
832   return a;
833 }
834
835 SCM
836 mes_builtins (SCM a)
837 {
838 #if 0
839   //__GNUC__
840 //#include "mes.i"
841
842 // #include "lib.i"
843 // #include "math.i"
844 // #include "posix.i"
845 // #include "reader.i"
846
847 // #include "lib.environment.i"
848 // #include "math.environment.i"
849 // #include "mes.environment.i"
850 // #include "posix.environment.i"
851 // #include "reader.environment.i"
852 #else
853 scm_make_cell.cdr = g_function;
854 g_functions[g_function++] = fun_make_cell;
855 cell_make_cell = g_free++;
856  g_cells[cell_make_cell] = scm_make_cell;
857  
858 scm_cons.cdr = g_function;
859 g_functions[g_function++] = fun_cons;
860 cell_cons = g_free++;
861 g_cells[cell_cons] = scm_cons;
862  
863 scm_car.cdr = g_function;
864 g_functions[g_function++] = fun_car;
865 cell_car = g_free++;
866 g_cells[cell_car] = scm_car;
867  
868 scm_cdr.cdr = g_function;
869 g_functions[g_function++] = fun_cdr;
870 cell_cdr = g_free++;
871 g_cells[cell_cdr] = scm_cdr;
872 #endif
873   return a;
874 }
875
876 SCM
877 bload_env (SCM a) ///((internal))
878 {
879   g_stdin = open ("module/mes/read-0.mo", 0);
880 #if __GNUC__
881   //FIXME GNUC
882   //g_stdin = g_stdin ? g_stdin : fopen (PREFIX "module/mes/read-0.mo", "r");
883 #endif
884   char *p = (char*)g_cells;
885   assert (getchar () == 'M');
886   assert (getchar () == 'E');
887   assert (getchar () == 'S');
888   g_stack = getchar () << 8;
889   g_stack += getchar ();
890   int c = getchar ();
891   while (c != EOF)
892     {
893       *p++ = c;
894       c = getchar ();
895     }
896   g_free = (p-(char*)g_cells) / sizeof (struct scm);
897   gc_peek_frame ();
898   g_symbols = r1;
899   g_stdin = STDIN;
900   r0 = mes_builtins (r0);
901   return r2;
902 }
903
904 SCM
905 fill ()
906 {
907   TYPE (0) = 0x6c6c6168;
908   CAR (0) = 0x6a746f6f;
909   CDR (0) = 0x00002165;
910
911   TYPE (1) = SYMBOL;
912   CAR (1) = 0x2d2d2d2d;
913   CDR (1) = 0x3e3e3e3e;
914
915   TYPE (9) = 0x2d2d2d2d;
916   CAR (9) = 0x2d2d2d2d;
917   CDR (9) = 0x3e3e3e3e;
918
919   // (cons 0 1)
920   TYPE (10) = PAIR;
921   CAR (10) = 11;
922   CDR (10) = 12;
923
924   TYPE (11) = TFUNCTION;
925   CAR (11) = 0x58585858;
926   // 0 = make_cell
927   // 1 = cons
928   // 2 = car
929   CDR (11) = 1;
930
931   TYPE (12) = PAIR;
932   CAR (12) = 13;
933   //CDR (12) = 1;
934   CDR (12) = 14;
935
936   TYPE (13) = NUMBER;
937   CAR (13) = 0x58585858;
938   CDR (13) = 0;
939
940   TYPE (14) = PAIR;
941   CAR (14) = 15;
942   CDR (14) = 1;
943
944   TYPE (15) = NUMBER;
945   CAR (15) = 0x58585858;
946   CDR (15) = 1;
947
948   return 0;
949 }
950
951 SCM
952 display_ (SCM x)
953 {
954   //puts ("<display>\n");
955   switch (TYPE (x))
956     {
957     case CHAR:
958       {
959         //puts ("<char>\n");
960         puts ("#\\");
961         putchar (VALUE (x));
962         break;
963       }
964     case TFUNCTION:
965       {
966         //puts ("<function>\n");
967         if (VALUE (x) == 0)
968           puts ("make-cell");
969         if (VALUE (x) == 1)
970           puts ("cons");
971         if (VALUE (x) == 2)
972           puts ("car");
973         if (VALUE (x) == 3)
974           puts ("cdr");
975         break;
976       }
977     case NUMBER:
978       {
979         //puts ("<number>\n");
980 #if __GNUC__
981         puts (itoa (VALUE (x)));
982 #else
983         int i;
984         i = VALUE (x);
985         i = i + 48;
986         putchar (i);
987 #endif
988         break;
989       }
990     case PAIR:
991       {
992         //puts ("<pair>\n");
993         //if (cont != cell_f) puts "(");
994         puts ("(");
995         if (x && x != cell_nil) display_ (CAR (x));
996         if (CDR (x) && CDR (x) != cell_nil)
997           {
998 #if __GNUC__
999             if (TYPE (CDR (x)) != PAIR)
1000               puts (" . ");
1001 #else
1002             int c;
1003             c = CDR (x);
1004             c = TYPE (c);
1005             if (c != PAIR)
1006               puts (" . ");
1007 #endif
1008             display_ (CDR (x));
1009           }
1010         //if (cont != cell_f) puts (")");
1011         puts (")");
1012         break;
1013       }
1014     case SPECIAL:
1015       {
1016         switch (x)
1017           {
1018           case 1: {puts ("()"); break;}
1019           case 2: {puts ("#f"); break;}
1020           case 3: {puts ("#t"); break;}
1021           default:
1022             {
1023 #if __GNUC__
1024         puts ("<x:");
1025         puts (itoa (x));
1026         puts (">");
1027 #else
1028         puts ("<x>");
1029 #endif
1030             }
1031           }
1032         break;
1033       }
1034     case SYMBOL:
1035       {
1036         switch (x)
1037           {
1038           case 11: {puts (" . "); break;}
1039           case 12: {puts ("lambda"); break;}
1040           case 13: {puts ("begin"); break;}
1041           case 14: {puts ("if"); break;}
1042           case 15: {puts ("quote"); break;}
1043           case 37: {puts ("car"); break;}
1044           case 38: {puts ("cdr"); break;}
1045           case 39: {puts ("null?"); break;}
1046           case 40: {puts ("eq?"); break;}
1047           case 41: {puts ("cons"); break;}
1048           default:
1049             {
1050 #if __GNUC__
1051         puts ("<s:");
1052         puts (itoa (x));
1053         puts (">");
1054 #else
1055         puts ("<s>");
1056 #endif
1057             }
1058           }
1059         break;
1060       }
1061     default:
1062       {
1063         //puts ("<default>\n");
1064 #if __GNUC__
1065         puts ("<");
1066         puts (itoa (TYPE (x)));
1067         puts (":");
1068         puts (itoa (x));
1069         puts (">");
1070 #else
1071         puts ("_");
1072 #endif
1073         break;
1074       }
1075     }
1076   return 0;
1077 }
1078
1079 SCM
1080 simple_bload_env (SCM a) ///((internal))
1081 {
1082   puts ("reading: ");
1083   char *mo = "module/mes/hack-32.mo";
1084   puts (mo);
1085   puts ("\n");
1086   g_stdin = open (mo, 0);
1087   if (g_stdin < 0) {eputs ("no such file: module/mes/read-0-32.mo\n");return 1;} 
1088
1089   char *p = (char*)g_cells;
1090   int c;
1091
1092 #if 0
1093   //__GNUC__
1094   puts ("fd: ");
1095   puts (itoa (g_stdin));
1096   puts ("\n");
1097 #endif
1098
1099   assert (getchar () == 'M');
1100   assert (getchar () == 'E');
1101   assert (getchar () == 'S');
1102   puts (" *GOT MES*\n");
1103   g_stack = getchar () << 8;
1104   g_stack += getchar ();
1105
1106 #if __GNUC__
1107   puts ("stack: ");
1108   puts (itoa (g_stack));
1109   puts ("\n");
1110 #endif
1111
1112   c = getchar ();
1113   while (c != -1)
1114     {
1115       *p++ = c;
1116       c = getchar ();
1117       putchar (c);
1118     }
1119
1120   puts ("read done\n");
1121
1122   g_free = (p-(char*)g_cells) / sizeof (struct scm);
1123   
1124   if (g_free != 15) exit (33);
1125   
1126 #if 0
1127   gc_peek_frame ();
1128   g_symbols = r1;
1129 #else
1130   g_symbols = 1;
1131 #endif
1132   g_stdin = STDIN;
1133   r0 = mes_builtins (r0);
1134   
1135   if (g_free != 19) exit (34);
1136   
1137 #if __GNUC__
1138   puts ("cells read: ");
1139   puts (itoa (g_free));
1140   puts ("\n");
1141
1142   puts ("symbols: ");
1143   puts (itoa (g_symbols));
1144   puts ("\n");
1145   // display_ (g_symbols);
1146   // puts ("\n");
1147 #endif
1148
1149   display_ (10);
1150   puts ("\n");
1151
1152   fill ();
1153   r2 = 10;
1154
1155   if (TYPE (12) != PAIR)
1156     exit (33);
1157
1158   puts ("program[");
1159 #if __GNUC__
1160   puts (itoa (r2));
1161 #endif
1162   puts ("]: ");
1163
1164   display_ (r2);
1165   //display_ (14);
1166   puts ("\n");
1167
1168   r0 = 1;
1169   //r2 = 10;
1170   return r2;
1171 }
1172
1173 char string_to_cstring_buf[1024];
1174 char const*
1175 string_to_cstring (SCM s)
1176 {
1177   //static char buf[1024];
1178   //char *p = buf;
1179   char *p = string_to_cstring_buf;
1180   s = STRING(s);
1181   while (s != cell_nil)
1182     {
1183       *p++ = VALUE (car (s));
1184       s = cdr (s);
1185     }
1186   *p = 0;
1187   //return buf;
1188   return string_to_cstring_buf;
1189 }
1190
1191 SCM
1192 stderr_ (SCM x)
1193 {
1194   //SCM write;
1195 #if __NYACC__ || FIXME_NYACC
1196   if (TYPE (x) == TSTRING)
1197 // #else
1198 //   if (TYPE (x) == STRING)
1199 #endif
1200     eputs (string_to_cstring (x));
1201   // else if ((write = assq_ref_env (cell_symbol_write, r0)) != cell_undefined)
1202   //   apply (assq_ref_env (cell_symbol_display, r0), cons (x, cons (MAKE_NUMBER (2), cell_nil)), r0);
1203 #if __NYACC__ || FIXME_NYACC
1204   else if (TYPE (x) == SPECIAL || TYPE (x) == TSTRING || TYPE (x) == SYMBOL)
1205 // #else
1206 //   else if (TYPE (x) == SPECIAL || TYPE (x) == STRING || TYPE (x) == SYMBOL)
1207 #endif
1208     eputs (string_to_cstring (x));
1209   else if (TYPE (x) == NUMBER)
1210     eputs (itoa (VALUE (x)));
1211   else
1212     eputs ("display: undefined\n");
1213   return cell_unspecified;
1214 }
1215
1216 int
1217 main (int argc, char *argv[])
1218 {
1219   puts ("Hello cons-mes!\n");
1220   if (argc > 1 && !strcmp (argv[1], "--help")) return eputs ("Usage: mes [--dump|--load] < FILE");
1221 #if __GNUC__
1222   if (argc > 1 && !strcmp (argv[1], "--version")) {eputs ("Mes ");return eputs (VERSION);};
1223 #else
1224   if (argc > 1 && !strcmp (argv[1], "--version")) {eputs ("Mes ");return eputs ("0.4");};
1225 #endif
1226   g_stdin = STDIN;
1227
1228   r0 = mes_environment ();
1229   
1230 #if MES_MINI
1231   SCM program = simple_bload_env (r0);
1232 #else  
1233   SCM program = (argc > 1 && !strcmp (argv[1], "--load"))
1234     ? bload_env (r0) : load_env (r0);
1235   if (argc > 1 && !strcmp (argv[1], "--dump")) return dump ();
1236 #endif
1237
1238 #if __GNUC__
1239   puts ("g_free=");
1240   puts (itoa(g_free));
1241   puts ("\n");
1242 #endif
1243
1244   push_cc (r2, cell_unspecified, r0, cell_unspecified);
1245
1246 #if __GNUC__
1247
1248   puts ("g_free=");
1249   puts (itoa(g_free));
1250   puts ("\n");
1251
1252   puts ("g_stack=");
1253   puts (itoa(g_stack));
1254   puts ("\n");
1255
1256   puts ("r0=");
1257   puts (itoa(r0));
1258   puts ("\n");
1259
1260   puts ("r1=");
1261   puts (itoa(r1));
1262   puts ("\n");
1263
1264   puts ("r2=");
1265   puts (itoa(r2));
1266   puts ("\n");
1267
1268   puts ("r3=");
1269   puts (itoa(r3));
1270   puts ("\n");
1271 #endif
1272
1273   r3 = cell_vm_apply;
1274   r1 = eval_apply ();
1275   display_ (r1);
1276
1277   eputs ("\n");
1278 #if !MES_MINI
1279   gc (g_stack);
1280 #endif
1281 #if __GNUC__
1282   if (g_debug)
1283     {
1284       eputs ("\nstats: [");
1285       eputs (itoa (g_free));
1286       eputs ("]\n");
1287     }
1288 #endif
1289   return 0;
1290 }
1291
1292 #if __GNUC__
1293 void
1294 _start ()
1295 {
1296   int r;
1297   asm (
1298        "mov %%ebp,%%eax\n\t"
1299        "addl $8,%%eax\n\t"
1300        "push %%eax\n\t"
1301
1302        "mov %%ebp,%%eax\n\t"
1303        "addl $4,%%eax\n\t"
1304        "movzbl (%%eax),%%eax\n\t"
1305        "push %%eax\n\t"
1306
1307        "call main\n\t"
1308        "movl %%eax,%0\n\t"
1309        : "=r" (r)
1310        : //no inputs "" (&main)
1311        );
1312   exit (r);
1313 }
1314 #endif