1 /* -*-comment-start: "//";comment-end:""-*-
2 * Mes --- Maxwell Equations of Software
3 * Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
5 * This file is part of Mes.
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.
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.
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/>.
21 #define STRING_MAX 2048
34 enum type {CHAR, MACRO, NUMBER, PAIR, SCM, STRING, SYMBOL, VALUES, VECTOR,
35 FUNCTION0, FUNCTION1, FUNCTION2, FUNCTION3, FUNCTIONn};
37 typedef struct scm_t* (*function0_t) (void);
38 typedef struct scm_t* (*function1_t) (struct scm_t*);
39 typedef struct scm_t* (*function2_t) (struct scm_t*, struct scm_t*);
40 typedef struct scm_t* (*function3_t) (struct scm_t*, struct scm_t*, struct scm_t*);
41 typedef struct scm_t* (*functionn_t) (struct scm_t*);
43 typedef struct scm_t {
52 function0_t function0;
53 function1_t function1;
54 function2_t function2;
55 function3_t function3;
56 functionn_t functionn;
59 struct scm_t** vector;
63 scm temp_number = {NUMBER, .name="nul", .value=0};
65 #include "type.environment.h"
66 #include "define.environment.h"
67 #include "quasiquote.environment.h"
68 #include "mes.environment.h"
70 scm *display_ (FILE* f, scm *x);
71 scm *display_helper (FILE*, scm*, bool, char const*, bool);
73 scm scm_nil = {SCM, "()"};
74 scm scm_dot = {SCM, "."};
75 scm scm_f = {SCM, "#f"};
76 scm scm_t = {SCM, "#t"};
77 scm scm_undefined = {SCM, "*undefined*"};
78 scm scm_unspecified = {SCM, "*unspecified*"};
79 scm scm_closure = {SCM, "*closure*"};
80 scm scm_circular = {SCM, "*circular*"};
85 scm scm_lambda = {SCM, "lambda"};
87 scm symbol_begin = {SCM, "begin"};
88 scm symbol_if = {SCM, "if"};
89 scm symbol_define = {SCM, "define"};
90 scm symbol_define_macro = {SCM, "define-macro"};
91 scm symbol_set_x = {SCM, "set!"};
93 scm symbol_quote = {SYMBOL, "quote"};
94 scm symbol_quasiquote = {SYMBOL, "quasiquote"};
95 scm symbol_unquote = {SYMBOL, "unquote"};
96 scm symbol_unquote_splicing = {SYMBOL, "unquote-splicing"};
98 scm symbol_sc_expand = {SYMBOL, "sc-expand"};
99 scm symbol_syntax = {SYMBOL, "syntax"};
100 scm symbol_quasisyntax = {SYMBOL, "quasisyntax"};
101 scm symbol_unsyntax = {SYMBOL, "unsyntax"};
102 scm symbol_unsyntax_splicing = {SYMBOL, "unsyntax-splicing"};
104 scm symbol_call_with_values = {SYMBOL, "call-with-values"};
105 scm symbol_current_module = {SYMBOL, "current-module"};
108 scm char_nul = {CHAR, .name="nul", .value=0};
109 scm char_backspace = {CHAR, .name="backspace", .value=8};
110 scm char_tab = {CHAR, .name="tab", .value=9};
111 scm char_newline = {CHAR, .name="newline", .value=10};
112 scm char_vt = {CHAR, .name="vt", .value=11};
113 scm char_page = {CHAR, .name="page", .value=12};
114 scm char_return = {CHAR, .name="return", .value=13};
115 scm char_space = {CHAR, .name="space", .value=32};
122 assert (x->type == PAIR);
129 assert (x->type == PAIR);
134 cons (scm *x, scm *y)
136 scm *p = (scm*)malloc (sizeof (scm));
144 eq_p (scm *x, scm *y)
147 || (x->type == CHAR && y->type == CHAR
148 && x->value == y->value)
149 || (x->type == NUMBER && y->type == NUMBER
150 && x->value == y->value))
155 set_car_x (scm *x, scm *e)
157 assert (x->type == PAIR);
159 return &scm_unspecified;
163 set_cdr_x (scm *x, scm *e)
165 assert (x->type == PAIR);
166 cache_invalidate (x->cdr);
168 return &scm_unspecified;
172 set_env_x (scm *x, scm *e, scm *a)
174 cache_invalidate (x);
175 return set_cdr_x (assq (x, a), e);
181 return cons (&symbol_quote, x);
187 return cons (&symbol_quasiquote, x);
193 return cons (&symbol_quasisyntax, x);
198 #include "quasiquote.c"
202 // Derived, non-primitives
203 scm *caar (scm *x) {return car (car (x));}
204 scm *cadr (scm *x) {return car (cdr (x));}
205 scm *cdar (scm *x) {return cdr (car (x));}
206 scm *cddr (scm *x) {return cdr (cdr (x));}
207 scm *caaar (scm *x) {return car (car (car (x)));}
208 scm *caadr (scm *x) {return car (car (cdr (x)));}
209 scm *caddr (scm *x) {return car (cdr (cdr (x)));}
210 scm *cdadr (scm *x) {return cdr (car (cdr (x)));}
211 scm *cadar (scm *x) {return car (cdr (car (x)));}
212 scm *cddar (scm *x) {return cdr (cdr (car (x)));}
213 scm *cdddr (scm *x) {return cdr (cdr (cdr (x)));}
216 pairlis (scm *x, scm *y, scm *a)
220 if (pair_p (x) == &scm_f)
221 return cons (cons (x, y), a);
222 return cons (cons (car (x), car (y)),
223 pairlis (cdr (x), cdr (y), a));
227 assq (scm *x, scm *a)
229 while (a != &scm_nil && eq_p (x, a->car->car) == &scm_f) a = a->cdr;
230 return a != &scm_nil ? a->car : &scm_f;
234 #define CACHE_SIZE 30
239 assq_ref_cache (scm *x, scm *a)
242 if (x == &scm_f) return &scm_f;
245 scm*cache_invalidate (scm*x){}
246 scm*cache_invalidate_range (scm*p,scm*a){}
247 scm*cache_save (scm*p){}
248 scm*cache_lookup (scm*x){}
252 scm *env_cache_cars[CACHE_SIZE];
253 scm *env_cache_cdrs[CACHE_SIZE];
254 int cache_threshold = 0;
258 int n = p->car->value;
259 if (n < cache_threshold) return &scm_unspecified;
261 for (int i=0; i < CACHE_SIZE; i++) {
262 if (!env_cache_cars[i]) {
266 if (env_cache_cars[i] == p->car) return &scm_unspecified;
267 if (n > env_cache_cars[i]->value) {
268 n = env_cache_cars[i]->value;
273 cache_threshold = p->car->value;
274 env_cache_cars[j] = p->car;
275 env_cache_cdrs[j] = p->cdr;
277 return &scm_unspecified;
281 cache_lookup (scm *x)
283 for (int i=0; i < CACHE_SIZE; i++) {
284 if (!env_cache_cars[i]) break;
285 if (env_cache_cars[i] == x) return env_cache_cdrs[i];
287 return &scm_undefined;
291 cache_invalidate (scm *x)
293 for (int i=0; i < CACHE_SIZE; i++) {
294 if (env_cache_cars[i] == x) {
295 env_cache_cars[i] = 0;
299 return &scm_unspecified;
303 cache_invalidate_range (scm *p, scm *a)
306 cache_invalidate (p->car->car);
309 return &scm_unspecified;
313 assq_ref_cache (scm *x, scm *a)
316 scm *c = cache_lookup (x);
317 if (c != &scm_undefined) return c;
319 while (a != &scm_nil && x != a->car->car) {i++;a = a->cdr;}
320 if (a == &scm_nil) return &scm_undefined;
321 if (i>ENV_HEAD) cache_save (a->car);
327 evlis_env (scm *m, scm *a)
329 if (m == &scm_nil) return &scm_nil;
330 if (m->type != PAIR) return builtin_eval (m, a);
331 scm *e = builtin_eval (car (m), a);
332 return cons (e, evlis_env (cdr (m), a));
336 apply_env (scm *fn, scm *x, scm *a)
338 if (fn->type != PAIR)
340 if (fn == &scm_car) return x->car->car;
341 if (fn == &scm_cdr) return x->car->cdr;
342 if (builtin_p (fn) == &scm_t)
344 if (eq_p (fn, &symbol_call_with_values) == &scm_t)
345 return call (&scm_call_with_values_env, append2 (x, cons (a, &scm_nil)));
346 if (fn == &symbol_current_module) return a;
348 else if (fn->car == &scm_lambda) {
349 scm *p = pairlis (cadr (fn), x, a);
350 cache_invalidate_range (p, a->cdr);
351 scm *r = builtin_eval (cons (&symbol_begin, cddr (fn)), cons (cons (&scm_closure, p), p));
352 cache_invalidate_range (p, a->cdr);
355 else if (fn->car == &scm_closure) {
356 scm *args = caddr (fn);
357 scm *body = cdddr (fn);
360 scm *p = pairlis (args, x, a);
361 cache_invalidate_range (p, a->cdr);
362 scm *r = builtin_eval (cons (&symbol_begin, body), cons (cons (&scm_closure, p), p));
363 cache_invalidate_range (p, a->cdr);
367 else if (fn->car == &scm_label)
368 return apply_env (caddr (fn), x, cons (cons (cadr (fn), caddr (fn)), a));
370 scm *efn = builtin_eval (fn, a);
371 if (efn == &scm_f || efn == &scm_t) assert (!"apply bool");
372 if (efn->type == NUMBER) assert (!"apply number");
373 if (efn->type == STRING) assert (!"apply string");
374 return apply_env (efn, x, a);
378 builtin_eval (scm *e, scm *a)
380 if (builtin_p (e) == &scm_t) return e;
381 if (e->type == SCM) return e;
383 e = expand_macro_env (e, a);
385 if (e->type == SYMBOL) {
386 scm *y = assq_ref_cache (e, a);
387 if (y == &scm_undefined) {
388 fprintf (stderr, "eval: unbound variable: %s\n", e->name);
389 assert (!"unbound variable");
393 else if (e->type != PAIR)
395 else if (e->car->type != PAIR)
397 if (e->car == &symbol_quote)
399 if (e->car == &symbol_syntax)
401 if (e->car == &symbol_begin)
403 if (e->car == &scm_lambda)
404 return make_closure (cadr (e), cddr (e), assq (&scm_closure, a));
405 if (e->car == &scm_closure)
407 if (e->car == &symbol_if)
408 return builtin_if (cdr (e), a);
410 if (e->car == &symbol_define)
411 return define (e, a);
412 if (e->car == &symbol_define_macro)
413 return define (e, a);
415 if (e->car == &symbol_define) {
416 fprintf (stderr, "C DEFINE: %s\n", e->cdr->car->type == SYMBOL
418 : e->cdr->car->car->name);
420 assert (e->car != &symbol_define);
421 assert (e->car != &symbol_define_macro);
423 if (e->car == &symbol_set_x)
424 return set_env_x (cadr (e), builtin_eval (caddr (e), a), a);
426 if (e->car == &symbol_unquote)
427 return builtin_eval (cadr (e), a);
428 if (e->car == &symbol_quasiquote)
429 return eval_quasiquote (cadr (e), add_unquoters (a));
430 if (e->car == &symbol_unsyntax)
431 return builtin_eval (cadr (e), a);
432 if (e->car == &symbol_quasisyntax)
433 return eval_quasisyntax (cadr (e), add_unsyntaxers (a));
436 return apply_env (e->car, evlis_env (e->cdr, a), a);
440 expand_macro_env (scm *e, scm *a)
444 && (macro = lookup_macro (e->car, a)) != &scm_f)
445 return expand_macro_env (apply_env (macro, e->cdr, a), a);
450 begin (scm *e, scm *a)
452 scm *r = &scm_unspecified;
453 while (e != &scm_nil) {
454 r = builtin_eval (e->car, a);
461 builtin_if (scm *e, scm *a)
463 if (builtin_eval (car (e), a) != &scm_f)
464 return builtin_eval (cadr (e), a);
465 if (cddr (e) != &scm_nil)
466 return builtin_eval (caddr (e), a);
467 return &scm_unspecified;
473 display (scm *x) ///((args . n))
478 if (p->type == PAIR && p->car->type == NUMBER) fd = p->car->value;
479 FILE *f = fd == 1 ? stdout : stderr;
480 return display_helper (f, e, false, "", false);
484 display_ (FILE* f, scm *x)
486 return display_helper (f, x, false, "", false);
490 call (scm *fn, scm *x)
492 if (fn->type == FUNCTION0)
493 return fn->function0 ();
494 if (x->car->type == VALUES)
495 x = cons (x->car->cdr->car, &scm_nil);
496 if (fn->type == FUNCTION1)
497 return fn->function1 (car (x));
498 if (fn->type == FUNCTION2)
499 return fn->function2 (car (x), cadr (x));
500 if (fn->type == FUNCTION3)
501 return fn->function3 (car (x), cadr (x), caddr (x));
502 if (fn->type == FUNCTIONn)
503 return fn->functionn (x);
504 return &scm_unspecified;
508 append2 (scm *x, scm *y)
510 if (x == &scm_nil) return y;
511 assert (x->type == PAIR);
512 return cons (car (x), append2 (cdr (x), y));
516 append (scm *x) ///((args . n))
518 if (x == &scm_nil) return &scm_nil;
519 return append2 (car (x), append (cdr (x)));
525 scm *p = (scm*)malloc (sizeof (scm));
532 make_macro (scm *name, scm *x)
534 scm *p = (scm*)malloc (sizeof (scm));
537 p->name = name->name;
544 scm *p = (scm*)malloc (sizeof (scm));
551 make_string (char const *s)
553 scm *p = (scm*)malloc (sizeof (scm));
555 p->name = strdup (s);
562 internal_lookup_symbol (char const *s)
565 while (x && strcmp (s, x->car->name)) x = x->cdr;
571 internal_make_symbol (char const *s)
573 scm *x = (scm*)malloc (sizeof (scm));
575 x->name = strdup (s);
577 symbols = cons (x, symbols);
582 make_symbol (char const *s)
584 scm *x = internal_lookup_symbol (s);
585 return x ? x : internal_make_symbol (s);
591 scm *p = (scm*)malloc (sizeof (scm));
593 p->length = n->value;
594 p->vector = (scm**)malloc (n->value * sizeof (scm*));
595 for (int i=0; i<n->value; i++) p->vector[i] = &scm_unspecified;
600 string (scm *x) ///((args . n))
602 char buf[STRING_MAX] = "";
604 while (x != &scm_nil)
607 assert (s->type == CHAR);
611 return make_string (buf);
615 string_append (scm *x) ///((args . n))
617 char buf[STRING_MAX] = "";
619 while (x != &scm_nil)
622 assert (s->type == STRING);
623 strcat (buf, s->name);
626 return make_string (buf);
630 list_to_string (scm *x)
632 char buf[STRING_MAX] = "";
634 while (x != &scm_nil)
637 assert (s->type == CHAR);
642 return make_string (buf);
646 string_length (scm *x)
648 assert (x->type == STRING);
649 return make_number (strlen (x->name));
653 string_ref (scm *x, scm *k)
655 assert (x->type == STRING);
656 assert (k->type == NUMBER);
657 return make_char (x->name[k->value]);
661 substring (scm *x) ///((args . n))
663 assert (x->type == PAIR);
664 assert (x->car->type == STRING);
665 char const *s = x->car->name;
666 assert (x->cdr->car->type == NUMBER);
667 int start = x->cdr->car->value;
668 int end = strlen (s);
669 if (x->cdr->cdr->type == PAIR) {
670 assert (x->cdr->cdr->car->type == NUMBER);
671 assert (x->cdr->cdr->car->value <= end);
672 end = x->cdr->cdr->car->value;
674 char buf[STRING_MAX];
675 strncpy (buf, s+start, end - start);
677 return make_string (buf);
684 while (x != &scm_nil)
689 return make_number (n);
695 //if (x != &scm_nil && cdr (x) != &scm_nil)
696 //return last_pair (cdr (x));
697 while (x != &scm_nil && cdr (x) != &scm_nil)
703 builtin_list (scm *x) ///((args . n))
709 values (scm *x) ///((args . n))
711 scm *v = cons (0, x);
717 call_with_values_env (scm *producer, scm *consumer, scm *a)
719 scm *v = apply_env (producer, &scm_nil, a);
720 if (v->type == VALUES)
722 return apply_env (consumer, v, a);
726 vector_length (scm *x)
728 assert (x->type == VECTOR);
729 return make_number (x->length);
733 vector_ref (scm *x, scm *i)
735 assert (x->type == VECTOR);
736 assert (i->value < x->length);
737 return x->vector[i->value];
741 vector_set_x (scm *x, scm *i, scm *e)
743 assert (x->type == VECTOR);
744 assert (i->value < x->length);
745 x->vector[i->value] = e;
746 return &scm_unspecified;
750 lookup (char const *s, scm *a)
752 if (isdigit (*s) || (*s == '-' && isdigit (*(s+1))))
753 return make_number (atoi (s));
756 x = internal_lookup_symbol (s);
759 if (*s == '\'') return &symbol_quote;
760 if (*s == '`') return &symbol_quasiquote;
761 if (*s == ',' && *(s+1) == '@') return &symbol_unquote_splicing;
762 if (*s == ',') return &symbol_unquote;
764 if (*s == '#' && *(s+1) == '\'') return &symbol_syntax;
765 if (*s == '#' && *(s+1) == '`') return &symbol_quasisyntax;
766 if (*s == '#' && *(s+1) == ',' && *(s+2) == '@') return &symbol_unsyntax_splicing;
767 if (*s == '#' && *(s+1) == ',') return &symbol_unsyntax;
769 if (!strcmp (s, "EOF")) {
770 fprintf (stderr, "mes: got EOF\n");
771 return &scm_nil; // `EOF': eval program, which may read stdin
774 return internal_make_symbol (s);
778 lookup_char (int c, scm *a)
783 return lookup (buf, a);
789 static char buf[STRING_MAX];
791 while (l != &scm_nil) {
793 assert (c->type == NUMBER);
802 list_to_vector (scm *x)
804 temp_number.value = length (x)->value;
805 scm *v = make_vector (&temp_number);
807 while (x != &scm_nil)
816 integer_to_char (scm *x)
818 assert (x->type == NUMBER);
819 return make_char (x->value);
823 char_to_integer (scm *x)
825 assert (x->type == CHAR);
826 return make_number (x->value);
830 number_to_string (scm *x)
832 assert (x->type == NUMBER);
833 char buf[STRING_MAX];
834 sprintf (buf,"%d", x->value);
835 return make_string (buf);
839 builtin_exit (scm *x)
841 assert (x->type == NUMBER);
846 string_to_symbol (scm *x)
848 assert (x->type == STRING);
849 return make_symbol (x->name);
853 symbol_to_string (scm *x)
855 assert (x->type == SYMBOL);
856 return make_string (x->name);
860 vector_to_list (scm *v)
863 for (int i = 0; i < v->length; i++)
864 x = append2 (x, cons (v->vector[i], &scm_nil));
869 newline (scm *p) ///((args . n))
872 if (p->type == PAIR && p->car->type == NUMBER) fd = p->car->value;
873 FILE *f = fd == 1 ? stdout : stderr;
875 return &scm_unspecified;
879 force_output (scm *p) ///((args . n))
882 if (p->type == PAIR && p->car->type == NUMBER) fd = p->car->value;
883 FILE *f = fd == 1 ? stdout : stderr;
888 display_helper (FILE* f, scm *x, bool cont, char const *sep, bool quote)
891 fprintf (f, "%s", sep);
892 if (x->type == CHAR && x->value == char_nul.value) fprintf (f, "#\\%s", char_nul.name);
893 else if (x->type == CHAR && x->value == char_backspace.value) fprintf (f, "#\\%s", char_backspace.name);
894 else if (x->type == CHAR && x->value == char_tab.value) fprintf (f, "#\\%s", char_tab.name);
895 else if (x->type == CHAR && x->value == char_newline.value) fprintf (f, "#\\%s", char_newline.name);
896 else if (x->type == CHAR && x->value == char_vt.value) fprintf (f, "#\\%s", char_vt.name);
897 else if (x->type == CHAR && x->value == char_page.value) fprintf (f, "#\\%s", char_page.name);
898 else if (x->type == CHAR && x->value == char_return.value) fprintf (f, "#\\%s", char_return.name);
899 else if (x->type == CHAR && x->value == char_space.value) fprintf (f, "#\\%s", char_space.name);
900 else if (x->type == CHAR) fprintf (f, "#\\%c", x->value);
901 else if (x->type == MACRO) {
902 fprintf (f, "(*macro* ");
903 display_helper (f, x->macro, cont, sep, quote);
906 else if (x->type == NUMBER) fprintf (f, "%d", x->value);
907 else if (x->type == PAIR) {
908 if (car (x) == &scm_circular) {
909 fprintf (f, "(*circ* . #-1#)");
910 return &scm_unspecified;
912 if (car (x) == &scm_closure) {
913 fprintf (f, "(*closure* . #-1#)");
914 return &scm_unspecified;
916 if (car (x) == &scm_quote) {
918 return display_helper (f, car (cdr (x)), cont, "", true);
920 if (!cont) fprintf (f, "(");
921 display_ (f, car (x));
922 if (cdr (x)->type == PAIR)
923 display_helper (f, cdr (x), true, " ", false);
924 else if (cdr (x) != &scm_nil) {
926 display_ (f, cdr (x));
928 if (!cont) fprintf (f, ")");
930 else if (x->type == VECTOR) {
931 fprintf (f, "#(", x->length);
932 for (int i = 0; i < x->length; i++) {
933 if (x->vector[i]->type == VECTOR)
934 fprintf (f, "%s#(...)", i ? " " : "");
936 display_helper (f, x->vector[i], false, i ? " " : "", false);
940 else if (builtin_p (x) == &scm_t) fprintf (f, "#<procedure %s>", x->name);
941 else if (pair_p (x) == &scm_f) fprintf (f, "%s", x->name);
943 return &scm_unspecified;
951 return ungetc (c, stdin);
965 return make_char (peekchar ());
971 return make_char (getchar ());
975 write_char (scm *x) ///((args . n))
980 if (p->type == PAIR && p->car->type == NUMBER) fd = p->car->value;
981 FILE *f = fd == 1 ? stdout : stderr;
982 assert (c->type == NUMBER || c->type == CHAR);
990 assert (c->type == NUMBER || c->type == CHAR);
991 ungetchar (c->value);
998 if (c == '\n') return c;
999 return readcomment (getchar ());
1005 if (c == '!' && peekchar () == '#') return getchar ();
1006 return readblock (getchar ());
1010 readword (int c, char *w, scm *a)
1012 if (c == EOF && !w) return &scm_nil;
1013 if (c == '\n' && !w) return readword (getchar (), w, a);
1014 if (c == '\n' && *w == '.' && w[1] == 0) return &scm_dot;
1015 if (c == EOF || c == '\n') return lookup (w, a);
1016 if (c == ' ') return readword ('\n', w, a);
1017 if (c == '"' && !w) return readstring ();
1018 if (c == '"') {ungetchar (c); return lookup (w, a);}
1019 if (c == '(' && !w) return readlist (a);
1020 if (c == '(') {ungetchar (c); return lookup (w, a);}
1021 if (c == ')' && !w) {ungetchar (c); return &scm_nil;}
1022 if (c == ')') {ungetchar (c); return lookup (w, a);}
1023 if (c == ',' && peekchar () == '@') {getchar (); return cons (lookup (",@", a),
1024 cons (readword (getchar (), w, a),
1029 && !w) {return cons (lookup_char (c, a),
1030 cons (readword (getchar (), w, a),
1032 if (c == '#' && peekchar () == ',' && !w) {
1034 if (peekchar () == '@'){getchar (); return cons (lookup ("#,@", a),
1035 cons (readword (getchar (), w, a),
1037 return cons (lookup ("#,", a), cons (readword (getchar (), w, a), &scm_nil));
1040 && (peekchar () == '\''
1041 || peekchar () == '`')
1042 && !w) {char buf[3] = "#"; buf[1] = getchar (); return cons (lookup (buf, a),
1043 cons (readword (getchar (), w, a),
1045 if (c == ';') {readcomment (c); return readword ('\n', w, a);}
1046 if (c == '#' && peekchar () == 'x') {getchar (); return read_hex ();}
1047 if (c == '#' && peekchar () == '\\') {getchar (); return read_character ();}
1048 if (c == '#' && !w && peekchar () == '(') {getchar (); return list_to_vector (readlist (a));}
1049 if (c == '#' && peekchar () == '(') {ungetchar (c); return lookup (w, a);}
1050 if (c == '#' && peekchar () == '!') {getchar (); readblock (getchar ()); return readword (getchar (), w, a);}
1051 char buf[STRING_MAX] = {0};
1053 char *p = w ? w + strlen (w) : buf;
1056 return readword (getchar (), w ? w : buf, a);
1063 int c = peekchar ();
1064 while ((c >= '0' && c <= '9')
1065 || (c >= 'A' && c <= 'F')
1066 || (c >= 'a' && c <= 'f')) {
1068 if (c >= 'a') n += c - 'a' + 10;
1069 else if (c >= 'A') n += c - 'A' + 10;
1074 return make_number (n);
1081 if (c >= '0' && c <= '7'
1082 && peekchar () >= '0' && peekchar () <= '7') {
1084 while (peekchar () >= '0' && peekchar () <= '7') {
1086 c += getchar () - '0';
1089 else if (c >= 'a' && c <= 'z'
1090 && peekchar () >= 'a' && peekchar () <= 'z') {
1091 char buf[STRING_MAX];
1094 while (peekchar () >= 'a' && peekchar () <= 'z') {
1098 if (!strcmp (buf, char_nul.name)) c = char_nul.value;
1099 else if (!strcmp (buf, char_backspace.name)) c = char_backspace.value;
1100 else if (!strcmp (buf, char_tab.name)) c = char_tab.value;
1101 else if (!strcmp (buf, char_newline.name)) c = char_newline.value;
1102 else if (!strcmp (buf, char_vt.name)) c = char_vt.value;
1103 else if (!strcmp (buf, char_page.name)) c = char_page.value;
1104 else if (!strcmp (buf, char_return.name)) c = char_return.value;
1105 else if (!strcmp (buf, char_space.name)) c = char_space.value;
1107 fprintf (stderr, "char not supported: %s\n", buf);
1108 assert (!"char not supported");
1111 return make_char (c);
1117 char buf[STRING_MAX];
1121 if (c == '"') break;
1122 if (c == '\\' && peekchar () == '"') *p++ = getchar ();
1123 else if (c == '\\' && peekchar () == 'n') {getchar (); *p++ = '\n';}
1124 else if (c == EOF) assert (!"EOF in string");
1129 return make_string (buf);
1133 eat_whitespace (int c)
1135 while (c == ' ' || c == '\t' || c == '\n') c = getchar ();
1136 if (c == ';') return eat_whitespace (readcomment (c));
1137 if (c == '#' && peekchar () == '!') {getchar (); readblock (getchar ()); return eat_whitespace (getchar ());}
1145 c = eat_whitespace (c);
1146 if (c == ')') return &scm_nil;
1147 scm *w = readword (c, 0, a);
1149 return car (readlist (a));
1150 return cons (w, readlist (a));
1156 return readword (getchar (), 0, a);
1160 greater_p (scm *x) ///((name . ">") (args . n))
1163 while (x != &scm_nil)
1165 assert (x->car->type == NUMBER);
1166 if (x->car->value >= n) return &scm_f;
1174 less_p (scm *x) ///((name . "<") (args . n))
1177 while (x != &scm_nil)
1179 assert (x->car->type == NUMBER);
1180 if (x->car->value <= n) return &scm_f;
1188 is_p (scm *x) ///((name . "=") (args . n))
1190 if (x == &scm_nil) return &scm_t;
1191 assert (x->car->type == NUMBER);
1192 int n = x->car->value;
1194 while (x != &scm_nil)
1196 if (x->car->value != n) return &scm_f;
1203 minus (scm *x) ///((name . "-") (args . n))
1206 assert (a->type == NUMBER);
1211 while (x != &scm_nil)
1213 assert (x->car->type == NUMBER);
1217 return make_number (n);
1221 plus (scm *x) ///((name . "+") (args . n))
1224 while (x != &scm_nil)
1226 assert (x->car->type == NUMBER);
1230 return make_number (n);
1234 divide (scm *x) ///((name . "/") (args . n))
1237 if (x != &scm_nil) {
1238 assert (x->car->type == NUMBER);
1242 while (x != &scm_nil)
1244 assert (x->car->type == NUMBER);
1248 return make_number (n);
1252 modulo (scm *a, scm *b)
1254 assert (a->type == NUMBER);
1255 assert (b->type == NUMBER);
1256 return make_number (a->value % b->value);
1260 multiply (scm *x) ///((name . "*") (args . n))
1263 while (x != &scm_nil)
1265 assert (x->car->type == NUMBER);
1269 return make_number (n);
1273 logior (scm *x) ///((args . n))
1276 while (x != &scm_nil)
1278 assert (x->car->type == NUMBER);
1282 return make_number (n);
1286 add_environment (scm *a, char const *name, scm *x)
1288 return cons (cons (make_symbol (name), x), a);
1292 mes_environment () ///((internal))
1296 #include "mes.symbols.i"
1299 symbols = cons (&scm_label, symbols);
1300 a = cons (cons (&scm_label, &scm_t), a);
1303 a = cons (cons (&scm_f, &scm_f), a);
1304 a = cons (cons (&scm_nil, &scm_nil), a);
1305 a = cons (cons (&scm_t, &scm_t), a);
1306 a = cons (cons (&scm_unspecified, &scm_unspecified), a);
1307 a = cons (cons (&symbol_begin, &symbol_begin), a);
1308 a = cons (cons (&symbol_quote, &scm_quote), a);
1309 a = cons (cons (&symbol_syntax, &scm_syntax), a);
1311 #include "mes.environment.i"
1312 #include "define.environment.i"
1313 #include "type.environment.i"
1315 a = cons (cons (&scm_closure, a), a);
1320 make_lambda (scm *args, scm *body)
1322 return cons (&scm_lambda, cons (args, body));
1326 make_closure (scm *args, scm *body, scm *a)
1328 return cons (&scm_closure, cons (cons (&scm_circular, a), cons (args, body)));
1332 lookup_macro (scm *x, scm *a)
1334 if (x->type != SYMBOL) return &scm_f;
1335 scm *m = assq_ref_cache (x, a);
1336 if (macro_p (m) == &scm_t) return m->macro;
1341 read_file (scm *e, scm *a)
1343 if (e == &scm_nil) return e;
1345 scm *x = cons (e, read_file (read_env (a), a));
1346 display_ (stderr, x);
1348 return cons (e, read_file (read_env (a), a));
1353 main (int argc, char *argv[])
1355 if (argc > 1 && !strcmp (argv[1], "--help")) return puts ("Usage: mes < FILE\n");
1356 if (argc > 1 && !strcmp (argv[1], "--version")) return puts ("Mes 0.0\n");
1357 scm *a = mes_environment ();
1358 display_ (stderr, builtin_eval (cons (&symbol_begin, read_file (read_env (a), a)), a));