mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 08:17:40 +03:00
Merge pull request #779 from rtfeldman/package-qualified-example
Package qualified example
This commit is contained in:
commit
f72cc7c497
@ -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.
|
||||
|
@ -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()
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
),
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -8,6 +8,6 @@ edition = "2018"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
roc_std = { path = "../../../roc_std" }
|
||||
roc_std = { path = "../../../../roc_std" }
|
||||
|
||||
[workspace]
|
||||
|
@ -4,6 +4,6 @@ interface Task
|
||||
|
||||
Task a : Effect.Effect a
|
||||
|
||||
putLine = Effect.putLine
|
||||
putLine = \line -> Effect.putLine line
|
||||
|
||||
after = Effect.after
|
||||
|
Loading…
Reference in New Issue
Block a user