altos/lisp: Add quasiquote
[fw/altos] / src / lisp / ao_lisp_make_builtin
1 #!/usr/bin/nickle
2
3 typedef struct {
4         string  type;
5         string  c_name;
6         string[*]       lisp_names;
7 } builtin_t;
8
9 string[string] type_map = {
10         "lambda" => "LAMBDA",
11         "nlambda" => "NLAMBDA",
12         "lexpr" => "LEXPR",
13         "macro" => "MACRO",
14         "f_lambda" => "F_LAMBDA",
15         "f_lexpr" => "F_LEXPR",
16         "atom" => "atom",
17 };
18
19 string[*]
20 make_lisp(string[*] tokens)
21 {
22         string[...] lisp = {};
23
24         if (dim(tokens) < 3)
25                 return (string[1]) { tokens[dim(tokens) - 1] };
26         return (string[dim(tokens)-2]) { [i] = tokens[i+2] };
27 }
28
29 builtin_t
30 read_builtin(file f) {
31         string  line = File::fgets(f);
32         string[*]       tokens = String::wordsplit(line, " \t");
33
34         return (builtin_t) {
35                 .type = dim(tokens) > 0 ? type_map[tokens[0]] : "#",
36                 .c_name = dim(tokens) > 1 ? tokens[1] : "#",
37                 .lisp_names = make_lisp(tokens),
38         };
39 }
40
41 builtin_t[*]
42 read_builtins(file f) {
43         builtin_t[...] builtins = {};
44
45         while (!File::end(f)) {
46                 builtin_t       b = read_builtin(f);
47
48                 if (b.type[0] != '#')
49                         builtins[dim(builtins)] = b;
50         }
51         return builtins;
52 }
53
54 bool is_atom(builtin_t b) = b.type == "atom";
55
56 void
57 dump_ids(builtin_t[*] builtins) {
58         printf("#ifdef AO_LISP_BUILTIN_ID\n");
59         printf("#undef AO_LISP_BUILTIN_ID\n");
60         printf("enum ao_lisp_builtin_id {\n");
61         for (int i = 0; i < dim(builtins); i++)
62                 if (!is_atom(builtins[i]))
63                         printf("\tbuiltin_%s,\n", builtins[i].c_name);
64         printf("\t_builtin_last\n");
65         printf("};\n");
66         printf("#endif /* AO_LISP_BUILTIN_ID */\n");
67 }
68
69 void
70 dump_casename(builtin_t[*] builtins) {
71         printf("#ifdef AO_LISP_BUILTIN_CASENAME\n");
72         printf("#undef AO_LISP_BUILTIN_CASENAME\n");
73         printf("static char *ao_lisp_builtin_name(enum ao_lisp_builtin_id b) {\n");
74         printf("\tswitch(b) {\n");
75         for (int i = 0; i < dim(builtins); i++)
76                 if (!is_atom(builtins[i]))
77                         printf("\tcase builtin_%s: return ao_lisp_poly_atom(_atom(\"%s\"))->name;\n",
78                                builtins[i].c_name, builtins[i].lisp_names[0]);
79         printf("\tdefault: return \"???\";\n");
80         printf("\t}\n");
81         printf("}\n");
82         printf("#endif /* AO_LISP_BUILTIN_CASENAME */\n");
83 }
84
85 void
86 cify_lisp(string l) {
87         for (int j = 0; j < String::length(l); j++) {
88                 int c= l[j];
89                 if (Ctype::isalnum(c) || c == '_')
90                         printf("%c", c);
91                 else
92                         printf("%02x", c);
93         }
94 }
95
96 void
97 dump_arrayname(builtin_t[*] builtins) {
98         printf("#ifdef AO_LISP_BUILTIN_ARRAYNAME\n");
99         printf("#undef AO_LISP_BUILTIN_ARRAYNAME\n");
100         printf("static const ao_poly builtin_names[] = {\n");
101         for (int i = 0; i < dim(builtins); i++) {
102                 if (!is_atom(builtins[i])) {
103                         printf("\t[builtin_%s] = _ao_lisp_atom_",
104                                builtins[i].c_name);
105                         cify_lisp(builtins[i].lisp_names[0]);
106                         printf(",\n");
107                 }
108         }
109         printf("};\n");
110         printf("#endif /* AO_LISP_BUILTIN_ARRAYNAME */\n");
111 }
112
113 void
114 dump_funcs(builtin_t[*] builtins) {
115         printf("#ifdef AO_LISP_BUILTIN_FUNCS\n");
116         printf("#undef AO_LISP_BUILTIN_FUNCS\n");
117         printf("const ao_lisp_func_t ao_lisp_builtins[] = {\n");
118         for (int i = 0; i < dim(builtins); i++) {
119                 if (!is_atom(builtins[i]))
120                         printf("\t[builtin_%s] = ao_lisp_do_%s,\n",
121                                builtins[i].c_name,
122                                builtins[i].c_name);
123         }
124         printf("};\n");
125         printf("#endif /* AO_LISP_BUILTIN_FUNCS */\n");
126 }
127
128 void
129 dump_decls(builtin_t[*] builtins) {
130         printf("#ifdef AO_LISP_BUILTIN_DECLS\n");
131         printf("#undef AO_LISP_BUILTIN_DECLS\n");
132         for (int i = 0; i < dim(builtins); i++) {
133                 if (!is_atom(builtins[i])) {
134                         printf("ao_poly\n");
135                         printf("ao_lisp_do_%s(struct ao_lisp_cons *cons);\n",
136                                builtins[i].c_name);
137                 }
138         }
139         printf("#endif /* AO_LISP_BUILTIN_DECLS */\n");
140 }
141
142 void
143 dump_consts(builtin_t[*] builtins) {
144         printf("#ifdef AO_LISP_BUILTIN_CONSTS\n");
145         printf("#undef AO_LISP_BUILTIN_CONSTS\n");
146         printf("struct builtin_func funcs[] = {\n");
147         for (int i = 0; i < dim(builtins); i++) {
148                 if (!is_atom(builtins[i])) {
149                         for (int j = 0; j < dim(builtins[i].lisp_names); j++) {
150                                 printf ("\t{ .name = \"%s\", .args = AO_LISP_FUNC_%s, .func = builtin_%s },\n",
151                                         builtins[i].lisp_names[j],
152                                         builtins[i].type,
153                                         builtins[i].c_name);
154                         }
155                 }
156         }
157         printf("};\n");
158         printf("#endif /* AO_LISP_BUILTIN_CONSTS */\n");
159 }
160
161 void
162 dump_atoms(builtin_t[*] builtins) {
163         printf("#ifdef AO_LISP_BUILTIN_ATOMS\n");
164         printf("#undef AO_LISP_BUILTIN_ATOMS\n");
165         for (int i = 0; i < dim(builtins); i++) {
166                 for (int j = 0; j < dim(builtins[i].lisp_names); j++) {
167                         printf("#define _ao_lisp_atom_");
168                         cify_lisp(builtins[i].lisp_names[j]);
169                         printf(" _atom(\"%s\")\n", builtins[i].lisp_names[j]);
170                 }
171         }
172         printf("#endif /* AO_LISP_BUILTIN_ATOMS */\n");
173 }
174
175 void main() {
176         if (dim(argv) < 2) {
177                 File::fprintf(stderr, "usage: %s <file>\n", argv[0]);
178                 exit(1);
179         }
180         twixt(file f = File::open(argv[1], "r"); File::close(f)) {
181                 builtin_t[*]    builtins = read_builtins(f);
182                 dump_ids(builtins);
183                 dump_casename(builtins);
184                 dump_arrayname(builtins);
185                 dump_funcs(builtins);
186                 dump_decls(builtins);
187                 dump_consts(builtins);
188                 dump_atoms(builtins);
189         }
190 }
191
192 main();