#include #include #include #include #include #include "ast.h" #include "desugar.h" #include "gen.h" #include "io.h" #include "module.h" #include "options.h" #include "parser.h" #include "resolver.h" #include "scanner.h" #include "strings.h" #include "symtab.h" #include "types.h" #include "util.h" static int compile(struct options *o) { if (o->ninputs > 1) { bail("too many inputs (%d)", o->ninputs); } if (o->ninputs < 1) { bail("no input files"); } if (!o->output) { bail("an output file must be specified with `-o`"); } FILE *text = NULL; FILE *data_ro = NULL; FILE *data_rw = NULL; const char *rootpath = o->inputs[0]; int err = MODULE_OK; static module_manager_t mm; module_manager_init(&mm, rootpath); /* Register the root module */ if (!(mm.root = module_manager_register(&mm, rootpath))) { bail("error registering root module '%s'", rootpath); } /* Register additional modules specified with -mod. * * Module paths are given as full relative paths (e.g. `lib/std/foo.rad`). * The qualified name is derived by stripping the leading directory * component (e.g. `std/foo.rad`). */ for (int i = 0; i < o->nmodules; i++) { const char *path = o->modules[i]; const char *qualified = strchr(path, '/'); qualified = qualified ? qualified + 1 : path; if (!module_manager_register_qualified(&mm, path, qualified)) { bail("error registering module '%s'", path); } } /* Parse all modules */ if (!module_manager_parse(&mm, &err)) { bail("error parsing modules"); } /* Run desugaring pass on all modules */ for (usize i = 0; i < mm.nmodules; i++) { module_t *mod = &mm.modules[i]; if (mod->ast) { static desugar_t d; mod->ast = desugar_run(&d, mod, mod->ast); if (!mod->ast) { bail("desugaring failed for module %s", mod->name); } } } static resolve_t t; resolve_init(&t, &mm); if (!resolve_run(&t, mm.root)) { bail("type checking failed"); } /* Initialize code generator */ static gen_t g; gen_init(&g, &t.types, &mm, 0); if (!(text = fopen(o->output, "w"))) { bail("failed to open '%s' for writing: %s", o->output, strerror(errno)); } /* Generate code */ if (gen_emit(&g, mm.root) != 0) { bail("code generation failed"); } /* Write binary output */ if (g.data.ro_size > 0) { char datapath_ro[MAX_PATH_LEN] = { 0 }; strncpy(datapath_ro, o->output, MAX_PATH_LEN); strlcat(datapath_ro, ".ro.data", MAX_PATH_LEN); if (!(data_ro = fopen(datapath_ro, "w"))) { bail( "failed to open '%s' for writing: %s", datapath_ro, strerror(errno) ); } } if (g.data.rw_init_total > 0) { char datapath[MAX_PATH_LEN] = { 0 }; strncpy(datapath, o->output, MAX_PATH_LEN); strlcat(datapath, ".rw.data", MAX_PATH_LEN); if (!(data_rw = fopen(datapath, "w"))) { bail( "failed to open '%s' for writing: %s", datapath, strerror(errno) ); } } gen_dump_bin(&g, text, data_ro, data_rw); if (data_ro) fclose(data_ro); if (data_rw) fclose(data_rw); if (text) fclose(text); return 0; } int main(int argc, char *argv[]) { strings_init(); struct options o = options(argc, argv); options_parse(&o); if (compile(&o) != 0) { bail("compilation failed"); } return 0; }