From 170079be7771f0b2cfc450329aa5c0c096861598 Mon Sep 17 00:00:00 2001 From: Thomas Coratger Date: Wed, 24 Sep 2025 21:04:41 +0200 Subject: [PATCH 1/2] compiler: calling inline functions from inline functions --- crates/lean_compiler/src/a_simplify_lang.rs | 72 ++++++++++++++++----- crates/lean_compiler/tests/test_compiler.rs | 50 ++++++++++++++ 2 files changed, 105 insertions(+), 17 deletions(-) diff --git a/crates/lean_compiler/src/a_simplify_lang.rs b/crates/lean_compiler/src/a_simplify_lang.rs index 5c7308eed..73d8ff6ab 100644 --- a/crates/lean_compiler/src/a_simplify_lang.rs +++ b/crates/lean_compiler/src/a_simplify_lang.rs @@ -1514,6 +1514,7 @@ fn handle_inlined_functions(program: &mut Program) { .map(|(name, func)| (name.clone(), func.clone())) .collect::>(); + for func in inlined_functions.values() { assert!( !func.has_const_arguments(), @@ -1521,28 +1522,65 @@ fn handle_inlined_functions(program: &mut Program) { ); } - for func in program.functions.values_mut() { - if func.inlined { - let mut func_called = Vec::new(); - get_function_called(&func.body, &mut func_called); - for func_called in func_called { - assert!( - !inlined_functions.contains_key(&func_called), - "Inlined functions calling other inlined functions are not supported yet" + // Process inline functions iteratively to handle dependencies + // Repeat until all inline function calls are resolved + let mut max_iterations = 10; + while max_iterations > 0 { + let mut any_changes = false; + + // Process non-inlined functions + for func in program.functions.values_mut() { + if !func.inlined { + let mut counter1 = Counter::new(); + let mut counter2 = Counter::new(); + let old_body = func.body.clone(); + + handle_inlined_functions_helper( + &mut func.body, + &inlined_functions, + &mut counter1, + &mut counter2, ); + + if func.body != old_body { + any_changes = true; + } } - } else { - handle_inlined_functions_helper( - &mut func.body, - &inlined_functions, - &mut Counter::new(), - &mut Counter::new(), - ); } + + // Process inlined functions that may call other inlined functions + // We need to update them so that when they get inlined later, they don't have unresolved calls + for func in program.functions.values_mut() { + if func.inlined { + let mut counter1 = Counter::new(); + let mut counter2 = Counter::new(); + let old_body = func.body.clone(); + + handle_inlined_functions_helper( + &mut func.body, + &inlined_functions, + &mut counter1, + &mut counter2, + ); + + if func.body != old_body { + any_changes = true; + } + } + } + + if !any_changes { + break; + } + + max_iterations -= 1; } - for func in inlined_functions.keys() { - program.functions.remove(func); + assert!(max_iterations > 0, "Too many iterations processing inline functions"); + + // Remove all inlined functions from the program (they've been inlined) + for func_name in inlined_functions.keys() { + program.functions.remove(func_name); } } diff --git a/crates/lean_compiler/tests/test_compiler.rs b/crates/lean_compiler/tests/test_compiler.rs index a96c202a7..a82652484 100644 --- a/crates/lean_compiler/tests/test_compiler.rs +++ b/crates/lean_compiler/tests/test_compiler.rs @@ -464,3 +464,53 @@ fn test_const_functions_calling_const_functions() { compile_and_run(program, &[], &[], false); } + +#[test] +fn test_inline_functions_calling_inline_functions() { + let program = r#" + fn main() { + x = double(3); + y = quad(x); + print(y); + return; + } + + fn double(a) inline -> 1 { + return a + a; + } + + fn quad(b) inline -> 1 { + result = double(b); + return result + result; + } + "#; + + compile_and_run(program, &[], &[], false); +} + +#[test] +fn test_nested_inline_functions() { + let program = r#" + fn main() { + result = level_one(3); + print(result); + return; + } + + fn level_one(x) inline -> 1 { + result = level_two(x); + return result; + } + + fn level_two(y) inline -> 1 { + result = level_three(y); + return result; + } + + fn level_three(z) inline -> 1 { + return z * z * z; + } + "#; + + compile_and_run(program, &[], &[], false); +} From aade07464a4a54d38960eec89b4c926f2c9424c6 Mon Sep 17 00:00:00 2001 From: Thomas Coratger Date: Wed, 24 Sep 2025 21:05:25 +0200 Subject: [PATCH 2/2] fmt --- crates/lean_compiler/src/a_simplify_lang.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/lean_compiler/src/a_simplify_lang.rs b/crates/lean_compiler/src/a_simplify_lang.rs index 73d8ff6ab..2a028d718 100644 --- a/crates/lean_compiler/src/a_simplify_lang.rs +++ b/crates/lean_compiler/src/a_simplify_lang.rs @@ -1514,7 +1514,6 @@ fn handle_inlined_functions(program: &mut Program) { .map(|(name, func)| (name.clone(), func.clone())) .collect::>(); - for func in inlined_functions.values() { assert!( !func.has_const_arguments(), @@ -1576,7 +1575,10 @@ fn handle_inlined_functions(program: &mut Program) { max_iterations -= 1; } - assert!(max_iterations > 0, "Too many iterations processing inline functions"); + assert!( + max_iterations > 0, + "Too many iterations processing inline functions" + ); // Remove all inlined functions from the program (they've been inlined) for func_name in inlined_functions.keys() {