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