From 0c366949cb822ebccb3d507afc569a22b291036d Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Wed, 22 Mar 2023 23:03:54 -0700 Subject: [PATCH] add basic checking for if an ingested file exists --- crates/compiler/load_internal/src/file.rs | 67 ++++++++++++++++------- crates/compiler/parse/src/module.rs | 1 + examples/helloWorld.roc | 2 +- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 11ae58e9c5..f7e157e9de 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -3636,7 +3636,7 @@ fn load_package_from_disk<'a>( &header, comments, pkg_module_timing, - ); + )?; Ok(Msg::Header(package_module_msg)) } @@ -3667,7 +3667,7 @@ fn load_package_from_disk<'a>( &header, comments, pkg_module_timing, - ); + )?; Ok(Msg::Header(platform_module_msg)) } @@ -3763,7 +3763,7 @@ fn load_builtin_module<'a>( module_timing: ModuleTiming, module_id: ModuleId, module_name: &str, -) -> (ModuleId, Msg<'a>) { +) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { let src_bytes = module_source(module_id); let (info, parse_state) = load_builtin_module_help(arena, module_name, src_bytes); @@ -3775,8 +3775,8 @@ fn load_builtin_module<'a>( module_ids, ident_ids_by_module, module_timing, - ); - (module_id, Msg::Header(header)) + )?; + Ok((module_id, Msg::Header(header))) } /// Load a module by its module name, rather than by its filename @@ -3812,7 +3812,7 @@ fn load_module<'a>( module_timing, $module_id, concat!($name, ".roc") - ); + )?; return Ok(HeaderOutput { module_id, msg, opt_platform_shorthand: None }); } @@ -4056,7 +4056,7 @@ fn parse_header<'a>( module_ids, ident_ids_by_module, module_timing, - ); + )?; if let Some(expected_module_name) = opt_expected_module_name { if expected_module_name != module_name { @@ -4111,7 +4111,7 @@ fn parse_header<'a>( module_ids, ident_ids_by_module, module_timing, - ); + )?; Ok(HeaderOutput { module_id, @@ -4173,7 +4173,7 @@ fn parse_header<'a>( module_ids.clone(), ident_ids_by_module.clone(), module_timing, - ); + )?; let mut messages = Vec::with_capacity(packages.len() + 1); @@ -4232,7 +4232,7 @@ fn parse_header<'a>( &header, comments, module_timing, - ); + )?; Ok(HeaderOutput { module_id, @@ -4267,7 +4267,7 @@ fn parse_header<'a>( &header, comments, module_timing, - ); + )?; Ok(HeaderOutput { module_id, @@ -4441,7 +4441,7 @@ fn build_header<'a>( module_ids: Arc>>, ident_ids_by_module: SharedIdentIdsByModule, module_timing: ModuleTiming, -) -> (ModuleId, PQModuleName<'a>, ModuleHeader<'a>) { +) -> Result<(ModuleId, PQModuleName<'a>, ModuleHeader<'a>), LoadingProblem<'a>> { let HeaderInfo { filename, is_root_module, @@ -4503,7 +4503,7 @@ fn build_header<'a>( imported.push((qualified_module_name, exposed, loc_entry.region)); } - if let Some(value) = value_def_from_imports(arena, loc_entry) { + if let Some(value) = value_def_from_imports(arena, loc_entry)? { defined_values.push(value); } } @@ -4732,7 +4732,7 @@ fn build_header<'a>( } }; - ( + Ok(( home, name, ModuleHeader { @@ -4753,7 +4753,7 @@ fn build_header<'a>( module_timing, defined_values, }, - ) + )) } impl<'a> BuildTask<'a> { @@ -5280,7 +5280,7 @@ fn build_package_header<'a>( header: &PackageHeader<'a>, comments: &'a [CommentOrNewline<'a>], module_timing: ModuleTiming, -) -> (ModuleId, PQModuleName<'a>, ModuleHeader<'a>) { +) -> Result<(ModuleId, PQModuleName<'a>, ModuleHeader<'a>), LoadingProblem<'a>> { let exposes = bumpalo::collections::Vec::from_iter_in( unspace(arena, header.exposes.item.items).iter().copied(), arena, @@ -5331,7 +5331,7 @@ fn build_platform_header<'a>( header: &PlatformHeader<'a>, comments: &'a [CommentOrNewline<'a>], module_timing: ModuleTiming, -) -> (ModuleId, PQModuleName<'a>, ModuleHeader<'a>) { +) -> Result<(ModuleId, PQModuleName<'a>, ModuleHeader<'a>), LoadingProblem<'a>> { // If we have an app module, then it's the root module; // otherwise, we must be the root. let is_root_module = opt_app_module_id.is_none(); @@ -5681,13 +5681,38 @@ fn exposed_from_import<'a>( fn value_def_from_imports<'a>( arena: &'a Bump, entry: &Loc>, -) -> Option> { +) -> Result>, LoadingProblem<'a>> { use roc_parse::header::ImportsEntry::*; - match entry.value { + let value = match entry.value { Module(_, _) => None, Package(_, _, _) => None, IngestedFile(file_name, typed_ident) => { + if let StrLiteral::PlainLine(file_name) = file_name { + // TODO: This check should be relative to the current module location. + let file_path = Path::new(file_name); + match fs::metadata(file_path) { + Ok(md) => { + if !md.is_file() { + // TODO: is there a better loading problem to return when not a file. + return Err(LoadingProblem::FileProblem { + filename: file_path.to_path_buf(), + error: io::ErrorKind::InvalidInput, + }); + } + } + Err(e) => { + return Err(LoadingProblem::FileProblem { + filename: file_path.to_path_buf(), + error: e.kind(), + }); + } + } + } else { + todo!( + "Only plain strings are supported. Other cases should be made impossible here" + ); + } let typed_ident = typed_ident.extract_spaces().item; let ident = arena.alloc(typed_ident.ident.map_owned(Pattern::Identifier)); Some(ValueDef::AnnotatedBody { @@ -5698,7 +5723,9 @@ fn value_def_from_imports<'a>( body_expr: arena.alloc(entry.with_value(Expr::IngestedFile(file_name.to_owned()))), }) } - } + }; + + Ok(value) } fn ident_from_exposed(entry: &Spaced<'_, ExposedName<'_>>) -> Ident { diff --git a/crates/compiler/parse/src/module.rs b/crates/compiler/parse/src/module.rs index bc3c11bc09..aea466ae9f 100644 --- a/crates/compiler/parse/src/module.rs +++ b/crates/compiler/parse/src/module.rs @@ -664,6 +664,7 @@ fn imports_entry<'a>() -> impl Parser<'a, Spaced<'a, ImportsEntry<'a>>, EImports specialize(|_, pos| EImports::TypedIdent(pos), typed_ident()) ), |((file_name, _), typed_ident)| { + // TODO: look at blacking block strings during parsing. Spaced::Item(ImportsEntry::IngestedFile(file_name, typed_ident)) } ) diff --git a/examples/helloWorld.roc b/examples/helloWorld.roc index bf727c1436..0422062cd7 100644 --- a/examples/helloWorld.roc +++ b/examples/helloWorld.roc @@ -4,4 +4,4 @@ app "helloWorld" provides [main] to pf main = - Stdout.line file + Stdout.line "Hello, World!"