int func;
};
-struct builtin_func funcs[] = {
- { .name = "eval", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_eval },
- { .name = "read", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_read },
- { .name = "lambda", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_lambda },
- { .name = "lexpr", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_lexpr },
- { .name = "nlambda", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_nlambda },
- { .name = "macro", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_macro },
- { .name = "car", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_car },
- { .name = "cdr", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_cdr },
- { .name = "cons", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_cons },
- { .name = "last", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_last },
- { .name = "length", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_length },
- { .name = "quote", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_quote },
- { .name = "set", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_set },
- { .name = "setq", .args = AO_LISP_FUNC_MACRO, .func = builtin_setq },
- { .name = "cond", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_cond },
- { .name = "progn", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_progn },
- { .name = "while", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_while },
- { .name = "print", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_print },
- { .name = "patom", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_patom },
- { .name = "+", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_plus },
- { .name = "-", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_minus },
- { .name = "*", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_times },
- { .name = "/", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_divide },
- { .name = "%", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_mod },
- { .name = "=", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_equal },
- { .name = "<", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_less },
- { .name = ">", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_greater },
- { .name = "<=", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_less_equal },
- { .name = ">=", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_greater_equal },
- { .name = "pack", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_pack },
- { .name = "unpack", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_unpack },
- { .name = "flush", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_flush },
- { .name = "delay", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_delay },
- { .name = "led", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_led },
- { .name = "save", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_save },
- { .name = "restore", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_restore },
-};
+#define AO_LISP_BUILTIN_CONSTS
+#include "ao_lisp_builtin.h"
#define N_FUNC (sizeof funcs / sizeof funcs[0])
return crc;
}
+struct ao_lisp_macro_stack {
+ struct ao_lisp_macro_stack *next;
+ ao_poly p;
+};
+
+struct ao_lisp_macro_stack *macro_stack;
+
int
+ao_lisp_macro_push(ao_poly p)
+{
+ struct ao_lisp_macro_stack *m = macro_stack;
+
+ while (m) {
+ if (m->p == p)
+ return 1;
+ m = m->next;
+ }
+ m = malloc (sizeof (struct ao_lisp_macro_stack));
+ m->p = p;
+ m->next = macro_stack;
+ macro_stack = m;
+ return 0;
+}
+
+void
+ao_lisp_macro_pop(void)
+{
+ struct ao_lisp_macro_stack *m = macro_stack;
+
+ macro_stack = m->next;
+ free(m);
+}
+
+#define DBG_MACRO 0
+#if DBG_MACRO
+int macro_scan_depth;
+
+void indent(void)
+{
+ int i;
+ for (i = 0; i < macro_scan_depth; i++)
+ printf(" ");
+}
+#define MACRO_DEBUG(a) a
+#else
+#define MACRO_DEBUG(a)
+#endif
+
+ao_poly
+ao_has_macro(ao_poly p);
+
+ao_poly
+ao_macro_test_get(ao_poly atom)
+{
+ ao_poly *ref = ao_lisp_atom_ref(ao_lisp_frame_global, atom);
+ if (ref)
+ return *ref;
+ return AO_LISP_NIL;
+}
+
+ao_poly
ao_is_macro(ao_poly p)
{
struct ao_lisp_builtin *builtin;
struct ao_lisp_lambda *lambda;
+ ao_poly ret;
-// printf ("macro scanning "); ao_lisp_poly_print(p); printf("\n");
+ MACRO_DEBUG(indent(); printf ("is macro "); ao_lisp_poly_print(p); printf("\n"); ++macro_scan_depth);
switch (ao_lisp_poly_type(p)) {
case AO_LISP_ATOM:
- return ao_is_macro(ao_lisp_atom_get(p));
+ if (ao_lisp_macro_push(p))
+ ret = AO_LISP_NIL;
+ else {
+ if (ao_is_macro(ao_macro_test_get(p)))
+ ret = p;
+ else
+ ret = AO_LISP_NIL;
+ ao_lisp_macro_pop();
+ }
+ break;
+ case AO_LISP_CONS:
+ ret = ao_has_macro(p);
+ break;
case AO_LISP_BUILTIN:
builtin = ao_lisp_poly_builtin(p);
if ((builtin->args & AO_LISP_FUNC_MASK) == AO_LISP_FUNC_MACRO)
- return 1;
- return 0;
+ ret = p;
+ else
+ ret = 0;
+ break;
+
case AO_LISP_LAMBDA:
lambda = ao_lisp_poly_lambda(p);
if (lambda->args == AO_LISP_FUNC_MACRO)
- return 1;
- return 0;
+ ret = p;
+ else
+ ret = ao_has_macro(lambda->code);
+ break;
default:
- return 0;
+ ret = AO_LISP_NIL;
+ break;
}
+ MACRO_DEBUG(--macro_scan_depth; indent(); printf ("... "); ao_lisp_poly_print(ret); printf("\n"));
+ return ret;
}
ao_poly
if (p == AO_LISP_NIL)
return AO_LISP_NIL;
+ MACRO_DEBUG(indent(); printf("has macro "); ao_lisp_poly_print(p); printf("\n"); ++macro_scan_depth);
switch (ao_lisp_poly_type(p)) {
case AO_LISP_LAMBDA:
lambda = ao_lisp_poly_lambda(p);
- return ao_has_macro(lambda->code);
+ p = ao_has_macro(lambda->code);
+ break;
case AO_LISP_CONS:
cons = ao_lisp_poly_cons(p);
- if (ao_is_macro(cons->car))
- return cons->car;
+ if ((p = ao_is_macro(cons->car)))
+ break;
cons = ao_lisp_poly_cons(cons->cdr);
+ p = AO_LISP_NIL;
while (cons) {
m = ao_has_macro(cons->car);
- if (m)
- return m;
+ if (m) {
+ p = m;
+ break;
+ }
cons = ao_lisp_poly_cons(cons->cdr);
}
- return AO_LISP_NIL;
+ break;
default:
- return AO_LISP_NIL;
+ p = AO_LISP_NIL;
+ break;
}
+ MACRO_DEBUG(--macro_scan_depth; indent(); printf("... "); ao_lisp_poly_print(p); printf("\n"));
+ return p;
}
int
ao_poly val;
struct ao_lisp_atom *a;
struct ao_lisp_builtin *b;
- int in_atom;
- char *out_name;
+ int in_atom = 0;
+ char *out_name = NULL;
int c;
in = stdin;
}
}
+ /* Boolean values #f and #t */
+ ao_lisp_bool_get(0);
+ ao_lisp_bool_get(1);
+
for (f = 0; f < (int) N_FUNC; f++) {
b = ao_lisp_make_builtin(funcs[f].func, funcs[f].args);
a = ao_lisp_atom_intern(funcs[f].name);
ao_lisp_builtin_poly(b));
}
- /* boolean constants */
- ao_lisp_atom_set(ao_lisp_atom_poly(ao_lisp_atom_intern("nil")),
- AO_LISP_NIL);
- a = ao_lisp_atom_intern("t");
- ao_lisp_atom_set(ao_lisp_atom_poly(a),
- ao_lisp_atom_poly(a));
-
/* end of file value */
a = ao_lisp_atom_intern("eof");
ao_lisp_atom_set(ao_lisp_atom_poly(a),
ao_lisp_atom_poly(a));
+ /* 'else' */
+ a = ao_lisp_atom_intern("else");
+
if (argv[optind]){
in = fopen(argv[optind], "r");
if (!in) {
}
/* Reduce to referenced values */
- ao_lisp_collect();
+ ao_lisp_collect(AO_LISP_COLLECT_FULL);
for (f = 0; f < ao_lisp_frame_global->num; f++) {
val = ao_has_macro(ao_lisp_frame_global->vals[f].val);
printf("error: function %s contains unresolved macro: ",
ao_lisp_poly_atom(ao_lisp_frame_global->vals[f].atom)->name);
ao_lisp_poly_print(val);
- printf(stderr, "\n");
+ printf("\n");
exit(1);
}
}
fprintf(out, "#define ao_builtin_frame 0x%04x\n", ao_lisp_frame_poly(ao_lisp_frame_global));
fprintf(out, "#define ao_lisp_const_checksum ((uint16_t) 0x%04x)\n", ao_fec_crc(ao_lisp_const, ao_lisp_top));
+ fprintf(out, "#define _ao_lisp_bool_false 0x%04x\n", ao_lisp_bool_poly(ao_lisp_false));
+ fprintf(out, "#define _ao_lisp_bool_true 0x%04x\n", ao_lisp_bool_poly(ao_lisp_true));
for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next)) {
char *n = a->name, c;
fprintf(out, " 0x%04x\n", ao_lisp_atom_poly(a));
}
fprintf(out, "#ifdef AO_LISP_CONST_BITS\n");
- fprintf(out, "const uint8_t ao_lisp_const[] = {");
+ fprintf(out, "const uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute((aligned(4))) = {");
for (o = 0; o < ao_lisp_top; o++) {
uint8_t c;
if ((o & 0xf) == 0)