mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 08:17:40 +03:00
Merge pull request #752 from rtfeldman/task_can
Package Qualified Modules
This commit is contained in:
commit
d008cc1d7b
@ -97,6 +97,7 @@ pub fn canonicalize_module_defs<'a>(
|
||||
let first_char = ident.as_inline_str().chars().next().unwrap();
|
||||
|
||||
if first_char.is_lowercase() {
|
||||
// this is a value definition
|
||||
let expr_var = var_store.fresh();
|
||||
|
||||
match scope.import(ident, symbol, region) {
|
||||
@ -116,6 +117,15 @@ 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");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#[macro_use]
|
||||
extern crate pretty_assertions;
|
||||
|
||||
#[macro_use]
|
||||
extern crate indoc;
|
||||
|
||||
|
@ -75,7 +75,6 @@ pub fn helper<'a>(
|
||||
println!("{:?}", exposed_to_host);
|
||||
println!("=================================\n");
|
||||
*/
|
||||
|
||||
debug_assert_eq!(exposed_to_host.len(), 1);
|
||||
let main_fn_symbol = exposed_to_host.keys().copied().nth(0).unwrap();
|
||||
|
||||
|
@ -13,14 +13,16 @@ use roc_constrain::module::{
|
||||
constrain_imports, pre_constrain_imports, ConstrainableImports, Import,
|
||||
};
|
||||
use roc_constrain::module::{constrain_module, ExposedModuleTypes, SubsByModule};
|
||||
use roc_module::ident::{Ident, Lowercase, ModuleName, TagName};
|
||||
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, Symbol};
|
||||
use roc_module::ident::{Ident, Lowercase, ModuleName, QualifiedModuleName, TagName};
|
||||
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds, PackageModuleIds, Symbol};
|
||||
use roc_mono::ir::{
|
||||
CapturedSymbols, ExternalSpecializations, PartialProc, PendingSpecialization, Proc, Procs,
|
||||
};
|
||||
use roc_mono::layout::{Layout, LayoutCache};
|
||||
use roc_parse::ast::{self, Attempting, StrLiteral, TypeAnnotation};
|
||||
use roc_parse::header::{ExposesEntry, ImportsEntry, PlatformHeader, TypedIdent};
|
||||
use roc_parse::header::{
|
||||
ExposesEntry, ImportsEntry, PackageEntry, PackageOrPath, PlatformHeader, To, TypedIdent,
|
||||
};
|
||||
use roc_parse::module::module_defs;
|
||||
use roc_parse::parser::{self, Fail, Parser};
|
||||
use roc_region::all::{Located, Region};
|
||||
@ -101,6 +103,7 @@ impl Dependencies {
|
||||
pub fn add_module(
|
||||
&mut self,
|
||||
module_id: ModuleId,
|
||||
opt_effect_module: Option<ModuleId>,
|
||||
dependencies: &MutSet<ModuleId>,
|
||||
goal_phase: Phase,
|
||||
) -> MutSet<(ModuleId, Phase)> {
|
||||
@ -143,7 +146,8 @@ impl Dependencies {
|
||||
// all the dependencies can be loaded
|
||||
for dep in dependencies {
|
||||
// TODO figure out how to "load" (because it doesn't exist on the file system) the Effect module
|
||||
if !format!("{:?}", dep).contains("Effect") {
|
||||
|
||||
if Some(*dep) != opt_effect_module {
|
||||
output.insert((*dep, LoadHeader));
|
||||
}
|
||||
}
|
||||
@ -346,6 +350,7 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
|
||||
// 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),
|
||||
ident_ids_by_module: Arc::clone(&state.ident_ids_by_module),
|
||||
mode: state.stdlib.mode,
|
||||
}
|
||||
@ -541,6 +546,7 @@ struct ModuleHeader<'a> {
|
||||
exposed_ident_ids: IdentIds,
|
||||
deps_by_name: MutMap<ModuleName, ModuleId>,
|
||||
imported_modules: MutSet<ModuleId>,
|
||||
imported_package_modules: MutSet<ModuleId>,
|
||||
exposes: Vec<Symbol>,
|
||||
exposed_imports: MutMap<Ident, (Symbol, Region)>,
|
||||
src: &'a [u8],
|
||||
@ -676,6 +682,7 @@ struct State<'a> {
|
||||
pub stdlib: StdLib,
|
||||
pub exposed_types: SubsByModule,
|
||||
pub output_path: Option<&'a str>,
|
||||
pub opt_effect_module: Option<ModuleId>,
|
||||
|
||||
pub headers_parsed: MutSet<ModuleId>,
|
||||
|
||||
@ -690,6 +697,7 @@ struct State<'a> {
|
||||
|
||||
/// 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 ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
|
||||
@ -819,11 +827,14 @@ enum BuildTask<'a> {
|
||||
LoadModule {
|
||||
module_name: ModuleName,
|
||||
module_ids: Arc<Mutex<ModuleIds>>,
|
||||
package_module_ids: Arc<Mutex<PackageModuleIds<'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>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
mode: Mode,
|
||||
},
|
||||
@ -989,6 +1000,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 ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
pub root_id: ModuleId,
|
||||
pub root_msg: Msg<'a>,
|
||||
@ -1001,6 +1013,7 @@ impl<'a> LoadStart<'a> {
|
||||
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 root_exposed_ident_ids = IdentIds::exposed_builtins(0);
|
||||
let ident_ids_by_module = Arc::new(Mutex::new(root_exposed_ident_ids));
|
||||
|
||||
@ -1012,6 +1025,7 @@ impl<'a> LoadStart<'a> {
|
||||
arena,
|
||||
filename,
|
||||
Arc::clone(&arc_modules),
|
||||
Arc::clone(&arc_package_modules),
|
||||
Arc::clone(&ident_ids_by_module),
|
||||
root_start_time,
|
||||
mode,
|
||||
@ -1020,6 +1034,7 @@ impl<'a> LoadStart<'a> {
|
||||
|
||||
Ok(LoadStart {
|
||||
arc_modules,
|
||||
arc_package_modules,
|
||||
ident_ids_by_module,
|
||||
root_id,
|
||||
root_msg,
|
||||
@ -1033,6 +1048,7 @@ impl<'a> LoadStart<'a> {
|
||||
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 root_exposed_ident_ids = IdentIds::exposed_builtins(0);
|
||||
let ident_ids_by_module = Arc::new(Mutex::new(root_exposed_ident_ids));
|
||||
|
||||
@ -1045,6 +1061,7 @@ 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,
|
||||
@ -1053,6 +1070,7 @@ impl<'a> LoadStart<'a> {
|
||||
|
||||
Ok(LoadStart {
|
||||
arc_modules,
|
||||
arc_package_modules,
|
||||
ident_ids_by_module,
|
||||
root_id,
|
||||
root_msg,
|
||||
@ -1121,6 +1139,7 @@ where
|
||||
{
|
||||
let LoadStart {
|
||||
arc_modules,
|
||||
arc_package_modules,
|
||||
ident_ids_by_module,
|
||||
root_id,
|
||||
root_msg,
|
||||
@ -1248,6 +1267,7 @@ where
|
||||
goal_phase,
|
||||
stdlib,
|
||||
output_path: None,
|
||||
opt_effect_module: None,
|
||||
module_cache: ModuleCache::default(),
|
||||
dependencies: Dependencies::default(),
|
||||
procedures: MutMap::default(),
|
||||
@ -1256,6 +1276,7 @@ where
|
||||
headers_parsed,
|
||||
loading_started,
|
||||
arc_modules,
|
||||
arc_package_modules,
|
||||
constrained_ident_ids: IdentIds::exposed_builtins(0),
|
||||
ident_ids_by_module,
|
||||
declarations_by_id: MutMap::default(),
|
||||
@ -1412,6 +1433,7 @@ fn update<'a>(
|
||||
|
||||
let work = state.dependencies.add_module(
|
||||
header.module_id,
|
||||
state.opt_effect_module,
|
||||
&header.imported_modules,
|
||||
state.goal_phase,
|
||||
);
|
||||
@ -1499,6 +1521,9 @@ fn update<'a>(
|
||||
module_docs,
|
||||
} => {
|
||||
let module_id = constrained_module.module.module_id;
|
||||
|
||||
state.opt_effect_module = Some(module_id);
|
||||
|
||||
log!("made effect module for {:?}", module_id);
|
||||
state
|
||||
.module_cache
|
||||
@ -1843,19 +1868,15 @@ fn finish<'a>(
|
||||
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>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
mode: Mode,
|
||||
) -> Result<Msg<'a>, LoadingProblem> {
|
||||
let module_start_time = SystemTime::now();
|
||||
|
||||
let mut filename = PathBuf::from(src_dir);
|
||||
|
||||
filename.push("platform");
|
||||
filename.push(PKG_CONFIG_FILE_NAME);
|
||||
|
||||
// End with .roc
|
||||
filename.set_extension(ROC_FILE_EXTENSION);
|
||||
let filename = PathBuf::from(src_dir);
|
||||
|
||||
let file_io_start = SystemTime::now();
|
||||
let file = fs::read(&filename);
|
||||
@ -1889,7 +1910,9 @@ fn load_pkg_config<'a>(
|
||||
}
|
||||
Ok((ast::Module::Platform { header }, _parse_state)) => fabricate_effects_module(
|
||||
arena,
|
||||
shorthand,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
header,
|
||||
@ -1913,6 +1936,7 @@ fn load_module<'a>(
|
||||
src_dir: &Path,
|
||||
module_name: ModuleName,
|
||||
module_ids: Arc<Mutex<ModuleIds>>,
|
||||
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
mode: Mode,
|
||||
) -> Result<(ModuleId, Msg<'a>), LoadingProblem> {
|
||||
@ -1933,6 +1957,7 @@ fn load_module<'a>(
|
||||
arena,
|
||||
filename,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
module_start_time,
|
||||
mode,
|
||||
@ -1971,6 +1996,7 @@ fn parse_header<'a>(
|
||||
read_file_duration: Duration,
|
||||
filename: PathBuf,
|
||||
module_ids: Arc<Mutex<ModuleIds>>,
|
||||
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
mode: Mode,
|
||||
src_bytes: &'a [u8],
|
||||
@ -1998,6 +2024,7 @@ fn parse_header<'a>(
|
||||
header.imports.into_bump_slice(),
|
||||
parse_state,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
module_timing,
|
||||
)),
|
||||
@ -2015,36 +2042,91 @@ fn parse_header<'a>(
|
||||
header.imports.into_bump_slice(),
|
||||
parse_state,
|
||||
module_ids.clone(),
|
||||
package_module_ids.clone(),
|
||||
ident_ids_by_module.clone(),
|
||||
module_timing,
|
||||
);
|
||||
|
||||
// check whether we can find a Pkg-Config.roc file
|
||||
let mut pkg_config_roc = pkg_config_dir.clone();
|
||||
pkg_config_roc.push("platform");
|
||||
pkg_config_roc.push(PKG_CONFIG_FILE_NAME);
|
||||
pkg_config_roc.set_extension(ROC_FILE_EXTENSION);
|
||||
match header.to.value {
|
||||
To::ExistingPackage(existing_package) => {
|
||||
let opt_base_package = header.packages.iter().find(|loc_package_entry| {
|
||||
let Located { value, .. } = loc_package_entry;
|
||||
|
||||
if pkg_config_roc.as_path().exists() {
|
||||
let load_pkg_config_msg = load_pkg_config(
|
||||
arena,
|
||||
&pkg_config_dir,
|
||||
module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
)?;
|
||||
match value {
|
||||
PackageEntry::Entry { shorthand, .. } => shorthand == &existing_package,
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
|
||||
Ok((
|
||||
module_id,
|
||||
Msg::Many(vec![app_module_header_msg, load_pkg_config_msg]),
|
||||
))
|
||||
} else {
|
||||
Ok((module_id, app_module_header_msg))
|
||||
match opt_base_package {
|
||||
Some(Located {
|
||||
value:
|
||||
PackageEntry::Entry {
|
||||
shorthand,
|
||||
package_or_path:
|
||||
Located {
|
||||
value: package_or_path,
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
..
|
||||
}) => {
|
||||
match package_or_path {
|
||||
PackageOrPath::Path(StrLiteral::PlainLine(package)) => {
|
||||
// check whether we can find a Pkg-Config.roc file
|
||||
let mut pkg_config_roc = pkg_config_dir;
|
||||
pkg_config_roc.push(package);
|
||||
pkg_config_roc.push(PKG_CONFIG_FILE_NAME);
|
||||
pkg_config_roc.set_extension(ROC_FILE_EXTENSION);
|
||||
|
||||
if pkg_config_roc.as_path().exists() {
|
||||
let load_pkg_config_msg = load_pkg_config(
|
||||
arena,
|
||||
&pkg_config_roc,
|
||||
shorthand,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
)?;
|
||||
|
||||
Ok((
|
||||
module_id,
|
||||
Msg::Many(vec![
|
||||
app_module_header_msg,
|
||||
load_pkg_config_msg,
|
||||
]),
|
||||
))
|
||||
} else {
|
||||
Ok((module_id, app_module_header_msg))
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => panic!("could not find base"),
|
||||
}
|
||||
}
|
||||
To::NewPackage(package_or_path) => match package_or_path {
|
||||
PackageOrPath::Package(_, _) => panic!("TODO implement packages"),
|
||||
PackageOrPath::Path(StrLiteral::PlainLine(_package)) => {
|
||||
Ok((module_id, app_module_header_msg))
|
||||
}
|
||||
PackageOrPath::Path(StrLiteral::Block(_)) => {
|
||||
panic!("TODO implement block package path")
|
||||
}
|
||||
PackageOrPath::Path(StrLiteral::Line(_)) => {
|
||||
panic!("TODO implement line package path")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok((ast::Module::Platform { header }, _parse_state)) => fabricate_effects_module(
|
||||
arena,
|
||||
&"",
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
header,
|
||||
@ -2059,6 +2141,7 @@ fn load_filename<'a>(
|
||||
arena: &'a Bump,
|
||||
filename: PathBuf,
|
||||
module_ids: Arc<Mutex<ModuleIds>>,
|
||||
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
module_start_time: SystemTime,
|
||||
mode: Mode,
|
||||
@ -2073,6 +2156,7 @@ fn load_filename<'a>(
|
||||
file_io_duration,
|
||||
filename,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
arena.alloc(bytes),
|
||||
@ -2087,11 +2171,13 @@ fn load_filename<'a>(
|
||||
|
||||
/// Load a module from a str
|
||||
/// the `filename` is never read, but used for the module name
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
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>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
module_start_time: SystemTime,
|
||||
mode: Mode,
|
||||
@ -2104,6 +2190,7 @@ fn load_from_str<'a>(
|
||||
file_io_duration,
|
||||
filename,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
src.as_bytes(),
|
||||
@ -2126,6 +2213,7 @@ fn send_header<'a>(
|
||||
imports: &'a [Located<ImportsEntry<'a>>],
|
||||
parse_state: parser::State<'a>,
|
||||
module_ids: Arc<Mutex<ModuleIds>>,
|
||||
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
module_timing: ModuleTiming,
|
||||
) -> (ModuleId, Msg<'a>) {
|
||||
@ -2141,16 +2229,18 @@ fn send_header<'a>(
|
||||
}
|
||||
};
|
||||
|
||||
let mut imported: Vec<(ModuleName, Vec<Ident>, Region)> = Vec::with_capacity(imports.len());
|
||||
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 {
|
||||
let (module_name, exposed) = exposed_from_import(&loc_entry.value);
|
||||
let (qualified_module_name, exposed) = exposed_from_import(&loc_entry.value);
|
||||
|
||||
scope_size += exposed.len();
|
||||
|
||||
imported.push((module_name, exposed, loc_entry.region));
|
||||
imported.push((qualified_module_name, exposed, loc_entry.region));
|
||||
}
|
||||
|
||||
let num_exposes = exposes.len();
|
||||
@ -2167,6 +2257,7 @@ 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());
|
||||
@ -2178,16 +2269,30 @@ fn send_header<'a>(
|
||||
|
||||
// For each of our imports, add an entry to deps_by_name
|
||||
//
|
||||
// e.g. for `imports [ Foo.{ bar } ]`, add `Foo` to deps_by_name
|
||||
// e.g. for `imports [ base.Foo.{ bar } ]`, add `Foo` to deps_by_name
|
||||
//
|
||||
// Also build a list of imported_values_to_expose (like `bar` above.)
|
||||
for (module_name, exposed_idents, region) in imported.into_iter() {
|
||||
let cloned_module_name = module_name.clone();
|
||||
let module_id = module_ids.get_or_insert(&module_name.into());
|
||||
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());
|
||||
|
||||
deps_by_name.insert(cloned_module_name, module_id);
|
||||
imported_modules.insert(id);
|
||||
|
||||
imported_modules.insert(module_id);
|
||||
deps_by_name.insert(cloned_module_name, id);
|
||||
|
||||
id
|
||||
}
|
||||
Some(package) => {
|
||||
let id =
|
||||
package_module_ids.get_or_insert(&(package, cloned_module_name.into()));
|
||||
|
||||
imported_package_modules.insert(id);
|
||||
|
||||
id
|
||||
}
|
||||
};
|
||||
|
||||
// Add the new exposed idents to the dep module's IdentIds, so
|
||||
// once that module later gets loaded, its lookups will resolve
|
||||
@ -2250,6 +2355,7 @@ fn send_header<'a>(
|
||||
exposed_ident_ids: ident_ids,
|
||||
module_name: loc_name.value,
|
||||
imported_modules,
|
||||
imported_package_modules,
|
||||
deps_by_name,
|
||||
exposes: exposed,
|
||||
src: parse_state.bytes,
|
||||
@ -2370,9 +2476,12 @@ fn run_solve<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn fabricate_effects_module<'a>(
|
||||
arena: &'a Bump,
|
||||
shorthand: &'a str,
|
||||
module_ids: Arc<Mutex<ModuleIds>>,
|
||||
package_module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
|
||||
ident_ids_by_module: Arc<Mutex<MutMap<ModuleId, IdentIds>>>,
|
||||
mode: Mode,
|
||||
header: PlatformHeader<'a>,
|
||||
@ -2398,6 +2507,14 @@ fn fabricate_effects_module<'a>(
|
||||
functions
|
||||
};
|
||||
|
||||
let mut package_module_ids = (*package_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()));
|
||||
}
|
||||
}
|
||||
|
||||
let exposed_ident_ids = {
|
||||
// Lock just long enough to perform the minimal operations necessary.
|
||||
let mut module_ids = (*module_ids).lock();
|
||||
@ -2782,7 +2899,7 @@ fn parse<'a>(arena: &'a Bump, header: ModuleHeader<'a>) -> Result<Msg<'a>, Loadi
|
||||
Ok(Msg::Parsed(parsed))
|
||||
}
|
||||
|
||||
fn exposed_from_import(entry: &ImportsEntry<'_>) -> (ModuleName, Vec<Ident>) {
|
||||
fn exposed_from_import<'a>(entry: &ImportsEntry<'a>) -> (QualifiedModuleName<'a>, Vec<Ident>) {
|
||||
use roc_parse::header::ImportsEntry::*;
|
||||
|
||||
match entry {
|
||||
@ -2793,11 +2910,27 @@ fn exposed_from_import(entry: &ImportsEntry<'_>) -> (ModuleName, Vec<Ident>) {
|
||||
exposed.push(ident_from_exposed(&loc_entry.value));
|
||||
}
|
||||
|
||||
(module_name.as_str().into(), exposed)
|
||||
let qualified_module_name = QualifiedModuleName {
|
||||
opt_package: None,
|
||||
module: module_name.as_str().into(),
|
||||
};
|
||||
|
||||
(qualified_module_name, exposed)
|
||||
}
|
||||
|
||||
Package(_package_name, _module_name, _exposes) => {
|
||||
todo!("TODO support exposing package-qualified module names.");
|
||||
Package(package_name, module_name, exposes) => {
|
||||
let mut exposed = Vec::with_capacity(exposes.len());
|
||||
|
||||
for loc_entry in exposes {
|
||||
exposed.push(ident_from_exposed(&loc_entry.value));
|
||||
}
|
||||
|
||||
let qualified_module_name = QualifiedModuleName {
|
||||
opt_package: Some(package_name),
|
||||
module: module_name.as_str().into(),
|
||||
};
|
||||
|
||||
(qualified_module_name, exposed)
|
||||
}
|
||||
|
||||
SpaceBefore(sub_entry, _) | SpaceAfter(sub_entry, _) => {
|
||||
@ -3074,6 +3207,7 @@ fn run_task<'a>(
|
||||
LoadModule {
|
||||
module_name,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
} => load_module(
|
||||
@ -3081,15 +3215,26 @@ fn run_task<'a>(
|
||||
src_dir,
|
||||
module_name,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
)
|
||||
.map(|(_, msg)| msg),
|
||||
LoadPkgConfig {
|
||||
shorthand,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
} => load_pkg_config(arena, src_dir, module_ids, ident_ids_by_module, mode),
|
||||
} => load_pkg_config(
|
||||
arena,
|
||||
src_dir,
|
||||
shorthand,
|
||||
module_ids,
|
||||
package_module_ids,
|
||||
ident_ids_by_module,
|
||||
mode,
|
||||
),
|
||||
Parse { header } => parse(arena, header),
|
||||
CanonicalizeAndConstrain {
|
||||
parsed,
|
||||
|
@ -12,6 +12,11 @@ impl Ident {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct QualifiedModuleName<'a> {
|
||||
pub opt_package: Option<&'a str>,
|
||||
pub module: ModuleName,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct ModuleName(InlinableString);
|
||||
|
||||
|
@ -310,6 +310,69 @@ impl fmt::Debug for ModuleId {
|
||||
}
|
||||
}
|
||||
|
||||
/// base.Task
|
||||
/// 1. build mapping from short name to package
|
||||
/// 2. when adding new modules from package we need to register them in some other map (this module id goes with short name) (shortname, module-name) -> moduleId
|
||||
/// 3. pass this around to other modules getting headers parsed. when parsing interfaces we need to use this map to reference shortnames
|
||||
/// 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);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PackageModuleIds<'a> {
|
||||
by_name: MutMap<PackageModule<'a>, ModuleId>,
|
||||
by_id: Vec<PackageModule<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> PackageModuleIds<'a> {
|
||||
pub fn get_or_insert(&mut self, module_name: &PackageModule<'a>) -> ModuleId {
|
||||
match self.by_name.get(module_name) {
|
||||
Some(id) => *id,
|
||||
None => {
|
||||
let by_id = &mut self.by_id;
|
||||
let module_id = ModuleId(by_id.len() as u32);
|
||||
|
||||
by_id.push(module_name.clone());
|
||||
|
||||
self.by_name.insert(module_name.clone(), module_id);
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
Self::insert_debug_name(module_id, &module_name);
|
||||
}
|
||||
|
||||
module_id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
fn insert_debug_name(module_id: ModuleId, module_name: &PackageModule) {
|
||||
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());
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn insert_debug_name(_module_id: ModuleId, _module_name: &PackageModule) {
|
||||
// By design, this is a no-op in release builds!
|
||||
}
|
||||
|
||||
pub fn get_id(&self, module_name: &PackageModule<'a>) -> Option<&ModuleId> {
|
||||
self.by_name.get(module_name)
|
||||
}
|
||||
|
||||
pub fn get_name(&self, id: ModuleId) -> Option<&PackageModule> {
|
||||
self.by_id.get(id.0 as usize)
|
||||
}
|
||||
|
||||
pub fn available_modules(&self) -> impl Iterator<Item = &PackageModule> {
|
||||
self.by_id.iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores a mapping between ModuleId and InlinableString.
|
||||
///
|
||||
/// Each module name is stored twice, for faster lookups.
|
||||
@ -551,6 +614,18 @@ macro_rules! define_builtins {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Default for PackageModuleIds<'a> {
|
||||
fn default() -> Self {
|
||||
// +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);
|
||||
|
||||
PackageModuleIds { by_name, by_id }
|
||||
}
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
$(
|
||||
$(
|
||||
|
@ -1,7 +1,9 @@
|
||||
app "effect-example" imports [ Effect ] provides [ main ] to "./platform"
|
||||
app "effect-example"
|
||||
packages { base: "./thing/platform-dir" }
|
||||
imports [ base.Task.{ Task, after } ]
|
||||
provides [ main ] to base
|
||||
|
||||
|
||||
main : Effect.Effect {} as Fx
|
||||
main : Task {}
|
||||
main =
|
||||
when if 1 == 1 then True 3 else False 3.14 is
|
||||
True n -> Effect.putLine (Str.fromInt n)
|
||||
|
@ -1,6 +1,6 @@
|
||||
platform folkertdev/foo
|
||||
requires { main : Effect {} }
|
||||
exposes []
|
||||
exposes [ Task ]
|
||||
packages {}
|
||||
imports []
|
||||
provides [ mainForHost ]
|
9
examples/effect/thing/platform-dir/Task.roc
Normal file
9
examples/effect/thing/platform-dir/Task.roc
Normal file
@ -0,0 +1,9 @@
|
||||
interface Task
|
||||
exposes [ Task, putLine, after ]
|
||||
imports [ Effect ]
|
||||
|
||||
Task a : Effect.Effect a
|
||||
|
||||
putLine = Effect.putLine
|
||||
|
||||
after = Effect.after
|
Loading…
Reference in New Issue
Block a user