Merge pull request #779 from rtfeldman/package-qualified-example

Package qualified example
This commit is contained in:
Richard Feldman 2020-12-07 22:46:01 -05:00 committed by GitHub
commit f72cc7c497
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 290 additions and 130 deletions

View File

@ -45,6 +45,9 @@ pub fn build_file(
src_dir.as_path(),
subs_by_module,
)?;
let path_to_platform = loaded.platform_path.clone();
let app_o_file = roc_file_path.with_file_name("roc_app.o");
let buf = &mut String::with_capacity(1024);
@ -127,7 +130,9 @@ pub fn build_file(
);
// Step 2: link the precompiled host and compiled app
let host_input_path = cwd.join("platform").join("host.o");
let mut host_input_path = PathBuf::from(cwd);
host_input_path.push(&*path_to_platform);
host_input_path.push("host.o");
// TODO we should no longer need to do this once we have platforms on
// a package repository, as we can then get precompiled hosts from there.

View File

@ -88,7 +88,7 @@ pub fn rebuild_host(host_input_path: &Path) {
.output()
.unwrap();
validate_output("host.rs", "cargo build --release", output);
validate_output("src/lib.rs", "cargo build --release", output);
let output = Command::new("ld")
.env_clear()

View File

@ -119,14 +119,8 @@ pub fn canonicalize_module_defs<'a>(
} else {
// This is a type alias
// the same scheme as with identifiers won't work here, e.g.
//
// Task : Effect
//
// really is not the same as
//
// Task a : Effect a
panic!("TODO add type aliases to type alias dictionary, based on exposed types");
// the should already be added to the scope when this module is canonicalized
debug_assert!(scope.contains_alias(symbol));
}
}

View File

@ -192,4 +192,8 @@ impl Scope {
self.aliases.insert(name, alias);
}
pub fn contains_alias(&mut self, name: Symbol) -> bool {
self.aliases.contains_key(&name)
}
}

View File

@ -14,7 +14,9 @@ use roc_constrain::module::{
};
use roc_constrain::module::{constrain_module, ExposedModuleTypes, SubsByModule};
use roc_module::ident::{Ident, Lowercase, ModuleName, QualifiedModuleName, TagName};
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, PackageModuleIds, Symbol};
use roc_module::symbol::{
IdentIds, Interns, ModuleId, ModuleIds, PQModuleName, PackageModuleIds, Symbol,
};
use roc_mono::ir::{
CapturedSymbols, ExternalSpecializations, PartialProc, PendingSpecialization, Proc, Procs,
};
@ -230,7 +232,13 @@ impl Dependencies {
self.add_dependency_help(a, b, phase, phase);
}
/// phase_a of module a is waiting for phase_b of module_b
fn add_dependency_help(&mut self, a: ModuleId, b: ModuleId, phase_a: Phase, phase_b: Phase) {
// no need to wait if the dependency is already done!
if let Some(Status::Done) = self.status.get(&(b, phase_b)) {
return;
}
let key = (a, phase_a);
let value = (b, phase_b);
match self.waiting_for.get_mut(&key) {
@ -279,7 +287,7 @@ impl Dependencies {
/// Struct storing various intermediate stages by their ModuleId
#[derive(Debug, Default)]
struct ModuleCache<'a> {
module_names: MutMap<ModuleId, ModuleName>,
module_names: MutMap<ModuleId, PQModuleName<'a>>,
/// Phases
headers: MutMap<ModuleId, ModuleHeader<'a>>,
@ -342,15 +350,16 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
let dep_name = state
.module_cache
.module_names
.remove(&module_id)
.expect("module id is present");
.get(&module_id)
.expect("module id is present")
.clone();
BuildTask::LoadModule {
module_name: dep_name,
// Provide mutexes of ModuleIds and IdentIds by module,
// so other modules can populate them as they load.
module_ids: Arc::clone(&state.arc_modules),
package_module_ids: Arc::clone(&state.arc_package_modules),
shorthands: Arc::clone(&state.arc_shorthands),
ident_ids_by_module: Arc::clone(&state.ident_ids_by_module),
mode: state.stdlib.mode,
}
@ -399,8 +408,10 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
// This should be small, and cloning it should be quick.
// We release the lock as soon as we're done cloning, so we don't have
// to lock the global module_ids while canonicalizing any given module.
let module_ids = Arc::clone(&state.arc_modules);
let module_ids = { (*module_ids).lock().clone() };
let qualified_module_ids = Arc::clone(&state.arc_modules);
let qualified_module_ids = { (*qualified_module_ids).lock().clone() };
let module_ids = qualified_module_ids.into_module_ids();
let exposed_symbols = state
.exposed_symbols_by_module
@ -411,17 +422,16 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
for imported in parsed.imported_modules.iter() {
match state.module_cache.aliases.get(imported) {
None => unreachable!(
"imported module {:?} did not register its aliases, so {:?} cannot use them",
imported,
parsed.module_id,
),
Some(new) => {
// TODO filter to only add imported aliases
aliases.extend(new.iter().map(|(s, a)| (*s, a.clone())));
None => unreachable!(
r"imported module {:?} did not register its aliases, so {:?} cannot use them",
imported, parsed.module_id,
),
Some(new) => {
// TODO filter to only add imported aliases
aliases.extend(new.iter().map(|(s, a)| (*s, a.clone())));
}
}
}
}
BuildTask::CanonicalizeAndConstrain {
parsed,
@ -544,11 +554,12 @@ struct ModuleHeader<'a> {
module_name: AppOrInterfaceName<'a>,
module_path: PathBuf,
exposed_ident_ids: IdentIds,
deps_by_name: MutMap<ModuleName, ModuleId>,
deps_by_name: MutMap<PQModuleName<'a>, ModuleId>,
packages: MutMap<&'a str, PackageOrPath<'a>>,
imported_modules: MutSet<ModuleId>,
imported_package_modules: MutSet<ModuleId>,
exposes: Vec<Symbol>,
exposed_imports: MutMap<Ident, (Symbol, Region)>,
to_platform: Option<To<'a>>,
src: &'a [u8],
module_timing: ModuleTiming,
}
@ -590,6 +601,7 @@ pub struct MonomorphizedModule<'a> {
pub interns: Interns,
pub subs: Subs,
pub output_path: Box<str>,
pub platform_path: Box<str>,
pub can_problems: MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
pub type_problems: MutMap<ModuleId, Vec<solve::TypeError>>,
pub mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>,
@ -612,7 +624,7 @@ struct ParsedModule<'a> {
module_path: PathBuf,
src: &'a str,
module_timing: ModuleTiming,
deps_by_name: MutMap<ModuleName, ModuleId>,
deps_by_name: MutMap<PQModuleName<'a>, ModuleId>,
imported_modules: MutSet<ModuleId>,
exposed_ident_ids: IdentIds,
exposed_imports: MutMap<Ident, (Symbol, Region)>,
@ -682,6 +694,7 @@ struct State<'a> {
pub stdlib: StdLib,
pub exposed_types: SubsByModule,
pub output_path: Option<&'a str>,
pub platform_path: Option<To<'a>>,
pub opt_effect_module: Option<ModuleId>,
pub headers_parsed: MutSet<ModuleId>,
@ -696,8 +709,8 @@ struct State<'a> {
pub constrained_ident_ids: MutMap<ModuleId, IdentIds>,
/// From now on, these will be used by multiple threads; time to make an Arc<Mutex<_>>!
pub arc_modules: Arc<Mutex<ModuleIds>>,
pub arc_package_modules: Arc<Mutex<PackageModuleIds<'a>>>,
pub arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
pub arc_shorthands: Arc<Mutex<MutMap<&'a str, PackageOrPath<'a>>>>,
pub ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
@ -825,16 +838,15 @@ impl ModuleTiming {
#[allow(dead_code)]
enum BuildTask<'a> {
LoadModule {
module_name: ModuleName,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
module_name: PQModuleName<'a>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
shorthands: Arc<Mutex<MutMap<&'a str, PackageOrPath<'a>>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
mode: Mode,
},
LoadPkgConfig {
shorthand: &'a str,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
mode: Mode,
},
@ -888,6 +900,7 @@ pub enum LoadingProblem {
FileProblem {
filename: PathBuf,
error: io::ErrorKind,
msg: &'static str,
},
ParsingFailed {
filename: PathBuf,
@ -999,8 +1012,7 @@ pub fn load_and_monomorphize_from_str<'a>(
}
struct LoadStart<'a> {
pub arc_modules: Arc<Mutex<ModuleIds>>,
pub arc_package_modules: Arc<Mutex<PackageModuleIds<'a>>>,
pub arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
pub ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
pub root_id: ModuleId,
pub root_msg: Msg<'a>,
@ -1012,8 +1024,7 @@ impl<'a> LoadStart<'a> {
filename: PathBuf,
mode: Mode,
) -> Result<Self, LoadingProblem> {
let arc_modules = Arc::new(Mutex::new(ModuleIds::default()));
let arc_package_modules = Arc::new(Mutex::new(PackageModuleIds::default()));
let arc_modules = Arc::new(Mutex::new(PackageModuleIds::default()));
let root_exposed_ident_ids = IdentIds::exposed_builtins(0);
let ident_ids_by_module = Arc::new(Mutex::new(root_exposed_ident_ids));
@ -1024,8 +1035,8 @@ impl<'a> LoadStart<'a> {
load_filename(
arena,
filename,
None,
Arc::clone(&arc_modules),
Arc::clone(&arc_package_modules),
Arc::clone(&ident_ids_by_module),
root_start_time,
mode,
@ -1034,7 +1045,6 @@ impl<'a> LoadStart<'a> {
Ok(LoadStart {
arc_modules,
arc_package_modules,
ident_ids_by_module,
root_id,
root_msg,
@ -1047,8 +1057,7 @@ impl<'a> LoadStart<'a> {
src: &'a str,
mode: Mode,
) -> Result<Self, LoadingProblem> {
let arc_modules = Arc::new(Mutex::new(ModuleIds::default()));
let arc_package_modules = Arc::new(Mutex::new(PackageModuleIds::default()));
let arc_modules = Arc::new(Mutex::new(PackageModuleIds::default()));
let root_exposed_ident_ids = IdentIds::exposed_builtins(0);
let ident_ids_by_module = Arc::new(Mutex::new(root_exposed_ident_ids));
@ -1061,7 +1070,6 @@ impl<'a> LoadStart<'a> {
filename,
src,
Arc::clone(&arc_modules),
Arc::clone(&arc_package_modules),
Arc::clone(&ident_ids_by_module),
root_start_time,
mode,
@ -1070,7 +1078,6 @@ impl<'a> LoadStart<'a> {
Ok(LoadStart {
arc_modules,
arc_package_modules,
ident_ids_by_module,
root_id,
root_msg,
@ -1139,12 +1146,13 @@ where
{
let LoadStart {
arc_modules,
arc_package_modules,
ident_ids_by_module,
root_id,
root_msg,
} = load_start;
let arc_shorthands = Arc::new(Mutex::new(MutMap::default()));
let (msg_tx, msg_rx) = bounded(1024);
msg_tx
.send(root_msg)
@ -1267,6 +1275,7 @@ where
goal_phase,
stdlib,
output_path: None,
platform_path: None,
opt_effect_module: None,
module_cache: ModuleCache::default(),
dependencies: Dependencies::default(),
@ -1276,7 +1285,7 @@ where
headers_parsed,
loading_started,
arc_modules,
arc_package_modules,
arc_shorthands,
constrained_ident_ids: IdentIds::exposed_builtins(0),
ident_ids_by_module,
declarations_by_id: MutMap::default(),
@ -1409,6 +1418,16 @@ fn update<'a>(
log!("loaded header for {:?}", header.module_id);
let home = header.module_id;
{
let mut shorthands = (*state.arc_shorthands).lock();
for (shorthand, package_or_path) in header.packages.iter() {
shorthands.insert(shorthand, package_or_path.clone());
}
}
state.platform_path = state.platform_path.or_else(|| header.to_platform.clone());
// store an ID to name mapping, so we know the file to read when fetching dependencies' headers
for (name, id) in header.deps_by_name.iter() {
state.module_cache.module_names.insert(*id, name.clone());
@ -1786,7 +1805,8 @@ fn finish_specialization<'a>(
) -> MonomorphizedModule<'a> {
let module_ids = Arc::try_unwrap(state.arc_modules)
.unwrap_or_else(|_| panic!("There were still outstanding Arc references to module_ids"))
.into_inner();
.into_inner()
.into_module_ids();
let interns = Interns {
module_ids,
@ -1797,6 +1817,7 @@ fn finish_specialization<'a>(
procedures,
module_cache,
output_path,
platform_path,
..
} = state;
@ -1813,11 +1834,33 @@ fn finish_specialization<'a>(
.map(|(id, (path, src))| (id, (path, src.into())))
.collect();
let path_to_platform = {
let package_or_path = match platform_path {
Some(To::ExistingPackage(shorthand)) => {
match (*state.arc_shorthands).lock().get(shorthand) {
Some(p_or_p) => p_or_p.clone(),
None => unreachable!(),
}
}
Some(To::NewPackage(p_or_p)) => p_or_p,
None => panic!("no platform!"),
};
match package_or_path {
PackageOrPath::Path(StrLiteral::PlainLine(path)) => path,
PackageOrPath::Path(_) => unreachable!("invalid"),
_ => todo!("packages"),
}
};
let platform_path = path_to_platform.into();
MonomorphizedModule {
can_problems,
mono_problems,
type_problems,
output_path: output_path.unwrap_or(DEFAULT_APP_OUTPUT_PATH).into(),
platform_path,
exposed_to_host,
module_id: state.root_id,
subs,
@ -1836,7 +1879,8 @@ fn finish<'a>(
) -> LoadedModule {
let module_ids = Arc::try_unwrap(state.arc_modules)
.unwrap_or_else(|_| panic!("There were still outstanding Arc references to module_ids"))
.into_inner();
.into_inner()
.into_module_ids();
let interns = Interns {
module_ids,
@ -1869,8 +1913,7 @@ fn load_pkg_config<'a>(
arena: &'a Bump,
src_dir: &Path,
shorthand: &'a str,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
mode: Mode,
) -> Result<Msg<'a>, LoadingProblem> {
@ -1912,7 +1955,6 @@ fn load_pkg_config<'a>(
arena,
shorthand,
module_ids,
package_module_ids,
ident_ids_by_module,
mode,
header,
@ -1926,6 +1968,7 @@ fn load_pkg_config<'a>(
Err(err) => Err(LoadingProblem::FileProblem {
filename,
error: err.kind(),
msg: "while reading a Pkg-Config.roc file",
}),
}
}
@ -1934,9 +1977,9 @@ fn load_pkg_config<'a>(
fn load_module<'a>(
arena: &'a Bump,
src_dir: &Path,
module_name: ModuleName,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
module_name: PQModuleName<'a>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
arc_shorthands: Arc<Mutex<MutMap<&'a str, PackageOrPath<'a>>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
mode: Mode,
) -> Result<(ModuleId, Msg<'a>), LoadingProblem> {
@ -1945,9 +1988,35 @@ fn load_module<'a>(
filename.push(src_dir);
// Convert dots in module name to directories
for part in module_name.as_str().split(MODULE_SEPARATOR) {
filename.push(part);
let opt_shorthand;
match module_name {
PQModuleName::Unqualified(name) => {
opt_shorthand = None;
// Convert dots in module name to directories
for part in name.split(MODULE_SEPARATOR) {
filename.push(part);
}
}
PQModuleName::Qualified(shorthand, name) => {
opt_shorthand = Some(shorthand);
let shorthands = arc_shorthands.lock();
match shorthands.get(shorthand) {
Some(PackageOrPath::Path(StrLiteral::PlainLine(path))) => {
filename.push(path);
}
Some(PackageOrPath::Path(_str_liteal)) => {
unreachable!("invalid structure for path")
}
Some(PackageOrPath::Package(_name, _version)) => todo!("packages"),
None => unreachable!("there is no shorthand named {:?}", shorthand),
}
// Convert dots in module name to directories
for part in name.split(MODULE_SEPARATOR) {
filename.push(part);
}
}
}
// End with .roc
@ -1956,8 +2025,8 @@ fn load_module<'a>(
load_filename(
arena,
filename,
opt_shorthand,
module_ids,
package_module_ids,
ident_ids_by_module,
module_start_time,
mode,
@ -1995,8 +2064,8 @@ fn parse_header<'a>(
arena: &'a Bump,
read_file_duration: Duration,
filename: PathBuf,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
opt_shorthand: Option<&'a str>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
mode: Mode,
src_bytes: &'a [u8],
@ -2020,11 +2089,13 @@ fn parse_header<'a>(
value: AppOrInterfaceName::Interface(header.name.value),
},
filename,
opt_shorthand,
&[],
header.exposes.into_bump_slice(),
header.imports.into_bump_slice(),
None,
parse_state,
module_ids,
package_module_ids,
ident_ids_by_module,
module_timing,
)),
@ -2032,24 +2103,28 @@ fn parse_header<'a>(
let mut pkg_config_dir = filename.clone();
pkg_config_dir.pop();
let packages = header.packages.into_bump_slice();
let (module_id, app_module_header_msg) = send_header(
Located {
region: header.name.region,
value: AppOrInterfaceName::App(header.name.value),
},
filename,
opt_shorthand,
packages,
header.provides.into_bump_slice(),
header.imports.into_bump_slice(),
Some(header.to.value.clone()),
parse_state,
module_ids.clone(),
package_module_ids.clone(),
ident_ids_by_module.clone(),
module_timing,
);
match header.to.value {
To::ExistingPackage(existing_package) => {
let opt_base_package = header.packages.iter().find(|loc_package_entry| {
let opt_base_package = packages.iter().find(|loc_package_entry| {
let Located { value, .. } = loc_package_entry;
match value {
@ -2086,7 +2161,6 @@ fn parse_header<'a>(
&pkg_config_roc,
shorthand,
module_ids,
package_module_ids,
ident_ids_by_module,
mode,
)?;
@ -2126,7 +2200,6 @@ fn parse_header<'a>(
arena,
&"",
module_ids,
package_module_ids,
ident_ids_by_module,
mode,
header,
@ -2140,8 +2213,8 @@ fn parse_header<'a>(
fn load_filename<'a>(
arena: &'a Bump,
filename: PathBuf,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
opt_shorthand: Option<&'a str>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
module_start_time: SystemTime,
mode: Mode,
@ -2155,8 +2228,8 @@ fn load_filename<'a>(
arena,
file_io_duration,
filename,
opt_shorthand,
module_ids,
package_module_ids,
ident_ids_by_module,
mode,
arena.alloc(bytes),
@ -2165,6 +2238,7 @@ fn load_filename<'a>(
Err(err) => Err(LoadingProblem::FileProblem {
filename,
error: err.kind(),
msg: "in `load_filename`",
}),
}
}
@ -2176,8 +2250,7 @@ fn load_from_str<'a>(
arena: &'a Bump,
filename: PathBuf,
src: &'a str,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
module_start_time: SystemTime,
mode: Mode,
@ -2189,8 +2262,8 @@ fn load_from_str<'a>(
arena,
file_io_duration,
filename,
None,
module_ids,
package_module_ids,
ident_ids_by_module,
mode,
src.as_bytes(),
@ -2209,11 +2282,13 @@ enum AppOrInterfaceName<'a> {
fn send_header<'a>(
loc_name: Located<AppOrInterfaceName<'a>>,
filename: PathBuf,
opt_shorthand: Option<&'a str>,
packages: &'a [Located<PackageEntry<'a>>],
exposes: &'a [Located<ExposesEntry<'a, &'a str>>],
imports: &'a [Located<ImportsEntry<'a>>],
to_platform: Option<To<'a>>,
parse_state: parser::State<'a>,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
module_timing: ModuleTiming,
) -> (ModuleId, Msg<'a>) {
@ -2232,7 +2307,6 @@ fn send_header<'a>(
let mut imported: Vec<(QualifiedModuleName, Vec<Ident>, Region)> =
Vec::with_capacity(imports.len());
let mut imported_modules: MutSet<ModuleId> = MutSet::default();
let mut imported_package_modules: MutSet<ModuleId> = MutSet::default();
let mut scope_size = 0;
for loc_entry in imports {
@ -2244,7 +2318,7 @@ fn send_header<'a>(
}
let num_exposes = exposes.len();
let mut deps_by_name: MutMap<ModuleName, ModuleId> =
let mut deps_by_name: MutMap<PQModuleName, ModuleId> =
HashMap::with_capacity_and_hasher(num_exposes, default_hasher());
let mut exposed: Vec<Symbol> = Vec::with_capacity(num_exposes);
@ -2257,10 +2331,15 @@ fn send_header<'a>(
let ident_ids = {
// Lock just long enough to perform the minimal operations necessary.
let mut module_ids = (*module_ids).lock();
let mut package_module_ids = (*package_module_ids).lock();
let mut ident_ids_by_module = (*ident_ids_by_module).lock();
home = module_ids.get_or_insert(&declared_name.as_inline_str());
let name = match opt_shorthand {
Some(shorthand) => {
PQModuleName::Qualified(&shorthand, declared_name.as_inline_str().clone())
}
None => PQModuleName::Unqualified(declared_name.as_inline_str().clone()),
};
home = module_ids.get_or_insert(&name);
// Ensure this module has an entry in the exposed_ident_ids map.
ident_ids_by_module
@ -2274,26 +2353,23 @@ fn send_header<'a>(
// Also build a list of imported_values_to_expose (like `bar` above.)
for (qualified_module_name, exposed_idents, region) in imported.into_iter() {
let cloned_module_name = qualified_module_name.module.clone();
let module_id = match qualified_module_name.opt_package {
None => {
let id = module_ids.get_or_insert(&qualified_module_name.module.into());
imported_modules.insert(id);
deps_by_name.insert(cloned_module_name, id);
id
}
let pq_module_name = match qualified_module_name.opt_package {
None => match opt_shorthand {
Some(shorthand) => {
PQModuleName::Qualified(shorthand, qualified_module_name.module.into())
}
None => PQModuleName::Unqualified(qualified_module_name.module.into()),
},
Some(package) => {
let id =
package_module_ids.get_or_insert(&(package, cloned_module_name.into()));
imported_package_modules.insert(id);
id
PQModuleName::Qualified(package, cloned_module_name.clone().into())
}
};
let module_id = module_ids.get_or_insert(&pq_module_name);
imported_modules.insert(module_id);
deps_by_name.insert(pq_module_name, module_id);
// Add the new exposed idents to the dep module's IdentIds, so
// once that module later gets loaded, its lookups will resolve
// to the same symbols as the ones we're using here.
@ -2341,6 +2417,25 @@ fn send_header<'a>(
ident_ids.clone()
};
let mut parse_entries: Vec<_> = (&packages).iter().map(|x| &x.value).collect();
let mut package_entries = MutMap::default();
while let Some(parse_entry) = parse_entries.pop() {
use PackageEntry::*;
match parse_entry {
Entry {
shorthand,
package_or_path,
..
} => {
package_entries.insert(*shorthand, package_or_path.value.clone());
}
SpaceBefore(inner, _) | SpaceAfter(inner, _) => {
parse_entries.push(inner);
}
}
}
// Send the deps to the coordinator thread for processing,
// then continue on to parsing and canonicalizing defs.
//
@ -2354,10 +2449,11 @@ fn send_header<'a>(
module_path: filename,
exposed_ident_ids: ident_ids,
module_name: loc_name.value,
packages: package_entries,
imported_modules,
imported_package_modules,
deps_by_name,
exposes: exposed,
to_platform,
src: parse_state.bytes,
exposed_imports: scope,
module_timing,
@ -2480,8 +2576,7 @@ fn run_solve<'a>(
fn fabricate_effects_module<'a>(
arena: &'a Bump,
shorthand: &'a str,
module_ids: Arc<Mutex<ModuleIds>>,
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
mode: Mode,
header: PlatformHeader<'a>,
@ -2507,11 +2602,13 @@ fn fabricate_effects_module<'a>(
functions
};
let mut package_module_ids = (*package_module_ids).lock();
{
let mut module_ids = (*module_ids).lock();
for exposed in header.exposes {
if let ExposesEntry::Exposed(module_name) = exposed.value {
package_module_ids.get_or_insert(&(shorthand, module_name.into()));
for exposed in header.exposes {
if let ExposesEntry::Exposed(module_name) = exposed.value {
module_ids.get_or_insert(&PQModuleName::Qualified(shorthand, module_name.into()));
}
}
}
@ -2520,7 +2617,8 @@ fn fabricate_effects_module<'a>(
let mut module_ids = (*module_ids).lock();
let mut ident_ids_by_module = (*ident_ids_by_module).lock();
module_id = module_ids.get_or_insert(&declared_name.as_inline_str());
let name = PQModuleName::Qualified(shorthand, declared_name.as_inline_str().clone());
module_id = module_ids.get_or_insert(&name);
// Ensure this module has an entry in the exposed_ident_ids map.
ident_ids_by_module
@ -2575,7 +2673,7 @@ fn fabricate_effects_module<'a>(
let mut var_store = VarStore::default();
let module_ids = { (*module_ids).lock().clone() };
let module_ids = { (*module_ids).lock().clone() }.into_module_ids();
let mut scope = roc_can::scope::Scope::new(module_id, &mut var_store);
let mut can_env = roc_can::env::Env::new(module_id, dep_idents, &module_ids, exposed_ident_ids);
@ -3207,7 +3305,7 @@ fn run_task<'a>(
LoadModule {
module_name,
module_ids,
package_module_ids,
shorthands,
ident_ids_by_module,
mode,
} => load_module(
@ -3215,7 +3313,7 @@ fn run_task<'a>(
src_dir,
module_name,
module_ids,
package_module_ids,
shorthands,
ident_ids_by_module,
mode,
)
@ -3223,7 +3321,6 @@ fn run_task<'a>(
LoadPkgConfig {
shorthand,
module_ids,
package_module_ids,
ident_ids_by_module,
mode,
} => load_pkg_config(
@ -3231,7 +3328,6 @@ fn run_task<'a>(
src_dir,
shorthand,
module_ids,
package_module_ids,
ident_ids_by_module,
mode,
),

View File

@ -317,16 +317,30 @@ impl fmt::Debug for ModuleId {
/// 4. throw away short names. stash the module id in the can env under the resolved module name
/// 5. test:
type PackageModule<'a> = (&'a str, InlinableString);
/// Package-qualified module name
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PQModuleName<'a> {
Unqualified(InlinableString),
Qualified(&'a str, InlinableString),
}
impl<'a> PQModuleName<'a> {
pub fn to_module_name(&self) -> &InlinableString {
match self {
PQModuleName::Unqualified(name) => name,
PQModuleName::Qualified(_, name) => name,
}
}
}
#[derive(Debug, Clone)]
pub struct PackageModuleIds<'a> {
by_name: MutMap<PackageModule<'a>, ModuleId>,
by_id: Vec<PackageModule<'a>>,
by_name: MutMap<PQModuleName<'a>, ModuleId>,
by_id: Vec<PQModuleName<'a>>,
}
impl<'a> PackageModuleIds<'a> {
pub fn get_or_insert(&mut self, module_name: &PackageModule<'a>) -> ModuleId {
pub fn get_or_insert(&mut self, module_name: &PQModuleName<'a>) -> ModuleId {
match self.by_name.get(module_name) {
Some(id) => *id,
None => {
@ -346,29 +360,53 @@ impl<'a> PackageModuleIds<'a> {
}
}
pub fn into_module_ids(self) -> ModuleIds {
let by_name: MutMap<InlinableString, ModuleId> = self
.by_name
.into_iter()
.map(|(pqname, module_id)| (pqname.to_module_name().clone(), module_id))
.collect();
let by_id: Vec<InlinableString> = self
.by_id
.into_iter()
.map(|pqname| pqname.to_module_name().clone())
.collect();
ModuleIds { by_name, by_id }
}
#[cfg(debug_assertions)]
fn insert_debug_name(module_id: ModuleId, module_name: &PackageModule) {
fn insert_debug_name(module_id: ModuleId, module_name: &PQModuleName) {
let mut names = DEBUG_MODULE_ID_NAMES.lock().expect("Failed to acquire lock for Debug interning into DEBUG_MODULE_ID_NAMES, presumably because a thread panicked.");
let (_package, module) = module_name;
names.insert(module_id.0, module.to_string().into());
if !names.contains_key(&module_id.0) {
match module_name {
PQModuleName::Unqualified(module) => {
names.insert(module_id.0, module.to_string().into());
}
PQModuleName::Qualified(package, module) => {
let name = format!("{}.{}", package, module).into();
names.insert(module_id.0, name);
}
}
}
}
#[cfg(not(debug_assertions))]
fn insert_debug_name(_module_id: ModuleId, _module_name: &PackageModule) {
fn insert_debug_name(_module_id: ModuleId, _module_name: &PQModuleName) {
// By design, this is a no-op in release builds!
}
pub fn get_id(&self, module_name: &PackageModule<'a>) -> Option<&ModuleId> {
pub fn get_id(&self, module_name: &PQModuleName<'a>) -> Option<&ModuleId> {
self.by_name.get(module_name)
}
pub fn get_name(&self, id: ModuleId) -> Option<&PackageModule> {
pub fn get_name(&self, id: ModuleId) -> Option<&PQModuleName> {
self.by_id.get(id.0 as usize)
}
pub fn available_modules(&self) -> impl Iterator<Item = &PackageModule> {
pub fn available_modules(&self) -> impl Iterator<Item = &PQModuleName> {
self.by_id.iter()
}
}
@ -409,7 +447,10 @@ impl ModuleIds {
fn insert_debug_name(module_id: ModuleId, module_name: &InlinableString) {
let mut names = DEBUG_MODULE_ID_NAMES.lock().expect("Failed to acquire lock for Debug interning into DEBUG_MODULE_ID_NAMES, presumably because a thread panicked.");
names.insert(module_id.0, module_name.to_string().into());
// TODO make sure modules are never added more than once!
if !names.contains_key(&module_id.0) {
names.insert(module_id.0, module_name.to_string().into());
}
}
#[cfg(not(debug_assertions))]
@ -558,7 +599,8 @@ macro_rules! define_builtins {
if cfg!(debug_assertions) {
let module_id = ModuleId($module_id);
ModuleIds::insert_debug_name(module_id, &$module_name.into());
let name = PQModuleName::Unqualified($module_name.into());
PackageModuleIds::insert_debug_name(module_id, &name);
module_id.register_debug_idents(&ident_ids);
}
@ -619,8 +661,24 @@ macro_rules! define_builtins {
// +1 because the user will be compiling at least 1 non-builtin module!
let capacity = $total + 1;
let by_name = HashMap::with_capacity_and_hasher(capacity, default_hasher());
let by_id = Vec::with_capacity(capacity);
let mut by_name = HashMap::with_capacity_and_hasher(capacity, default_hasher());
let mut by_id = Vec::with_capacity(capacity);
let mut insert_both = |id: ModuleId, name_str: &'static str| {
let raw_name: InlinableString = name_str.into();
let name = PQModuleName::Unqualified(raw_name);
if cfg!(debug_assertions) {
Self::insert_debug_name(id, &name);
}
by_name.insert(name.clone(), id);
by_id.push(name);
};
$(
insert_both(ModuleId($module_id), $module_name);
)+
PackageModuleIds { by_name, by_id }
}

View File

@ -1,13 +1,16 @@
app "effect-example"
packages { base: "./thing/platform-dir" }
packages { base: "thing/platform-dir" }
imports [ base.Task.{ Task, after } ]
provides [ main ] to base
main : Task {}
# TODO `main : Task {}` does not work
# it will then think that the `Task` module is unused
# (if we also don't use any of the other importd symbols)
main : Task.Task {} as Fx
main =
when if 1 == 1 then True 3 else False 3.14 is
True n -> Effect.putLine (Str.fromInt n)
_ -> Effect.putLine "Yay"
True n -> Task.putLine (Str.fromInt n)
_ -> Task.putLine "Yay"
# main : Effect.Effect {} as Fx
# main =

View File

@ -8,6 +8,6 @@ edition = "2018"
crate-type = ["staticlib"]
[dependencies]
roc_std = { path = "../../../roc_std" }
roc_std = { path = "../../../../roc_std" }
[workspace]

View File

@ -4,6 +4,6 @@ interface Task
Task a : Effect.Effect a
putLine = Effect.putLine
putLine = \line -> Effect.putLine line
after = Effect.after