mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Use app module's to
to determine platform
This commit is contained in:
parent
fa58838f97
commit
16ce22d455
1 changed files with 124 additions and 95 deletions
|
@ -915,6 +915,8 @@ struct State<'a> {
|
|||
pub root_id: ModuleId,
|
||||
pub root_subs: Option<Subs>,
|
||||
pub cache_dir: PathBuf,
|
||||
/// If the root is an app module, the shorthand specified in its header's `to` field
|
||||
pub opt_platform_shorthand: Option<&'a str>,
|
||||
pub platform_data: Option<PlatformData<'a>>,
|
||||
pub exposed_types: ExposedByModule,
|
||||
pub output_path: Option<&'a str>,
|
||||
|
@ -976,6 +978,7 @@ impl<'a> State<'a> {
|
|||
|
||||
fn new(
|
||||
root_id: ModuleId,
|
||||
opt_platform_shorthand: Option<&'a str>,
|
||||
target_info: TargetInfo,
|
||||
exposed_types: ExposedByModule,
|
||||
arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||
|
@ -993,6 +996,7 @@ impl<'a> State<'a> {
|
|||
Self {
|
||||
root_id,
|
||||
root_subs: None,
|
||||
opt_platform_shorthand,
|
||||
cache_dir,
|
||||
target_info,
|
||||
platform_data: None,
|
||||
|
@ -1269,6 +1273,7 @@ pub struct LoadStart<'a> {
|
|||
arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||
ident_ids_by_module: SharedIdentIdsByModule,
|
||||
root_id: ModuleId,
|
||||
opt_platform_shorthand: Option<&'a str>,
|
||||
root_msg: Msg<'a>,
|
||||
src_dir: PathBuf,
|
||||
}
|
||||
|
@ -1287,7 +1292,7 @@ impl<'a> LoadStart<'a> {
|
|||
let mut src_dir = filename.parent().unwrap().to_path_buf();
|
||||
|
||||
// Load the root module synchronously; we can't proceed until we have its id.
|
||||
let (root_id, root_msg) = {
|
||||
let header_output = {
|
||||
let root_start_time = Instant::now();
|
||||
|
||||
let res_loaded = load_filename(
|
||||
|
@ -1303,15 +1308,15 @@ impl<'a> LoadStart<'a> {
|
|||
);
|
||||
|
||||
match res_loaded {
|
||||
Ok((module_id, msg)) => {
|
||||
Ok(header_output) => {
|
||||
if let Msg::Header(ModuleHeader {
|
||||
module_id: header_id,
|
||||
header_type,
|
||||
is_root_module,
|
||||
..
|
||||
}) = &msg
|
||||
}) = &header_output.msg
|
||||
{
|
||||
debug_assert_eq!(*header_id, module_id);
|
||||
debug_assert_eq!(*header_id, header_output.module_id);
|
||||
debug_assert!(is_root_module);
|
||||
|
||||
if let HeaderType::Interface { name, .. } = header_type {
|
||||
|
@ -1327,7 +1332,7 @@ impl<'a> LoadStart<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
(module_id, msg)
|
||||
header_output
|
||||
}
|
||||
|
||||
Err(LoadingProblem::ParsingFailed(problem)) => {
|
||||
|
@ -1401,8 +1406,9 @@ impl<'a> LoadStart<'a> {
|
|||
arc_modules,
|
||||
ident_ids_by_module,
|
||||
src_dir,
|
||||
root_id,
|
||||
root_msg,
|
||||
root_id: header_output.module_id,
|
||||
root_msg: header_output.msg,
|
||||
opt_platform_shorthand: header_output.opt_platform_shorthand,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1418,7 +1424,11 @@ impl<'a> LoadStart<'a> {
|
|||
let ident_ids_by_module = Arc::new(Mutex::new(root_exposed_ident_ids));
|
||||
|
||||
// Load the root module synchronously; we can't proceed until we have its id.
|
||||
let (root_id, root_msg) = {
|
||||
let HeaderOutput {
|
||||
module_id: root_id,
|
||||
msg: root_msg,
|
||||
opt_platform_shorthand: opt_platform_id,
|
||||
} = {
|
||||
let root_start_time = Instant::now();
|
||||
|
||||
load_from_str(
|
||||
|
@ -1438,6 +1448,7 @@ impl<'a> LoadStart<'a> {
|
|||
ident_ids_by_module,
|
||||
root_id,
|
||||
root_msg,
|
||||
opt_platform_shorthand: opt_platform_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1581,6 +1592,7 @@ pub fn load_single_threaded<'a>(
|
|||
root_id,
|
||||
root_msg,
|
||||
src_dir,
|
||||
opt_platform_shorthand,
|
||||
..
|
||||
} = load_start;
|
||||
|
||||
|
@ -1593,6 +1605,7 @@ pub fn load_single_threaded<'a>(
|
|||
let number_of_workers = 1;
|
||||
let mut state = State::new(
|
||||
root_id,
|
||||
opt_platform_shorthand,
|
||||
target_info,
|
||||
exposed_types,
|
||||
arc_modules,
|
||||
|
@ -1851,6 +1864,7 @@ fn load_multi_threaded<'a>(
|
|||
root_id,
|
||||
root_msg,
|
||||
src_dir,
|
||||
opt_platform_shorthand,
|
||||
..
|
||||
} = load_start;
|
||||
|
||||
|
@ -1878,6 +1892,7 @@ fn load_multi_threaded<'a>(
|
|||
|
||||
let mut state = State::new(
|
||||
root_id,
|
||||
opt_platform_shorthand,
|
||||
target_info,
|
||||
exposed_types,
|
||||
arc_modules,
|
||||
|
@ -2360,8 +2375,6 @@ fn update<'a>(
|
|||
provides,
|
||||
..
|
||||
} => {
|
||||
debug_assert!(matches!(state.platform_data, None));
|
||||
|
||||
work.extend(state.dependencies.notify_package(config_shorthand));
|
||||
|
||||
let is_prebuilt = if header.is_root_module {
|
||||
|
@ -2371,7 +2384,7 @@ fn update<'a>(
|
|||
));
|
||||
state.platform_path = PlatformPath::RootIsPlatformModule;
|
||||
|
||||
// If the root module is a platform, then the platform is the very
|
||||
// If the root module is this platform, then the platform is the very
|
||||
// thing we're rebuilding!
|
||||
false
|
||||
} else {
|
||||
|
@ -2382,11 +2395,17 @@ fn update<'a>(
|
|||
)
|
||||
};
|
||||
|
||||
state.platform_data = Some(PlatformData {
|
||||
module_id: header.module_id,
|
||||
provides,
|
||||
is_prebuilt,
|
||||
});
|
||||
// If we're building an app module, and this was the platform
|
||||
// specified in its header's `to` field, record it as our platform.
|
||||
if state.opt_platform_shorthand == Some(config_shorthand) {
|
||||
debug_assert!(matches!(state.platform_data, None));
|
||||
|
||||
state.platform_data = Some(PlatformData {
|
||||
module_id: header.module_id,
|
||||
provides,
|
||||
is_prebuilt,
|
||||
});
|
||||
}
|
||||
}
|
||||
Builtin { .. } | Interface { .. } => {
|
||||
if header.is_root_module {
|
||||
|
@ -3490,7 +3509,7 @@ fn load_module<'a>(
|
|||
arc_shorthands: Arc<Mutex<MutMap<&'a str, ShorthandPath>>>,
|
||||
roc_cache_dir: RocCacheDir<'_>,
|
||||
ident_ids_by_module: SharedIdentIdsByModule,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
) -> Result<HeaderOutput<'a>, LoadingProblem<'a>> {
|
||||
let module_start_time = Instant::now();
|
||||
|
||||
let parse_start = Instant::now();
|
||||
|
@ -3507,14 +3526,16 @@ fn load_module<'a>(
|
|||
match module_name.as_inner().as_str() {
|
||||
$(
|
||||
$name => {
|
||||
return Ok(load_builtin_module(
|
||||
let (module_id, msg) = load_builtin_module(
|
||||
arena,
|
||||
module_ids,
|
||||
ident_ids_by_module,
|
||||
module_timing,
|
||||
$module_id,
|
||||
concat!($name, ".roc")
|
||||
));
|
||||
);
|
||||
|
||||
return Ok(HeaderOutput { module_id, msg, opt_platform_shorthand: None });
|
||||
}
|
||||
)*
|
||||
_ => { /* fall through */ }
|
||||
|
@ -3693,6 +3714,14 @@ fn verify_interface_matches_file_path<'a>(
|
|||
Err(problem)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct HeaderOutput<'a> {
|
||||
module_id: ModuleId,
|
||||
msg: Msg<'a>,
|
||||
/// Only comes up if we're parsing an app module
|
||||
opt_platform_shorthand: Option<&'a str>,
|
||||
}
|
||||
|
||||
fn parse_header<'a>(
|
||||
arena: &'a Bump,
|
||||
read_file_duration: Duration,
|
||||
|
@ -3705,7 +3734,7 @@ fn parse_header<'a>(
|
|||
src_bytes: &'a [u8],
|
||||
roc_cache_dir: RocCacheDir<'_>,
|
||||
start_time: Instant,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
) -> Result<HeaderOutput<'a>, LoadingProblem<'a>> {
|
||||
let parse_start = Instant::now();
|
||||
let parse_state = roc_parse::state::State::new(src_bytes);
|
||||
let parsed = roc_parse::module::parse_header(arena, parse_state.clone());
|
||||
|
@ -3767,7 +3796,11 @@ fn parse_header<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
Ok((module_id, Msg::Header(header)))
|
||||
Ok(HeaderOutput {
|
||||
module_id,
|
||||
msg: Msg::Header(header),
|
||||
opt_platform_shorthand: None,
|
||||
})
|
||||
}
|
||||
Ok((
|
||||
ast::Module {
|
||||
|
@ -3798,7 +3831,11 @@ fn parse_header<'a>(
|
|||
module_timing,
|
||||
);
|
||||
|
||||
Ok((module_id, Msg::Header(header)))
|
||||
Ok(HeaderOutput {
|
||||
module_id,
|
||||
msg: Msg::Header(header),
|
||||
opt_platform_shorthand: None,
|
||||
})
|
||||
}
|
||||
Ok((
|
||||
ast::Module {
|
||||
|
@ -3857,92 +3894,81 @@ fn parse_header<'a>(
|
|||
);
|
||||
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 {
|
||||
To::ExistingPackage(existing_package) => {
|
||||
let opt_base_package = packages.iter().find_map(|loc_package_entry| {
|
||||
To::ExistingPackage(shorthand) => {
|
||||
let package_path = packages.iter().find_map(|loc_package_entry| {
|
||||
let Loc { value, .. } = loc_package_entry;
|
||||
|
||||
if value.shorthand == existing_package {
|
||||
Some(value)
|
||||
if value.shorthand == shorthand {
|
||||
Some(value.package_name.value)
|
||||
} else {
|
||||
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 {
|
||||
shorthand,
|
||||
package_name:
|
||||
Loc {
|
||||
value: package_path,
|
||||
..
|
||||
},
|
||||
..
|
||||
}) = opt_base_package
|
||||
{
|
||||
let src = package_path.to_str();
|
||||
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.
|
||||
// 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 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"),
|
||||
}
|
||||
// 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)
|
||||
};
|
||||
|
||||
if platform_module_path.as_path().exists() {
|
||||
let load_platform_module_msg = load_platform_module(
|
||||
arena,
|
||||
&platform_module_path,
|
||||
shorthand,
|
||||
module_id,
|
||||
module_ids,
|
||||
ident_ids_by_module,
|
||||
)?;
|
||||
|
||||
Ok((
|
||||
module_id,
|
||||
Msg::Many(vec![app_module_header_msg, load_platform_module_msg]),
|
||||
))
|
||||
} else {
|
||||
Err(LoadingProblem::FileProblem {
|
||||
filename: platform_module_path,
|
||||
error: io::ErrorKind::NotFound,
|
||||
})
|
||||
}
|
||||
#[cfg(target_family = "wasm")]
|
||||
{
|
||||
panic!("Specifying packages via URLs is curently unsupported in wasm.");
|
||||
}
|
||||
} else {
|
||||
panic!("could not find base")
|
||||
app_file_dir.join(src)
|
||||
};
|
||||
|
||||
if platform_module_path.as_path().exists() {
|
||||
let load_platform_module_msg = load_platform_module(
|
||||
arena,
|
||||
&platform_module_path,
|
||||
shorthand,
|
||||
module_id,
|
||||
module_ids,
|
||||
ident_ids_by_module,
|
||||
)?;
|
||||
|
||||
Ok(HeaderOutput {
|
||||
module_id,
|
||||
msg: Msg::Many(vec![app_module_header_msg, load_platform_module_msg]),
|
||||
opt_platform_shorthand: Some(shorthand),
|
||||
})
|
||||
} else {
|
||||
Err(LoadingProblem::FileProblem {
|
||||
filename: platform_module_path,
|
||||
error: io::ErrorKind::NotFound,
|
||||
})
|
||||
}
|
||||
}
|
||||
To::NewPackage(_package_name) => Ok((module_id, app_module_header_msg)),
|
||||
To::NewPackage(_package_name) => Ok(HeaderOutput {
|
||||
module_id,
|
||||
msg: app_module_header_msg,
|
||||
opt_platform_shorthand: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
Ok((
|
||||
|
@ -3964,9 +3990,12 @@ fn parse_header<'a>(
|
|||
module_timing,
|
||||
);
|
||||
|
||||
Ok((module_id, Msg::Header(header)))
|
||||
Ok(HeaderOutput {
|
||||
module_id,
|
||||
msg: Msg::Header(header),
|
||||
opt_platform_shorthand: None,
|
||||
})
|
||||
}
|
||||
|
||||
Err(fail) => Err(LoadingProblem::ParsingFailed(
|
||||
fail.map_problem(SyntaxError::Header)
|
||||
.into_file_error(filename),
|
||||
|
@ -3985,7 +4014,7 @@ fn load_filename<'a>(
|
|||
ident_ids_by_module: SharedIdentIdsByModule,
|
||||
roc_cache_dir: RocCacheDir<'_>,
|
||||
module_start_time: Instant,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
) -> Result<HeaderOutput<'a>, LoadingProblem<'a>> {
|
||||
let file_io_start = Instant::now();
|
||||
let file = fs::read(&filename);
|
||||
let file_io_duration = file_io_start.elapsed();
|
||||
|
@ -4021,7 +4050,7 @@ fn load_from_str<'a>(
|
|||
ident_ids_by_module: SharedIdentIdsByModule,
|
||||
roc_cache_dir: RocCacheDir<'_>,
|
||||
module_start_time: Instant,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> {
|
||||
) -> Result<HeaderOutput<'a>, LoadingProblem<'a>> {
|
||||
let file_io_start = Instant::now();
|
||||
let file_io_duration = file_io_start.elapsed();
|
||||
|
||||
|
@ -5822,7 +5851,7 @@ fn run_task<'a>(
|
|||
roc_cache_dir,
|
||||
ident_ids_by_module,
|
||||
)
|
||||
.map(|(_, msg)| msg),
|
||||
.map(|HeaderOutput { msg, .. }| msg),
|
||||
Parse { header } => parse(arena, header),
|
||||
CanonicalizeAndConstrain {
|
||||
parsed,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue