a34affce12ed55cbfc15fb5abda4a849a80b1eed
[fw/altos] / src / scheme / ao_scheme_make_builtin
1 #!/usr/bin/nickle
2
3 typedef struct {
4         string  name;
5         string  feature;
6 } lisp_name_t;
7
8 typedef struct {
9         string  feature;
10         string  type;
11         string  c_name;
12         lisp_name_t[*]  lisp_names;
13 } builtin_t;
14
15 string[string] type_map = {
16         "lambda" => "LAMBDA",
17         "nlambda" => "NLAMBDA",
18         "macro" => "MACRO",
19         "f_lambda" => "F_LAMBDA",
20         "atom" => "atom",
21         "feature" => "feature",
22 };
23
24 lisp_name_t
25 make_one_lisp(string token)
26 {
27         string[*] bits = String::split(token, "@");
28         string  name = bits[0];
29         string  feature = "all";
30
31         if (dim(bits) > 1)
32                 feature = bits[1];
33         return (lisp_name_t) {.name = name, .feature = feature };
34 }
35
36 lisp_name_t[*]
37 make_lisp(string[*] tokens)
38 {
39         lisp_name_t[...] lisp = {};
40
41         if (dim(tokens) < 4)
42                 return (lisp_name_t[1]) { make_one_lisp(tokens[dim(tokens) - 1]) };
43         return (lisp_name_t[dim(tokens)-3]) { [i] = make_one_lisp(tokens[i+3]) };
44 }
45
46 builtin_t
47 read_builtin(file f) {
48         string  line = File::fgets(f);
49         string[*]       tokens = String::wordsplit(line, " \t");
50
51         return (builtin_t) {
52                 .feature = dim(tokens) > 0 ? tokens[0] : "#",
53                 .type = dim(tokens) > 1 ? type_map[tokens[1]] : "#",
54                 .c_name = dim(tokens) > 2 ? tokens[2] : "#",
55                 .lisp_names = make_lisp(tokens),
56         };
57 }
58
59 builtin_t[*]
60 read_builtins(file f) {
61         builtin_t[...] builtins = {};
62
63         while (!File::end(f)) {
64                 builtin_t       b = read_builtin(f);
65
66                 if (b.type[0] != '#')
67                         builtins[dim(builtins)] = b;
68         }
69         return builtins;
70 }
71
72 void
73 dump_ifdef(builtin_t builtin)
74 {
75         if (builtin.feature != "all")
76                 printf("#ifdef AO_SCHEME_FEATURE_%s\n", builtin.feature);
77 }
78
79 void
80 dump_endif(builtin_t builtin)
81 {
82         if (builtin.feature != "all")
83                 printf("#endif /* AO_SCHEME_FEATURE_%s */\n", builtin.feature);
84 }
85
86 bool is_atom(builtin_t b) = b.type == "atom";
87
88 bool is_func(builtin_t b) = b.type != "atom" && b.type != "feature";
89
90 bool is_feature(builtin_t b) = b.type == "feature";
91
92 void
93 dump_ids(builtin_t[*] builtins) {
94         printf("#ifdef AO_SCHEME_BUILTIN_ID\n");
95         printf("#undef AO_SCHEME_BUILTIN_ID\n");
96         printf("enum ao_scheme_builtin_id {\n");
97         for (int i = 0; i < dim(builtins); i++)
98                 if (is_func(builtins[i])) {
99                         dump_ifdef(builtins[i]);
100                         printf("\tbuiltin_%s,\n", builtins[i].c_name);
101                         dump_endif(builtins[i]);
102                 }
103         printf("\t_builtin_last\n");
104         printf("};\n");
105         printf("#endif /* AO_SCHEME_BUILTIN_ID */\n");
106 }
107
108 void
109 dump_casename(builtin_t[*] builtins) {
110         printf("#ifdef AO_SCHEME_BUILTIN_CASENAME\n");
111         printf("#undef AO_SCHEME_BUILTIN_CASENAME\n");
112         printf("static char *ao_scheme_builtin_name(enum ao_scheme_builtin_id b) {\n");
113         printf("\tswitch(b) {\n");
114         for (int i = 0; i < dim(builtins); i++)
115                 if (is_func(builtins[i])) {
116                         dump_ifdef(builtins[i]);
117                         printf("\tcase builtin_%s: return ao_scheme_poly_atom(_atom(\"%s\"))->name;\n",
118                                builtins[i].c_name, builtins[i].lisp_names[0].name);
119                         dump_endif(builtins[i]);
120                 }
121         printf("\tdefault: return (char *) \"???\";\n");
122         printf("\t}\n");
123         printf("}\n");
124         printf("#endif /* AO_SCHEME_BUILTIN_CASENAME */\n");
125 }
126
127 void
128 cify_lisp(string l) {
129         for (int j = 0; j < String::length(l); j++) {
130                 int c= l[j];
131                 if (Ctype::isalnum(c) || c == '_')
132                         printf("%c", c);
133                 else
134                         printf("%02x", c);
135         }
136 }
137
138 void
139 dump_arrayname(builtin_t[*] builtins) {
140         printf("#ifdef AO_SCHEME_BUILTIN_ARRAYNAME\n");
141         printf("#undef AO_SCHEME_BUILTIN_ARRAYNAME\n");
142         printf("static const ao_poly builtin_names[] = {\n");
143         for (int i = 0; i < dim(builtins); i++) {
144                 if (is_func(builtins[i])) {
145                         dump_ifdef(builtins[i]);
146                         printf("\t[builtin_%s] = _ao_scheme_atom_",
147                                builtins[i].c_name);
148                         cify_lisp(builtins[i].lisp_names[0].name);
149                         printf(",\n");
150                         dump_endif(builtins[i]);
151                 }
152         }
153         printf("};\n");
154         printf("#endif /* AO_SCHEME_BUILTIN_ARRAYNAME */\n");
155 }
156
157 void
158 dump_funcs(builtin_t[*] builtins) {
159         printf("#ifdef AO_SCHEME_BUILTIN_FUNCS\n");
160         printf("#undef AO_SCHEME_BUILTIN_FUNCS\n");
161         printf("const ao_scheme_func_t ao_scheme_builtins[] = {\n");
162         for (int i = 0; i < dim(builtins); i++) {
163                 if (is_func(builtins[i])) {
164                         dump_ifdef(builtins[i]);
165                         printf("\t[builtin_%s] = ao_scheme_do_%s,\n",
166                                builtins[i].c_name,
167                                builtins[i].c_name);
168                         dump_endif(builtins[i]);
169                 }
170         }
171         printf("};\n");
172         printf("#endif /* AO_SCHEME_BUILTIN_FUNCS */\n");
173 }
174
175 void
176 dump_decls(builtin_t[*] builtins) {
177         printf("#ifdef AO_SCHEME_BUILTIN_DECLS\n");
178         printf("#undef AO_SCHEME_BUILTIN_DECLS\n");
179         for (int i = 0; i < dim(builtins); i++) {
180                 if (is_func(builtins[i])) {
181                         dump_ifdef(builtins[i]);
182                         printf("ao_poly\n");
183                         printf("ao_scheme_do_%s(struct ao_scheme_cons *cons);\n",
184                                builtins[i].c_name);
185                         dump_endif(builtins[i]);
186                 }
187         }
188         printf("#endif /* AO_SCHEME_BUILTIN_DECLS */\n");
189 }
190
191 void
192 dump_consts(builtin_t[*] builtins) {
193         printf("#ifdef AO_SCHEME_BUILTIN_CONSTS\n");
194         printf("#undef AO_SCHEME_BUILTIN_CONSTS\n");
195         printf("struct builtin_func funcs[] = {\n");
196         for (int i = 0; i < dim(builtins); i++) {
197                 if (is_func(builtins[i])) {
198                         dump_ifdef(builtins[i]);
199                         for (int j = 0; j < dim(builtins[i].lisp_names); j++) {
200                                 string feature = builtins[i].feature;
201                                 if (builtins[i].lisp_names[j].feature != "all")
202                                         feature = builtins[i].lisp_names[j].feature;
203                                 printf ("\t{ .feature = \"%s\", .name = \"%s\", .args = AO_SCHEME_FUNC_%s, .func = builtin_%s },\n",
204                                         feature,
205                                         builtins[i].lisp_names[j].name,
206                                         builtins[i].type,
207                                         builtins[i].c_name);
208                         }
209                         dump_endif(builtins[i]);
210                 }
211         }
212         printf("};\n");
213         printf("#endif /* AO_SCHEME_BUILTIN_CONSTS */\n");
214 }
215
216 void
217 dump_atoms(builtin_t[*] builtins) {
218         printf("#ifdef AO_SCHEME_BUILTIN_ATOMS\n");
219         printf("#undef AO_SCHEME_BUILTIN_ATOMS\n");
220         for (int i = 0; i < dim(builtins); i++) {
221                 if (!is_feature(builtins[i])) {
222                         for (int j = 0; j < dim(builtins[i].lisp_names); j++) {
223                                 printf("#define _ao_scheme_atom_");
224                                 cify_lisp(builtins[i].lisp_names[j].name);
225                                 printf(" _atom(\"%s\")\n", builtins[i].lisp_names[j].name);
226                         }
227                 }
228         }
229         printf("#endif /* AO_SCHEME_BUILTIN_ATOMS */\n");
230 }
231
232 void
233 dump_atom_names(builtin_t[*] builtins) {
234         printf("#ifdef AO_SCHEME_BUILTIN_ATOM_NAMES\n");
235         printf("#undef AO_SCHEME_BUILTIN_ATOM_NAMES\n");
236         printf("static struct builtin_atom atoms[] = {\n");
237         for (int i = 0; i < dim(builtins); i++) {
238                 if (is_atom(builtins[i])) {
239                         for (int j = 0; j < dim(builtins[i].lisp_names); j++) {
240                                 string feature = builtins[i].feature;
241                                 if (builtins[i].lisp_names[j].feature != "all")
242                                         feature = builtins[i].lisp_names[j].feature;
243                                 printf("\t{ .feature = \"%s\", .name = \"%s\" },\n",
244                                        feature,
245                                        builtins[i].lisp_names[j].name);
246                         }
247                 }
248         }
249         printf("};\n");
250         printf("#endif /* AO_SCHEME_BUILTIN_ATOM_NAMES */\n");
251 }
252
253 void
254 dump_syntax_atoms(builtin_t[*] builtins) {
255         printf("#ifdef AO_SCHEME_BUILTIN_SYNTAX_ATOMS\n");
256         printf("#undef AO_SCHEME_BUILTIN_SYNTAX_ATOMS\n");
257         printf("static const char *syntax_atoms[] = {\n");
258         for (int i = 0; i < dim(builtins); i++) {
259                 if (is_atom(builtins[i])) {
260                         for (int j = 0; j < dim(builtins[i].lisp_names); j++) {
261                                 printf("\t\"%s\",\n", builtins[i].lisp_names[j].name);
262                         }
263                 }
264         }
265         printf("};\n");
266         printf("#endif /* AO_SCHEME_BUILTIN_SYNTAX_ATOMS */\n");
267 }
268
269 bool
270 has_feature(string[*] features, string feature)
271 {
272         for (int i = 0; i < dim(features); i++)
273                 if (features[i] == feature)
274                         return true;
275         return false;
276 }
277
278 void
279 dump_features(builtin_t[*] builtins) {
280         string[...] features = {};
281         printf("#ifdef AO_SCHEME_BUILTIN_FEATURES\n");
282         for (int i = 0; i < dim(builtins); i++) {
283                 if (builtins[i].feature != "all") {
284                         string feature = builtins[i].feature;
285                         if (!has_feature(features, feature)) {
286                                 features[dim(features)] = feature;
287                                 printf("#ifndef AO_SCHEME_NO_FEATURE_%s\n", feature);
288                                 printf("#define AO_SCHEME_FEATURE_%s\n", feature);
289                                 printf("#endif /* AO_SCHEME_NO_FEATURE_%s */\n", feature);
290                         }
291                 }
292         }
293         printf("#endif /* AO_SCHEME_BUILTIN_FEATURES */\n");
294 }
295
296 void main() {
297         if (dim(argv) < 2) {
298                 File::fprintf(stderr, "usage: %s <file>\n", argv[0]);
299                 exit(1);
300         }
301         twixt(file f = File::open(argv[1], "r"); File::close(f)) {
302                 builtin_t[*]    builtins = read_builtins(f);
303
304                 printf("/* %d builtins */\n", dim(builtins));
305                 dump_ids(builtins);
306                 dump_casename(builtins);
307                 dump_arrayname(builtins);
308                 dump_funcs(builtins);
309                 dump_decls(builtins);
310                 dump_consts(builtins);
311                 dump_atoms(builtins);
312                 dump_atom_names(builtins);
313                 dump_syntax_atoms(builtins);
314                 dump_features(builtins);
315         }
316 }
317
318 main();