Skip to content

Commit

Permalink
feat(compiler)!: Require extension when including relative file paths (
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-snezhko committed Mar 2, 2024
1 parent 5cf726e commit dde62d3
Show file tree
Hide file tree
Showing 383 changed files with 2,043 additions and 1,995 deletions.
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";

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) =>
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(
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

0 comments on commit dde62d3

Please sign in to comment.