Skip to content

Commit 9299e41

Browse files
Use groups of mututally recursive functions in typed modules
1 parent 60e36fe commit 9299e41

File tree

17 files changed

+536
-33
lines changed

17 files changed

+536
-33
lines changed

compiler-cli/src/publish.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ fn check_for_name_squatting(package: &Package) -> Result<(), Error> {
151151
.definitions
152152
.functions
153153
.iter()
154+
.flatten()
154155
.find_map(|function| function.main_function())
155156
else {
156157
return Ok(());
@@ -173,7 +174,7 @@ fn check_for_default_main(package: &Package) -> Result<(), Error> {
173174
let has_default_main = package
174175
.modules
175176
.iter()
176-
.flat_map(|module| module.ast.definitions.functions.iter())
177+
.flat_map(|module| module.ast.definitions.functions.iter().flatten())
177178
.filter_map(|function| function.main_function())
178179
.any(|main| main.documentation.is_none() && is_default_main(main, package_name));
179180

compiler-core/src/analyse.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
UntypedTypeAlias,
1717
},
1818
build::{Origin, Outcome, Target},
19-
call_graph::{CallGraphNode, into_dependency_order},
19+
call_graph::{CallGraphNode, into_dependency_order, into_mutually_recursive_groups},
2020
config::PackageConfig,
2121
dep_tree,
2222
inline::{self, InlinableFunction},
@@ -282,7 +282,7 @@ impl<'a, A> ModuleAnalyzer<'a, A> {
282282
// Sort functions and constants into dependency order for inference.
283283
// Definitions that do not depend on other definitions are inferred
284284
// first, then ones that depend on those, etc.
285-
let mut typed_functions = Vec::with_capacity(definitions.functions.len());
285+
let mut typed_functions_groups = Vec::with_capacity(definitions.functions.len());
286286
let mut typed_constants = Vec::with_capacity(definitions.constants.len());
287287
let definition_groups =
288288
match into_dependency_order(definitions.functions, definitions.constants) {
@@ -314,21 +314,27 @@ impl<'a, A> ModuleAnalyzer<'a, A> {
314314
&self.module_name,
315315
))
316316
}
317-
for inferred_function in working_functions.drain(..) {
318-
typed_functions.push(generalise_function(
319-
inferred_function,
320-
&mut env,
321-
&self.module_name,
322-
));
323-
}
317+
318+
let generalised_functions = working_functions
319+
.drain(..)
320+
.map(|function| generalise_function(function, &mut env, &self.module_name))
321+
.collect_vec();
322+
323+
// After analysing a group of functions that depend on each other we
324+
// further split them in groups of mutually recursive functions.
325+
// We work on these smaller already existing groups as two functions
326+
// that don't depend on each other are never going to be mutually
327+
// recursive.
328+
typed_functions_groups
329+
.append(&mut into_mutually_recursive_groups(generalised_functions));
324330
}
325331

326332
let typed_definitions = TypedDefinitions {
327333
imports: typed_imports,
328334
constants: typed_constants,
329335
custom_types: typed_custom_types,
330336
type_aliases: typed_type_aliases,
331-
functions: typed_functions,
337+
functions: typed_functions_groups,
332338
};
333339

334340
// Generate warnings for unused items

compiler-core/src/ast.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,12 @@ impl TypedModule {
8585
.or_else(|| (constants.iter()).find_map(|constant| constant.find_node(byte_index)))
8686
.or_else(|| (custom_types.iter()).find_map(|type_| type_.find_node(byte_index)))
8787
.or_else(|| (type_aliases.iter()).find_map(|alias| alias.find_node(byte_index)))
88-
.or_else(|| (functions.iter()).find_map(|function| function.find_node(byte_index)))
88+
.or_else(|| {
89+
functions
90+
.iter()
91+
.flatten()
92+
.find_map(|function| function.find_node(byte_index))
93+
})
8994
}
9095

9196
pub fn find_statement(&self, byte_index: u32) -> Option<&TypedStatement> {
@@ -94,6 +99,7 @@ impl TypedModule {
9499
self.definitions
95100
.functions
96101
.iter()
102+
.flatten()
97103
.find_map(|function| function.find_statement(byte_index))
98104
}
99105

@@ -106,7 +112,11 @@ impl TypedModule {
106112
functions,
107113
} = &self.definitions;
108114

109-
imports.len() + constants.len() + custom_types.len() + type_aliases.len() + functions.len()
115+
imports.len()
116+
+ constants.len()
117+
+ custom_types.len()
118+
+ type_aliases.len()
119+
+ functions.iter().map(|group| group.len()).sum::<usize>()
110120
}
111121
}
112122

@@ -116,7 +126,11 @@ pub struct TypedDefinitions {
116126
pub constants: Vec<TypedModuleConstant>,
117127
pub custom_types: Vec<TypedCustomType>,
118128
pub type_aliases: Vec<TypedTypeAlias>,
119-
pub functions: Vec<TypedFunction>,
129+
130+
/// All the functions in the module. Instead of just using a flat vector of
131+
/// functions, we divide them in groups of functions that are mutually
132+
/// recursive.
133+
pub functions: Vec<Vec<TypedFunction>>,
120134
}
121135

122136
/// The `@target(erlang)` and `@target(javascript)` attributes can be used to

compiler-core/src/ast/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ where
846846
v.visit_typed_custom_type(custom_type);
847847
}
848848

849-
for function in functions {
849+
for function in functions.iter().flatten() {
850850
v.visit_typed_function(function);
851851
}
852852
}

compiler-core/src/build.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,12 @@ impl Module {
329329
.chain((constants.iter_mut()).map(DocumentableDefinition::Constant))
330330
.chain((custom_types.iter_mut()).map(DocumentableDefinition::CustomType))
331331
.chain((type_aliases.iter_mut()).map(DocumentableDefinition::TypeAlias))
332-
.chain((functions.iter_mut()).map(DocumentableDefinition::Function))
332+
.chain(
333+
functions
334+
.iter_mut()
335+
.flatten()
336+
.map(DocumentableDefinition::Function),
337+
)
333338
.sorted_by_key(|definition| definition.location())
334339
.collect_vec();
335340

0 commit comments

Comments
 (0)