Merge pull request #4737 from roc-lang/to

Use app module's `to` to determine platform
This commit is contained in:
Richard Feldman 2022-12-13 06:04:25 -05:00 committed by GitHub
commit 3d1cdf1fd4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 168 additions and 139 deletions

View file

@ -9,7 +9,7 @@ use roc_parse::ast::{Collection, Header, Module, Spaced, Spaces};
use roc_parse::header::{ use roc_parse::header::{
AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword, HostedHeader, ImportsEntry, AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword, HostedHeader, ImportsEntry,
ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName, PackageEntry, ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName, PackageEntry,
PackageKeyword, PackageName, PackagesKeyword, PlatformHeader, PlatformRequires, PackageKeyword, PackagePath, PackagesKeyword, PlatformHeader, PlatformRequires,
ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword, ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
}; };
use roc_parse::ident::UppercaseIdent; use roc_parse::ident::UppercaseIdent;
@ -276,7 +276,7 @@ impl<'a> Formattable for TypedIdent<'a> {
} }
} }
fn fmt_package_name<'buf>(buf: &mut Buf<'buf>, name: PackageName, _indent: u16) { fn fmt_package_name<'buf>(buf: &mut Buf<'buf>, name: PackagePath, _indent: u16) {
buf.push('"'); buf.push('"');
buf.push_str_allow_spaces(name.to_str()); buf.push_str_allow_spaces(name.to_str());
buf.push('"'); buf.push('"');
@ -453,7 +453,7 @@ fn fmt_packages_entry<'a, 'buf>(buf: &mut Buf<'buf>, entry: &PackageEntry<'a>, i
buf.push_str(entry.shorthand); buf.push_str(entry.shorthand);
buf.push(':'); buf.push(':');
fmt_default_spaces(buf, entry.spaces_after_shorthand, indent); fmt_default_spaces(buf, entry.spaces_after_shorthand, indent);
fmt_package_name(buf, entry.package_name.value, indent); fmt_package_name(buf, entry.package_path.value, indent);
} }
fn fmt_imports_entry<'a, 'buf>(buf: &mut Buf<'buf>, entry: &ImportsEntry<'a>, indent: u16) { fn fmt_imports_entry<'a, 'buf>(buf: &mut Buf<'buf>, entry: &ImportsEntry<'a>, indent: u16) {

View file

@ -9,7 +9,7 @@ use roc_parse::{
}, },
header::{ header::{
AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, KeywordItem, AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, KeywordItem,
ModuleName, PackageEntry, PackageName, PlatformHeader, PlatformRequires, ProvidesTo, To, ModuleName, PackageEntry, PackagePath, PlatformHeader, PlatformRequires, ProvidesTo, To,
TypedIdent, TypedIdent,
}, },
ident::UppercaseIdent, ident::UppercaseIdent,
@ -349,7 +349,7 @@ impl<'a> RemoveSpaces<'a> for ModuleName<'a> {
} }
} }
impl<'a> RemoveSpaces<'a> for PackageName<'a> { impl<'a> RemoveSpaces<'a> for PackagePath<'a> {
fn remove_spaces(&self, _arena: &'a Bump) -> Self { fn remove_spaces(&self, _arena: &'a Bump) -> Self {
*self *self
} }
@ -394,7 +394,7 @@ impl<'a> RemoveSpaces<'a> for PackageEntry<'a> {
PackageEntry { PackageEntry {
shorthand: self.shorthand, shorthand: self.shorthand,
spaces_after_shorthand: &[], spaces_after_shorthand: &[],
package_name: self.package_name.remove_spaces(arena), package_path: self.package_path.remove_spaces(arena),
} }
} }
} }

View file

@ -43,7 +43,7 @@ use roc_packaging::cache::{self, RocCacheDir};
use roc_packaging::https::PackageMetadata; use roc_packaging::https::PackageMetadata;
use roc_parse::ast::{self, Defs, ExtractSpaces, Spaced, StrLiteral, TypeAnnotation}; use roc_parse::ast::{self, Defs, ExtractSpaces, Spaced, StrLiteral, TypeAnnotation};
use roc_parse::header::{ExposedName, ImportsEntry, PackageEntry, PlatformHeader, To, TypedIdent}; use roc_parse::header::{ExposedName, ImportsEntry, PackageEntry, PlatformHeader, To, TypedIdent};
use roc_parse::header::{HeaderType, PackageName}; use roc_parse::header::{HeaderType, PackagePath};
use roc_parse::module::module_defs; use roc_parse::module::module_defs;
use roc_parse::parser::{FileError, Parser, SourceError, SyntaxError}; use roc_parse::parser::{FileError, Parser, SourceError, SyntaxError};
use roc_problem::Severity; use roc_problem::Severity;
@ -642,7 +642,7 @@ struct ModuleHeader<'a> {
is_root_module: bool, is_root_module: bool,
exposed_ident_ids: IdentIds, exposed_ident_ids: IdentIds,
deps_by_name: MutMap<PQModuleName<'a>, ModuleId>, deps_by_name: MutMap<PQModuleName<'a>, ModuleId>,
packages: MutMap<&'a str, PackageName<'a>>, packages: MutMap<&'a str, PackagePath<'a>>,
imported_modules: MutMap<ModuleId, Region>, imported_modules: MutMap<ModuleId, Region>,
package_qualified_imported_modules: MutSet<PackageQualified<'a, ModuleId>>, package_qualified_imported_modules: MutSet<PackageQualified<'a, ModuleId>>,
exposes: Vec<Symbol>, exposes: Vec<Symbol>,
@ -915,6 +915,8 @@ struct State<'a> {
pub root_id: ModuleId, pub root_id: ModuleId,
pub root_subs: Option<Subs>, pub root_subs: Option<Subs>,
pub cache_dir: PathBuf, 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 platform_data: Option<PlatformData<'a>>,
pub exposed_types: ExposedByModule, pub exposed_types: ExposedByModule,
pub output_path: Option<&'a str>, pub output_path: Option<&'a str>,
@ -976,6 +978,7 @@ impl<'a> State<'a> {
fn new( fn new(
root_id: ModuleId, root_id: ModuleId,
opt_platform_shorthand: Option<&'a str>,
target_info: TargetInfo, target_info: TargetInfo,
exposed_types: ExposedByModule, exposed_types: ExposedByModule,
arc_modules: Arc<Mutex<PackageModuleIds<'a>>>, arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
@ -993,6 +996,7 @@ impl<'a> State<'a> {
Self { Self {
root_id, root_id,
root_subs: None, root_subs: None,
opt_platform_shorthand,
cache_dir, cache_dir,
target_info, target_info,
platform_data: None, platform_data: None,
@ -1269,6 +1273,7 @@ pub struct LoadStart<'a> {
arc_modules: Arc<Mutex<PackageModuleIds<'a>>>, arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: SharedIdentIdsByModule, ident_ids_by_module: SharedIdentIdsByModule,
root_id: ModuleId, root_id: ModuleId,
opt_platform_shorthand: Option<&'a str>,
root_msg: Msg<'a>, root_msg: Msg<'a>,
src_dir: PathBuf, src_dir: PathBuf,
} }
@ -1287,7 +1292,7 @@ impl<'a> LoadStart<'a> {
let mut src_dir = filename.parent().unwrap().to_path_buf(); let mut src_dir = filename.parent().unwrap().to_path_buf();
// Load the root module synchronously; we can't proceed until we have its id. // 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 root_start_time = Instant::now();
let res_loaded = load_filename( let res_loaded = load_filename(
@ -1303,15 +1308,15 @@ impl<'a> LoadStart<'a> {
); );
match res_loaded { match res_loaded {
Ok((module_id, msg)) => { Ok(header_output) => {
if let Msg::Header(ModuleHeader { if let Msg::Header(ModuleHeader {
module_id: header_id, module_id: header_id,
header_type, header_type,
is_root_module, 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); debug_assert!(is_root_module);
if let HeaderType::Interface { name, .. } = header_type { if let HeaderType::Interface { name, .. } = header_type {
@ -1327,7 +1332,7 @@ impl<'a> LoadStart<'a> {
} }
} }
(module_id, msg) header_output
} }
Err(LoadingProblem::ParsingFailed(problem)) => { Err(LoadingProblem::ParsingFailed(problem)) => {
@ -1401,8 +1406,9 @@ impl<'a> LoadStart<'a> {
arc_modules, arc_modules,
ident_ids_by_module, ident_ids_by_module,
src_dir, src_dir,
root_id, root_id: header_output.module_id,
root_msg, 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)); 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. // 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(); let root_start_time = Instant::now();
load_from_str( load_from_str(
@ -1438,6 +1448,7 @@ impl<'a> LoadStart<'a> {
ident_ids_by_module, ident_ids_by_module,
root_id, root_id,
root_msg, root_msg,
opt_platform_shorthand: opt_platform_id,
}) })
} }
} }
@ -1581,6 +1592,7 @@ pub fn load_single_threaded<'a>(
root_id, root_id,
root_msg, root_msg,
src_dir, src_dir,
opt_platform_shorthand,
.. ..
} = load_start; } = load_start;
@ -1593,6 +1605,7 @@ pub fn load_single_threaded<'a>(
let number_of_workers = 1; let number_of_workers = 1;
let mut state = State::new( let mut state = State::new(
root_id, root_id,
opt_platform_shorthand,
target_info, target_info,
exposed_types, exposed_types,
arc_modules, arc_modules,
@ -1851,6 +1864,7 @@ fn load_multi_threaded<'a>(
root_id, root_id,
root_msg, root_msg,
src_dir, src_dir,
opt_platform_shorthand,
.. ..
} = load_start; } = load_start;
@ -1878,6 +1892,7 @@ fn load_multi_threaded<'a>(
let mut state = State::new( let mut state = State::new(
root_id, root_id,
opt_platform_shorthand,
target_info, target_info,
exposed_types, exposed_types,
arc_modules, arc_modules,
@ -2360,8 +2375,6 @@ fn update<'a>(
provides, provides,
.. ..
} => { } => {
debug_assert!(matches!(state.platform_data, None));
work.extend(state.dependencies.notify_package(config_shorthand)); work.extend(state.dependencies.notify_package(config_shorthand));
let is_prebuilt = if header.is_root_module { let is_prebuilt = if header.is_root_module {
@ -2371,7 +2384,7 @@ fn update<'a>(
)); ));
state.platform_path = PlatformPath::RootIsPlatformModule; 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! // thing we're rebuilding!
false false
} else { } else {
@ -2382,11 +2395,17 @@ fn update<'a>(
) )
}; };
state.platform_data = Some(PlatformData { // If we're building an app module, and this was the platform
module_id: header.module_id, // specified in its header's `to` field, record it as our platform.
provides, if state.opt_platform_shorthand == Some(config_shorthand) {
is_prebuilt, debug_assert!(matches!(state.platform_data, None));
});
state.platform_data = Some(PlatformData {
module_id: header.module_id,
provides,
is_prebuilt,
});
}
} }
Builtin { .. } | Interface { .. } => { Builtin { .. } | Interface { .. } => {
if header.is_root_module { if header.is_root_module {
@ -3490,7 +3509,7 @@ fn load_module<'a>(
arc_shorthands: Arc<Mutex<MutMap<&'a str, ShorthandPath>>>, arc_shorthands: Arc<Mutex<MutMap<&'a str, ShorthandPath>>>,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
ident_ids_by_module: SharedIdentIdsByModule, ident_ids_by_module: SharedIdentIdsByModule,
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { ) -> Result<HeaderOutput<'a>, LoadingProblem<'a>> {
let module_start_time = Instant::now(); let module_start_time = Instant::now();
let parse_start = Instant::now(); let parse_start = Instant::now();
@ -3507,14 +3526,16 @@ fn load_module<'a>(
match module_name.as_inner().as_str() { match module_name.as_inner().as_str() {
$( $(
$name => { $name => {
return Ok(load_builtin_module( let (module_id, msg) = load_builtin_module(
arena, arena,
module_ids, module_ids,
ident_ids_by_module, ident_ids_by_module,
module_timing, module_timing,
$module_id, $module_id,
concat!($name, ".roc") concat!($name, ".roc")
)); );
return Ok(HeaderOutput { module_id, msg, opt_platform_shorthand: None });
} }
)* )*
_ => { /* fall through */ } _ => { /* fall through */ }
@ -3693,6 +3714,14 @@ fn verify_interface_matches_file_path<'a>(
Err(problem) 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>( fn parse_header<'a>(
arena: &'a Bump, arena: &'a Bump,
read_file_duration: Duration, read_file_duration: Duration,
@ -3705,7 +3734,7 @@ fn parse_header<'a>(
src_bytes: &'a [u8], src_bytes: &'a [u8],
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
start_time: Instant, start_time: Instant,
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { ) -> Result<HeaderOutput<'a>, LoadingProblem<'a>> {
let parse_start = Instant::now(); let parse_start = Instant::now();
let parse_state = roc_parse::state::State::new(src_bytes); let parse_state = roc_parse::state::State::new(src_bytes);
let parsed = roc_parse::module::parse_header(arena, parse_state.clone()); 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(( Ok((
ast::Module { ast::Module {
@ -3798,7 +3831,11 @@ fn parse_header<'a>(
module_timing, module_timing,
); );
Ok((module_id, Msg::Header(header))) Ok(HeaderOutput {
module_id,
msg: Msg::Header(header),
opt_platform_shorthand: None,
})
} }
Ok(( Ok((
ast::Module { ast::Module {
@ -3857,92 +3894,81 @@ fn parse_header<'a>(
); );
let app_module_header_msg = Msg::Header(resolved_header); 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(shorthand) => {
let opt_base_package = packages.iter().find_map(|loc_package_entry| { let package_path = packages.iter().find_map(|loc_package_entry| {
let Loc { value, .. } = loc_package_entry; let Loc { value, .. } = loc_package_entry;
if value.shorthand == existing_package { if value.shorthand == shorthand {
Some(value) Some(value.package_path.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 { let src = package_path.to_str();
shorthand,
package_name:
Loc {
value: package_path,
..
},
..
}) = opt_base_package
{
let src = package_path.to_str();
// check whether we can find a `platform` module file on disk // check whether we can find a `platform` module file on disk
let platform_module_path = if src.starts_with("https://") { let platform_module_path = if src.starts_with("https://") {
#[cfg(not(target_family = "wasm"))] #[cfg(not(target_family = "wasm"))]
{ {
// If this is a HTTPS package, synchronously download it // If this is a HTTPS package, synchronously download it
// to the cache before proceeding. // to the cache before proceeding.
// TODO we should do this async; however, with the current // TODO we should do this async; however, with the current
// architecture of file.rs (which doesn't use async/await), // architecture of file.rs (which doesn't use async/await),
// this would be very difficult! // this would be very difficult!
let (package_dir, opt_root_module) = cache::install_package( let (package_dir, opt_root_module) =
roc_cache_dir, cache::install_package(roc_cache_dir, src).unwrap_or_else(|err| {
src,
)
.unwrap_or_else(|err| {
todo!("TODO gracefully handle package install error {:?}", err); todo!("TODO gracefully handle package install error {:?}", err);
}); });
// You can optionally specify the root module using the URL fragment, // You can optionally specify the root module using the URL fragment,
// e.g. #foo.roc // e.g. #foo.roc
// (defaults to main.roc) // (defaults to main.roc)
match opt_root_module { match opt_root_module {
Some(root_module) => package_dir.join(root_module), Some(root_module) => package_dir.join(root_module),
None => package_dir.join("main.roc"), None => package_dir.join("main.roc"),
}
} }
}
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
{ {
panic!( panic!("Specifying packages via URLs is curently unsupported in wasm.");
"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,
})
} }
} else { } 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(( Ok((
@ -3964,9 +3990,12 @@ fn parse_header<'a>(
module_timing, 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( Err(fail) => Err(LoadingProblem::ParsingFailed(
fail.map_problem(SyntaxError::Header) fail.map_problem(SyntaxError::Header)
.into_file_error(filename), .into_file_error(filename),
@ -3985,7 +4014,7 @@ fn load_filename<'a>(
ident_ids_by_module: SharedIdentIdsByModule, ident_ids_by_module: SharedIdentIdsByModule,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
module_start_time: Instant, module_start_time: Instant,
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { ) -> Result<HeaderOutput<'a>, LoadingProblem<'a>> {
let file_io_start = Instant::now(); let file_io_start = Instant::now();
let file = fs::read(&filename); let file = fs::read(&filename);
let file_io_duration = file_io_start.elapsed(); let file_io_duration = file_io_start.elapsed();
@ -4021,7 +4050,7 @@ fn load_from_str<'a>(
ident_ids_by_module: SharedIdentIdsByModule, ident_ids_by_module: SharedIdentIdsByModule,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
module_start_time: Instant, module_start_time: Instant,
) -> Result<(ModuleId, Msg<'a>), LoadingProblem<'a>> { ) -> Result<HeaderOutput<'a>, LoadingProblem<'a>> {
let file_io_start = Instant::now(); let file_io_start = Instant::now();
let file_io_duration = file_io_start.elapsed(); let file_io_duration = file_io_start.elapsed();
@ -4289,7 +4318,7 @@ fn build_header<'a>(
let package_entries = packages let package_entries = packages
.iter() .iter()
.map(|Loc { value: pkg, .. }| (pkg.shorthand, pkg.package_name.value)) .map(|Loc { value: pkg, .. }| (pkg.shorthand, pkg.package_path.value))
.collect::<MutMap<_, _>>(); .collect::<MutMap<_, _>>();
// Send the deps to the coordinator thread for processing, // Send the deps to the coordinator thread for processing,
@ -5822,7 +5851,7 @@ fn run_task<'a>(
roc_cache_dir, roc_cache_dir,
ident_ids_by_module, ident_ids_by_module,
) )
.map(|(_, msg)| msg), .map(|HeaderOutput { msg, .. }| msg),
Parse { header } => parse(arena, header), Parse { header } => parse(arena, header),
CanonicalizeAndConstrain { CanonicalizeAndConstrain {
parsed, parsed,

View file

@ -2,7 +2,7 @@ use crate::ast::{Collection, CommentOrNewline, Spaced, Spaces, StrLiteral, TypeA
use crate::blankspace::space0_e; use crate::blankspace::space0_e;
use crate::ident::{lowercase_ident, UppercaseIdent}; use crate::ident::{lowercase_ident, UppercaseIdent};
use crate::parser::{optional, then}; use crate::parser::{optional, then};
use crate::parser::{specialize, word1, EPackageEntry, EPackageName, Parser}; use crate::parser::{specialize, word1, EPackageEntry, EPackagePath, Parser};
use crate::string_literal; use crate::string_literal;
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use roc_module::symbol::{ModuleId, Symbol}; use roc_module::symbol::{ModuleId, Symbol};
@ -59,9 +59,9 @@ pub enum VersionComparison {
} }
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct PackageName<'a>(&'a str); pub struct PackagePath<'a>(&'a str);
impl<'a> PackageName<'a> { impl<'a> PackagePath<'a> {
pub fn to_str(self) -> &'a str { pub fn to_str(self) -> &'a str {
self.0 self.0
} }
@ -71,13 +71,13 @@ impl<'a> PackageName<'a> {
} }
} }
impl<'a> From<PackageName<'a>> for &'a str { impl<'a> From<PackagePath<'a>> for &'a str {
fn from(name: PackageName<'a>) -> &'a str { fn from(name: PackagePath<'a>) -> &'a str {
name.0 name.0
} }
} }
impl<'a> From<&'a str> for PackageName<'a> { impl<'a> From<&'a str> for PackagePath<'a> {
fn from(string: &'a str) -> Self { fn from(string: &'a str) -> Self {
Self(string) Self(string)
} }
@ -181,7 +181,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(PackagePath<'a>),
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@ -209,13 +209,13 @@ pub struct ProvidesTo<'a> {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct PackageHeader<'a> { pub struct PackageHeader<'a> {
pub before_name: &'a [CommentOrNewline<'a>], pub before_name: &'a [CommentOrNewline<'a>],
pub name: Loc<PackageName<'a>>, pub name: Loc<PackagePath<'a>>,
pub exposes_keyword: Spaces<'a, ExposesKeyword>, pub exposes_keyword: Spaces<'a, ExposesKeyword>,
pub exposes: Vec<'a, Loc<Spaced<'a, ExposedName<'a>>>>, pub exposes: Vec<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
pub packages_keyword: Spaces<'a, PackagesKeyword>, pub packages_keyword: Spaces<'a, PackagesKeyword>,
pub packages: Vec<'a, (Loc<&'a str>, Loc<PackageName<'a>>)>, pub packages: Vec<'a, (Loc<&'a str>, Loc<PackagePath<'a>>)>,
pub imports_keyword: Spaces<'a, ImportsKeyword>, pub imports_keyword: Spaces<'a, ImportsKeyword>,
pub imports: Vec<'a, Loc<ImportsEntry<'a>>>, pub imports: Vec<'a, Loc<ImportsEntry<'a>>>,
@ -230,7 +230,7 @@ pub struct PlatformRequires<'a> {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct PlatformHeader<'a> { pub struct PlatformHeader<'a> {
pub before_name: &'a [CommentOrNewline<'a>], pub before_name: &'a [CommentOrNewline<'a>],
pub name: Loc<PackageName<'a>>, pub name: Loc<PackagePath<'a>>,
pub requires: KeywordItem<'a, RequiresKeyword, PlatformRequires<'a>>, pub requires: KeywordItem<'a, RequiresKeyword, PlatformRequires<'a>>,
pub exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>>, pub exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc<Spaced<'a, ModuleName<'a>>>>>,
@ -271,7 +271,7 @@ pub struct TypedIdent<'a> {
pub struct PackageEntry<'a> { pub struct PackageEntry<'a> {
pub shorthand: &'a str, pub shorthand: &'a str,
pub spaces_after_shorthand: &'a [CommentOrNewline<'a>], pub spaces_after_shorthand: &'a [CommentOrNewline<'a>],
pub package_name: Loc<PackageName<'a>>, pub package_path: Loc<PackagePath<'a>>,
} }
pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPackageEntry<'a>> { pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPackageEntry<'a>> {
@ -288,19 +288,19 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
), ),
space0_e(EPackageEntry::IndentPackage) space0_e(EPackageEntry::IndentPackage)
)), )),
loc!(specialize(EPackageEntry::BadPackage, package_name())) loc!(specialize(EPackageEntry::BadPackage, package_path()))
), ),
move |(opt_shorthand, package_or_path)| { move |(opt_shorthand, package_or_path)| {
let entry = match opt_shorthand { let entry = match opt_shorthand {
Some((shorthand, spaces_after_shorthand)) => PackageEntry { Some((shorthand, spaces_after_shorthand)) => PackageEntry {
shorthand, shorthand,
spaces_after_shorthand, spaces_after_shorthand,
package_name: package_or_path, package_path: package_or_path,
}, },
None => PackageEntry { None => PackageEntry {
shorthand: "", shorthand: "",
spaces_after_shorthand: &[], spaces_after_shorthand: &[],
package_name: package_or_path, package_path: package_or_path,
}, },
}; };
@ -309,13 +309,13 @@ pub fn package_entry<'a>() -> impl Parser<'a, Spaced<'a, PackageEntry<'a>>, EPac
) )
} }
pub fn package_name<'a>() -> impl Parser<'a, PackageName<'a>, EPackageName<'a>> { pub fn package_path<'a>() -> impl Parser<'a, PackagePath<'a>, EPackagePath<'a>> {
then( then(
loc!(specialize(EPackageName::BadPath, string_literal::parse())), loc!(specialize(EPackagePath::BadPath, string_literal::parse())),
move |_arena, state, progress, text| match text.value { move |_arena, state, progress, text| match text.value {
StrLiteral::PlainLine(text) => Ok((progress, PackageName(text), state)), StrLiteral::PlainLine(text) => Ok((progress, PackagePath(text), state)),
StrLiteral::Line(_) => Err((progress, EPackageName::Escapes(text.region.start()))), StrLiteral::Line(_) => Err((progress, EPackagePath::Escapes(text.region.start()))),
StrLiteral::Block(_) => Err((progress, EPackageName::Multiline(text.region.start()))), StrLiteral::Block(_) => Err((progress, EPackagePath::Multiline(text.region.start()))),
}, },
) )
} }

View file

@ -1,7 +1,7 @@
use crate::ast::{Collection, Defs, Header, Module, Spaced, Spaces}; use crate::ast::{Collection, Defs, Header, Module, Spaced, Spaces};
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e}; use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
use crate::header::{ use crate::header::{
package_entry, package_name, AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword, package_entry, package_path, AppHeader, ExposedName, ExposesKeyword, GeneratesKeyword,
HostedHeader, ImportsEntry, ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName, HostedHeader, ImportsEntry, ImportsKeyword, InterfaceHeader, Keyword, KeywordItem, ModuleName,
PackageEntry, PackagesKeyword, PlatformHeader, PlatformRequires, ProvidesKeyword, ProvidesTo, PackageEntry, PackagesKeyword, PlatformHeader, PlatformRequires, ProvidesKeyword, ProvidesTo,
RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword, RequiresKeyword, To, ToKeyword, TypedIdent, WithKeyword,
@ -187,7 +187,7 @@ fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> {
fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> { fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> {
record!(PlatformHeader { record!(PlatformHeader {
before_name: space0_e(EHeader::IndentStart), before_name: space0_e(EHeader::IndentStart),
name: loc!(specialize(EHeader::PlatformName, package_name())), name: loc!(specialize(EHeader::PlatformName, package_path())),
requires: specialize(EHeader::Requires, requires()), requires: specialize(EHeader::Requires, requires()),
exposes: specialize(EHeader::Exposes, exposes_modules()), exposes: specialize(EHeader::Exposes, exposes_modules()),
packages: specialize(EHeader::Packages, packages()), packages: specialize(EHeader::Packages, packages()),
@ -203,7 +203,7 @@ fn provides_to_package<'a>() -> impl Parser<'a, To<'a>, EProvides<'a>> {
|_, pos| EProvides::Identifier(pos), |_, pos| EProvides::Identifier(pos),
map!(lowercase_ident(), To::ExistingPackage) map!(lowercase_ident(), To::ExistingPackage)
), ),
specialize(EProvides::Package, map!(package_name(), To::NewPackage)) specialize(EProvides::Package, map!(package_path(), To::NewPackage))
] ]
} }

View file

@ -127,7 +127,7 @@ pub enum EHeader<'a> {
Start(Position), Start(Position),
ModuleName(Position), ModuleName(Position),
AppName(EString<'a>, Position), AppName(EString<'a>, Position),
PlatformName(EPackageName<'a>, Position), PlatformName(EPackagePath<'a>, Position),
IndentStart(Position), IndentStart(Position),
InconsistentModuleName(Region), InconsistentModuleName(Region),
@ -146,7 +146,7 @@ pub enum EProvides<'a> {
ListStart(Position), ListStart(Position),
ListEnd(Position), ListEnd(Position),
Identifier(Position), Identifier(Position),
Package(EPackageName<'a>, Position), Package(EPackagePath<'a>, Position),
Space(BadInputError, Position), Space(BadInputError, Position),
} }
@ -202,7 +202,7 @@ pub enum EPackages<'a> {
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum EPackageName<'a> { pub enum EPackagePath<'a> {
BadPath(EString<'a>, Position), BadPath(EString<'a>, Position),
Escapes(Position), Escapes(Position),
Multiline(Position), Multiline(Position),
@ -210,7 +210,7 @@ pub enum EPackageName<'a> {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum EPackageEntry<'a> { pub enum EPackageEntry<'a> {
BadPackage(EPackageName<'a>, Position), BadPackage(EPackagePath<'a>, Position),
Shorthand(Position), Shorthand(Position),
Colon(Position), Colon(Position),
IndentPackage(Position), IndentPackage(Position),

View file

@ -3,7 +3,7 @@ Module {
header: Platform( header: Platform(
PlatformHeader { PlatformHeader {
before_name: [], before_name: [],
name: @9-25 PackageName( name: @9-25 PackagePath(
"rtfeldman/blah", "rtfeldman/blah",
), ),
requires: KeywordItem { requires: KeywordItem {

View file

@ -19,7 +19,7 @@ Module {
@31-47 PackageEntry { @31-47 PackageEntry {
shorthand: "pf", shorthand: "pf",
spaces_after_shorthand: [], spaces_after_shorthand: [],
package_name: @35-47 PackageName( package_path: @35-47 PackagePath(
"./platform", "./platform",
), ),
}, },

View file

@ -19,7 +19,7 @@ Module {
@31-47 PackageEntry { @31-47 PackageEntry {
shorthand: "pf", shorthand: "pf",
spaces_after_shorthand: [], spaces_after_shorthand: [],
package_name: @35-47 PackageName( package_path: @35-47 PackagePath(
"./platform", "./platform",
), ),
}, },

View file

@ -3,7 +3,7 @@ Module {
header: Platform( header: Platform(
PlatformHeader { PlatformHeader {
before_name: [], before_name: [],
name: @9-14 PackageName( name: @9-14 PackagePath(
"cli", "cli",
), ),
requires: KeywordItem { requires: KeywordItem {

View file

@ -22,7 +22,7 @@ Module {
after: [], after: [],
}, },
to: @30-38 NewPackage( to: @30-38 NewPackage(
PackageName( PackagePath(
"./blah", "./blah",
), ),
), ),

View file

@ -3,7 +3,7 @@ Module {
header: Platform( header: Platform(
PlatformHeader { PlatformHeader {
before_name: [], before_name: [],
name: @9-21 PackageName( name: @9-21 PackagePath(
"foo/barbaz", "foo/barbaz",
), ),
requires: KeywordItem { requires: KeywordItem {
@ -52,7 +52,7 @@ Module {
@87-99 PackageEntry { @87-99 PackageEntry {
shorthand: "foo", shorthand: "foo",
spaces_after_shorthand: [], spaces_after_shorthand: [],
package_name: @92-99 PackageName( package_path: @92-99 PackagePath(
"./foo", "./foo",
), ),
}, },

View file

@ -19,7 +19,7 @@ Module {
@26-42 PackageEntry { @26-42 PackageEntry {
shorthand: "pf", shorthand: "pf",
spaces_after_shorthand: [], spaces_after_shorthand: [],
package_name: @30-42 PackageName( package_path: @30-42 PackagePath(
"./platform", "./platform",
), ),
}, },

View file

@ -3,7 +3,7 @@ Module {
header: Platform( header: Platform(
PlatformHeader { PlatformHeader {
before_name: [], before_name: [],
name: @9-21 PackageName( name: @9-21 PackagePath(
"test/types", "test/types",
), ),
requires: KeywordItem { requires: KeywordItem {