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