altos/scheme: Rename to 'scheme', clean up build
[fw/altos] / src / scheme / ao_scheme_make_builtin
diff --git a/src/scheme/ao_scheme_make_builtin b/src/scheme/ao_scheme_make_builtin
new file mode 100644 (file)
index 0000000..8e9c2c0
--- /dev/null
@@ -0,0 +1,190 @@
+#!/usr/bin/nickle
+
+typedef struct {
+       string  type;
+       string  c_name;
+       string[*]       lisp_names;
+} builtin_t;
+
+string[string] type_map = {
+       "lambda" => "LAMBDA",
+       "nlambda" => "NLAMBDA",
+       "macro" => "MACRO",
+       "f_lambda" => "F_LAMBDA",
+       "atom" => "atom",
+};
+
+string[*]
+make_lisp(string[*] tokens)
+{
+       string[...] lisp = {};
+
+       if (dim(tokens) < 3)
+               return (string[1]) { tokens[dim(tokens) - 1] };
+       return (string[dim(tokens)-2]) { [i] = tokens[i+2] };
+}
+
+builtin_t
+read_builtin(file f) {
+       string  line = File::fgets(f);
+       string[*]       tokens = String::wordsplit(line, " \t");
+
+       return (builtin_t) {
+               .type = dim(tokens) > 0 ? type_map[tokens[0]] : "#",
+               .c_name = dim(tokens) > 1 ? tokens[1] : "#",
+               .lisp_names = make_lisp(tokens),
+       };
+}
+
+builtin_t[*]
+read_builtins(file f) {
+       builtin_t[...] builtins = {};
+
+       while (!File::end(f)) {
+               builtin_t       b = read_builtin(f);
+
+               if (b.type[0] != '#')
+                       builtins[dim(builtins)] = b;
+       }
+       return builtins;
+}
+
+bool is_atom(builtin_t b) = b.type == "atom";
+
+void
+dump_ids(builtin_t[*] builtins) {
+       printf("#ifdef AO_SCHEME_BUILTIN_ID\n");
+       printf("#undef AO_SCHEME_BUILTIN_ID\n");
+       printf("enum ao_scheme_builtin_id {\n");
+       for (int i = 0; i < dim(builtins); i++)
+               if (!is_atom(builtins[i]))
+                       printf("\tbuiltin_%s,\n", builtins[i].c_name);
+       printf("\t_builtin_last\n");
+       printf("};\n");
+       printf("#endif /* AO_SCHEME_BUILTIN_ID */\n");
+}
+
+void
+dump_casename(builtin_t[*] builtins) {
+       printf("#ifdef AO_SCHEME_BUILTIN_CASENAME\n");
+       printf("#undef AO_SCHEME_BUILTIN_CASENAME\n");
+       printf("static char *ao_scheme_builtin_name(enum ao_scheme_builtin_id b) {\n");
+       printf("\tswitch(b) {\n");
+       for (int i = 0; i < dim(builtins); i++)
+               if (!is_atom(builtins[i]))
+                       printf("\tcase builtin_%s: return ao_scheme_poly_atom(_atom(\"%s\"))->name;\n",
+                              builtins[i].c_name, builtins[i].lisp_names[0]);
+       printf("\tdefault: return \"???\";\n");
+       printf("\t}\n");
+       printf("}\n");
+       printf("#endif /* AO_SCHEME_BUILTIN_CASENAME */\n");
+}
+
+void
+cify_lisp(string l) {
+       for (int j = 0; j < String::length(l); j++) {
+               int c= l[j];
+               if (Ctype::isalnum(c) || c == '_')
+                       printf("%c", c);
+               else
+                       printf("%02x", c);
+       }
+}
+
+void
+dump_arrayname(builtin_t[*] builtins) {
+       printf("#ifdef AO_SCHEME_BUILTIN_ARRAYNAME\n");
+       printf("#undef AO_SCHEME_BUILTIN_ARRAYNAME\n");
+       printf("static const ao_poly builtin_names[] = {\n");
+       for (int i = 0; i < dim(builtins); i++) {
+               if (!is_atom(builtins[i])) {
+                       printf("\t[builtin_%s] = _ao_scheme_atom_",
+                              builtins[i].c_name);
+                       cify_lisp(builtins[i].lisp_names[0]);
+                       printf(",\n");
+               }
+       }
+       printf("};\n");
+       printf("#endif /* AO_SCHEME_BUILTIN_ARRAYNAME */\n");
+}
+
+void
+dump_funcs(builtin_t[*] builtins) {
+       printf("#ifdef AO_SCHEME_BUILTIN_FUNCS\n");
+       printf("#undef AO_SCHEME_BUILTIN_FUNCS\n");
+       printf("const ao_scheme_func_t ao_scheme_builtins[] = {\n");
+       for (int i = 0; i < dim(builtins); i++) {
+               if (!is_atom(builtins[i]))
+                       printf("\t[builtin_%s] = ao_scheme_do_%s,\n",
+                              builtins[i].c_name,
+                              builtins[i].c_name);
+       }
+       printf("};\n");
+       printf("#endif /* AO_SCHEME_BUILTIN_FUNCS */\n");
+}
+
+void
+dump_decls(builtin_t[*] builtins) {
+       printf("#ifdef AO_SCHEME_BUILTIN_DECLS\n");
+       printf("#undef AO_SCHEME_BUILTIN_DECLS\n");
+       for (int i = 0; i < dim(builtins); i++) {
+               if (!is_atom(builtins[i])) {
+                       printf("ao_poly\n");
+                       printf("ao_scheme_do_%s(struct ao_scheme_cons *cons);\n",
+                              builtins[i].c_name);
+               }
+       }
+       printf("#endif /* AO_SCHEME_BUILTIN_DECLS */\n");
+}
+
+void
+dump_consts(builtin_t[*] builtins) {
+       printf("#ifdef AO_SCHEME_BUILTIN_CONSTS\n");
+       printf("#undef AO_SCHEME_BUILTIN_CONSTS\n");
+       printf("struct builtin_func funcs[] = {\n");
+       for (int i = 0; i < dim(builtins); i++) {
+               if (!is_atom(builtins[i])) {
+                       for (int j = 0; j < dim(builtins[i].lisp_names); j++) {
+                               printf ("\t{ .name = \"%s\", .args = AO_SCHEME_FUNC_%s, .func = builtin_%s },\n",
+                                       builtins[i].lisp_names[j],
+                                       builtins[i].type,
+                                       builtins[i].c_name);
+                       }
+               }
+       }
+       printf("};\n");
+       printf("#endif /* AO_SCHEME_BUILTIN_CONSTS */\n");
+}
+
+void
+dump_atoms(builtin_t[*] builtins) {
+       printf("#ifdef AO_SCHEME_BUILTIN_ATOMS\n");
+       printf("#undef AO_SCHEME_BUILTIN_ATOMS\n");
+       for (int i = 0; i < dim(builtins); i++) {
+               for (int j = 0; j < dim(builtins[i].lisp_names); j++) {
+                       printf("#define _ao_scheme_atom_");
+                       cify_lisp(builtins[i].lisp_names[j]);
+                       printf(" _atom(\"%s\")\n", builtins[i].lisp_names[j]);
+               }
+       }
+       printf("#endif /* AO_SCHEME_BUILTIN_ATOMS */\n");
+}
+
+void main() {
+       if (dim(argv) < 2) {
+               File::fprintf(stderr, "usage: %s <file>\n", argv[0]);
+               exit(1);
+       }
+       twixt(file f = File::open(argv[1], "r"); File::close(f)) {
+               builtin_t[*]    builtins = read_builtins(f);
+               dump_ids(builtins);
+               dump_casename(builtins);
+               dump_arrayname(builtins);
+               dump_funcs(builtins);
+               dump_decls(builtins);
+               dump_consts(builtins);
+               dump_atoms(builtins);
+       }
+}
+
+main();