Load all packages, not just the platform

This commit is contained in:
Richard Feldman 2022-12-04 05:31:08 -05:00
parent 0d2692f776
commit f20c7db029
No known key found for this signature in database
GPG key ID: F1F21AA5B1D9E43B
2 changed files with 129 additions and 99 deletions

View file

@ -3293,21 +3293,21 @@ fn finish(
} }
} }
/// Load a `platform` module from disk /// Load a `package` or `platform` module from disk
fn load_platform_module<'a>( fn load_package_from_disk<'a>(
arena: &'a Bump, arena: &'a Bump,
filename: &Path, filename: &Path,
shorthand: &'a str, shorthand: &'a str,
app_module_id: ModuleId, app_module_id: ModuleId,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>, module_ids: &Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: SharedIdentIdsByModule, ident_ids_by_module: &SharedIdentIdsByModule,
) -> Result<Msg<'a>, LoadingProblem<'a>> { ) -> Result<Msg<'a>, LoadingProblem<'a>> {
let module_start_time = Instant::now(); let module_start_time = Instant::now();
let file_io_start = Instant::now(); let file_io_start = Instant::now();
let file = fs::read(filename); let read_result = fs::read(filename);
let file_io_duration = file_io_start.elapsed(); let file_io_duration = file_io_start.elapsed();
match file { match read_result {
Ok(bytes_vec) => { Ok(bytes_vec) => {
let parse_start = Instant::now(); let parse_start = Instant::now();
let bytes = arena.alloc(bytes_vec); let bytes = arena.alloc(bytes_vec);
@ -3360,7 +3360,7 @@ fn load_platform_module<'a>(
parser_state, parser_state,
)) => { )) => {
todo!( todo!(
"Send `packag` module using {:?} and {:?}", "Make a Msg for a `package` module using {:?} and {:?}",
header, header,
parser_state parser_state
) )
@ -3379,7 +3379,7 @@ fn load_platform_module<'a>(
Some(app_module_id), Some(app_module_id),
filename.to_path_buf(), filename.to_path_buf(),
parser_state, parser_state,
module_ids.clone(), module_ids,
ident_ids_by_module, ident_ids_by_module,
&header, &header,
pkg_module_timing, pkg_module_timing,
@ -3854,95 +3854,41 @@ fn parse_header<'a>(
ident_ids_by_module.clone(), ident_ids_by_module.clone(),
module_timing, module_timing,
); );
let app_module_header_msg = Msg::Header(resolved_header);
// Look at the app module's `to` keyword to determine which package was the platform.
match header.provides.to.value { match header.provides.to.value {
To::ExistingPackage(existing_package) => { To::ExistingPackage(existing_package) => {
let opt_base_package = packages.iter().find_map(|loc_package_entry| { let platform_entry = packages.iter()
let Loc { value, .. } = loc_package_entry; .find_map(|Loc { value, .. }| {
if value.shorthand == existing_package { if value.shorthand == existing_package {
Some(value) Some(value)
} else { } else {
None None
} }
}); })
.unwrap_or_else(|| todo!("Gracefully handle platform shorthand after `to` that didn't map to a shorthand specified in `packages`"));
if let Some(PackageEntry { dbg!(
shorthand, "TODO Now that we know which platform was specified, record that in the State.",
package_name: platform_entry
Loc {
value: package_path,
..
},
..
}) = opt_base_package
{
let src = package_path.to_str();
// check whether we can find a `platform` module file on disk
let platform_module_path = if src.starts_with("https://") {
#[cfg(not(target_family = "wasm"))]
{
// If this is a HTTPS package, synchronously download it
// to the cache before proceeding.
// TODO we should do this async; however, with the current
// architecture of file.rs (which doesn't use async/await),
// this would be very difficult!
let (package_dir, opt_root_module) = cache::install_package(
roc_cache_dir,
src,
)
.unwrap_or_else(|err| {
todo!("TODO gracefully handle package install error {:?}", err);
});
// You can optionally specify the root module using the URL fragment,
// e.g. #foo.roc
// (defaults to main.roc)
match opt_root_module {
Some(root_module) => package_dir.join(root_module),
None => package_dir.join("main.roc"),
}
}
#[cfg(target_family = "wasm")]
{
panic!(
"Specifying packages via URLs is curently unsupported in wasm."
); );
} }
} else { To::NewPackage(_package_name) => unreachable!("To::NewPackage is deprecated"),
app_file_dir.join(src) }
};
if platform_module_path.as_path().exists() { let mut messages = load_packages(
let load_platform_module_msg = load_platform_module( packages,
roc_cache_dir,
app_file_dir,
arena, arena,
&platform_module_path,
shorthand,
module_id, module_id,
module_ids, module_ids,
ident_ids_by_module, ident_ids_by_module,
)?; );
Ok(( messages.push(Msg::Header(resolved_header));
module_id,
Msg::Many(vec![app_module_header_msg, load_platform_module_msg]), Ok((module_id, Msg::Many(messages)))
))
} else {
Err(LoadingProblem::FileProblem {
filename: platform_module_path,
error: io::ErrorKind::NotFound,
})
}
} else {
panic!("could not find base")
}
}
To::NewPackage(_package_name) => Ok((module_id, app_module_header_msg)),
}
} }
Ok(( Ok((
ast::Module { ast::Module {
@ -3966,8 +3912,8 @@ fn parse_header<'a>(
None, None,
filename, filename,
parse_state, parse_state,
module_ids.clone(), &module_ids,
ident_ids_by_module, &ident_ids_by_module,
&header, &header,
module_timing, module_timing,
)), )),
@ -3979,6 +3925,90 @@ fn parse_header<'a>(
} }
} }
fn load_packages<'a>(
packages: &[Loc<PackageEntry<'a>>],
roc_cache_dir: RocCacheDir,
app_file_dir: PathBuf,
arena: &'a Bump,
module_id: ModuleId,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: SharedIdentIdsByModule,
) -> Vec<Msg<'a>> {
let mut load_messages = Vec::with_capacity(packages.len() + 1);
let mut problems = Vec::new();
// Load all the packages
for Loc { value: entry, .. } in packages.iter() {
let PackageEntry {
shorthand,
package_name:
Loc {
value: package_path,
..
},
..
} = entry;
let src = package_path.to_str();
// find the `package` or `platform` module on disk,
// downloading it into a cache dir first if necessary.
let root_module_path = if src.starts_with("https://") {
#[cfg(not(target_family = "wasm"))]
{
// If this is a HTTPS package, synchronously download it
// to the cache before proceeding.
// TODO we should do this async; however, with the current
// architecture of file.rs (which doesn't use async/await),
// this would be very difficult!
let (package_dir, opt_root_module) = cache::install_package(roc_cache_dir, src)
.unwrap_or_else(|err| {
todo!("TODO gracefully handle package install error {:?}", err);
});
// You can optionally specify the root module using the URL fragment,
// e.g. #foo.roc
// (defaults to main.roc)
match opt_root_module {
Some(root_module) => package_dir.join(root_module),
None => package_dir.join("main.roc"),
}
}
#[cfg(target_family = "wasm")]
{
panic!("Specifying packages via URLs is curently unsupported in wasm.");
}
} else {
app_file_dir.join(src)
};
match load_package_from_disk(
arena,
&root_module_path,
shorthand,
module_id,
&module_ids,
&ident_ids_by_module,
) {
Ok(msg) => {
load_messages.push(msg);
}
Err(problem) => {
problems.push(problem);
}
}
}
dbg!("TODO Push extra msgs for any loading problems we encountered!");
for _problem in problems {
// TODO see dbg! message above
}
load_messages
}
/// Load a module by its filename /// Load a module by its filename
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn load_filename<'a>( fn load_filename<'a>(
@ -4286,11 +4316,11 @@ struct PlatformHeaderInfo<'a> {
// TODO refactor so more logic is shared with `send_header` // TODO refactor so more logic is shared with `send_header`
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn send_header_two<'a>( fn send_platform_header<'a>(
info: PlatformHeaderInfo<'a>, info: PlatformHeaderInfo<'a>,
parse_state: roc_parse::state::State<'a>, parse_state: roc_parse::state::State<'a>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>, module_ids: &Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: SharedIdentIdsByModule, ident_ids_by_module: &SharedIdentIdsByModule,
module_timing: ModuleTiming, module_timing: ModuleTiming,
) -> (ModuleId, Msg<'a>) { ) -> (ModuleId, Msg<'a>) {
let PlatformHeaderInfo { let PlatformHeaderInfo {
@ -4975,8 +5005,8 @@ fn fabricate_platform_module<'a>(
opt_app_module_id: Option<ModuleId>, opt_app_module_id: Option<ModuleId>,
filename: PathBuf, filename: PathBuf,
parse_state: roc_parse::state::State<'a>, parse_state: roc_parse::state::State<'a>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>, module_ids: &Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: SharedIdentIdsByModule, ident_ids_by_module: &SharedIdentIdsByModule,
header: &PlatformHeader<'a>, header: &PlatformHeader<'a>,
module_timing: ModuleTiming, module_timing: ModuleTiming,
) -> (ModuleId, Msg<'a>) { ) -> (ModuleId, Msg<'a>) {
@ -4999,7 +5029,7 @@ fn fabricate_platform_module<'a>(
imports: unspace(arena, header.imports.item.items), imports: unspace(arena, header.imports.item.items),
}; };
send_header_two( send_platform_header(
info, info,
parse_state, parse_state,
module_ids, module_ids,

View file

@ -183,7 +183,7 @@ pub struct HostedHeader<'a> {
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum To<'a> { pub enum To<'a> {
ExistingPackage(&'a str), ExistingPackage(&'a str),
NewPackage(PackageName<'a>), NewPackage(PackageName<'a>), // TODO is this obsolete? Seems like it should be deleted!
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]