Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(compiler)!: Require extension when including relative file paths #1842

Merged
merged 4 commits into from Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 4 additions & 4 deletions compiler/src/codegen/compcore.re
Expand Up @@ -57,26 +57,26 @@ let reloc_base = Ident.create_persistent("relocBase");
let table_size = Ident.create_persistent("GRAIN$TABLE_SIZE");

/* Memory allocation */
let malloc_mod = "GRAIN$MODULE$runtime/malloc";
let malloc_mod = "GRAIN$MODULE$runtime/malloc.gr";
let malloc_ident = Ident.create_persistent("malloc");
let malloc_closure_ident = Ident.create_persistent("GRAIN$EXPORT$malloc");

/* Garbage collection */
let gc_mod = "GRAIN$MODULE$runtime/gc";
let gc_mod = "GRAIN$MODULE$runtime/gc.gr";
let incref_ident = Ident.create_persistent("incRef");
let incref_closure_ident = Ident.create_persistent("GRAIN$EXPORT$incRef");
let decref_ident = Ident.create_persistent("decRef");
let decref_closure_ident = Ident.create_persistent("GRAIN$EXPORT$decRef");

/* Exceptions */
let exception_mod = "GRAIN$MODULE$runtime/exception";
let exception_mod = "GRAIN$MODULE$runtime/exception.gr";
let panic_with_exception_ident =
Ident.create_persistent("panicWithException");
let panic_with_exception_closure_ident =
Ident.create_persistent("GRAIN$EXPORT$panicWithException");

/* Equality checking */
let equal_mod = "GRAIN$MODULE$runtime/equal";
let equal_mod = "GRAIN$MODULE$runtime/equal.gr";
let equal_ident = Ident.create_persistent("equal");
let equal_closure_ident = Ident.create_persistent("GRAIN$EXPORT$equal");

Expand Down
3 changes: 1 addition & 2 deletions compiler/src/compile.re
Expand Up @@ -41,8 +41,7 @@ type error =

exception InlineFlagsError(Location.t, error);

let default_output_filename = name =>
Filepath.String.remove_extension(name) ++ ".gr.wasm";
let default_output_filename = name => name ++ ".wasm";
alex-snezhko marked this conversation as resolved.
Show resolved Hide resolved

let default_mashtree_filename = name =>
Filepath.String.remove_extension(name) ++ ".mashtree";
Expand Down
9 changes: 8 additions & 1 deletion compiler/src/formatting/fmt.re
Expand Up @@ -3214,6 +3214,13 @@ let print_primitive_description = (fmt, {pprim_ident, pprim_name, pprim_loc}) =>

let print_include_declaration =
(fmt, {pinc_path, pinc_module, pinc_alias, pinc_loc}) => {
open Filepath.String;
let path =
if (!is_relpath(pinc_path.txt) && check_suffix(pinc_path.txt, ".gr")) {
chop_suffix(pinc_path.txt, ".gr");
} else {
pinc_path.txt;
};
string("from")
++ fmt.print_comment_range(
fmt,
Expand All @@ -3224,7 +3231,7 @@ let print_include_declaration =
enclosing_start_location(pinc_loc),
pinc_path.loc,
)
++ double_quotes(string(pinc_path.txt))
++ double_quotes(string(path))
++ fmt.print_comment_range(
fmt,
~allow_breaks=false,
Expand Down
6 changes: 2 additions & 4 deletions compiler/src/linking/link.re
Expand Up @@ -31,10 +31,8 @@ let is_grain_module = mod_name => {
Str.string_match(Str.regexp_string("GRAIN$MODULE$"), mod_name, 0);
};

let wasi_polyfill_module = () => {
Filepath.String.remove_extension(Option.get(Config.wasi_polyfill_path()))
++ ".gr.wasm";
};
let wasi_polyfill_module = () =>
Option.get(Config.wasi_polyfill_path()) ++ ".wasm";

let is_wasi_module = mod_name => {
mod_name == "wasi_snapshot_preview1";
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/middle_end/analyze_inline_wasm.re
Expand Up @@ -59,7 +59,7 @@ let analyze = ({imports, body, analyses}) => {
mod_has_inlineable_wasm := false;
let process_import = ({imp_use_id, imp_desc}) => {
switch (imp_desc) {
| GrainValue("runtime/unsafe/memory", name) =>
| GrainValue("runtime/unsafe/memory.gr", name) =>
phated marked this conversation as resolved.
Show resolved Hide resolved
mod_has_inlineable_wasm := true;
switch (get_primitive_memory(name)) {
| Some(prim) => set_inlineable_wasm(imp_use_id, prim)
Expand Down
Expand Up @@ -19,7 +19,7 @@ let analyze = ({imports, body, analyses}) => {
mod_has_manual_memory_management := false;
let process_import = ({imp_use_id, imp_desc}) => {
switch (imp_desc) {
| GrainValue("runtime/unsafe/memory", "incRef" | "decRef") =>
| GrainValue("runtime/unsafe/memory.gr", "incRef" | "decRef") =>
mod_has_manual_memory_management := true;
set_manual_call(imp_use_id);
| GrainValue(_)
Expand Down
15 changes: 9 additions & 6 deletions compiler/src/parsing/ast_helper.re
Expand Up @@ -473,12 +473,15 @@ module MatchBranch = {

module IncludeDeclaration = {
let mk = (~loc, path, module_, alias) => {
{
pinc_alias: alias,
pinc_module: module_,
pinc_path: normalize_string(~loc, path),
pinc_loc: loc,
};
let path = normalize_string(~loc, path);
let filename =
if (!Grain_utils.Filepath.String.is_relpath(path.txt)) {
path.txt ++ ".gr";
} else {
path.txt;
};
let path = {txt: filename, loc: path.loc};
{pinc_alias: alias, pinc_module: module_, pinc_path: path, pinc_loc: loc};
};
};

Expand Down
5 changes: 3 additions & 2 deletions compiler/src/parsing/driver.re
Expand Up @@ -154,8 +154,9 @@ let read_imports = (program: Parsetree.parsed_program) => {
List.map(
o => {
switch (o) {
| Grain_utils.Config.Pervasives_mod => Location.mknoloc("pervasives")
| Grain_utils.Config.Gc_mod => Location.mknoloc("runtime/gc")
| Grain_utils.Config.Pervasives_mod =>
Location.mknoloc("pervasives.gr")
| Grain_utils.Config.Gc_mod => Location.mknoloc("runtime/gc.gr")
}
},
switch (program.comments) {
Expand Down
14 changes: 11 additions & 3 deletions compiler/src/typed/env.re
Expand Up @@ -758,7 +758,14 @@ let check_consistency = ps =>
~base_dir=Filepath.String.dirname(ps.ps_filename),
name,
);
Consistbl.check(crc_units, resolved_file_name, crc, ps.ps_filename);
Consistbl.check(
crc_units,
// This is a workaround; should address
// TODO(#1843): Investigate CRC behavior
Filepath.String.chop_suffix(resolved_file_name, ".gr"),
crc,
ps.ps_filename,
);
},
ps.ps_crcs,
)
Expand Down Expand Up @@ -2625,9 +2632,10 @@ let report_error = ppf =>
alt,
)
| Unbound_module(_, modname) => fprintf(ppf, "Unbound module %s", modname)
| No_module_file(m, None) => fprintf(ppf, "Missing file for module %s", m)
| No_module_file(m, None) =>
fprintf(ppf, "Missing file for module \"%s\"", m)
| No_module_file(m, Some(msg)) =>
fprintf(ppf, "Missing file for module %s: %s", m, msg)
fprintf(ppf, "Missing file for module \"%s\": %s", m, msg)
| Value_not_found_in_module(_, name, path) =>
fprintf(ppf, "Unbound value %s in module %s", name, path)
| Module_not_found_in_module(_, name, path, None) =>
Expand Down
132 changes: 74 additions & 58 deletions compiler/src/typed/module_resolution.re
Expand Up @@ -49,22 +49,22 @@ let read_file_cmi = f => {
};
};

let get_output_name = name => {
Filepath.String.remove_extension(name) ++ ".gr.wasm";
};
let get_output_name = name => name ++ ".wasm";

let find_ext_in_dir = (dir, name) => {
let fullname = Filepath.String.concat(dir, name);
let rec process_ext =
fun
| [] => None
| [ext, ..._] when file_exists(fullname ++ ext) =>
Some((fullname ++ ext, dir, name, ext))
Some((fullname ++ ext, dir, name))
| [_, ...tl] => process_ext(tl);
process_ext;
};

let find_in_path_uncap = (~exts=[], base_dir, path, name) => {
let find_in_path_uncap =
(~check_src=false, ~check_wasm=false, base_dir, path, name) => {
let exts = (check_src ? [""] : []) @ (check_wasm ? [".wasm"] : []);
let rec try_dir =
fun
| [] => raise(Not_found)
Expand All @@ -75,12 +75,7 @@ let find_in_path_uncap = (~exts=[], base_dir, path, name) => {
};
};
if (!Filepath.String.is_relative(name) && Fs_access.file_exists(name)) {
(
name,
Filepath.String.dirname(name),
Filepath.String.(remove_extension(basename(name))),
Filepath.String.extension(name),
);
(name, Filepath.String.dirname(name), Filepath.String.basename(name));
} else if (Filepath.String.is_relpath(name)) {
try_dir([base_dir]);
} else {
Expand Down Expand Up @@ -177,9 +172,14 @@ let resolve_unit = (~search_path=?, ~cache=true, ~base_dir=?, unit_name) => {
) {
| (true, Some(res)) => res
| _ =>
let exts = [".gr", ".gr.wasm"];
let (_, dir, basename, _) =
find_in_path_uncap(~exts, base_dir, path, unit_name);
let (_, dir, basename) =
find_in_path_uncap(
~check_src=true,
~check_wasm=true,
base_dir,
path,
unit_name,
);
if (cache) {
log_resolution(unit_name, dir, basename);
} else {
Expand All @@ -202,30 +202,65 @@ let locate_module = (~disable_relpath=false, base_dir, path, unit_name) => {
) {
| Some(m) => m
| None =>
let grain_src_exts = [".gr"];
let (dir, m) =
switch (
find_in_path_uncap(~exts=[".gr.wasm"], base_dir, path, unit_name)
) {
| (objpath, dir, basename, ext) =>
switch (find_in_path_uncap(~check_wasm=true, base_dir, path, unit_name)) {
| (objpath, dir, basename) =>
ignore(log_resolution(unit_name, dir, basename));
switch (find_ext_in_dir(dir, basename, grain_src_exts)) {
| Some((srcpath, _, _, _)) => (
let file = find_ext_in_dir(dir, basename, [""]);
switch (file) {
| Some((srcpath, _, _)) => (
dir,
GrainModule(srcpath, Some(objpath)),
)
| None => (dir, WasmModule(objpath))
};
| exception Not_found =>
let (srcpath, dir, _, _) =
find_in_path_uncap(~exts=grain_src_exts, base_dir, path, unit_name);
let (srcpath, dir, _) =
find_in_path_uncap(~check_src=true, base_dir, path, unit_name);
(dir, GrainModule(srcpath, None));
};
PathTbl.add(current_located_module_cache(), (dir, unit_name), m);
m;
};
};

let try_locate_module =
(~disable_relpath=false, base_dir, active_search_path, name, loc) => {
let locate = locate_module(~disable_relpath, base_dir, active_search_path);
Filepath.String.(
try(locate(name)) {
| Not_found =>
if (check_suffix(name, ".gr")) {
let no_extension = chop_suffix(name, ".gr");
switch (locate(no_extension)) {
| exception Not_found => error(No_module_file(loc, name, None))
| _ =>
let name = !is_relpath(name) ? no_extension : name;
error(
No_module_file(
phated marked this conversation as resolved.
Show resolved Hide resolved
loc,
name,
Some("did you mean \"" ++ no_extension ++ "\"?"),
),
);
};
} else {
switch (locate(name ++ ".gr")) {
| exception Not_found => error(No_module_file(loc, name, None))
| _ =>
error(
No_module_file(
loc,
name,
Some("did you mean \"" ++ name ++ ".gr\"?"),
),
)
};
}
}
);
};

type dependency_node = {
// dn_unit_name is a hashtable because we may have a situation
// where A depends on B and C, and both B and C depend on D.
Expand Down Expand Up @@ -281,22 +316,12 @@ module Dependency_graph =
List.map(
name => {
let located =
try(
locate_module(
base_dir,
active_search_path,
name.Location.txt,
)
) {
| Not_found =>
error(
No_module_file(
name.Location.loc,
name.Location.txt,
None,
),
)
};
try_locate_module(
base_dir,
active_search_path,
name.Location.txt,
name.Location.loc,
);
let out_file_name = located_to_out_file_name(located);
let existing_dependency = lookup(out_file_name);
switch (existing_dependency) {
Expand Down Expand Up @@ -331,16 +356,12 @@ module Dependency_graph =
List.map(
((name, _)) => {
let located =
try(locate_module(base_dir, active_search_path, name)) {
| Not_found =>
error(
No_module_file(
Location.in_file(dn.dn_file_name),
name,
None,
),
)
};
try_locate_module(
base_dir,
active_search_path,
name,
Location.in_file(dn.dn_file_name),
);
let out_file_name = located_to_out_file_name(located);
let existing_dependency = lookup(out_file_name);
switch (existing_dependency) {
Expand Down Expand Up @@ -457,19 +478,14 @@ let locate_module_file = (~loc, ~disable_relpath=false, unit_name) => {
let base_dir = Filepath.String.dirname(current_filename^());
let path = Config.module_search_path();
let located =
try(locate_module(~disable_relpath, base_dir, path, unit_name)) {
| Not_found => error(No_module_file(loc, unit_name, None))
};
try_locate_module(~disable_relpath, base_dir, path, unit_name, loc);
located_to_out_file_name(located);
};

let process_dependency = (~loc, ~base_file, unit_name) => {
let base_dir = Filepath.String.dirname(base_file);
let path = Config.module_search_path();
let located =
try(locate_module(~disable_relpath=false, base_dir, path, unit_name)) {
| Not_found => error(No_module_file(loc, unit_name, None))
};
let located = try_locate_module(base_dir, path, unit_name, loc);
let out_file = located_to_out_file_name(located);
let current_dep_node = Dependency_graph.lookup_filename(base_file);
let existing_dependency = Dependency_graph.lookup_filename(out_file);
Expand Down Expand Up @@ -553,9 +569,9 @@ let report_error = ppf =>
);
}
| No_module_file(_, m, None) =>
fprintf(ppf, "Missing file for module %s", m)
fprintf(ppf, "Missing file for module \"%s\"", m)
| No_module_file(_, m, Some(msg)) =>
fprintf(ppf, "Missing file for module %s: %s", m, msg);
fprintf(ppf, "Missing file for module \"%s\": %s", m, msg);

let () =
Location.register_error_of_exn(
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/typed/typemod.re
Expand Up @@ -993,8 +993,8 @@ let register_implicit_modules = modules => {
m => {
let filepath =
switch (m) {
| Grain_utils.Config.Pervasives_mod => "pervasives"
| Grain_utils.Config.Gc_mod => "runtime/gc"
| Grain_utils.Config.Pervasives_mod => "pervasives.gr"
| Grain_utils.Config.Gc_mod => "runtime/gc.gr"
};
Env.add_import(filepath);
},
Expand All @@ -1004,7 +1004,7 @@ let register_implicit_modules = modules => {

let lookup_implicit_module_spec = m =>
switch (m) {
| Grain_utils.Config.Pervasives_mod => Some(("Pervasives", "pervasives"))
| Grain_utils.Config.Pervasives_mod => Some(("Pervasives", "pervasives.gr"))
| Grain_utils.Config.Gc_mod => None
};

Expand Down