mini-mes: Parse with Nyacc.
[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
23 #if __GNUC__
24 #define FIXME_NYACC 1
25 #define  __NYACC__ 0
26 #define NYACC_CAR
27 #define NYACC_CDR
28 #else
29 #define  __NYACC__ 1
30 #define NYACC_CAR nyacc_car
31 #define NYACC_CDR nyacc_cdr
32 #endif
33
34 typedef long size_t;
35 void *malloc (size_t i);
36
37
38 #if __GNUC__
39
40 int
41 open (char const *s, int mode)
42 {
43   //return syscall (SYS_open, s, mode);
44   return 0;
45 }
46
47 int
48 read (int fd, int n)
49 {
50   //syscall (SYS_read, 1, 1);
51   return 0;
52 }
53
54 void
55 write (int fd, char const* s, int n)
56 {
57   int r;
58   //syscall (SYS_write, fd, s, n));
59   asm (
60        "mov %0, %%ebx\n\t"
61        "mov %1, %%ecx\n\t"
62        "mov %2, %%edx\n\t"
63
64        "mov $0x4, %%eax\n\t"
65        "int $0x80\n\t"
66        : // no outputs "=" (r)
67        : "" (fd), "" (s), "" (n)
68        : "eax", "ebx", "ecx", "edx"
69        );
70   
71 }
72
73 void *
74 malloc (size_t size)
75 {
76   int *n;
77   int len = size + sizeof (size);
78   //n = mmap (0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );
79   *n = len;
80   return (void*)(n+1);
81 }
82
83 void
84 free (void *p)
85 {
86   int *n = (int*)p-1;
87   //munmap ((void*)p, *n);
88 }
89 #endif // __GNUC__
90
91 #define EOF -1
92 #define STDIN 0
93 #define STDOUT 1
94 #define STDERR 2
95
96 //#include <stdio.h>
97 //#include <string.h>
98 //#include <stdlib.h>
99
100 int g_stdin;
101
102 size_t
103 strlen (char const* s)
104 {
105   int i = 0;
106   while (s[i]) i++;
107   return i;
108 }
109
110 int
111 strcmp (char const* a, char const* b)
112 {
113   while (*a && *b && *a == *b) {a++;b++;}
114   return *a - *b;
115 }
116
117 int
118 getc ()
119 {
120   return read (g_stdin, 1);
121 }
122
123 int
124 puts (char const* s)
125 {
126   write (STDOUT, s, strlen (s));
127   return 0;
128 }
129
130 int
131 eputs (char const* s)
132 {
133   write (STDERR, s, strlen (s));
134   return 0;
135 }
136
137 char const*
138 itoa (int x)
139 {
140   static char buf[10];
141   char *p = buf+9;
142   *p-- = 0;
143
144   int sign = x < 0;
145   if (sign)
146     x = -x;
147   
148   do
149     {
150       *p-- = '0' + (x % 10);
151       x = x / 10;
152     } while (x);
153
154   if (sign)
155     *p-- = '-';
156
157   return p+1;
158 }
159
160 void
161 assert_fail (char* s)
162 {
163   eputs ("assert fail:");
164   eputs (s);
165   eputs ("\n");
166   *((int*)0) = 0;
167 }
168
169 #if __NYACC__ || FIXME_NYACC
170 #define assert(x) ((x) ? (void)0 : assert_fail(0))
171 // #else
172 // NYACC
173 // #define assert(x) ((x) ? (void)0 : assert_fail(#x))
174 #endif
175 #define false 0
176 #define true 1
177 typedef int bool;
178
179 int ARENA_SIZE = 100000;
180
181 typedef int SCM;
182 #if __NYACC__ || FIXME_NYACC
183 enum type_t {CHAR, CLOSURE, CONTINUATION, FUNCTION, KEYWORD, MACRO, NUMBER, PAIR, REF, SPECIAL, TSTRING, SYMBOL, VALUES, TVECTOR, BROKEN_HEART};
184 #else
185 enum type_t {CHAR, CLOSURE, CONTINUATION, FUNCTION, KEYWORD, MACRO, NUMBER, PAIR, REF, SPECIAL, STRING, SYMBOL, VALUES, VECTOR, BROKEN_HEART};
186 #endif
187 typedef SCM (*function0_t) (void);
188 typedef SCM (*function1_t) (SCM);
189 typedef SCM (*function2_t) (SCM, SCM);
190 typedef SCM (*function3_t) (SCM, SCM, SCM);
191 typedef SCM (*functionn_t) (SCM);
192 typedef struct function_struct {
193   union {
194     function0_t function0;
195     function1_t function1;
196     function2_t function2;
197     function3_t function3;
198     functionn_t functionn;
199   } data;
200   int arity;
201 } function_t;
202 struct scm;
203
204 typedef struct scm_struct {
205   enum type_t type;
206   union {
207     char const *name;
208     SCM string;
209     SCM car;
210     SCM ref;
211     int length;
212   } NYACC_CAR;
213   union {
214     int value;
215     int function;
216     SCM cdr;
217     SCM closure;
218     SCM continuation;
219     SCM macro;
220     SCM vector;
221     int hits;
222   } NYACC_CDR;
223 } scm;
224
225 scm scm_nil = {SPECIAL, "()"};
226 scm scm_f = {SPECIAL, "#f"};
227 scm scm_t = {SPECIAL, "#t"};
228 scm scm_dot = {SPECIAL, "."};
229 scm scm_arrow = {SPECIAL, "=>"};
230 scm scm_undefined = {SPECIAL, "*undefined*"};
231 scm scm_unspecified = {SPECIAL, "*unspecified*"};
232 scm scm_closure = {SPECIAL, "*closure*"};
233 scm scm_circular = {SPECIAL, "*circular*"};
234 scm scm_begin = {SPECIAL, "*begin*"};
235
236
237 //#include "mes.symbols.h"
238 #define cell_nil 1
239 #define cell_f 2
240 #define cell_t 3
241 #define cell_dot 4
242 #define cell_arrow 5
243 #define cell_undefined 6
244 #define cell_unspecified 7
245 #define cell_closure 8
246 #define cell_circular 9
247 #define cell_begin 10
248 #define cell_symbol_dot 11
249 #define cell_symbol_lambda 12
250 #define cell_symbol_begin 13
251 #define cell_symbol_if 14
252 #define cell_symbol_quote 15
253 #define cell_symbol_set_x 16
254
255 #if __GNUC__
256 bool g_debug = false;
257 #endif
258
259 int g_free = 0;
260 scm *g_cells;
261 //scm *g_news = 0;
262 SCM tmp;
263 SCM tmp_num;
264 SCM tmp_num2;
265
266 function_t functions[200];
267 int g_function = 0;
268
269 SCM g_symbols = 0;
270 SCM g_stack = 0;
271 SCM r0 = 0; // a/env
272 SCM r1 = 0; // param 1
273 SCM r2 = 0; // save 2+load/dump
274 SCM r3 = 0; // continuation
275
276 SCM make_cell (SCM type, SCM car, SCM cdr);
277 function_t fun_make_cell = {&make_cell, 3};
278 scm scm_make_cell = {FUNCTION, "make-cell", 0};
279 SCM cell_make_cell;
280
281 SCM cons (SCM x, SCM y);
282 function_t fun_cons = {&cons, 2};
283 scm scm_cons = {FUNCTION, "cons", 0};
284 SCM cell_cons;
285
286 SCM car (SCM x);
287 function_t fun_car = {&car, 1};
288 scm scm_car = {FUNCTION, "car", 0};
289 SCM cell_car;
290
291 SCM cdr (SCM x);
292 function_t fun_cdr = {&cdr, 1};
293 scm scm_cdr = {FUNCTION, "cdr", 0};
294 SCM cell_cdr;
295
296 // SCM eq_p (SCM x, SCM y);
297 // function_t fun_eq_p = {&eq_p, 2};
298 // scm scm_eq_p = {FUNCTION, "eq?", 0};
299 // SCM cell_eq_p;
300
301 #define TYPE(x) (g_cells[x].type)
302
303 #define CAR(x) g_cells[x].car
304 #define LENGTH(x) g_cells[x].length
305 #define STRING(x) g_cells[x].string
306
307 #define CDR(x) g_cells[x].cdr
308 #define VALUE(x) g_cells[x].value
309 #define VECTOR(x) g_cells[x].vector
310
311 #define MAKE_CHAR(n) make_cell (tmp_num_ (CHAR), 0, tmp_num2_ (n))
312 //#define MAKE_CONTINUATION(n) make_cell (tmp_num_ (CONTINUATION), n, g_stack)
313 //#define MAKE_NUMBER(n) make_cell (tmp_num_ (NUMBER), 0, tmp_num2_ (n))
314 //#define MAKE_REF(n) make_cell (tmp_num_ (REF), n, 0)
315
316 #if __NYACC__ || FIXME_NYACC
317 #define MAKE_STRING(x) make_cell (tmp_num_ (TSTRING), x, 0)
318 // #else
319 // #define MAKE_STRING(x) make_cell (tmp_num_ (STRING), x, 0)
320 #endif
321
322 SCM
323 alloc (int n)
324 {
325   assert (g_free + n < ARENA_SIZE);
326   SCM x = g_free;
327   g_free += n;
328   return x;
329 }
330
331 SCM
332 make_cell (SCM type, SCM car, SCM cdr)
333 {
334   SCM x = alloc (1);
335   assert (TYPE (type) == NUMBER);
336   TYPE (x) = VALUE (type);
337   if (VALUE (type) == CHAR || VALUE (type) == NUMBER) {
338     if (car) CAR (x) = CAR (car);
339     if (cdr) CDR(x) = CDR(cdr);
340   } else if (VALUE (type) == FUNCTION) {
341     if (car) CAR (x) = car;
342     if (cdr) CDR(x) = CDR(cdr);
343   } else {
344     CAR (x) = car;
345     CDR(x) = cdr;
346   }
347   return x;
348 }
349
350 SCM
351 tmp_num_ (int x)
352 {
353   VALUE (tmp_num) = x;
354   return tmp_num;
355 }
356
357 SCM
358 tmp_num2_ (int x)
359 {
360   VALUE (tmp_num2) = x;
361   return tmp_num2;
362 }
363
364 SCM
365 cons (SCM x, SCM y)
366 {
367   VALUE (tmp_num) = PAIR;
368   return make_cell (tmp_num, x, y);
369 }
370
371 SCM
372 car (SCM x)
373 {
374 #if MES_MINI
375   //Nyacc
376   //assert ("!car");
377 #else
378   if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_car));
379 #endif
380   return CAR (x);
381 }
382
383 SCM
384 cdr (SCM x)
385 {
386 #if MES_MINI
387   //Nyacc
388   //assert ("!cdr");
389 #else
390   if (TYPE (x) != PAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_cdr));
391 #endif
392   return CDR(x);
393 }
394
395 SCM
396 gc_push_frame ()
397 {
398   SCM frame = cons (r1, cons (r2, cons (r3, cons (r0, cell_nil))));
399   return g_stack = cons (frame, g_stack);
400 }
401
402 SCM
403 push_cc (SCM p1, SCM p2, SCM a, SCM c) ///((internal))
404 {
405   SCM x = r3;
406   r3 = c;
407   r2 = p2;
408   gc_push_frame ();
409   r1 = p1;
410   r0 = a;
411   r3 = x;
412   return cell_unspecified;
413 }
414
415 SCM caar (SCM x) {return car (car (x));}
416 SCM cadr (SCM x) {return car (cdr (x));}
417 SCM cdar (SCM x) {return cdr (car (x));}
418 SCM cddr (SCM x) {return cdr (cdr (x));}
419
420 SCM
421 gc_peek_frame ()
422 {
423   SCM frame = car (g_stack);
424   r1 = car (frame);
425   r2 = cadr (frame);
426   r3 = car (cddr (frame));
427   r0 = cadr (cddr (frame));
428   return frame;
429 }
430
431 SCM
432 mes_g_stack (SCM a) ///((internal))
433 {
434   r0 = a;
435   r1 = MAKE_CHAR (0);
436   r2 = MAKE_CHAR (0);
437   r3 = MAKE_CHAR (0);
438   g_stack = cons (cell_nil, cell_nil);
439   return r0;
440 }
441
442 //\f Environment setup
443 SCM
444 make_tmps (scm* cells)
445 {
446   tmp = g_free++;
447   cells[tmp].type = CHAR;
448   tmp_num = g_free++;
449   cells[tmp_num].type = NUMBER;
450   tmp_num2 = g_free++;
451   cells[tmp_num2].type = NUMBER;
452 }
453
454 SCM
455 make_symbol_ (SCM s)
456 {
457   VALUE (tmp_num) = SYMBOL;
458   SCM x = make_cell (tmp_num, s, 0);
459   g_symbols = cons (x, g_symbols);
460   return x;
461 }
462
463 SCM
464 make_symbol (SCM s)
465 {
466 #if MES_MINI
467   SCM x = 0;
468 #else
469   SCM x = lookup_symbol_ (s);
470 #endif
471   return x ? x : make_symbol_ (s);
472 }
473
474 SCM
475 cstring_to_list (char const* s)
476 {
477   SCM p = cell_nil;
478   int i = strlen (s);
479   while (i--)
480     p = cons (MAKE_CHAR (s[i]), p);
481   return p;
482 }
483
484 SCM
485 acons (SCM key, SCM value, SCM alist)
486 {
487   return cons (cons (key, value), alist);
488 }
489
490 //\f Jam Collector
491 SCM g_symbol_max;
492
493 SCM
494 gc_init_cells ()
495 {
496   g_cells = (scm *)malloc (2*ARENA_SIZE*sizeof(scm));
497 #if __NYACC__ || FIXME_NYACC
498   TYPE (0) = TVECTOR;
499 // #else
500 //   TYPE (0) = VECTOR;
501 #endif
502   LENGTH (0) = 1000;
503   VECTOR (0) = 0;
504   g_cells++;
505   TYPE (0) = CHAR;
506   VALUE (0) = 'c';
507 }
508
509 // INIT NEWS
510
511 SCM
512 mes_symbols () ///((internal))
513 {
514   gc_init_cells ();
515   //  gc_init_news ();
516
517 #if __GNUC__ && 0
518   //#include "mes.symbols.i"
519 #else
520 g_free++;
521 g_cells[cell_nil] = scm_nil;
522
523 g_free++;
524 g_cells[cell_f] = scm_f;
525
526 g_free++;
527 g_cells[cell_t] = scm_t;
528
529 g_free++;
530 g_cells[cell_dot] = scm_dot;
531
532 g_free++;
533 g_cells[cell_arrow] = scm_arrow;
534
535 g_free++;
536 g_cells[cell_undefined] = scm_undefined;
537
538 g_free++;
539 g_cells[cell_unspecified] = scm_unspecified;
540
541 g_free++;
542 g_cells[cell_closure] = scm_closure;
543
544 g_free++;
545 g_cells[cell_circular] = scm_circular;
546
547 g_free++;
548 g_cells[cell_begin] = scm_begin;
549
550 #endif
551
552   g_symbol_max = g_free;
553   make_tmps (g_cells);
554
555   g_symbols = 0;
556   for (int i=1; i<g_symbol_max; i++)
557     g_symbols = cons (i, g_symbols);
558
559   SCM a = cell_nil;
560
561 #if __GNUC__ && 0
562   //#include "mes.symbol-names.i"
563 #else
564 g_cells[cell_nil].car = cstring_to_list (scm_nil.name);
565 g_cells[cell_f].car = cstring_to_list (scm_f.name);
566 g_cells[cell_t].car = cstring_to_list (scm_t.name);
567 g_cells[cell_dot].car = cstring_to_list (scm_dot.name);
568 g_cells[cell_arrow].car = cstring_to_list (scm_arrow.name);
569 g_cells[cell_undefined].car = cstring_to_list (scm_undefined.name);
570 g_cells[cell_unspecified].car = cstring_to_list (scm_unspecified.name);
571 g_cells[cell_closure].car = cstring_to_list (scm_closure.name);
572 g_cells[cell_circular].car = cstring_to_list (scm_circular.name);
573 g_cells[cell_begin].car = cstring_to_list (scm_begin.name);
574 #endif
575
576   // a = acons (cell_symbol_mes_version, MAKE_STRING (cstring_to_list (VERSION)), a);
577   // a = acons (cell_symbol_mes_prefix, MAKE_STRING (cstring_to_list (PREFIX)), a);
578
579   a = acons (cell_symbol_dot, cell_dot, a); //
580   a = acons (cell_symbol_begin, cell_begin, a);
581   a = acons (cell_closure, a, a);
582
583   // a = acons (cell_symbol_call_with_current_continuation, cell_call_with_current_continuation, a);
584   // a = acons (cell_symbol_sc_expand, cell_f, a);
585
586   return a;
587 }
588
589 SCM
590 mes_environment () ///((internal))
591 {
592   SCM a = mes_symbols ();
593   return mes_g_stack (a);
594 }
595
596 SCM
597 mes_builtins (SCM a)
598 {
599 #if __GNUC__
600 //#include "mes.i"
601
602 // #include "lib.i"
603 // #include "math.i"
604 // #include "posix.i"
605 // #include "reader.i"
606
607 // #include "lib.environment.i"
608 // #include "math.environment.i"
609 // #include "mes.environment.i"
610 // #include "posix.environment.i"
611 // #include "reader.environment.i"
612 #else
613 scm_make_cell.function = g_function;
614 functions[g_function++] = fun_make_cell;
615 cell_make_cell = g_free++;
616 g_cells[cell_make_cell] = scm_make_cell;
617
618 scm_cons.function = g_function;
619 functions[g_function++] = fun_cons;
620 cell_cons = g_free++;
621 g_cells[cell_cons] = scm_cons;
622
623 scm_car.function = g_function;
624 functions[g_function++] = fun_car;
625 cell_car = g_free++;
626 g_cells[cell_car] = scm_car;
627
628 scm_cdr.function = g_function;
629 functions[g_function++] = fun_cdr;
630 cell_cdr = g_free++;
631 g_cells[cell_cdr] = scm_cdr;
632
633 scm_make_cell.string = cstring_to_list (scm_make_cell.name);
634 g_cells[cell_make_cell].string = MAKE_STRING (scm_make_cell.string);
635 a = acons (make_symbol (scm_make_cell.string), cell_make_cell, a);
636
637 scm_cons.string = cstring_to_list (scm_cons.name);
638 g_cells[cell_cons].string = MAKE_STRING (scm_cons.string);
639 a = acons (make_symbol (scm_cons.string), cell_cons, a);
640
641 scm_car.string = cstring_to_list (scm_car.name);
642 g_cells[cell_car].string = MAKE_STRING (scm_car.string);
643 a = acons (make_symbol (scm_car.string), cell_car, a);
644
645 scm_cdr.string = cstring_to_list (scm_cdr.name);
646 g_cells[cell_cdr].string = MAKE_STRING (scm_cdr.string);
647 a = acons (make_symbol (scm_cdr.string), cell_cdr, a);
648 #endif
649   return a;
650 }
651
652 int
653 getchar ()
654 {
655   return getc (g_stdin);
656 }
657
658 SCM
659 bload_env (SCM a) ///((internal))
660 {
661   g_stdin = open ("module/mes/read-0.mo", 0);
662 #if __GNUC__
663   //g_stdin = g_stdin ? g_stdin : fopen (PREFIX "module/mes/read-0.mo", "r");
664 #endif
665   char *p = (char*)g_cells;
666   assert (getchar () == 'M');
667   assert (getchar () == 'E');
668   assert (getchar () == 'S');
669   g_stack = getchar () << 8;
670   g_stack += getchar ();
671   int c = getchar ();
672   while (c != EOF)
673     {
674       *p++ = c;
675       c = getchar ();
676     }
677   g_free = (p-(char*)g_cells) / sizeof (scm);
678   gc_peek_frame ();
679   g_symbols = r1;
680   g_stdin = STDIN;
681   r0 = mes_builtins (r0);
682   return r2;
683 }
684
685 char const*
686 string_to_cstring (SCM s)
687 {
688   static char buf[1024];
689   char *p = buf;
690   s = STRING(s);
691   while (s != cell_nil)
692     {
693       *p++ = VALUE (car (s));
694       s = cdr (s);
695     }
696   *p = 0;
697   return buf;
698 }
699
700 SCM
701 stderr_ (SCM x)
702 {
703   //SCM write;
704 #if __NYACC__ || FIXME_NYACC
705   if (TYPE (x) == TSTRING)
706 // #else
707 //   if (TYPE (x) == STRING)
708 #endif
709     eputs (string_to_cstring (x));
710   // else if ((write = assq_ref_cache (cell_symbol_write, r0)) != cell_undefined)
711   //   apply (assq_ref_cache (cell_symbol_display, r0), cons (x, cons (MAKE_NUMBER (2), cell_nil)), r0);
712 #if __NYACC__ || FIXME_NYACC
713   else if (TYPE (x) == SPECIAL || TYPE (x) == TSTRING || TYPE (x) == SYMBOL)
714 // #else
715 //   else if (TYPE (x) == SPECIAL || TYPE (x) == STRING || TYPE (x) == SYMBOL)
716 #endif
717     eputs (string_to_cstring (x));
718   else if (TYPE (x) == NUMBER)
719     eputs (itoa (VALUE (x)));
720   else
721     eputs ("display: undefined\n");
722   return cell_unspecified;
723 }
724
725 int
726 main (int argc, char *argv[])
727 {
728 #if __GNUC__
729   //g_debug = getenv ("MES_DEBUG");
730 #endif
731   //if (getenv ("MES_ARENA")) ARENA_SIZE = atoi (getenv ("MES_ARENA"));
732   if (argc > 1 && !strcmp (argv[1], "--help")) return eputs ("Usage: mes [--dump|--load] < FILE");
733   if (argc > 1 && !strcmp (argv[1], "--version")) {eputs ("Mes ");return eputs (VERSION);};
734   g_stdin = STDIN;
735   r0 = mes_environment ();
736
737 #if MES_MINI
738   SCM program = bload_env (r0);
739 #else  
740   SCM program = (argc > 1 && !strcmp (argv[1], "--load"))
741     ? bload_env (r0) : load_env (r0);
742   if (argc > 1 && !strcmp (argv[1], "--dump")) return dump ();
743 #endif
744
745   push_cc (r2, cell_unspecified, r0, cell_unspecified);
746   // r3 = cell_vm_begin;
747   // r1 = eval_apply ();
748   stderr_ (r1);
749
750   eputs ("\n");
751 #if !MES_MINI
752   gc (g_stack);
753 #endif
754 #if __GNUC__
755   if (g_debug)
756     {
757       eputs ("\nstats: [");
758       eputs (itoa (g_free));
759       eputs ("]\n");
760     }
761 #endif
762   puts ("Hello mini-mes!\n");
763   return 0;
764 }
765
766 void
767 _start ()
768 {
769   /* main body of program: call main(), etc */
770   
771   /* exit system call */
772   asm (
773        "movl $1,%eax;"
774        "xorl %ebx,%ebx;"
775        "int  $0x80"
776        );
777 }