Skip to content

Commit 3e88dac

Browse files
committed
feat(compiler): Enable single-file compilation
1 parent 3b362a2 commit 3e88dac

File tree

26 files changed

+375
-353
lines changed

26 files changed

+375
-353
lines changed

cli/bin/grain.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ program
188188
.command("compile <file>")
189189
.description("compile a grain program into wasm")
190190
.forwardOption("-o <filename>", "output filename")
191+
.forwardOption(
192+
"--single-file",
193+
"compile a single file without compiling dependencies"
194+
)
191195
.forwardOption(
192196
"--use-start-section",
193197
"replaces the _start export with a start section during linking"

compiler/grainc/grainc.re

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
open Grain;
2+
open Grain_typed;
23
open Compile;
34
open Printf;
45
open Lexing;
@@ -26,24 +27,8 @@ let () =
2627
}
2728
);
2829

29-
let compile_file = (name, outfile_arg) => {
30-
if (!Printexc.backtrace_status() && Grain_utils.Config.verbose^) {
31-
Printexc.record_backtrace(true);
32-
};
33-
try({
34-
let outfile =
35-
Option.value(
36-
~default=Compile.default_wasm_filename(name),
37-
outfile_arg,
38-
);
39-
let hook =
40-
if (Grain_utils.Config.statically_link^) {
41-
Compile.stop_after_assembled;
42-
} else {
43-
Compile.stop_after_object_emitted;
44-
};
45-
ignore(Compile.compile_file(~is_root_file=true, ~hook, ~outfile, name));
46-
}) {
30+
let error_wrapped = f =>
31+
try(f()) {
4732
| exn =>
4833
let bt =
4934
if (Printexc.backtrace_status()) {
@@ -63,6 +48,59 @@ let compile_file = (name, outfile_arg) => {
6348
);
6449
exit(2);
6550
};
51+
52+
let compile_file = (~outfile=?, filename) => {
53+
let outfile =
54+
Option.value(
55+
~default=Compile.default_object_filename(filename),
56+
outfile,
57+
);
58+
ignore(Compile.compile_file(~outfile, filename));
59+
};
60+
let compile_file = (~outfile=?, filename) =>
61+
error_wrapped(() => compile_file(~outfile?, filename));
62+
63+
let grainc = (single_file_mode, name, outfile) => {
64+
Grain_utils.Config.set_root_config();
65+
66+
if (!Printexc.backtrace_status() && Grain_utils.Config.verbose^) {
67+
Printexc.record_backtrace(true);
68+
};
69+
70+
if (single_file_mode) {
71+
compile_file(~outfile?, name);
72+
} else {
73+
switch (Grain_utils.Config.wasi_polyfill^) {
74+
| Some(name) =>
75+
Grain_utils.Config.preserve_config(() => {
76+
Grain_utils.Config.compilation_mode := Grain_utils.Config.Runtime;
77+
Module_resolution.load_dependency_graph(name);
78+
let to_compile = Module_resolution.get_out_of_date_dependencies();
79+
List.iter(compile_file, to_compile);
80+
compile_file(name);
81+
})
82+
| None => ()
83+
};
84+
85+
Module_resolution.load_dependency_graph(name);
86+
let to_compile = Module_resolution.get_out_of_date_dependencies();
87+
List.iter(compile_file, to_compile);
88+
compile_file(name);
89+
90+
if (Grain_utils.Config.statically_link^) {
91+
let main_object =
92+
Option.value(
93+
~default=Compile.default_object_filename(name),
94+
outfile,
95+
);
96+
let outfile =
97+
Option.value(~default=Compile.default_wasm_filename(name), outfile);
98+
let dependencies = Module_resolution.get_dependencies();
99+
100+
Link.link(~main_object, ~outfile, dependencies);
101+
};
102+
};
103+
66104
`Ok();
67105
};
68106

@@ -107,6 +145,11 @@ let output_filename = {
107145
);
108146
};
109147

148+
let single_file_mode = {
149+
let doc = sprintf("Compile a single file without compiling dependencies");
150+
Arg.(value & vflag(false, [(true, info(["single-file"], ~doc))]));
151+
};
152+
110153
let cmd = {
111154
let doc = sprintf("Compile Grain programs");
112155
let version =
@@ -118,7 +161,8 @@ let cmd = {
118161
Cmd.info(Sys.argv[0], ~version, ~doc),
119162
Term.(
120163
ret(
121-
Grain_utils.Config.with_cli_options(compile_file)
164+
Grain_utils.Config.with_cli_options(grainc)
165+
$ single_file_mode
122166
$ input_filename
123167
$ output_filename,
124168
)

compiler/graindoc/docblock.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ let get_comments_from_loc = (loc: Grain_parsing.Location.t) => {
330330
| Some(comments) => comments
331331
| None =>
332332
let comments =
333-
switch (compile_file(~is_root_file=true, ~hook=stop_after_parse, file)) {
333+
switch (compile_file(~hook=stop_after_parse, file)) {
334334
| exception exn => []
335335
| {cstate_desc: Parsed(parsed_program)} => parsed_program.comments
336336
| _ => failwith("Invalid compilation state")

compiler/graindoc/graindoc.re

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,26 @@ type params = {
4747
current_version: option(string),
4848
};
4949

50-
let compile_typed = (input: Fp.t(Fp.absolute)) => {
51-
switch (
52-
Compile.compile_file(
53-
~is_root_file=true,
54-
~hook=stop_after_typed,
55-
Filepath.to_string(input),
56-
)
57-
) {
50+
let compile_typed = file => {
51+
Module_resolution.load_dependency_graph(file);
52+
let to_compile = Module_resolution.get_out_of_date_dependencies();
53+
List.iter(
54+
file =>
55+
ignore(
56+
compile_file(
57+
~hook=stop_after_object_emitted,
58+
~outfile=Compile.default_wasm_filename(file),
59+
file,
60+
),
61+
),
62+
to_compile,
63+
);
64+
compile_file(~hook=stop_after_typed, file);
65+
};
66+
67+
let compile = (input: Fp.t(Fp.absolute)) => {
68+
reset_compiler_state();
69+
switch (compile_typed(Filepath.to_string(input))) {
5870
| exception exn =>
5971
let bt =
6072
if (Printexc.backtrace_status()) {
@@ -180,9 +192,11 @@ let enumerate_runs = opts =>
180192
};
181193

182194
let graindoc = (opts, runs) => {
195+
Config.set_root_config();
196+
183197
List.iter(
184198
({input_path, output_path}) => {
185-
let program = compile_typed(input_path);
199+
let program = compile(input_path);
186200
try(
187201
generate_docs(
188202
~current_version=opts.current_version,

compiler/src/codegen/linkedtree.re

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ let internal_name = (id, dep_id) => {
3535
Printf.sprintf("%s_%d", id, dep_id);
3636
};
3737

38-
let link = main_mashtree => {
39-
let main_module = Module_resolution.current_filename^();
40-
38+
let link = (~main_object, dependencies) => {
4139
let new_base_dir = Filepath.String.dirname;
4240

4341
let resolve = (~base_dir=?, mod_name) =>
@@ -49,7 +47,6 @@ let link = main_mashtree => {
4947
Config.wasi_polyfill_path(),
5048
);
5149

52-
let dependencies = Module_resolution.get_dependencies();
5350
let dependencies =
5451
switch (wasi_polyfill) {
5552
| Some(polyfill) => [polyfill, ...dependencies]
@@ -214,7 +211,8 @@ let link = main_mashtree => {
214211
dependencies,
215212
);
216213

217-
let main_program = process_mashtree(~main=true, main_module, main_mashtree);
214+
let main_mashtree = Emitmod.load_object(main_object);
215+
let main_program = process_mashtree(~main=true, main_object, main_mashtree);
218216
let programs = List.rev([main_program, ...programs]);
219217
let num_function_table_elements = num_function_table_elements^;
220218
let signature = main_mashtree.signature;

0 commit comments

Comments
 (0)