mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Revert "idea (rejected): only generate work up to constraint gen, then look at what modules are actually used and generate Solve.. work based on that"
This reverts commit 2cbe5f5231
.
This commit is contained in:
parent
2cbe5f5231
commit
e914272bf5
5 changed files with 23 additions and 156 deletions
|
@ -157,8 +157,6 @@ pub fn build_file<'a>(
|
||||||
|
|
||||||
buf.push('\n');
|
buf.push('\n');
|
||||||
|
|
||||||
dbg!(module_id);
|
|
||||||
|
|
||||||
report_timing(buf, "Read .roc file from disk", module_timing.read_roc_file);
|
report_timing(buf, "Read .roc file from disk", module_timing.read_roc_file);
|
||||||
report_timing(buf, "Parse header", module_timing.parse_header);
|
report_timing(buf, "Parse header", module_timing.parse_header);
|
||||||
report_timing(buf, "Parse body", module_timing.parse_body);
|
report_timing(buf, "Parse body", module_timing.parse_body);
|
||||||
|
|
|
@ -32,21 +32,13 @@ impl ExposedByModule {
|
||||||
///
|
///
|
||||||
/// Useful when we know what modules a particular module imports, and want just
|
/// Useful when we know what modules a particular module imports, and want just
|
||||||
/// the exposed types for those exposed modules.
|
/// the exposed types for those exposed modules.
|
||||||
pub fn retain_modules<'a>(
|
pub fn retain_modules<'a>(&self, it: impl Iterator<Item = &'a ModuleId>) -> Self {
|
||||||
&self,
|
|
||||||
home: ModuleId,
|
|
||||||
it: impl Iterator<Item = &'a ModuleId>,
|
|
||||||
) -> Self {
|
|
||||||
let mut output = Self::default();
|
let mut output = Self::default();
|
||||||
|
|
||||||
for module_id in it {
|
for module_id in it {
|
||||||
match self.exposed.get(module_id) {
|
match self.exposed.get(module_id) {
|
||||||
None => {
|
None => {
|
||||||
internal_error!(
|
internal_error!("Module {:?} did not register its exposed values", module_id)
|
||||||
"Module {:?} did not register its exposed values for {:?}",
|
|
||||||
module_id,
|
|
||||||
home,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Some(exposed_types) => {
|
Some(exposed_types) => {
|
||||||
output.exposed.insert(*module_id, exposed_types.clone());
|
output.exposed.insert(*module_id, exposed_types.clone());
|
||||||
|
|
|
@ -1099,7 +1099,7 @@ fn load<'a>(
|
||||||
) -> Result<LoadResult<'a>, LoadingProblem<'a>> {
|
) -> Result<LoadResult<'a>, LoadingProblem<'a>> {
|
||||||
// When compiling to wasm, we cannot spawn extra threads
|
// When compiling to wasm, we cannot spawn extra threads
|
||||||
// so we have a single-threaded implementation
|
// so we have a single-threaded implementation
|
||||||
if cfg!(target_family = "wasm") {
|
if true || cfg!(target_family = "wasm") {
|
||||||
load_single_threaded(
|
load_single_threaded(
|
||||||
arena,
|
arena,
|
||||||
load_start,
|
load_start,
|
||||||
|
@ -1614,18 +1614,14 @@ fn report_unused_imported_modules<'a>(
|
||||||
state: &mut State<'a>,
|
state: &mut State<'a>,
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
constrained_module: &ConstrainedModule,
|
constrained_module: &ConstrainedModule,
|
||||||
) -> (Vec<ModuleId>, Vec<ModuleId>) {
|
) {
|
||||||
let mut kept = vec![];
|
|
||||||
let mut removed = vec![];
|
|
||||||
let mut unused_imported_modules = constrained_module.imported_modules.clone();
|
let mut unused_imported_modules = constrained_module.imported_modules.clone();
|
||||||
|
|
||||||
for symbol in constrained_module.module.referenced_values.iter() {
|
for symbol in constrained_module.module.referenced_values.iter() {
|
||||||
kept.push(symbol.module_id());
|
|
||||||
unused_imported_modules.remove(&symbol.module_id());
|
unused_imported_modules.remove(&symbol.module_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
for symbol in constrained_module.module.referenced_types.iter() {
|
for symbol in constrained_module.module.referenced_types.iter() {
|
||||||
kept.push(symbol.module_id());
|
|
||||||
unused_imported_modules.remove(&symbol.module_id());
|
unused_imported_modules.remove(&symbol.module_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1637,23 +1633,8 @@ fn report_unused_imported_modules<'a>(
|
||||||
for (unused, region) in unused_imported_modules.drain() {
|
for (unused, region) in unused_imported_modules.drain() {
|
||||||
if !unused.is_builtin() {
|
if !unused.is_builtin() {
|
||||||
existing.push(roc_problem::can::Problem::UnusedImport(unused, region));
|
existing.push(roc_problem::can::Problem::UnusedImport(unused, region));
|
||||||
|
|
||||||
// we will still typecheck this module to report errors
|
|
||||||
kept.push(unused)
|
|
||||||
} else {
|
|
||||||
// for builtin modules, we will just skip the rest of the process
|
|
||||||
// in the future, we can also do this for modules from packages
|
|
||||||
removed.push(unused);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kept.sort();
|
|
||||||
kept.dedup();
|
|
||||||
|
|
||||||
removed.sort();
|
|
||||||
removed.dedup();
|
|
||||||
|
|
||||||
(kept, removed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update<'a>(
|
fn update<'a>(
|
||||||
|
@ -1889,7 +1870,7 @@ fn update<'a>(
|
||||||
work.extend(state.dependencies.add_module(
|
work.extend(state.dependencies.add_module(
|
||||||
header.module_id,
|
header.module_id,
|
||||||
&header.package_qualified_imported_modules,
|
&header.package_qualified_imported_modules,
|
||||||
Phase::CanonicalizeAndConstrain,
|
state.goal_phase,
|
||||||
));
|
));
|
||||||
|
|
||||||
state.module_cache.headers.insert(header.module_id, header);
|
state.module_cache.headers.insert(header.module_id, header);
|
||||||
|
@ -1938,7 +1919,7 @@ fn update<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
CanonicalizedAndConstrained {
|
CanonicalizedAndConstrained {
|
||||||
mut constrained_module,
|
constrained_module,
|
||||||
canonicalization_problems,
|
canonicalization_problems,
|
||||||
module_docs,
|
module_docs,
|
||||||
} => {
|
} => {
|
||||||
|
@ -1953,52 +1934,8 @@ fn update<'a>(
|
||||||
state.module_cache.documentation.insert(module_id, docs);
|
state.module_cache.documentation.insert(module_id, docs);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (kept, removed) =
|
|
||||||
report_unused_imported_modules(&mut state, module_id, &constrained_module);
|
report_unused_imported_modules(&mut state, module_id, &constrained_module);
|
||||||
|
|
||||||
for rem in removed {
|
|
||||||
constrained_module.imported_modules.remove(&rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
use std::fmt::Write;
|
|
||||||
let mut buf = String::new();
|
|
||||||
writeln!(buf, "{:?} depends on:", module_id);
|
|
||||||
for dep in kept {
|
|
||||||
if !constrained_module.imported_modules.contains_key(&dep) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
writeln!(buf, " {:?} ", dep);
|
|
||||||
if module_id != dep {
|
|
||||||
state
|
|
||||||
.dependencies
|
|
||||||
.add_dependency(module_id, dep, Phase::SolveTypes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("{}", buf);
|
|
||||||
|
|
||||||
state.dependencies.add_dependency_help(
|
|
||||||
module_id,
|
|
||||||
module_id,
|
|
||||||
Phase::SolveTypes,
|
|
||||||
Phase::CanonicalizeAndConstrain,
|
|
||||||
);
|
|
||||||
|
|
||||||
state
|
|
||||||
.dependencies
|
|
||||||
.add_to_status(module_id, Phase::SolveTypes);
|
|
||||||
|
|
||||||
/*
|
|
||||||
for dependency in remove_dependencies {
|
|
||||||
println!("remove dep {:?} <- {:?}", module_id, dependency);
|
|
||||||
state.dependencies.remove_dependencies(
|
|
||||||
module_id,
|
|
||||||
dependency,
|
|
||||||
Phase::SolveTypes,
|
|
||||||
state.goal_phase,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
state
|
state
|
||||||
.module_cache
|
.module_cache
|
||||||
.aliases
|
.aliases
|
||||||
|
@ -2059,7 +1996,7 @@ fn update<'a>(
|
||||||
|
|
||||||
if is_host_exposed && state.goal_phase == Phase::SolveTypes {
|
if is_host_exposed && state.goal_phase == Phase::SolveTypes {
|
||||||
debug_assert!(work.is_empty());
|
debug_assert!(work.is_empty());
|
||||||
// debug_assert!(state.dependencies.solved_all());
|
debug_assert!(state.dependencies.solved_all());
|
||||||
|
|
||||||
state.timings.insert(module_id, module_timing);
|
state.timings.insert(module_id, module_timing);
|
||||||
|
|
||||||
|
@ -2850,7 +2787,10 @@ fn load_module<'a>(
|
||||||
roc_parse::header::ModuleName::new("Bool"),
|
roc_parse::header::ModuleName::new("Bool"),
|
||||||
Collection::with_items(&[Loc::at_zero(Spaced::Item(ExposedName::new("Bool")))]),
|
Collection::with_items(&[Loc::at_zero(Spaced::Item(ExposedName::new("Bool")))]),
|
||||||
)),
|
)),
|
||||||
// Note: List is only used for the type, which we ensure is always in scope
|
Loc::at_zero(ImportsEntry::Module(
|
||||||
|
roc_parse::header::ModuleName::new("List"),
|
||||||
|
Collection::with_items(&[Loc::at_zero(Spaced::Item(ExposedName::new("List")))]),
|
||||||
|
)),
|
||||||
Loc::at_zero(ImportsEntry::Module(
|
Loc::at_zero(ImportsEntry::Module(
|
||||||
roc_parse::header::ModuleName::new("Num"),
|
roc_parse::header::ModuleName::new("Num"),
|
||||||
Collection::with_items(&[
|
Collection::with_items(&[
|
||||||
|
@ -2916,6 +2856,9 @@ fn load_module<'a>(
|
||||||
|
|
||||||
toUtf8 : Str -> List U8
|
toUtf8 : Str -> List U8
|
||||||
|
|
||||||
|
# fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8Problem ]*
|
||||||
|
# fromUtf8Range : List U8 -> Result Str [ BadUtf8 Utf8Problem Nat, OutOfBounds ]*
|
||||||
|
|
||||||
fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8ByteProblem Nat ]*
|
fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8ByteProblem Nat ]*
|
||||||
fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [ BadUtf8 Utf8ByteProblem Nat, OutOfBounds ]*
|
fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [ BadUtf8 Utf8ByteProblem Nat, OutOfBounds ]*
|
||||||
|
|
||||||
|
@ -4401,8 +4344,7 @@ impl<'a> BuildTask<'a> {
|
||||||
dep_idents: MutMap<ModuleId, IdentIds>,
|
dep_idents: MutMap<ModuleId, IdentIds>,
|
||||||
declarations: Vec<Declaration>,
|
declarations: Vec<Declaration>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let exposed_by_module =
|
let exposed_by_module = exposed_types.retain_modules(imported_modules.keys());
|
||||||
exposed_types.retain_modules(module.module_id, imported_modules.keys());
|
|
||||||
let exposed_for_module =
|
let exposed_for_module =
|
||||||
ExposedForModule::new(module.referenced_values.iter(), exposed_by_module);
|
ExposedForModule::new(module.referenced_values.iter(), exposed_by_module);
|
||||||
|
|
||||||
|
@ -4693,10 +4635,6 @@ fn canonicalize_and_constrain<'a>(
|
||||||
let constraint =
|
let constraint =
|
||||||
constrain_module(&mut constraints, &module_output.declarations, module_id);
|
constrain_module(&mut constraints, &module_output.declarations, module_id);
|
||||||
|
|
||||||
if module_id == ModuleId::STR {
|
|
||||||
dbg!(&constraints);
|
|
||||||
}
|
|
||||||
|
|
||||||
let after = roc_types::types::get_type_clone_count();
|
let after = roc_types::types::get_type_clone_count();
|
||||||
|
|
||||||
log!(
|
log!(
|
||||||
|
|
|
@ -32,7 +32,7 @@ enum Status {
|
||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
enum Job<'a> {
|
enum Job<'a> {
|
||||||
Step(ModuleId, Phase),
|
Step(ModuleId, Phase),
|
||||||
ResolveShorthand(&'a str),
|
ResolveShorthand(&'a str),
|
||||||
|
@ -74,10 +74,8 @@ impl<'a> Dependencies<'a> {
|
||||||
// to canonicalize a module, all its dependencies must be canonicalized
|
// to canonicalize a module, all its dependencies must be canonicalized
|
||||||
self.add_dependency(module_id, dep, Phase::CanonicalizeAndConstrain);
|
self.add_dependency(module_id, dep, Phase::CanonicalizeAndConstrain);
|
||||||
|
|
||||||
if goal_phase >= Phase::SolveTypes {
|
|
||||||
// to typecheck a module, all its dependencies must be type checked already
|
// to typecheck a module, all its dependencies must be type checked already
|
||||||
self.add_dependency(module_id, dep, Phase::SolveTypes);
|
self.add_dependency(module_id, dep, Phase::SolveTypes);
|
||||||
}
|
|
||||||
|
|
||||||
if goal_phase >= FindSpecializations {
|
if goal_phase >= FindSpecializations {
|
||||||
self.add_dependency(module_id, dep, Phase::FindSpecializations);
|
self.add_dependency(module_id, dep, Phase::FindSpecializations);
|
||||||
|
@ -103,7 +101,7 @@ impl<'a> Dependencies<'a> {
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_to_status(&mut self, module_id: ModuleId, goal_phase: Phase) {
|
fn add_to_status(&mut self, module_id: ModuleId, goal_phase: Phase) {
|
||||||
for phase in PHASES.iter() {
|
for phase in PHASES.iter() {
|
||||||
if *phase > goal_phase {
|
if *phase > goal_phase {
|
||||||
break;
|
break;
|
||||||
|
@ -195,72 +193,13 @@ impl<'a> Dependencies<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_dependencies(
|
|
||||||
&mut self,
|
|
||||||
a: ModuleId,
|
|
||||||
b: ModuleId,
|
|
||||||
start_phase: Phase,
|
|
||||||
goal_phase: Phase,
|
|
||||||
) {
|
|
||||||
let mut i = 0;
|
|
||||||
while PHASES[i] < goal_phase {
|
|
||||||
let phase = PHASES[i];
|
|
||||||
|
|
||||||
if phase >= start_phase {
|
|
||||||
self.remove_dependency(a, b, phase);
|
|
||||||
}
|
|
||||||
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A waits for B, and B will notify A when it completes the phase
|
/// A waits for B, and B will notify A when it completes the phase
|
||||||
/// we will remove both of these connections
|
fn add_dependency(&mut self, a: ModuleId, b: ModuleId, phase: Phase) {
|
||||||
fn remove_dependency(&mut self, a: ModuleId, b: ModuleId, phase: Phase) {
|
|
||||||
let key = Job::Step(a, phase);
|
|
||||||
|
|
||||||
let mut notifications = vec![];
|
|
||||||
|
|
||||||
match self.waiting_for.get_mut(&key) {
|
|
||||||
None => unreachable!(),
|
|
||||||
Some(x) => {
|
|
||||||
x.retain(|job| match job {
|
|
||||||
Job::Step(module, _) => {
|
|
||||||
if *module == b {
|
|
||||||
notifications.push(*job);
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Job::ResolveShorthand(_) => true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for notification in notifications {
|
|
||||||
match self.notifies.get_mut(¬ification) {
|
|
||||||
None => unreachable!(),
|
|
||||||
Some(x) => {
|
|
||||||
x.retain(|notify_job| notify_job != &key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A waits for B, and B will notify A when it completes the phase
|
|
||||||
pub fn add_dependency(&mut self, a: ModuleId, b: ModuleId, phase: Phase) {
|
|
||||||
self.add_dependency_help(a, b, phase, phase);
|
self.add_dependency_help(a, b, phase, phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// phase_a of module a is waiting for phase_b of module_b
|
/// phase_a of module a is waiting for phase_b of module_b
|
||||||
pub fn add_dependency_help(
|
fn add_dependency_help(&mut self, a: ModuleId, b: ModuleId, phase_a: Phase, phase_b: Phase) {
|
||||||
&mut self,
|
|
||||||
a: ModuleId,
|
|
||||||
b: ModuleId,
|
|
||||||
phase_a: Phase,
|
|
||||||
phase_b: Phase,
|
|
||||||
) {
|
|
||||||
// no need to wait if the dependency is already done!
|
// no need to wait if the dependency is already done!
|
||||||
if let Some(Status::Done) = self.status.get(&Job::Step(b, phase_b)) {
|
if let Some(Status::Done) = self.status.get(&Job::Step(b, phase_b)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -293,7 +293,7 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A globally unique ID that gets assigned to each module as it is loaded.
|
/// A globally unique ID that gets assigned to each module as it is loaded.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ModuleId(u32);
|
pub struct ModuleId(u32);
|
||||||
|
|
||||||
impl ModuleId {
|
impl ModuleId {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue