radiance.c 3.7 KiB raw
1
#include <errno.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <string.h>
5
#include <unistd.h>
6
7
#include "ast.h"
8
#include "desugar.h"
9
#include "gen.h"
10
#include "io.h"
11
#include "module.h"
12
#include "options.h"
13
#include "parser.h"
14
#include "resolver.h"
15
#include "scanner.h"
16
#include "strings.h"
17
#include "symtab.h"
18
#include "types.h"
19
#include "util.h"
20
21
static int compile(struct options *o) {
22
    if (o->ninputs > 1) {
23
        bail("too many inputs (%d)", o->ninputs);
24
    }
25
    if (o->ninputs < 1) {
26
        bail("no input files");
27
    }
28
    if (!o->output) {
29
        bail("an output file must be specified with `-o`");
30
    }
31
32
    FILE       *text     = NULL;
33
    FILE       *data_ro  = NULL;
34
    FILE       *data_rw  = NULL;
35
    const char *rootpath = o->inputs[0];
36
    int         err      = MODULE_OK;
37
38
    static module_manager_t mm;
39
    module_manager_init(&mm, rootpath);
40
41
    /* Register the root module */
42
    if (!(mm.root = module_manager_register(&mm, rootpath))) {
43
        bail("error registering root module '%s'", rootpath);
44
    }
45
46
    /* Register additional modules specified with -mod.
47
     *
48
     * Module paths are given as full relative paths (e.g. `lib/std/foo.rad`).
49
     * The qualified name is derived by stripping the leading directory
50
     * component (e.g. `std/foo.rad`). */
51
    for (int i = 0; i < o->nmodules; i++) {
52
        const char *path      = o->modules[i];
53
        const char *qualified = strchr(path, '/');
54
        qualified             = qualified ? qualified + 1 : path;
55
56
        if (!module_manager_register_qualified(&mm, path, qualified)) {
57
            bail("error registering module '%s'", path);
58
        }
59
    }
60
61
    /* Parse all modules */
62
    if (!module_manager_parse(&mm, &err)) {
63
        bail("error parsing modules");
64
    }
65
66
    /* Run desugaring pass on all modules */
67
    for (usize i = 0; i < mm.nmodules; i++) {
68
        module_t *mod = &mm.modules[i];
69
70
        if (mod->ast) {
71
            static desugar_t d;
72
73
            mod->ast = desugar_run(&d, mod, mod->ast);
74
            if (!mod->ast) {
75
                bail("desugaring failed for module %s", mod->name);
76
            }
77
        }
78
    }
79
80
    static resolve_t t;
81
    resolve_init(&t, &mm);
82
83
    if (!resolve_run(&t, mm.root)) {
84
        bail("type checking failed");
85
    }
86
87
    /* Initialize code generator */
88
    static gen_t g;
89
    gen_init(&g, &t.types, &mm, 0);
90
91
    if (!(text = fopen(o->output, "w"))) {
92
        bail("failed to open '%s' for writing: %s", o->output, strerror(errno));
93
    }
94
95
    /* Generate code */
96
    if (gen_emit(&g, mm.root) != 0) {
97
        bail("code generation failed");
98
    }
99
100
    /* Write binary output */
101
    if (g.data.ro_size > 0) {
102
        char datapath_ro[MAX_PATH_LEN] = { 0 };
103
        strncpy(datapath_ro, o->output, MAX_PATH_LEN);
104
        strlcat(datapath_ro, ".ro.data", MAX_PATH_LEN);
105
106
        if (!(data_ro = fopen(datapath_ro, "w"))) {
107
            bail(
108
                "failed to open '%s' for writing: %s",
109
                datapath_ro,
110
                strerror(errno)
111
            );
112
        }
113
    }
114
    if (g.data.rw_init_total > 0) {
115
        char datapath[MAX_PATH_LEN] = { 0 };
116
        strncpy(datapath, o->output, MAX_PATH_LEN);
117
        strlcat(datapath, ".rw.data", MAX_PATH_LEN);
118
119
        if (!(data_rw = fopen(datapath, "w"))) {
120
            bail(
121
                "failed to open '%s' for writing: %s", datapath, strerror(errno)
122
            );
123
        }
124
    }
125
    gen_dump_bin(&g, text, data_ro, data_rw);
126
127
    if (data_ro)
128
        fclose(data_ro);
129
    if (data_rw)
130
        fclose(data_rw);
131
    if (text)
132
        fclose(text);
133
134
    return 0;
135
}
136
137
int main(int argc, char *argv[]) {
138
    strings_init();
139
140
    struct options o = options(argc, argv);
141
    options_parse(&o);
142
143
    if (compile(&o) != 0) {
144
        bail("compilation failed");
145
    }
146
    return 0;
147
}