f2e3cea162f23baa84c5c10c9502d442b641d97a
[fw/altos] / src / lisp / ao_lisp_make_const.c
1 /*
2  * Copyright © 2016 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14
15 #include "ao_lisp.h"
16 #include <stdlib.h>
17 #include <ctype.h>
18
19 static struct ao_lisp_builtin *
20 ao_lisp_make_builtin(enum ao_lisp_builtin_id func, int args) {
21         struct ao_lisp_builtin *b = ao_lisp_alloc(sizeof (struct ao_lisp_builtin));
22
23         b->type = AO_LISP_BUILTIN;
24         b->func = func;
25         b->args = args;
26         return b;
27 }
28
29 struct builtin_func {
30         char    *name;
31         int     args;
32         int     func;
33 };
34
35 struct builtin_func funcs[] = {
36         "car",          AO_LISP_LEXPR,  builtin_car,
37         "cdr",          AO_LISP_LEXPR,  builtin_cdr,
38         "cons",         AO_LISP_LEXPR,  builtin_cons,
39         "quote",        AO_LISP_NLAMBDA,builtin_quote,
40         "set",          AO_LISP_LEXPR,  builtin_set,
41         "setq",         AO_LISP_MACRO,  builtin_setq,
42         "cond",         AO_LISP_NLAMBDA,builtin_cond,
43         "print",        AO_LISP_LEXPR,  builtin_print,
44         "patom",        AO_LISP_LEXPR,  builtin_patom,
45         "+",            AO_LISP_LEXPR,  builtin_plus,
46         "-",            AO_LISP_LEXPR,  builtin_minus,
47         "*",            AO_LISP_LEXPR,  builtin_times,
48         "/",            AO_LISP_LEXPR,  builtin_divide,
49         "%",            AO_LISP_LEXPR,  builtin_mod,
50         "=",            AO_LISP_LEXPR,  builtin_equal,
51         "<",            AO_LISP_LEXPR,  builtin_less,
52         ">",            AO_LISP_LEXPR,  builtin_greater,
53         "<=",           AO_LISP_LEXPR,  builtin_less_equal,
54         ">=",           AO_LISP_LEXPR,  builtin_greater_equal,
55 };
56
57 ao_poly
58 ao_lisp_set_cond(struct ao_lisp_cons *c)
59 {
60         (void) c;
61         return AO_LISP_NIL;
62 }
63
64 #define N_FUNC (sizeof funcs / sizeof funcs[0])
65
66 /* Syntactic atoms */
67 char *atoms[] = {
68         "lambda",
69         "nlambda",
70         "lexpr",
71         "macro"
72 };
73
74 #define N_ATOM (sizeof atoms / sizeof atoms[0])
75
76 struct ao_lisp_frame    *globals;
77
78 static int
79 is_atom(int offset)
80 {
81         struct ao_lisp_atom *a;
82
83         for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next))
84                 if (((uint8_t *) a->name - ao_lisp_const) == offset)
85                         return strlen(a->name);
86         return 0;
87 }
88
89 int
90 main(int argc, char **argv)
91 {
92         int     f, o, i;
93         ao_poly atom, val;
94         struct ao_lisp_atom     *a;
95         struct ao_lisp_builtin  *b;
96         int     in_atom;
97
98         printf("/*\n");
99         printf(" * Generated file, do not edit\n");
100         ao_lisp_root_add(&ao_lisp_frame_type, &globals);
101         globals = ao_lisp_frame_new(0);
102         for (f = 0; f < N_FUNC; f++) {
103                 b = ao_lisp_make_builtin(funcs[f].func, funcs[f].args);
104                 a = ao_lisp_atom_intern(funcs[f].name);
105                 globals = ao_lisp_frame_add(globals, ao_lisp_atom_poly(a), ao_lisp_builtin_poly(b));
106         }
107
108         /* atoms for syntax */
109         for (i = 0; i < N_ATOM; i++)
110                 (void) ao_lisp_atom_intern(atoms[i]);
111
112         /* boolean constants */
113         a = ao_lisp_atom_intern("nil");
114         globals = ao_lisp_frame_add(globals, ao_lisp_atom_poly(a), AO_LISP_NIL);
115         a = ao_lisp_atom_intern("t");
116         globals = ao_lisp_frame_add(globals, ao_lisp_atom_poly(a), ao_lisp_atom_poly(a));
117
118         for (;;) {
119                 atom = ao_lisp_read();
120                 if (!atom)
121                         break;
122                 val = ao_lisp_read();
123                 if (!val)
124                         break;
125                 if (ao_lisp_poly_type(atom) != AO_LISP_ATOM) {
126                         fprintf(stderr, "input must be atom val pairs\n");
127                         exit(1);
128                 }
129                 globals = ao_lisp_frame_add(globals, atom, val);
130         }
131
132         /* Reduce to referenced values */
133         ao_lisp_collect();
134         printf(" */\n");
135
136         printf("#define AO_LISP_POOL_CONST %d\n", ao_lisp_top);
137         printf("extern const uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4)));\n");
138         printf("#define ao_builtin_atoms 0x%04x\n", ao_lisp_atom_poly(ao_lisp_atoms));
139         printf("#define ao_builtin_frame 0x%04x\n", ao_lisp_frame_poly(globals));
140
141         for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next)) {
142                 char    *n = a->name, c;
143                 printf ("#define _ao_lisp_atom_");
144                 while ((c = *n++)) {
145                         if (isalnum(c))
146                                 printf("%c", c);
147                         else
148                                 printf("%02x", c);
149                 }
150                 printf("  0x%04x\n", ao_lisp_atom_poly(a));
151         }
152         printf("#ifdef AO_LISP_CONST_BITS\n");
153         printf("const uint8_t ao_lisp_const[] = {");
154         for (o = 0; o < ao_lisp_top; o++) {
155                 uint8_t c;
156                 if ((o & 0xf) == 0)
157                         printf("\n\t");
158                 else
159                         printf(" ");
160                 c = ao_lisp_const[o];
161                 if (!in_atom)
162                         in_atom = is_atom(o);
163                 if (in_atom) {
164                         printf (" '%c',", c);
165                         in_atom--;
166                 } else {
167                         printf("0x%02x,", c);
168                 }
169         }
170         printf("\n};\n");
171         printf("#endif /* AO_LISP_CONST_BITS */\n");
172 }