mes.c, mes.mes: support quasiquote, unquote.

This commit is contained in:
Jan Nieuwenhuizen 2016-07-09 14:29:39 +02:00
parent 1513c0d5fb
commit 989cbab16a
3 changed files with 136 additions and 1 deletions

119
mes.c
View file

@ -37,6 +37,7 @@
#define DEBUG 0 #define DEBUG 0
#define MACROS 1 #define MACROS 1
#define QUASIQUOTE 1
#ifndef QUOTE_SUGAR #ifndef QUOTE_SUGAR
#define QUOTE_SUGAR 1 #define QUOTE_SUGAR 1
@ -74,7 +75,13 @@ scm scm_label = {ATOM, "label"};
scm scm_unspecified = {ATOM, "*unspecified*"}; scm scm_unspecified = {ATOM, "*unspecified*"};
scm scm_symbol_cond = {ATOM, "cond"}; scm scm_symbol_cond = {ATOM, "cond"};
scm scm_symbol_quote = {ATOM, "quote"}; scm scm_symbol_quote = {ATOM, "quote"};
#if QUASIQUOTE
scm scm_symbol_quasiquote = {ATOM, "quasiquote"};
scm scm_symbol_unquote = {ATOM, "unquote"};
#endif
#if MACROS
scm scm_macro = {ATOM, "*macro*"}; scm scm_macro = {ATOM, "*macro*"};
#endif
// PRIMITIVES // PRIMITIVES
@ -147,6 +154,25 @@ quote (scm *x)
return cons (&scm_quote, x); return cons (&scm_quote, x);
} }
#if QUASIQUOTE
scm scm_unquote;
scm *
unquote (scm *x)
{
return cons (&scm_unquote, x);
}
scm scm_quasiquote;
scm *
quasiquote (scm *x)
{
return cons (&scm_quasiquote, x);
}
scm *eval_quasiquote (scm *, scm *);
#endif
//Library functions //Library functions
scm scm_read; scm scm_read;
@ -300,6 +326,21 @@ eval_ (scm *e, scm *a)
#endif // MACROS #endif // MACROS
if (car (e) == &scm_symbol_quote) if (car (e) == &scm_symbol_quote)
return cadr (e); return cadr (e);
#if QUASIQUOTE
else if (car (e) == &scm_symbol_unquote)
return eval (cadr (e), a);
else if (car (e) == &scm_symbol_quasiquote) {
#if DEBUG
printf ("cadr e:");
display (cadr (e));
puts ("");
printf ("qq:");
display (eval_quasiquote (cadr (e), a));
puts ("");
#endif // DEBUG
return eval_quasiquote (cadr (e), a);
}
#endif // QUASIQUOTE
else if (car (e) == &scm_symbol_cond) else if (car (e) == &scm_symbol_cond)
return evcon (cdr (e), a); return evcon (cdr (e), a);
#if MACROS #if MACROS
@ -376,6 +417,11 @@ scm scm_null_p = {FUNCTION1, "null", .function1 = &null_p};
scm scm_pair_p = {FUNCTION1, "pair", .function1 = &pair_p}; scm scm_pair_p = {FUNCTION1, "pair", .function1 = &pair_p};
scm scm_quote = {FUNCTION1, "quote", .function1 = &quote}; scm scm_quote = {FUNCTION1, "quote", .function1 = &quote};
#if QUASIQUOTE
scm scm_unquote = {FUNCTION1, "unquote", .function1 = &unquote};
scm scm_quasiquote = {FUNCTION1, "quasiquote", .function1 = &quasiquote};
#endif
scm scm_eval = {FUNCTION2, .name="eval", .function2 = &eval}; scm scm_eval = {FUNCTION2, .name="eval", .function2 = &eval};
scm scm_apply = {FUNCTION3, .name="apply", .function3 = &apply}; scm scm_apply = {FUNCTION3, .name="apply", .function3 = &apply};
@ -481,9 +527,25 @@ lookup (char *x, scm *a)
if (!strcmp (x, scm_label.name)) return &scm_label; if (!strcmp (x, scm_label.name)) return &scm_label;
if (!strcmp (x, scm_nil.name)) return &scm_nil; if (!strcmp (x, scm_nil.name)) return &scm_nil;
#if QUASIQUOTE
if (*x == '`') return &scm_symbol_quasiquote;
if (*x == ',') return &scm_symbol_unquote;
if (!strcmp (x, scm_symbol_unquote.name)) return &scm_symbol_unquote;
if (!strcmp (x, scm_symbol_quasiquote.name)) return &scm_symbol_quasiquote;
#endif
return make_atom (x); return make_atom (x);
} }
scm *
lookup_char (int c, scm *a)
{
char buf[2];
buf[0] = c;
buf[1] = 0;
return lookup (buf, a);
}
char * char *
list2str (scm *l) list2str (scm *l)
{ {
@ -535,6 +597,18 @@ display_helper (scm *x, bool cont, char *sep, bool quote)
printf ("'"); printf ("'");
return display_helper (car (cdr (x)), cont, "", true); return display_helper (car (cdr (x)), cont, "", true);
} }
#if QUASIQUOTE
if (car (x) == &scm_symbol_quasiquote
|| car (x) == &scm_quasiquote) {
printf ("`");
return display_helper (car (cdr (x)), cont, "", true);
}
if (car (x) == &scm_symbol_unquote
|| car (x) == &scm_unquote) {
printf (",");
return display_helper (car (cdr (x)), cont, "", true);
}
#endif
#endif #endif
if (!cont) printf ("("); if (!cont) printf ("(");
display (car (x)); display (car (x));
@ -618,7 +692,13 @@ readword (int c, char* w, scm *a)
if (c == '(') {ungetchar (c); return lookup (w, a);} if (c == '(') {ungetchar (c); return lookup (w, a);}
if (c == ')' && !w) {ungetchar (c); return &scm_nil;} if (c == ')' && !w) {ungetchar (c); return &scm_nil;}
if (c == ')') {ungetchar (c); return lookup (w, a);} if (c == ')') {ungetchar (c); return lookup (w, a);}
if (c == '\'' && !w) {return cons (lookup ("'", a), if ((c == '\''
#if QUASIQUOTE
|| c == '`'
|| c == ','
#endif
)
&& !w) {return cons (lookup_char (c, a),
cons (readword (getchar (), w, a), cons (readword (getchar (), w, a),
&scm_nil));} &scm_nil));}
if (c == ';') {readcomment (c); return readword ('\n', w, a);} if (c == ';') {readcomment (c); return readword ('\n', w, a);}
@ -690,6 +770,35 @@ minus (scm *a, scm *b)
scm scm_less_p = {FUNCTION2, .name="<", .function2 = &less_p}; scm scm_less_p = {FUNCTION2, .name="<", .function2 = &less_p};
scm scm_minus = {FUNCTION2, .name="-", .function2 = &minus}; scm scm_minus = {FUNCTION2, .name="-", .function2 = &minus};
#if QUASIQUOTE
scm *
eval_quasiquote (scm *e, scm *a)
{
#if DEBUG
printf ("\nc:eval_quasiquote e=");
display (e);
if (pair_p (e) == &scm_t) {
printf ("\ncar (e)=");
display (car (e));
printf (" atom=");
display (atom_p (car (e)));
}
puts ("");
#endif
if (e == &scm_nil) return e;
else if (atom_p (e) == &scm_t) return e;
else if (atom_p (car (e)) == &scm_t)
return cons (car (e), eval_quasiquote (cdr (e), a));
else if (eq_p (caar (e), &scm_symbol_unquote) == &scm_t)
return cons (eval (cadar (e), a), &scm_nil);
else if (eq_p (caar (e), &scm_symbol_quote) == &scm_t)
return cons (cadar (e), &scm_nil);
else if (eq_p (caar (e), &scm_symbol_quasiquote) == &scm_t)
return cdar (e);
return cons (car (e), eval_quasiquote (cdr (e), a));
}
scm scm_eval_quasiquote = {FUNCTION2, .name="c:eval-quasiquote", .function2 = &eval_quasiquote};
#endif
scm * scm *
add_environment (scm *a, char *name, scm* x) add_environment (scm *a, char *name, scm* x)
@ -722,6 +831,14 @@ initial_environment ()
a = add_environment (a, "quote", &scm_quote); a = add_environment (a, "quote", &scm_quote);
a = add_environment (a, "'", &scm_quote); a = add_environment (a, "'", &scm_quote);
#if QUASIQUOTE
a = add_environment (a, "quasiquote", &scm_quasiquote);
a = add_environment (a, "unquote", &scm_unquote);
a = add_environment (a, ",", &scm_unquote);
a = add_environment (a, "`", &scm_quasiquote);
a = add_environment (a, "eval-quasiquote", &scm_eval_quasiquote);
#endif
a = add_environment (a, "evlis", &scm_evlis); a = add_environment (a, "evlis", &scm_evlis);
a = add_environment (a, "evcon", &scm_evcon); a = add_environment (a, "evcon", &scm_evcon);
a = add_environment (a, "pairlis", &scm_pairlis); a = add_environment (a, "pairlis", &scm_pairlis);

14
mes.mes
View file

@ -124,6 +124,8 @@
((atom (car e)) ((atom (car e))
(cond (cond
((eq (car e) 'quote) (cadr e)) ((eq (car e) 'quote) (cadr e))
((eq (car e) 'unquote) (eval (cadr e) a))
((eq (car e) 'quasiquote) (eval-quasiquote (cadr e) a))
((eq (car e) 'cond) (evcon (cdr e) a)) ((eq (car e) 'cond) (evcon (cdr e) a))
((pair (assoc (car e) (cdr (assoc '*macro* a)))) ((pair (assoc (car e) (cdr (assoc '*macro* a))))
(c:eval (c:eval
@ -135,6 +137,18 @@
(#t (apply (car e) (evlis (cdr e) a) a)))) (#t (apply (car e) (evlis (cdr e) a) a))))
(#t (apply (car e) (evlis (cdr e) a) a)))) (#t (apply (car e) (evlis (cdr e) a) a))))
(define (eval-quasiquote e a)
;; (display 'mes-eval-quasiquote:)
;; (display e)
;; (newline)
(cond ((null e) e)
((atom e) e)
((atom (car e)) (cons (car e) (eval-quasiquote (cdr e) a)))
((eq (caar e) 'unquote) (cons (eval (cadar e) a) '()))
((eq (caar e) 'quote) (cons (cadar e) '()))
((eq (caar e) 'quasiquote) (cons (cadar e) '()))
(#t (cons (car e) (eval-quasiquote (cdr e) a)))))
;; readenv et al works, but slows down dramatically ;; readenv et al works, but slows down dramatically
(define (DISABLED-readenv a) (define (DISABLED-readenv a)
(readword (getchar) '() a)) (readword (getchar) '() a))

View file

@ -124,4 +124,8 @@
(display 'let-dun) (display 'let-dun)
(newline) (newline)
(define c 'b)
`(aa bb ,c)
(display `(pp qq ,c))
(newline)
'() '()