mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
Bump-allocate LoadedModule
This commit is contained in:
parent
d06ad19eb0
commit
52dc4e9a03
2 changed files with 124 additions and 95 deletions
|
@ -36,7 +36,7 @@ const ROC_FILE_EXTENSION: &str = "roc";
|
||||||
const MODULE_SEPARATOR: char = '.';
|
const MODULE_SEPARATOR: char = '.';
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LoadedModule {
|
pub struct LoadedModule<'a> {
|
||||||
pub module_id: ModuleId,
|
pub module_id: ModuleId,
|
||||||
pub interns: Interns,
|
pub interns: Interns,
|
||||||
pub solved: Solved<Subs>,
|
pub solved: Solved<Subs>,
|
||||||
|
@ -44,7 +44,7 @@ pub struct LoadedModule {
|
||||||
pub type_problems: Vec<solve::TypeError>,
|
pub type_problems: Vec<solve::TypeError>,
|
||||||
pub declarations_by_id: MutMap<ModuleId, Vec<Declaration>>,
|
pub declarations_by_id: MutMap<ModuleId, Vec<Declaration>>,
|
||||||
pub exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
pub exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||||
pub src: Box<str>,
|
pub src: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -85,6 +85,7 @@ enum Msg<'a> {
|
||||||
},
|
},
|
||||||
Finished {
|
Finished {
|
||||||
solved: Solved<Subs>,
|
solved: Solved<Subs>,
|
||||||
|
problems: Vec<solve::TypeError>,
|
||||||
exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||||
src: &'a str,
|
src: &'a str,
|
||||||
},
|
},
|
||||||
|
@ -161,15 +162,15 @@ type MsgReceiver<'a> = Receiver<Msg<'a>>;
|
||||||
/// specializations, so if none of their specializations changed, we don't even need
|
/// specializations, so if none of their specializations changed, we don't even need
|
||||||
/// to rebuild the module and can link in the cached one directly.)
|
/// to rebuild the module and can link in the cached one directly.)
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
pub fn load(
|
pub fn load<'a>(
|
||||||
|
arena: &'a Bump,
|
||||||
stdlib: &StdLib,
|
stdlib: &StdLib,
|
||||||
src_dir: PathBuf,
|
src_dir: PathBuf,
|
||||||
filename: PathBuf,
|
filename: PathBuf,
|
||||||
exposed_types: SubsByModule,
|
exposed_types: SubsByModule,
|
||||||
) -> Result<LoadedModule, LoadingProblem> {
|
) -> Result<LoadedModule<'a>, LoadingProblem> {
|
||||||
use self::MaybeShared::*;
|
use self::MaybeShared::*;
|
||||||
|
|
||||||
let arena = Bump::new();
|
|
||||||
let (msg_tx, msg_rx) = bounded(1024);
|
let (msg_tx, msg_rx) = bounded(1024);
|
||||||
let arc_modules = Arc::new(Mutex::new(ModuleIds::default()));
|
let arc_modules = Arc::new(Mutex::new(ModuleIds::default()));
|
||||||
let root_exposed_ident_ids = IdentIds::exposed_builtins(0);
|
let root_exposed_ident_ids = IdentIds::exposed_builtins(0);
|
||||||
|
@ -278,7 +279,7 @@ fn load_deps<'a>(
|
||||||
arc_modules: Arc<Mutex<ModuleIds>>,
|
arc_modules: Arc<Mutex<ModuleIds>>,
|
||||||
ident_ids_by_module: Arc<Mutex<IdentIdsByModule>>,
|
ident_ids_by_module: Arc<Mutex<IdentIdsByModule>>,
|
||||||
exposed_types: SubsByModule,
|
exposed_types: SubsByModule,
|
||||||
) -> Result<LoadedModule, LoadingProblem> {
|
) -> Result<LoadedModule<'a>, LoadingProblem> {
|
||||||
// Reserve one CPU for the main thread, and let all the others be eligible
|
// Reserve one CPU for the main thread, and let all the others be eligible
|
||||||
// to spawn workers.
|
// to spawn workers.
|
||||||
let num_workers = num_cpus::get() - 1;
|
let num_workers = num_cpus::get() - 1;
|
||||||
|
@ -409,6 +410,7 @@ fn load_deps<'a>(
|
||||||
match msg {
|
match msg {
|
||||||
Msg::Finished {
|
Msg::Finished {
|
||||||
solved,
|
solved,
|
||||||
|
problems,
|
||||||
exposed_vars_by_symbol,
|
exposed_vars_by_symbol,
|
||||||
src,
|
src,
|
||||||
} => {
|
} => {
|
||||||
|
@ -417,6 +419,8 @@ fn load_deps<'a>(
|
||||||
|
|
||||||
dbg!("TODO send Shutdown messages to all the worker threads.");
|
dbg!("TODO send Shutdown messages to all the worker threads.");
|
||||||
|
|
||||||
|
state.type_problems.extend(problems);
|
||||||
|
|
||||||
let module_ids = Arc::try_unwrap(state.arc_modules)
|
let module_ids = Arc::try_unwrap(state.arc_modules)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
panic!("There were still outstanding Arc references to module_ids")
|
panic!("There were still outstanding Arc references to module_ids")
|
||||||
|
@ -762,19 +766,22 @@ fn update<'a>(
|
||||||
solved_module,
|
solved_module,
|
||||||
solved_subs,
|
solved_subs,
|
||||||
} => {
|
} => {
|
||||||
state.type_problems.extend(solved_module.problems);
|
|
||||||
|
|
||||||
if module_id == state.root_id {
|
if module_id == state.root_id {
|
||||||
let solved = Arc::try_unwrap(solved_subs).unwrap_or_else(|_| {
|
let solved = Arc::try_unwrap(solved_subs).unwrap_or_else(|_| {
|
||||||
panic!("There were still outstanding Arc references to Solved<Subs>")
|
panic!("There were still outstanding Arc references to Solved<Subs>")
|
||||||
});
|
});
|
||||||
|
|
||||||
msg_tx.send(Msg::Finished {
|
msg_tx
|
||||||
|
.send(Msg::Finished {
|
||||||
solved,
|
solved,
|
||||||
|
problems: solved_module.problems,
|
||||||
exposed_vars_by_symbol: solved_module.exposed_vars_by_symbol,
|
exposed_vars_by_symbol: solved_module.exposed_vars_by_symbol,
|
||||||
src,
|
src,
|
||||||
});
|
})
|
||||||
|
.map_err(|_| LoadingProblem::MsgChannelDied)?;
|
||||||
} else {
|
} else {
|
||||||
|
state.type_problems.extend(solved_module.problems);
|
||||||
|
|
||||||
// This was a dependency. Write it down and keep processing messages.
|
// This was a dependency. Write it down and keep processing messages.
|
||||||
debug_assert!(!state.exposed_types.contains_key(&module_id));
|
debug_assert!(!state.exposed_types.contains_key(&module_id));
|
||||||
state.exposed_types.insert(
|
state.exposed_types.insert(
|
||||||
|
@ -1147,84 +1154,84 @@ fn add_exposed_to_scope(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//// TODO trim down these arguments - possibly by moving Constraint into Module
|
// TODO trim down these arguments - possibly by moving Constraint into Module
|
||||||
//#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
//fn spawn_solve_module(
|
fn spawn_solve_module(
|
||||||
// module: Module,
|
module: Module,
|
||||||
// src: Box<str>,
|
src: Box<str>,
|
||||||
// constraint: Constraint,
|
constraint: Constraint,
|
||||||
// mut var_store: VarStore,
|
mut var_store: VarStore,
|
||||||
// imported_modules: MutSet<ModuleId>,
|
imported_modules: MutSet<ModuleId>,
|
||||||
// msg_tx: MsgSender,
|
msg_tx: MsgSender,
|
||||||
// exposed_types: &mut SubsByModule,
|
exposed_types: &mut SubsByModule,
|
||||||
// stdlib: &StdLib,
|
stdlib: &StdLib,
|
||||||
//) {
|
) {
|
||||||
// let home = module.module_id;
|
let home = module.module_id;
|
||||||
|
|
||||||
// // Get the constraints for this module's imports. We do this on the main thread
|
// Get the constraints for this module's imports. We do this on the main thread
|
||||||
// // to avoid having to lock the map of exposed types, or to clone it
|
// to avoid having to lock the map of exposed types, or to clone it
|
||||||
// // (which would be more expensive for the main thread).
|
// (which would be more expensive for the main thread).
|
||||||
// let ConstrainableImports {
|
let ConstrainableImports {
|
||||||
// imported_symbols,
|
imported_symbols,
|
||||||
// imported_aliases,
|
imported_aliases,
|
||||||
// unused_imports,
|
unused_imports,
|
||||||
// } = pre_constrain_imports(
|
} = pre_constrain_imports(
|
||||||
// home,
|
home,
|
||||||
// &module.references,
|
&module.references,
|
||||||
// imported_modules,
|
imported_modules,
|
||||||
// exposed_types,
|
exposed_types,
|
||||||
// stdlib,
|
stdlib,
|
||||||
// );
|
);
|
||||||
|
|
||||||
// for unused_import in unused_imports {
|
for unused_import in unused_imports {
|
||||||
// todo!(
|
todo!(
|
||||||
// "TODO gracefully handle unused import {:?} from module {:?}",
|
"TODO gracefully handle unused import {:?} from module {:?}",
|
||||||
// unused_import,
|
unused_import,
|
||||||
// home
|
home
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // We can't pass the reference to stdlib to the thread, but we can pass mode.
|
// We can't pass the reference to stdlib to the thread, but we can pass mode.
|
||||||
// let mode = stdlib.mode;
|
let mode = stdlib.mode;
|
||||||
|
|
||||||
// // Start solving this module in the background.
|
// Start solving this module in the background.
|
||||||
// thread_scope.spawn(move |_| {
|
// thread_scope.spawn(move |_| {
|
||||||
// // Rebuild the aliases in this thread, so we don't have to clone all of
|
// // Rebuild the aliases in this thread, so we don't have to clone all of
|
||||||
// // stdlib.aliases on the main thread.
|
// // stdlib.aliases on the main thread.
|
||||||
// let aliases = match mode {
|
// let aliases = match mode {
|
||||||
// Mode::Standard => roc_builtins::std::aliases(),
|
// Mode::Standard => roc_builtins::std::aliases(),
|
||||||
// Mode::Uniqueness => roc_builtins::unique::aliases(),
|
// Mode::Uniqueness => roc_builtins::unique::aliases(),
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// // Finish constraining the module by wrapping the existing Constraint
|
// // Finish constraining the module by wrapping the existing Constraint
|
||||||
// // in the ones we just computed. We can do this off the main thread.
|
// // in the ones we just computed. We can do this off the main thread.
|
||||||
// let constraint = constrain_imports(
|
// let constraint = constrain_imports(
|
||||||
// imported_symbols,
|
// imported_symbols,
|
||||||
// imported_aliases,
|
// imported_aliases,
|
||||||
// constraint,
|
// constraint,
|
||||||
// &mut var_store,
|
// &mut var_store,
|
||||||
// );
|
// );
|
||||||
// let mut constraint = load_builtin_aliases(aliases, constraint, &mut var_store);
|
// let mut constraint = load_builtin_aliases(aliases, constraint, &mut var_store);
|
||||||
|
|
||||||
// // Turn Apply into Alias
|
// // Turn Apply into Alias
|
||||||
// constraint.instantiate_aliases(&mut var_store);
|
// constraint.instantiate_aliases(&mut var_store);
|
||||||
|
|
||||||
// let (solved_subs, solved_module) =
|
// let (solved_subs, solved_module) =
|
||||||
// roc_solve::module::solve_module(module, constraint, var_store);
|
// roc_solve::module::solve_module(module, constraint, var_store);
|
||||||
|
|
||||||
// thread_scope.spawn(move |_| {
|
// thread_scope.spawn(move |_| {
|
||||||
// // Send the subs to the main thread for processing,
|
// // Send the subs to the main thread for processing,
|
||||||
// msg_tx
|
// msg_tx
|
||||||
// .send(Msg::Solved {
|
// .send(Msg::Solved {
|
||||||
// src,
|
// src,
|
||||||
// module_id: home,
|
// module_id: home,
|
||||||
// solved_subs: Arc::new(solved_subs),
|
// solved_subs: Arc::new(solved_subs),
|
||||||
// solved_module,
|
// solved_module,
|
||||||
// })
|
// })
|
||||||
// .unwrap_or_else(|_| panic!("Failed to send Solved message"));
|
// .unwrap_or_else(|_| panic!("Failed to send Solved message"));
|
||||||
// });
|
// });
|
||||||
// });
|
// });
|
||||||
//}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn build_parse_and_constrain_task<'a, 'b>(
|
fn build_parse_and_constrain_task<'a, 'b>(
|
||||||
|
|
|
@ -14,6 +14,7 @@ mod helpers;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_load {
|
mod test_load {
|
||||||
use crate::helpers::fixtures_dir;
|
use crate::helpers::fixtures_dir;
|
||||||
|
use bumpalo::Bump;
|
||||||
use inlinable_string::InlinableString;
|
use inlinable_string::InlinableString;
|
||||||
use roc_can::def::Declaration::*;
|
use roc_can::def::Declaration::*;
|
||||||
use roc_can::def::Def;
|
use roc_can::def::Def;
|
||||||
|
@ -27,14 +28,16 @@ mod test_load {
|
||||||
|
|
||||||
// HELPERS
|
// HELPERS
|
||||||
|
|
||||||
fn load_fixture(
|
fn load_fixture<'a>(
|
||||||
|
arena: &'a Bump,
|
||||||
dir_name: &str,
|
dir_name: &str,
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
subs_by_module: SubsByModule,
|
subs_by_module: SubsByModule,
|
||||||
) -> LoadedModule {
|
) -> LoadedModule<'a> {
|
||||||
let src_dir = fixtures_dir().join(dir_name);
|
let src_dir = fixtures_dir().join(dir_name);
|
||||||
let filename = src_dir.join(format!("{}.roc", module_name));
|
let filename = src_dir.join(format!("{}.roc", module_name));
|
||||||
let loaded = load(
|
let loaded = load(
|
||||||
|
&arena,
|
||||||
&roc_builtins::std::standard_stdlib(),
|
&roc_builtins::std::standard_stdlib(),
|
||||||
src_dir,
|
src_dir,
|
||||||
filename,
|
filename,
|
||||||
|
@ -128,7 +131,9 @@ mod test_load {
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let src_dir = fixtures_dir().join("interface_with_deps");
|
let src_dir = fixtures_dir().join("interface_with_deps");
|
||||||
let filename = src_dir.join("Primary.roc");
|
let filename = src_dir.join("Primary.roc");
|
||||||
|
let arena = Bump::new();
|
||||||
let loaded = load(
|
let loaded = load(
|
||||||
|
&arena,
|
||||||
&roc_builtins::std::standard_stdlib(),
|
&roc_builtins::std::standard_stdlib(),
|
||||||
src_dir,
|
src_dir,
|
||||||
filename,
|
filename,
|
||||||
|
@ -160,8 +165,9 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn load_unit() {
|
fn load_unit() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("no_deps", "Unit", subs_by_module);
|
let loaded_module = load_fixture(&arena, "no_deps", "Unit", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -173,8 +179,10 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn import_alias() {
|
fn import_alias() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "ImportAlias", subs_by_module);
|
let loaded_module =
|
||||||
|
load_fixture(&arena, "interface_with_deps", "ImportAlias", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -186,8 +194,14 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn load_and_typecheck() {
|
fn load_and_typecheck() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "WithBuiltins", subs_by_module);
|
let loaded_module = load_fixture(
|
||||||
|
&arena,
|
||||||
|
"interface_with_deps",
|
||||||
|
"WithBuiltins",
|
||||||
|
subs_by_module,
|
||||||
|
);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -206,8 +220,10 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn iface_quicksort() {
|
fn iface_quicksort() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Quicksort", subs_by_module);
|
let loaded_module =
|
||||||
|
load_fixture(&arena, "interface_with_deps", "Quicksort", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -221,8 +237,9 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn app_quicksort() {
|
fn app_quicksort() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("app_with_deps", "Quicksort", subs_by_module);
|
let loaded_module = load_fixture(&arena, "app_with_deps", "Quicksort", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -236,8 +253,9 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn load_astar() {
|
fn load_astar() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "AStar", subs_by_module);
|
let loaded_module = load_fixture(&arena, "interface_with_deps", "AStar", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -254,8 +272,9 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn load_principal_types() {
|
fn load_principal_types() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("no_deps", "Principal", subs_by_module);
|
let loaded_module = load_fixture(&arena, "no_deps", "Principal", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -268,8 +287,9 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn iface_dep_types() {
|
fn iface_dep_types() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "Primary", subs_by_module);
|
let loaded_module = load_fixture(&arena, "interface_with_deps", "Primary", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -290,8 +310,9 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn app_dep_types() {
|
fn app_dep_types() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("app_with_deps", "Primary", subs_by_module);
|
let loaded_module = load_fixture(&arena, "app_with_deps", "Primary", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -312,8 +333,9 @@ mod test_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn imported_dep_regression() {
|
fn imported_dep_regression() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let loaded_module = load_fixture("interface_with_deps", "OneDep", subs_by_module);
|
let loaded_module = load_fixture(&arena, "interface_with_deps", "OneDep", subs_by_module);
|
||||||
|
|
||||||
expect_types(
|
expect_types(
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue