11b828b04270081078c51f9a7d10e0417cadc07c
[mes.git] / src / mes.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2016,2017,2018 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 #include <stdio.h>
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <mlibc.h>
26
27 int ARENA_SIZE = 20000000; // 32B: 100 MiB, 64b: 200 MiB
28 #if __MESC__
29 //int MAX_ARENA_SIZE = 89478485; // 32b: ~1GiB
30 int MAX_ARENA_SIZE = 80000000; // 32b: ~1GiB
31 #else
32 int MAX_ARENA_SIZE = 200000000; // 32b: 2GiB, 64b: 4GiB
33 #endif
34
35 int GC_SAFETY = 250;
36
37 char *g_arena = 0;
38 typedef int SCM;
39
40 int g_debug = 0;
41 int g_free = 0;
42
43 SCM g_continuations = 0;
44 SCM g_symbols = 0;
45 SCM g_stack = 0;
46 // a/env
47 SCM r0 = 0;
48 // param 1
49 SCM r1 = 0;
50 // save 2+load/dump
51 SCM r2 = 0;
52 // continuation
53 SCM r3 = 0;
54
55 enum type_t {TCHAR, TCLOSURE, TCONTINUATION, TFUNCTION, TKEYWORD, TMACRO, TNUMBER, TPAIR, TREF, TSPECIAL, TSTRING, TSYMBOL, TVALUES, TVECTOR, TBROKEN_HEART};
56
57 #if !_POSIX_SOURCE
58 struct scm {
59   enum type_t type;
60   SCM car;
61   SCM cdr;
62 };
63 struct function {
64   int (*function) (void);
65   int arity;
66   char *name;
67 };
68 #else
69 typedef SCM (*function0_t) (void);
70 typedef SCM (*function1_t) (SCM);
71 typedef SCM (*function2_t) (SCM, SCM);
72 typedef SCM (*function3_t) (SCM, SCM, SCM);
73 typedef SCM (*functionn_t) (SCM);
74 struct function {
75   union {
76     function0_t function0;
77     function1_t function1;
78     function2_t function2;
79     function3_t function3;
80     functionn_t functionn;
81   };
82   int arity;
83   char const *name;
84 };
85 struct scm {
86   enum type_t type;
87   union {
88     char const* name;
89     SCM string;
90     SCM car;
91     SCM ref;
92     int length;
93   };
94   union {
95     int value;
96     int function;
97     SCM cdr;
98     SCM closure;
99     SCM continuation;
100     SCM macro;
101     SCM vector;
102     int hits;
103   };
104 };
105 #endif
106
107 #if __MESC__
108 //FIXME
109 char *foobar = 0;
110 struct scm *g_cells = foobar;
111 struct scm *g_news = foobar;
112 #else
113 struct scm *g_cells = 0;
114 struct scm *g_news = 0;
115 #endif
116
117 struct scm scm_nil = {TSPECIAL, "()",0};
118 struct scm scm_f = {TSPECIAL, "#f",0};
119 struct scm scm_t = {TSPECIAL, "#t",0};
120 struct scm scm_dot = {TSPECIAL, ".",0};
121 struct scm scm_arrow = {TSPECIAL, "=>",0};
122 struct scm scm_undefined = {TSPECIAL, "*undefined*",0};
123 struct scm scm_unspecified = {TSPECIAL, "*unspecified*",0};
124 struct scm scm_closure = {TSPECIAL, "*closure*",0};
125 struct scm scm_circular = {TSPECIAL, "*circular*",0};
126 struct scm scm_begin = {TSPECIAL, "*begin*",0};
127
128 struct scm scm_symbol_dot = {TSYMBOL, "*dot*",0};
129 struct scm scm_symbol_lambda = {TSYMBOL, "lambda",0};
130 struct scm scm_symbol_begin = {TSYMBOL, "begin",0};
131 struct scm scm_symbol_if = {TSYMBOL, "if",0};
132 struct scm scm_symbol_quote = {TSYMBOL, "quote",0};
133 struct scm scm_symbol_define = {TSYMBOL, "define",0};
134 struct scm scm_symbol_define_macro = {TSYMBOL, "define-macro",0};
135
136 struct scm scm_symbol_quasiquote = {TSYMBOL, "quasiquote", 0};
137 struct scm scm_symbol_unquote = {TSYMBOL, "unquote", 0};
138 struct scm scm_symbol_unquote_splicing = {TSYMBOL, "unquote-splicing", 0};
139 struct scm scm_symbol_syntax = {TSYMBOL, "syntax",0};
140 struct scm scm_symbol_quasisyntax = {TSYMBOL, "quasisyntax", 0};
141 struct scm scm_symbol_unsyntax = {TSYMBOL, "unsyntax", 0};
142 struct scm scm_symbol_unsyntax_splicing = {TSYMBOL, "unsyntax-splicing", 0};
143
144 struct scm scm_symbol_set_x = {TSYMBOL, "set!",0};
145
146 struct scm scm_symbol_sc_expand = {TSYMBOL, "sc-expand",0};
147 struct scm scm_symbol_macro_expand = {TSYMBOL, "macro-expand",0};
148 struct scm scm_symbol_sc_expander_alist = {TSYMBOL, "*sc-expander-alist*",0};
149
150 struct scm scm_symbol_call_with_values = {TSYMBOL, "call-with-values",0};
151 struct scm scm_call_with_current_continuation = {TSPECIAL, "*call/cc*",0};
152 struct scm scm_symbol_call_with_current_continuation = {TSYMBOL, "call-with-current-continuation",0};
153 struct scm scm_symbol_current_module = {TSYMBOL, "current-module",0};
154 struct scm scm_symbol_primitive_load = {TSYMBOL, "primitive-load",0};
155 struct scm scm_symbol_read_input_file = {TSYMBOL, "read-input-file",0};
156 struct scm scm_symbol_write = {TSYMBOL, "write",0};
157 struct scm scm_symbol_display = {TSYMBOL, "display",0};
158
159 struct scm scm_symbol_throw = {TSYMBOL, "throw",0};
160 struct scm scm_symbol_not_a_number = {TSYMBOL, "not-a-number",0};
161 struct scm scm_symbol_not_a_pair = {TSYMBOL, "not-a-pair",0};
162 struct scm scm_symbol_system_error = {TSYMBOL, "system-error",0};
163 struct scm scm_symbol_wrong_number_of_args = {TSYMBOL, "wrong-number-of-args",0};
164 struct scm scm_symbol_wrong_type_arg = {TSYMBOL, "wrong-type-arg",0};
165 struct scm scm_symbol_unbound_variable = {TSYMBOL, "unbound-variable",0};
166
167 struct scm scm_symbol_argv = {TSYMBOL, "%argv",0};
168 struct scm scm_symbol_mes_prefix = {TSYMBOL, "%prefix",0};
169 struct scm scm_symbol_mes_version = {TSYMBOL, "%version",0};
170
171 struct scm scm_symbol_car = {TSYMBOL, "car",0};
172 struct scm scm_symbol_cdr = {TSYMBOL, "cdr",0};
173 struct scm scm_symbol_null_p = {TSYMBOL, "null?",0};
174 struct scm scm_symbol_eq_p = {TSYMBOL, "eq?",0};
175 struct scm scm_symbol_cons = {TSYMBOL, "cons",0};
176
177 struct scm scm_vm_evlis = {TSPECIAL, "*vm-evlis*",0};
178 struct scm scm_vm_evlis2 = {TSPECIAL, "*vm-evlis2*",0};
179 struct scm scm_vm_evlis3 = {TSPECIAL, "*vm-evlis3*",0};
180 struct scm scm_vm_apply = {TSPECIAL, "core:apply",0};
181 struct scm scm_vm_apply2 = {TSPECIAL, "*vm-apply2*",0};
182 struct scm scm_vm_eval = {TSPECIAL, "core:eval",0};
183
184 //MES_FIXED_PRIMITIVES
185 struct scm scm_vm_eval_car = {TSPECIAL, "*vm-eval-car*",0};
186 struct scm scm_vm_eval_cdr = {TSPECIAL, "*vm-eval-cdr*",0};
187 struct scm scm_vm_eval_cons = {TSPECIAL, "*vm-eval-cons*",0};
188 struct scm scm_vm_eval_null_p = {TSPECIAL, "*vm-eval-null-p*",0};
189 struct scm scm_vm_eval_define = {TSPECIAL, "*vm-eval-define*",0};
190
191 struct scm scm_vm_eval_set_x = {TSPECIAL, "*vm-eval-set!*",0};
192 struct scm scm_vm_eval_macro_expand_eval = {TSPECIAL, "*vm:eval-macro-expand-eval*",0};
193 struct scm scm_vm_eval_macro_expand_expand = {TSPECIAL, "*vm:eval-macro-expand-expand*",0};
194 struct scm scm_vm_eval_check_func = {TSPECIAL, "*vm-eval-check-func*",0};
195 struct scm scm_vm_eval2 = {TSPECIAL, "*vm-eval2*",0};
196 struct scm scm_vm_macro_expand = {TSPECIAL, "core:macro-expand",0};
197 struct scm scm_vm_macro_expand_define = {TSPECIAL, "*vm:core:macro-expand-define*",0};
198 struct scm scm_vm_macro_expand_define_macro = {TSPECIAL, "*vm:core:macro-expand-define-macro*",0};
199 struct scm scm_vm_macro_expand_lambda = {TSPECIAL, "*vm:core:macro-expand-lambda*",0};
200 struct scm scm_vm_macro_expand_set_x = {TSPECIAL, "*vm:core:macro-expand-set!*",0};
201 struct scm scm_vm_begin_expand_primitive_load = {TSPECIAL, "*vm:core:begin-expand-primitive-load*",0};
202 struct scm scm_vm_begin_primitive_load = {TSPECIAL, "*vm:core:begin-primitive-load*",0};
203 struct scm scm_vm_macro_expand_car = {TSPECIAL, "*vm:core:macro-expand-car*",0};
204 struct scm scm_vm_macro_expand_cdr = {TSPECIAL, "*vm:macro-expand-cdr*",0};
205 struct scm scm_vm_begin_expand = {TSPECIAL, "*vm:begin-expand*",0};
206 struct scm scm_vm_begin_expand_eval = {TSPECIAL, "*vm:begin-expand-eval*",0};
207 struct scm scm_vm_begin_expand_macro = {TSPECIAL, "*vm:begin-expand-macro*",0};
208 struct scm scm_vm_begin = {TSPECIAL, "*vm-begin*",0};
209 struct scm scm_vm_begin_read_input_file = {TSPECIAL, "*vm-begin-read-input-file*",0};
210 struct scm scm_vm_begin_eval = {TSPECIAL, "*vm:begin-eval*",0};
211 struct scm scm_vm_if = {TSPECIAL, "*vm-if*",0};
212 struct scm scm_vm_if_expr = {TSPECIAL, "*vm-if-expr*",0};
213 struct scm scm_vm_call_with_values2 = {TSPECIAL, "*vm-call-with-values2*",0};
214 struct scm scm_vm_call_with_current_continuation2 = {TSPECIAL, "*vm-call-with-current-continuation2*",0};
215 struct scm scm_vm_return = {TSPECIAL, "*vm-return*",0};
216
217 struct scm scm_symbol_gnuc = {TSYMBOL, "%gnuc",0};
218 struct scm scm_symbol_mesc = {TSYMBOL, "%mesc",0};
219
220 struct scm scm_test = {TSYMBOL, "test",0};
221
222 #if !_POSIX_SOURCE
223 #include "mes.mes.symbols.h"
224 #else
225 #include "mes.symbols.h"
226 #endif
227
228 SCM tmp;
229 SCM tmp_num;
230 SCM tmp_num2;
231
232 struct function g_functions[200];
233 int g_function = 0;
234
235 #if !__GNUC__ || !_POSIX_SOURCE
236 #include "gc.mes.h"
237 #include "lib.mes.h"
238 #include "math.mes.h"
239 #include "mes.mes.h"
240 #include "posix.mes.h"
241 #include "reader.mes.h"
242 #include "vector.mes.h"
243 #else
244 #include "gc.h"
245 #include "lib.h"
246 #include "math.h"
247 #include "mes.h"
248 #include "posix.h"
249 #include "reader.h"
250 #include "vector.h"
251 #endif
252
253 #define TYPE(x) g_cells[x].type
254 #define CAR(x) g_cells[x].car
255 #define CDR(x) g_cells[x].cdr
256
257 #define NTYPE(x) g_news[x].type
258 #define NCAR(x) g_news[x].car
259 #define NCDR(x) g_news[x].cdr
260
261 #if !_POSIX_SOURCE
262 #define LENGTH(x) g_cells[x].car
263 #define REF(x) g_cells[x].car
264 #define STRING(x) g_cells[x].car
265
266 #define CLOSURE(x) g_cells[x].cdr
267 #define CONTINUATION(x) g_cells[x].cdr
268
269 #define FUNCTION(x) g_functions[g_cells[x].cdr]
270 #define MACRO(x) g_cells[x].cdr
271 #define VALUE(x) g_cells[x].cdr
272 #define VECTOR(x) g_cells[x].cdr
273
274 #define NLENGTH(x) g_news[x].car
275
276 #define NVALUE(x) g_news[x].cdr
277 #define NVECTOR(x) g_news[x].cdr
278
279 #else
280 #define CONTINUATION(x) g_cells[x].cdr
281 #define HITS(x) g_cells[x].hits
282 #define LENGTH(x) g_cells[x].length
283 #define NAME(x) g_cells[x].name
284 #define STRING(x) g_cells[x].string
285 #define CLOSURE(x) g_cells[x].closure
286 #define MACRO(x) g_cells[x].macro
287 #define REF(x) g_cells[x].ref
288 #define VALUE(x) g_cells[x].value
289 #define VECTOR(x) g_cells[x].vector
290 #define FUNCTION(x) g_functions[g_cells[x].function]
291
292 #define NLENGTH(x) g_news[x].length
293
294 #define NVALUE(x) g_news[x].value
295 #define NVECTOR(x) g_news[x].vector
296 #endif
297
298 #define MAKE_CHAR(n) make_cell_ (tmp_num_ (TCHAR), 0, tmp_num2_ (n))
299 #define MAKE_CONTINUATION(n) make_cell_ (tmp_num_ (TCONTINUATION), n, g_stack)
300 #define MAKE_NUMBER(n) make_cell_ (tmp_num_ (TNUMBER), 0, tmp_num2_ (n))
301 #define MAKE_REF(n) make_cell_ (tmp_num_ (TREF), n, 0)
302 #define MAKE_STRING(x) make_cell_ (tmp_num_ (TSTRING), x, 0)
303 #define MAKE_KEYWORD(x) make_cell_ (tmp_num_ (TKEYWORD), x, 0)
304 #define MAKE_MACRO(name, x) make_cell_ (tmp_num_ (TMACRO), STRING (name), x)
305
306 #define CAAR(x) CAR (CAR (x))
307 #define CADR(x) CAR (CDR (x))
308 #define CDAR(x) CDR (CAR (x))
309 #define CDDR(x) CDR (CDR (x))
310 #define CADAR(x) CAR (CDR (CAR (x)))
311 #define CADDR(x) CAR (CDR (CDR (x)))
312 #define CDADAR(x) CAR (CDR (CAR (CDR (x))))
313
314 SCM
315 alloc (int n)
316 {
317   assert (g_free + n < ARENA_SIZE);
318   SCM x = g_free;
319   g_free += n;
320   return x;
321 }
322
323 SCM
324 tmp_num_ (int x)
325 {
326   VALUE (tmp_num) = x;
327   return tmp_num;
328 }
329
330 SCM
331 tmp_num2_ (int x)
332 {
333   VALUE (tmp_num2) = x;
334   return tmp_num2;
335 }
336
337 SCM
338 make_cell_ (SCM type, SCM car, SCM cdr)
339 {
340   SCM x = alloc (1);
341   assert (TYPE (type) == TNUMBER);
342   TYPE (x) = VALUE (type);
343   if (VALUE (type) == TCHAR || VALUE (type) == TNUMBER) {
344     if (car) CAR (x) = CAR (car);
345     if (cdr) CDR(x) = CDR(cdr);
346   }
347   else if (VALUE (type) == TFUNCTION) {
348     if (car) CAR (x) = car;
349     if (cdr) CDR(x) = CDR(cdr);
350   }
351   else {
352     CAR (x) = car;
353     CDR(x) = cdr;
354   }
355   return x;
356 }
357
358 SCM
359 make_symbol_ (SCM s) ///((internal))
360 {
361   VALUE (tmp_num) = TSYMBOL;
362   SCM x = make_cell_ (tmp_num, s, 0);
363   g_symbols = cons (x, g_symbols);
364   return x;
365 }
366
367 SCM
368 list_of_char_equal_p (SCM a, SCM b) ///((internal))
369 {
370   while (a != cell_nil && b != cell_nil && VALUE (CAR (a)) == VALUE (CAR (b))) {
371     assert (TYPE (CAR (a)) == TCHAR);
372     assert (TYPE (CAR (b)) == TCHAR);
373     a = CDR (a);
374     b = CDR (b);
375   }
376   return (a == cell_nil && b == cell_nil) ? cell_t : cell_f;
377 }
378
379 SCM
380 lookup_symbol_ (SCM s)
381 {
382   SCM x = g_symbols;
383   while (x) {
384     if (list_of_char_equal_p (STRING (CAR (x)), s) == cell_t) break;
385     x = CDR (x);
386   }
387   if (x) x = CAR (x);
388   if (!x) x = make_symbol_ (s);
389   return x;
390 }
391
392 SCM
393 type_ (SCM x)
394 {
395   return MAKE_NUMBER (TYPE (x));
396 }
397
398 SCM
399 car_ (SCM x)
400 {
401   return (TYPE (x) != TCONTINUATION
402           && (TYPE (CAR (x)) == TPAIR // FIXME: this is weird
403               || TYPE (CAR (x)) == TREF
404               || TYPE (CAR (x)) == TSPECIAL
405               || TYPE (CAR (x)) == TSYMBOL
406               || TYPE (CAR (x)) == TSTRING)) ? CAR (x) : MAKE_NUMBER (CAR (x));
407 }
408
409 SCM
410 cdr_ (SCM x)
411 {
412   return (TYPE (CDR (x)) == TPAIR
413           || TYPE (CDR (x)) == TREF
414           || TYPE (CAR (x)) == TSPECIAL
415           || TYPE (CDR (x)) == TSYMBOL
416           || TYPE (CDR (x)) == TSTRING) ? CDR (x) : MAKE_NUMBER (CDR (x));
417 }
418
419 SCM
420 arity_ (SCM x)
421 {
422   assert (TYPE (x) == TFUNCTION);
423   return MAKE_NUMBER (FUNCTION (x).arity);
424 }
425
426 SCM
427 cons (SCM x, SCM y)
428 {
429   VALUE (tmp_num) = TPAIR;
430   return make_cell_ (tmp_num, x, y);
431 }
432
433 SCM
434 car (SCM x)
435 {
436 #if !__MESC_MES__
437   if (TYPE (x) != TPAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_car));
438 #endif
439   return CAR (x);
440 }
441
442 SCM
443 cdr (SCM x)
444 {
445 #if !__MESC_MES__
446   if (TYPE (x) != TPAIR) error (cell_symbol_not_a_pair, cons (x, cell_symbol_cdr));
447 #endif
448   return CDR (x);
449 }
450
451 SCM
452 list (SCM x) ///((arity . n))
453 {
454   return x;
455 }
456
457 SCM
458 null_p (SCM x)
459 {
460   return x == cell_nil ? cell_t : cell_f;
461 }
462
463 SCM
464 eq_p (SCM x, SCM y)
465 {
466   return (x == y
467           || ((TYPE (x) == TKEYWORD && TYPE (y) == TKEYWORD
468                && STRING (x) == STRING (y)))
469           || (TYPE (x) == TCHAR && TYPE (y) == TCHAR
470               && VALUE (x) == VALUE (y))
471           || (TYPE (x) == TNUMBER && TYPE (y) == TNUMBER
472               && VALUE (x) == VALUE (y)))
473     ? cell_t : cell_f;
474 }
475
476 SCM
477 values (SCM x) ///((arity . n))
478 {
479   SCM v = cons (0, x);
480   TYPE (v) = TVALUES;
481   return v;
482 }
483
484 SCM
485 acons (SCM key, SCM value, SCM alist)
486 {
487   return cons (cons (key, value), alist);
488 }
489
490 SCM
491 length (SCM x)
492 {
493   int n = 0;
494   while (x != cell_nil)
495     {
496       n++;
497       if (TYPE (x) != TPAIR) return MAKE_NUMBER (-1);
498       x = CDR (x);
499     }
500   return MAKE_NUMBER (n);
501 }
502
503 SCM apply (SCM, SCM, SCM);
504
505 SCM
506 error (SCM key, SCM x)
507 {
508 #if !__MESC_MES__
509   SCM throw;
510   if ((throw = assq_ref_env (cell_symbol_throw, r0)) != cell_undefined)
511     return apply (throw, cons (key, cons (x, cell_nil)), r0);
512 #endif
513   display_error_ (key);
514   eputs (": ");
515   write_error_ (x);
516   eputs ("\n");
517   exit (1);
518 }
519
520 SCM
521 cstring_to_list (char const* s)
522 {
523   SCM p = cell_nil;
524   int i = strlen (s);
525   while (i--)
526     p = cons (MAKE_CHAR (s[i]), p);
527   return p;
528 }
529
530 // \f extra lib
531 SCM
532 assert_defined (SCM x, SCM e) ///((internal))
533 {
534   if (e == cell_undefined) return error (cell_symbol_unbound_variable, x);
535   return e;
536 }
537
538 SCM
539 check_formals (SCM f, SCM formals, SCM args) ///((internal))
540 {
541   int flen = (TYPE (formals) == TNUMBER) ? VALUE (formals) : VALUE (length (formals));
542   int alen = VALUE (length (args));
543   if (alen != flen && alen != -1 && flen != -1)
544     {
545       char *s = "apply: wrong number of arguments; expected: ";
546       eputs (s);
547       eputs (itoa (flen));
548       eputs (", got: ");
549       eputs (itoa (alen));
550       eputs ("\n");
551       display_error_ (f);
552       SCM e = MAKE_STRING (cstring_to_list (s));
553       return error (cell_symbol_wrong_number_of_args, cons (e, f));
554     }
555   return cell_unspecified;
556 }
557
558 SCM
559 check_apply (SCM f, SCM e) ///((internal))
560 {
561   char* type = 0;
562   if (f == cell_f || f == cell_t) type = "bool";
563   if (f == cell_nil) type = "nil";
564   if (f == cell_unspecified) type = "*unspecified*";
565   if (f == cell_undefined) type = "*undefined*";
566   if (TYPE (f) == TCHAR) type = "char";
567   if (TYPE (f) == TNUMBER) type = "number";
568   if (TYPE (f) == TSTRING) type = "string";
569
570   if (type)
571     {
572       char *s = "cannot apply: ";
573       eputs (s);
574       eputs (type);
575       eputs ("[");
576       write_error_ (e);
577       eputs ("]\n");
578       SCM e = MAKE_STRING (cstring_to_list (s));
579       return error (cell_symbol_wrong_type_arg, cons (e, f));
580     }
581   return cell_unspecified;
582 }
583
584 SCM
585 gc_push_frame () ///((internal))
586 {
587   SCM frame = cons (r1, cons (r2, cons (r3, cons (r0, cell_nil))));
588   g_stack = cons (frame, g_stack);
589   return g_stack;
590 }
591
592 SCM
593 append2 (SCM x, SCM y)
594 {
595   if (x == cell_nil) return y;
596   if (TYPE (x) != TPAIR) error (cell_symbol_not_a_pair, cons (x, cell_append2));
597   return cons (car (x), append2 (cdr (x), y));
598 }
599
600 SCM
601 pairlis (SCM x, SCM y, SCM a)
602 {
603   if (x == cell_nil)
604     return a;
605   if (TYPE (x) != TPAIR)
606     return cons (cons (x, y), a);
607   return cons (cons (car (x), car (y)),
608                pairlis (cdr (x), cdr (y), a));
609 }
610
611 SCM
612 call (SCM fn, SCM x)
613 {
614   if ((FUNCTION (fn).arity > 0 || FUNCTION (fn).arity == -1)
615       && x != cell_nil && TYPE (CAR (x)) == TVALUES)
616     x = cons (CADAR (x), CDR (x));
617   if ((FUNCTION (fn).arity > 1 || FUNCTION (fn).arity == -1)
618       && x != cell_nil && TYPE (CDR (x)) == TPAIR && TYPE (CADR (x)) == TVALUES)
619     x = cons (CAR (x), cons (CDADAR (x), CDR (x)));
620   switch (FUNCTION (fn).arity)
621     {
622 #if __MESC__ || !_POSIX_SOURCE
623     case 0: return (FUNCTION (fn).function) ();
624     case 1: return ((SCM(*)(SCM))(FUNCTION (fn).function)) (CAR (x));
625     case 2: return ((SCM(*)(SCM,SCM))(FUNCTION (fn).function)) (CAR (x), CADR (x));
626     case 3: return ((SCM(*)(SCM,SCM,SCM))(FUNCTION (fn).function)) (CAR (x), CADR (x), CAR (CDDR (x)));
627     case -1: return ((SCM(*)(SCM))(FUNCTION (fn).function)) (x);
628     default: return ((SCM(*)(SCM))(FUNCTION (fn).function)) (x);
629 #else
630     case 0: return FUNCTION (fn).function0 ();
631     case 1: return FUNCTION (fn).function1 (CAR (x));
632     case 2: return FUNCTION (fn).function2 (CAR (x), CADR (x));
633     case 3: return FUNCTION (fn).function3 (CAR (x), CADR (x), CAR (CDDR (x)));
634     case -1: return FUNCTION (fn).functionn (x);
635 #endif
636     }
637
638   return cell_unspecified;
639 }
640
641 SCM
642 assq (SCM x, SCM a)
643 {
644   switch (TYPE (x))
645     {
646     case TCHAR:
647     case TNUMBER:
648       {
649         SCM v = VALUE (x);
650         while (a != cell_nil && v != VALUE (CAAR (a))) a = CDR (a); break;
651       }
652     case TKEYWORD:
653       {
654         SCM v = STRING (x);
655         while (a != cell_nil && v != STRING (CAAR (a))) a = CDR (a); break;
656       }
657     // case TSYMBOL:
658     // case TSPECIAL:
659     default:
660       while (a != cell_nil && x != CAAR (a)) a = CDR (a); break;
661     }
662   return a != cell_nil ? CAR (a) : cell_f;
663 }
664
665 SCM
666 assq_ref_env (SCM x, SCM a)
667 {
668   x = assq (x, a);
669   if (x == cell_f) return cell_undefined;
670   return CDR (x);
671 }
672
673 SCM
674 set_car_x (SCM x, SCM e)
675 {
676   if (TYPE (x) != TPAIR) error (cell_symbol_not_a_pair, cons (x, cell_set_car_x));
677   CAR (x) = e;
678   return cell_unspecified;
679 }
680
681 SCM
682 set_cdr_x (SCM x, SCM e)
683 {
684   if (TYPE (x) != TPAIR) error (cell_symbol_not_a_pair, cons (x, cell_set_cdr_x));
685   CDR (x) = e;
686   return cell_unspecified;
687 }
688
689 SCM
690 set_env_x (SCM x, SCM e, SCM a)
691 {
692   SCM p = assert_defined (x, assq (x, a));
693   if (TYPE (p) != TPAIR) error (cell_symbol_not_a_pair, cons (p, x));
694   return set_cdr_x (p, e);
695 }
696
697 SCM
698 call_lambda (SCM e, SCM x, SCM aa, SCM a) ///((internal))
699 {
700   SCM cl = cons (cons (cell_closure, x), x);
701   r1 = e;
702   r0 = cl;
703   return cell_unspecified;
704 }
705
706 SCM
707 make_closure_ (SCM args, SCM body, SCM a) ///((internal))
708 {
709   return make_cell_ (tmp_num_ (TCLOSURE), cell_f, cons (cons (cell_circular, a), cons (args, body)));
710 }
711
712 SCM
713 lookup_macro_ (SCM x, SCM a) ///((internal))
714 {
715   if (TYPE (x) != TSYMBOL) return cell_f;
716   SCM m = assq_ref_env (x, a);
717   if (TYPE (m) == TMACRO) return MACRO (m);
718   return cell_f;
719 }
720
721 SCM
722 push_cc (SCM p1, SCM p2, SCM a, SCM c) ///((internal))
723 {
724   SCM x = r3;
725   r3 = c;
726   r2 = p2;
727   gc_push_frame ();
728   r1 = p1;
729   r0 = a;
730   r3 = x;
731   return cell_unspecified;
732 }
733
734 SCM
735 gc_peek_frame () ///((internal))
736 {
737   SCM frame = CAR (g_stack);
738   r1 = CAR (frame);
739   r2 = CADR (frame);
740   r3 = CAR (CDDR (frame));
741   r0 = CADR (CDDR (frame));
742   return frame;
743 }
744
745 SCM
746 gc_pop_frame () ///((internal))
747 {
748   SCM frame = gc_peek_frame (g_stack);
749   g_stack = CDR (g_stack);
750   return frame;
751 }
752
753 SCM
754 eval_apply ()
755 {
756   int expanding_p = 0;
757  eval_apply:
758   gc_check ();
759   switch (r3)
760     {
761     case cell_vm_evlis: goto evlis;
762     case cell_vm_evlis2: goto evlis2;
763     case cell_vm_evlis3: goto evlis3;
764     case cell_vm_apply: goto apply;
765     case cell_vm_apply2: goto apply2;
766     case cell_vm_eval: goto eval;
767 #if MES_FIXED_PRIMITIVES
768     case cell_vm_eval_car: goto eval_car;
769     case cell_vm_eval_cdr: goto eval_cdr;
770     case cell_vm_eval_cons: goto eval_cons;
771     case cell_vm_eval_null_p: goto eval_null_p;
772 #endif
773     case cell_vm_eval_define: goto eval_define;
774     case cell_vm_eval_set_x: goto eval_set_x;
775     case cell_vm_eval_macro_expand_eval: goto eval_macro_expand_eval;
776     case cell_vm_eval_macro_expand_expand: goto eval_macro_expand_expand;
777     case cell_vm_eval_check_func: goto eval_check_func;
778     case cell_vm_eval2: goto eval2;
779     case cell_vm_macro_expand: goto macro_expand;
780     case cell_vm_macro_expand_define: goto macro_expand_define;
781     case cell_vm_macro_expand_define_macro: goto macro_expand_define_macro;
782     case cell_vm_macro_expand_lambda: goto macro_expand_lambda;
783     case cell_vm_macro_expand_set_x: goto macro_expand_set_x;
784     case cell_vm_macro_expand_car: goto macro_expand_car;
785     case cell_vm_macro_expand_cdr: goto macro_expand_cdr;
786     case cell_vm_begin: goto begin;
787     case cell_vm_begin_eval: goto begin_eval;
788     case cell_vm_begin_primitive_load: goto begin_primitive_load;
789     case cell_vm_begin_expand: goto begin_expand;
790     case cell_vm_begin_expand_eval: goto begin_expand_eval;
791     case cell_vm_begin_expand_macro: goto begin_expand_macro;
792     case cell_vm_begin_expand_primitive_load: goto begin_expand_primitive_load;
793     case cell_vm_if: goto vm_if;
794     case cell_vm_if_expr: goto if_expr;
795     case cell_vm_call_with_current_continuation2: goto call_with_current_continuation2;
796     case cell_vm_call_with_values2: goto call_with_values2;
797     case cell_vm_return: goto vm_return;
798     case cell_unspecified: return r1;
799     default:
800       assert (0);
801     }
802
803   SCM x = cell_nil;
804  evlis:
805   gc_check ();
806   if (r1 == cell_nil) goto vm_return;
807   if (TYPE (r1) != TPAIR) goto eval;
808   push_cc (CAR (r1), r1, r0, cell_vm_evlis2);
809   goto eval;
810  evlis2:
811   push_cc (CDR (r2), r1, r0, cell_vm_evlis3);
812   goto evlis;
813  evlis3:
814   r1 = cons (r2, r1);
815   goto vm_return;
816
817  apply:
818   gc_check ();
819   switch (TYPE (CAR (r1)))
820     {
821     case TFUNCTION: {
822       check_formals (CAR (r1), MAKE_NUMBER (FUNCTION (CAR (r1)).arity), CDR (r1));
823       r1 = call (CAR (r1), CDR (r1)); /// FIXME: move into eval_apply
824       goto vm_return;
825     }
826     case TCLOSURE:
827       {
828         SCM cl = CLOSURE (CAR (r1));
829         SCM formals = CADR (cl);
830         SCM body = CDDR (cl);
831         SCM aa = CDAR (cl);
832         aa = CDR (aa);
833         check_formals (CAR (r1), formals, CDR (r1));
834         SCM p = pairlis (formals, CDR (r1), aa);
835         call_lambda (body, p, aa, r0);
836         goto begin;
837       }
838       case TCONTINUATION:
839         {
840           x = r1;
841           g_stack = CONTINUATION (CAR (r1));
842           gc_pop_frame ();
843           r1 = CADR (x);
844           goto eval_apply;
845         }
846     case TSPECIAL:
847       {
848         switch (CAR (r1))
849           {
850           case cell_vm_apply:
851             {
852               push_cc (cons (CADR (r1), CADDR (r1)), r1, r0, cell_vm_return);
853               goto apply;
854             }
855           case cell_vm_eval:
856             {
857               push_cc (CADR (r1), r1, CADDR (r1), cell_vm_return);
858               goto eval;
859             }
860           case cell_call_with_current_continuation:
861             {
862               r1 = CDR (r1);
863               goto call_with_current_continuation;
864             }
865           default: check_apply (cell_f, CAR (r1));
866           }
867       }
868     case TSYMBOL:
869       {
870         if (CAR (r1) == cell_symbol_call_with_values)
871           {
872             r1 = CDR (r1);
873             goto call_with_values;
874           }
875         if (CAR (r1) == cell_symbol_current_module)
876           {
877             r1 = r0;
878             goto vm_return;
879           }
880         break;
881       }
882     case TPAIR:
883       {
884         switch (CAAR (r1))
885           {
886           case cell_symbol_lambda:
887             {
888               SCM formals = CADR (CAR (r1));
889               SCM body = CDDR (CAR (r1));
890               SCM p = pairlis (formals, CDR (r1), r0);
891               check_formals (r1, formals, CDR (r1));
892               call_lambda (body, p, p, r0);
893               goto begin;
894             }
895           }
896       }
897     }
898   push_cc (CAR (r1), r1, r0, cell_vm_apply2);
899   goto eval;
900  apply2:
901   check_apply (r1, CAR (r2));
902   r1 = cons (r1, CDR (r2));
903   goto apply;
904
905  eval:
906   gc_check ();
907   switch (TYPE (r1))
908     {
909     case TPAIR:
910       {
911         switch (CAR (r1))
912           {
913 #if MES_FIXED_PRIMITIVES
914           case cell_symbol_car:
915             {
916               push_cc (CADR (r1), r1, r0, cell_vm_eval_car); goto eval;
917             eval_car:
918               x = r1; gc_pop_frame (); r1 = CAR (x); goto eval_apply;
919             }
920           case cell_symbol_cdr:
921             {
922               push_cc (CADR (r1), r1, r0, cell_vm_eval_cdr); goto eval;
923             eval_cdr:
924               x = r1; gc_pop_frame (); r1 = CDR (x); goto eval_apply;
925             }
926           case cell_symbol_cons: {
927             push_cc (CDR (r1), r1, r0, cell_vm_eval_cons); goto evlis;
928             eval_cons:
929             x = r1;
930             gc_pop_frame ();
931             r1 = cons (CAR (x), CADR (x));
932             goto eval_apply;
933           }
934           case cell_symbol_null_p:
935             {
936               push_cc (CADR (r1), r1, r0, cell_vm_eval_null_p);
937               goto eval;
938             eval_null_p:
939               x = r1; gc_pop_frame (); r1 = null_p (x); goto eval_apply;
940             }
941 #else
942           eval_car:;
943           eval_cdr:;
944           eval_cons:;
945           eval_null_p:;
946             
947 #endif // MES_FIXED_PRIMITIVES
948           case cell_symbol_quote:
949             {
950               x = r1; gc_pop_frame (); r1 = CADR (x); goto eval_apply;
951             }
952           case cell_symbol_begin: goto begin;
953           case cell_symbol_lambda:
954             {
955               r1 = make_closure_ (CADR (r1), CDDR (r1), assq (cell_closure, r0));
956               goto vm_return;
957             }
958           case cell_symbol_if: {r1=CDR (r1); goto vm_if;}
959           case cell_symbol_set_x:
960             {
961               push_cc (CAR (CDDR (r1)), r1, r0, cell_vm_eval_set_x);
962               goto eval;
963             eval_set_x:
964               x = r2;
965               r1 = set_env_x (CADR (x), r1, r0);
966               goto vm_return;
967             }
968           case cell_vm_macro_expand:
969             {
970               push_cc (CADR (r1), r1, r0, cell_vm_eval_macro_expand_eval);
971               goto eval;
972             eval_macro_expand_eval:
973               push_cc (r1, r2, r0, cell_vm_eval_macro_expand_expand);
974               expanding_p++;
975               goto macro_expand;
976             eval_macro_expand_expand:
977               expanding_p--;
978               goto vm_return;
979             }
980           default:
981             {
982               if (TYPE (r1) == TPAIR
983                   && (CAR (r1) == cell_symbol_define
984                     || CAR (r1) == cell_symbol_define_macro))
985                 {
986                   r2 = r1;
987                   if (TYPE (CADR (r1)) != TPAIR)
988                     {
989                       push_cc (CAR (CDDR (r1)), r2, cons (cons (CADR (r1), CADR (r1)), r0), cell_vm_eval_define);
990                       goto eval;
991                     }
992                   else
993                     {
994                       SCM p = pairlis (CADR (r1), CADR (r1), r0);
995                       SCM args = CDR (CADR (r1));
996                       SCM body = CDDR (r1);
997                       r1 = cons (cell_symbol_lambda, cons (args, body));
998                       push_cc (r1, r2, p, cell_vm_eval_define);
999                       goto eval;
1000                     }
1001                 eval_define:;
1002                   SCM name = CADR (r2);
1003                   if (TYPE (CADR (r2)) == TPAIR) name = CAR (name);
1004                   if (CAR (r2) == cell_symbol_define_macro)
1005                     r1 = MAKE_MACRO (name, r1);
1006                   SCM entry = cons (name, r1);
1007                   SCM aa = cons (entry, cell_nil);
1008                   set_cdr_x (aa, cdr (r0));
1009                   set_cdr_x (r0, aa);
1010                   SCM cl = assq (cell_closure, r0);
1011                   set_cdr_x (cl, aa);
1012                   //r1 = entry;
1013                   r1 = cell_unspecified;
1014                   goto vm_return;
1015                 }
1016               push_cc (CAR (r1), r1, r0, cell_vm_eval_check_func); goto eval;
1017             eval_check_func:
1018               push_cc (CDR (r2), r2, r0, cell_vm_eval2); goto evlis;
1019             eval2:
1020               r1 = cons (CAR (r2), r1);
1021               goto apply;
1022           }
1023           }
1024       }
1025     case TSYMBOL:
1026       {
1027         r1 = assert_defined (r1, assq_ref_env (r1, r0));
1028         goto vm_return;
1029       }
1030     default: goto vm_return;
1031     }
1032
1033  macro_expand:
1034   {
1035     SCM macro;
1036     SCM expanders;
1037
1038     if (TYPE (r1) != TPAIR || CAR (r1) == cell_symbol_quote)
1039       goto vm_return;
1040
1041     if (TYPE (r1) == TPAIR
1042         && (macro = lookup_macro_ (CAR (r1), r0)) != cell_f)
1043       {
1044         r1 = cons (macro, CDR (r1));
1045         push_cc (r1, cell_nil, r0, cell_vm_macro_expand);
1046         goto apply;
1047       }
1048     if (CAR (r1) == cell_symbol_define
1049         || CAR (r1) == cell_symbol_define_macro)
1050       {
1051         push_cc (CDDR (r1), r1, r0, cell_vm_macro_expand_define);
1052         goto macro_expand;
1053       macro_expand_define:
1054         CDDR (r2) = r1;
1055         r1 = r2;
1056         if (CAR (r1) == cell_symbol_define_macro)
1057           {
1058             push_cc (r1, r1, r0, cell_vm_macro_expand_define_macro);
1059             goto eval;
1060           macro_expand_define_macro:
1061             r1 = r2;
1062           }
1063         goto vm_return;
1064       }
1065
1066     if (CAR (r1) == cell_symbol_lambda)
1067       {
1068         push_cc (CDDR (r1), r1, r0, cell_vm_macro_expand_lambda);
1069         goto macro_expand;
1070       macro_expand_lambda:
1071         CDDR (r2) = r1;
1072         r1 = r2;
1073         goto vm_return;
1074       }
1075
1076     if (CAR (r1) == cell_symbol_set_x)
1077       {
1078         push_cc (CDDR (r1), r1, r0, cell_vm_macro_expand_set_x);
1079         goto macro_expand;
1080       macro_expand_set_x:
1081         CDDR (r2) = r1;
1082         r1 = r2;
1083         goto vm_return;
1084       }
1085
1086     if (TYPE (r1) == TPAIR
1087         && TYPE (CAR (r1)) == TSYMBOL
1088         && CAR (r1) != cell_symbol_begin
1089         && ((expanders = assq_ref_env (cell_symbol_sc_expander_alist, r0)) != cell_undefined)
1090         && ((macro = assq (CAR (r1), expanders)) != cell_f))
1091       {
1092         SCM sc_expand = assq_ref_env (cell_symbol_macro_expand, r0);
1093         r2 = r1;
1094         if (sc_expand != cell_undefined && sc_expand != cell_f)
1095           {
1096             r1 = cons (sc_expand, cons (r1, cell_nil));
1097             goto apply;
1098           }
1099       }
1100
1101     push_cc (CAR (r1), r1, r0, cell_vm_macro_expand_car);
1102     goto macro_expand;
1103
1104   macro_expand_car:
1105     CAR (r2) = r1;
1106     r1 = r2;
1107     if (CDR (r1) == cell_nil)
1108       goto vm_return;
1109
1110     push_cc (CDR (r1), r1, r0, cell_vm_macro_expand_cdr);
1111     goto macro_expand;
1112
1113   macro_expand_cdr:
1114     CDR (r2) = r1;
1115     r1 = r2;
1116
1117     goto vm_return;
1118   }
1119
1120  begin:
1121   x = cell_unspecified;
1122   while (r1 != cell_nil)
1123     {
1124       gc_check ();
1125       if (TYPE (r1) == TPAIR)
1126         {
1127           if (CAAR (r1) == cell_symbol_primitive_load)
1128             {
1129               SCM program = cons (CAR (r1), cell_nil);
1130               push_cc (program, r1, r0, cell_vm_begin_primitive_load);
1131               goto begin_expand;
1132             begin_primitive_load:
1133               CAR (r2) = r1;
1134               r1 = r2;
1135             }
1136         }
1137
1138       if (TYPE (r1) == TPAIR && TYPE (CAR (r1)) == TPAIR)
1139         {
1140           if (CAAR (r1) == cell_symbol_begin)
1141             r1 = append2 (CDAR (r1), CDR (r1));
1142         }
1143       if (CDR (r1) == cell_nil)
1144         {
1145           r1 = CAR (r1);
1146           goto eval;
1147         }
1148       push_cc (CAR (r1), r1, r0, cell_vm_begin_eval);
1149       goto eval;
1150     begin_eval:
1151       x = r1;
1152       r1 = CDR (r2);
1153     }
1154   r1 = x;
1155   goto vm_return;
1156
1157
1158  begin_expand:
1159   x = cell_unspecified;
1160   while (r1 != cell_nil)
1161     {
1162       gc_check ();
1163
1164       if (TYPE (r1) == TPAIR)
1165         {
1166           if (TYPE (CAR (r1)) == TPAIR && CAAR (r1) == cell_symbol_begin)
1167             r1 = append2 (CDAR (r1), CDR (r1));
1168           if (CAAR (r1) == cell_symbol_primitive_load)
1169             {
1170               push_cc (CADR (CAR (r1)), r1, r0, cell_vm_begin_expand_primitive_load);
1171               goto eval; // FIXME: expand too?!
1172             begin_expand_primitive_load:;
1173               SCM input; // = current_input_port ();
1174               if (TYPE (r1) == TNUMBER && VALUE (r1) == 0)
1175                 ;
1176               else if (TYPE (r1) == TSTRING)
1177                 input = set_current_input_port (open_input_file (r1));
1178               else
1179                 assert (0);
1180               
1181               push_cc (input, r2, r0, cell_vm_return);
1182               x = read_input_file_env (r0);
1183               gc_pop_frame ();
1184               input = r1;
1185               r1 = x;
1186               set_current_input_port (input);
1187               r1 = cons (cell_symbol_begin, r1);
1188               CAR (r2) = r1;
1189               r1 = r2;
1190               continue;
1191             }
1192         }
1193
1194       push_cc (CAR (r1), r1, r0, cell_vm_begin_expand_macro);
1195       expanding_p++;
1196       goto macro_expand;
1197     begin_expand_macro:
1198       expanding_p--;
1199       if (r1 != CAR (r2))
1200         {
1201           CAR (r2) = r1;
1202           r1 = r2;
1203           continue;
1204         }
1205       r1 = r2;
1206
1207       push_cc (CAR (r1), r1, r0, cell_vm_begin_expand_eval);
1208       goto eval;
1209     begin_expand_eval:
1210       x = r1;
1211       r1 = CDR (r2);
1212     }
1213   r1 = x;
1214   goto vm_return;
1215
1216  vm_if:
1217   push_cc (CAR (r1), r1, r0, cell_vm_if_expr);
1218   goto eval;
1219  if_expr:
1220   x = r1;
1221   r1 = r2;
1222   if (x != cell_f)
1223     {
1224       r1 = CADR (r1);
1225       goto eval;
1226     }
1227   if (CDDR (r1) != cell_nil)
1228     {
1229       r1 = CAR (CDDR (r1));
1230       goto eval;
1231     }
1232   r1 = cell_unspecified;
1233   goto vm_return;
1234
1235  call_with_current_continuation:
1236   gc_push_frame ();
1237   x = MAKE_CONTINUATION (g_continuations++);
1238   gc_pop_frame ();
1239   push_cc (cons (CAR (r1), cons (x, cell_nil)), x, r0, cell_vm_call_with_current_continuation2);
1240   goto apply;
1241  call_with_current_continuation2:
1242   CONTINUATION (r2) = g_stack;
1243   goto vm_return;
1244
1245  call_with_values:
1246   push_cc (cons (CAR (r1), cell_nil), r1, r0, cell_vm_call_with_values2);
1247   goto apply;
1248  call_with_values2:
1249   if (TYPE (r1) == TVALUES)
1250     r1 = CDR (r1);
1251   r1 = cons (CADR (r2), r1);
1252   goto apply;
1253
1254  vm_return:
1255   x = r1;
1256   gc_pop_frame ();
1257   r1 = x;
1258   goto eval_apply;
1259 }
1260
1261 SCM
1262 apply (SCM f, SCM x, SCM a) ///((internal))
1263 {
1264   push_cc (cons (f, x), cell_unspecified, r0, cell_unspecified);
1265   r3 = cell_vm_apply;
1266   return eval_apply ();
1267 }
1268
1269 SCM
1270 mes_g_stack (SCM a) ///((internal))
1271 {
1272   r0 = a;
1273   r1 = MAKE_CHAR (0);
1274   r2 = MAKE_CHAR (0);
1275   r3 = MAKE_CHAR (0);
1276   g_stack = cons (cell_nil, cell_nil);
1277   return r0;
1278 }
1279
1280 //\f Environment setup
1281
1282 SCM
1283 make_tmps (struct scm* cells)
1284 {
1285   tmp = g_free++;
1286   cells[tmp].type = TCHAR;
1287   tmp_num = g_free++;
1288   cells[tmp_num].type = TNUMBER;
1289   tmp_num2 = g_free++;
1290   cells[tmp_num2].type = TNUMBER;
1291   return 0;
1292 }
1293
1294 #include "posix.c"
1295 #include "math.c"
1296 #include "lib.c"
1297
1298 //\f Jam Collector
1299 SCM g_symbol_max;
1300
1301 SCM
1302 gc_init_cells () ///((internal))
1303 {
1304   g_cells = (struct scm *)malloc (2*ARENA_SIZE*sizeof (struct scm));
1305
1306   TYPE (0) = TVECTOR;
1307   LENGTH (0) = 1000;
1308   VECTOR (0) = 0;
1309 #if __MESC__
1310   g_cells += sizeof (struct scm);
1311 #else
1312   g_cells++;
1313 #endif
1314   TYPE (0) = TCHAR;
1315   VALUE (0) = 'c';
1316   return 0;
1317 }
1318
1319 SCM
1320 gc_init_news () ///((internal))
1321 {
1322 #if __MESC__
1323   char *p = g_cells;
1324   p -= sizeof (struct scm);
1325   p += ARENA_SIZE * sizeof (struct scm);
1326   g_news = p;
1327 #else
1328   g_news = g_cells-1 + ARENA_SIZE;
1329 #endif
1330
1331   NTYPE (0) = TVECTOR;
1332   NLENGTH (0) = 1000;
1333   NVECTOR (0) = 0;
1334 #if __MESC__
1335   g_news += sizeof (struct scm);
1336 #else
1337   g_news++;
1338 #endif
1339   NTYPE (0) = TCHAR;
1340   NVALUE (0) = 'n';
1341   return 0;
1342 }
1343
1344 SCM
1345 mes_symbols () ///((internal))
1346 {
1347   gc_init_cells ();
1348   gc_init_news ();
1349
1350 #if !_POSIX_SOURCE
1351 #include "mes.mes.symbols.i"
1352 #else
1353 #include "mes.symbols.i"
1354 #endif
1355
1356   g_symbol_max = g_free;
1357   make_tmps (g_cells);
1358
1359   g_symbols = 0;
1360   for (int i=1; i<g_symbol_max; i++)
1361     g_symbols = cons (i, g_symbols);
1362
1363   SCM a = cell_nil;
1364
1365 #if !_POSIX_SOURCE
1366 #include "mes.mes.symbol-names.i"
1367 #else
1368 #include "mes.symbol-names.i"
1369 #endif
1370
1371   a = acons (cell_symbol_mes_version, MAKE_STRING (cstring_to_list (VERSION)), a);
1372   a = acons (cell_symbol_mes_prefix, MAKE_STRING (cstring_to_list (PREFIX)), a);
1373
1374   a = acons (cell_symbol_dot, cell_dot, a);
1375   a = acons (cell_symbol_begin, cell_begin, a);
1376   a = acons (cell_symbol_call_with_values, cell_symbol_call_with_values, a);
1377   a = acons (cell_symbol_current_module, cell_symbol_current_module, a);
1378   a = acons (cell_symbol_call_with_current_continuation, cell_call_with_current_continuation, a);
1379   a = acons (cell_symbol_sc_expand, cell_f, a);
1380
1381 #if __GNUC__
1382   a = acons (cell_symbol_gnuc, cell_t, a);
1383   a = acons (cell_symbol_mesc, cell_f, a);
1384 #else
1385   a = acons (cell_symbol_gnuc, cell_f, a);
1386   a = acons (cell_symbol_mesc, cell_t, a);
1387 #endif
1388   a = acons (cell_closure, a, a);
1389
1390   return a;
1391 }
1392
1393 SCM
1394 mes_environment () ///((internal))
1395 {
1396   SCM a = mes_symbols ();
1397   return mes_g_stack (a);
1398 }
1399
1400 SCM
1401 mes_builtins (SCM a) ///((internal))
1402 {
1403 #if !__GNUC__ || !_POSIX_SOURCE
1404 #include "mes.mes.i"
1405
1406 // Do not sort: Order of these includes define builtins
1407 #include "posix.mes.i"
1408 #include "math.mes.i"
1409 #include "lib.mes.i"
1410 #include "vector.mes.i"
1411 #include "gc.mes.i"
1412 #include "reader.mes.i"
1413
1414 #include "gc.mes.environment.i"
1415 #include "lib.mes.environment.i"
1416 #include "math.mes.environment.i"
1417 #include "mes.mes.environment.i"
1418 #include "posix.mes.environment.i"
1419 #include "reader.mes.environment.i"
1420 #include "vector.mes.environment.i"
1421 #else
1422 #include "mes.i"
1423
1424 // Do not sort: Order of these includes define builtins
1425 #include "posix.i"
1426 #include "math.i"
1427 #include "lib.i"
1428 #include "vector.i"
1429 #include "gc.i"
1430 #include "reader.i"
1431
1432 #include "gc.environment.i"
1433 #include "lib.environment.i"
1434 #include "math.environment.i"
1435 #include "mes.environment.i"
1436 #include "posix.environment.i"
1437 #include "reader.environment.i"
1438 #include "vector.environment.i"
1439 #endif
1440
1441   if (g_debug > 1)
1442     {
1443       fputs ("functions: ", STDERR);
1444       fputs (itoa (g_function), STDERR);
1445       fputs ("\n", STDERR);
1446       for (int i = 0; i < g_function; i++)
1447         {
1448           fputs ("[", STDERR);
1449           fputs (itoa (i), STDERR);
1450           fputs ("]: ", STDERR);
1451           fputs (g_functions[i].name, STDERR);
1452           fputs ("\n", STDERR);
1453         }
1454       fputs ("\n", STDERR);
1455     }
1456
1457   return a;
1458 }
1459
1460 SCM read_input_file_env (SCM);
1461
1462 SCM
1463 load_env (SCM a) ///((internal))
1464 {
1465   r0 = a;
1466   g_stdin = -1;
1467   char boot[128];
1468   char buf[128];
1469   if (getenv ("MES_BOOT"))
1470     strcpy (boot, getenv ("MES_BOOT"));
1471   else
1472     strcpy (boot, "boot-0.scm");
1473   if (getenv ("MES_PREFIX"))
1474     {
1475       strcpy (buf, getenv ("MES_PREFIX"));
1476       strcpy (buf + strlen (buf), "/module");
1477       strcpy (buf + strlen (buf), "/mes/");
1478       strcpy (buf + strlen (buf), boot);
1479       if (getenv ("MES_DEBUG"))
1480         {
1481           eputs ("MES_PREFIX reading boot-0:");
1482           eputs (buf);
1483           eputs ("\n");
1484         }
1485       g_stdin = open (buf, O_RDONLY);
1486     }
1487   if (g_stdin < 0)
1488     {
1489       char const *prefix = MODULEDIR "mes/";
1490       strcpy (buf, prefix);
1491       strcpy (buf + strlen (buf), boot);
1492       if (getenv ("MES_DEBUG"))
1493         {
1494           eputs ("MODULEDIR reading boot-0:");
1495           eputs (buf);
1496           eputs ("\n");
1497         }
1498       g_stdin = open (buf, O_RDONLY);
1499     }
1500   if (g_stdin < 0)
1501     {
1502       strcpy (buf, "module/mes/");
1503       strcpy (buf + strlen (buf), boot);
1504       if (getenv ("MES_DEBUG"))
1505         {
1506           eputs (". reading boot-0:");
1507           eputs (buf);
1508           eputs ("\n");
1509         }
1510       g_stdin = open (buf, O_RDONLY);
1511     }
1512   if (g_stdin < 0)
1513     {
1514       if (getenv ("MES_DEBUG"))
1515         {
1516           eputs (". reading boot-0:");
1517           eputs (boot);
1518           eputs ("\n");
1519         }
1520       g_stdin = open (boot, O_RDONLY);
1521     }
1522   if (g_stdin < 0)
1523     {
1524       eputs ("mes: boot failed: no such file: ");
1525       eputs (boot);
1526       eputs ("\n");
1527       exit (1);
1528     }
1529
1530   if (!g_function) r0 = mes_builtins (r0);
1531   r2 = read_input_file_env (r0);
1532   g_stdin = STDIN;
1533   return r2;
1534 }
1535
1536 SCM
1537 bload_env (SCM a) ///((internal))
1538 {
1539 #if __MESC__
1540   char *mo = "mes/read-0-32.mo";
1541   g_stdin = open ("module/mes/read-0-32.mo", O_RDONLY);
1542   char *read0 = MODULEDIR "mes/read-0-32.mo";
1543   g_stdin = g_stdin >= 0 ? g_stdin : open (read0, O_RDONLY);
1544 #else
1545   char *mo ="mes/read-0.mo";
1546   g_stdin = open ("module/mes/read-0.mo", O_RDONLY);
1547   g_stdin = g_stdin >= 0 ? g_stdin : open (MODULEDIR "mes/read-0.mo", O_RDONLY);
1548 #endif
1549
1550   if (g_stdin < 0) {eputs ("no such file: ");eputs (mo);eputs ("\n");return 1;} 
1551   assert (getchar () == 'M');
1552   assert (getchar () == 'E');
1553   assert (getchar () == 'S');
1554
1555   if (g_debug) eputs ("*GOT MES*\n");
1556   g_stack = getchar () << 8;
1557   g_stack += getchar ();
1558
1559   char *p = (char*)g_cells;
1560   int c = getchar ();
1561   while (c != EOF)
1562     {
1563       *p++ = c;
1564       c = getchar ();
1565     }
1566   g_free = (p-(char*)g_cells) / sizeof (struct scm);
1567   gc_peek_frame ();
1568   g_symbols = r1;
1569   g_stdin = STDIN;
1570   r0 = mes_builtins (r0);
1571
1572 #if __GNUC__
1573   set_env_x (cell_symbol_gnuc, cell_t, r0);
1574   set_env_x (cell_symbol_mesc, cell_f, r0);
1575 #else
1576   set_env_x (cell_symbol_gnuc, cell_f, r0);
1577   set_env_x (cell_symbol_mesc, cell_t, r0);
1578 #endif
1579
1580   if (g_debug > 1)
1581     {
1582       eputs ("symbols: ");
1583       SCM s = g_symbols;
1584       while (s && s != cell_nil) {
1585         display_error_ (CAR (s));
1586         eputs (" ");
1587         s = CDR (s);
1588       }
1589       eputs ("\n");
1590       eputs ("functions: ");
1591       eputs (itoa (g_function));
1592       eputs ("\n");
1593       for (int i = 0; i < g_function; i++)
1594         {
1595           eputs ("[");
1596           eputs (itoa (i));
1597           eputs ("]: ");
1598           eputs (g_functions[i].name);
1599           eputs ("\n");
1600         }
1601       //display_error_ (r0);
1602       //puts ("\n");
1603     }
1604   return r2;
1605 }
1606
1607 #include "vector.c"
1608 #include "gc.c"
1609 #include "reader.c"
1610
1611 int
1612 main (int argc, char *argv[])
1613 {
1614   char *p;
1615   if (p = getenv ("MES_DEBUG")) g_debug = atoi (p);
1616   if (g_debug) {eputs (";;; MODULEDIR=");eputs (MODULEDIR);eputs ("\n");}
1617   if (p = getenv ("MES_MAX_ARENA")) MAX_ARENA_SIZE = atoi (p);
1618   if (p = getenv ("MES_ARENA")) ARENA_SIZE = atoi (p);
1619   GC_SAFETY = ARENA_SIZE / 400;
1620   if (argc > 1 && !strcmp (argv[1], "--help")) return puts ("Usage: mes [--dump|--load] < FILE\n");
1621   if (argc > 1 && !strcmp (argv[1], "--version")) {puts ("Mes ");puts (VERSION);puts ("\n");return 0;};
1622   g_stdin = STDIN;
1623   g_stdout = STDOUT;
1624   r0 = mes_environment ();
1625
1626   SCM program = (argc > 1 && !strcmp (argv[1], "--load"))
1627     ? bload_env (r0) : load_env (r0);
1628   g_tiny = argc > 2 && !strcmp (argv[2], "--tiny");
1629   if (argc > 1 && !strcmp (argv[1], "--dump")) return dump ();
1630
1631   SCM lst = cell_nil;
1632   for (int i=argc-1; i>=0; i--) lst = cons (MAKE_STRING (cstring_to_list (argv[i])), lst);
1633   r0 = acons (cell_symbol_argv, lst, r0); // FIXME
1634   r0 = acons (cell_symbol_argv, lst, r0);
1635   push_cc (r2, cell_unspecified, r0, cell_unspecified);
1636   if (g_debug > 1)
1637     {
1638       eputs ("program: ");
1639       write_error_ (r1);
1640       eputs ("\n");
1641     }
1642   r3 = cell_vm_begin_expand;
1643   r1 = eval_apply ();
1644   write_error_ (r1);
1645   eputs ("\n");
1646   gc (g_stack);
1647   if (g_debug)
1648     {
1649       eputs ("\ngc stats: [");
1650       eputs (itoa (g_free));
1651       eputs ("]\n");
1652     }
1653   return 0;
1654 }