diff --git a/cspell.json b/cspell.json index 6648ab40..8521501c 100644 --- a/cspell.json +++ b/cspell.json @@ -36,6 +36,7 @@ "interner", "itertools", "lcons", + "linearization", "linearizes", "linearizing", "lnet", diff --git a/docs/lazy-definitions.md b/docs/lazy-definitions.md index de3115eb..51e63dca 100644 --- a/docs/lazy-definitions.md +++ b/docs/lazy-definitions.md @@ -40,7 +40,7 @@ This code will work as expected, because `Nat.add` is unrolled lazily only when ### Automatic optimization -HVM-lang carries out [match linearization](compiler-options#linearize-matches) and [combinator floating](compiler-options#float-combinators) optimizations, enabled through the CLI, which is active by default in strict mode. +HVM-lang carries out [match linearization](compiler-options#linearize-matches) and [combinator floating](compiler-options#float-combinators) optimizations, enabled through the CLI, which are active by default in strict mode. Consider the code below: diff --git a/src/hvmc_net/mutual_recursion.rs b/src/hvmc_net/mutual_recursion.rs index 8ae25453..276c117c 100644 --- a/src/hvmc_net/mutual_recursion.rs +++ b/src/hvmc_net/mutual_recursion.rs @@ -13,7 +13,17 @@ pub fn check_cycles(book: &Book) -> Result<(), String> { let graph = Graph::from(book); let cycles = graph.cycles(); - if cycles.is_empty() { Ok(()) } else { Err(pretty_print_cycles(&cycles)) } + if cycles.is_empty() { + Ok(()) + } else { + Err(format!( + "{}\n{}\n{}\n{}", + "Mutual recursion cycle detected in compiled funcions:", + pretty_print_cycles(&cycles), + "This program will expand infinitely in strict evaluation mode.", + "Read https://github.com/HigherOrderCO/hvm-lang/blob/main/docs/lazy-definitions.md for more information." + )) + } } fn pretty_print_cycles(cycles: &[Vec]) -> String { diff --git a/tests/golden_tests/mutual_recursion/multiple.hvm b/tests/golden_tests/mutual_recursion/multiple.hvm new file mode 100644 index 00000000..9d306cc2 --- /dev/null +++ b/tests/golden_tests/mutual_recursion/multiple.hvm @@ -0,0 +1,11 @@ +(A) = (B) +(B) = (C) +(C) = (A) + +(H) = (I) +(I) = (H) + +(M) = (N) +(N) = (M) + +(Main) = * diff --git a/tests/snapshots/mutual_recursion__a_b_c.hvm.snap b/tests/snapshots/mutual_recursion__a_b_c.hvm.snap index 58df8e23..73ac6869 100644 --- a/tests/snapshots/mutual_recursion__a_b_c.hvm.snap +++ b/tests/snapshots/mutual_recursion__a_b_c.hvm.snap @@ -2,4 +2,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/a_b_c.hvm --- +Mutual recursion cycle detected in compiled funcions: Cycle 1: A -> B -> C +This program will expand infinitely in strict evaluation mode. +Read https://github.com/HigherOrderCO/hvm-lang/blob/main/docs/lazy-definitions.md for more information. diff --git a/tests/snapshots/mutual_recursion__multiple.hvm.snap b/tests/snapshots/mutual_recursion__multiple.hvm.snap new file mode 100644 index 00000000..b85d00ec --- /dev/null +++ b/tests/snapshots/mutual_recursion__multiple.hvm.snap @@ -0,0 +1,10 @@ +--- +source: tests/golden_tests.rs +input_file: tests/golden_tests/mutual_recursion/multiple.hvm +--- +Mutual recursion cycle detected in compiled funcions: +Cycle 1: A -> B -> C +Cycle 2: H -> I +Cycle 3: M -> N +This program will expand infinitely in strict evaluation mode. +Read https://github.com/HigherOrderCO/hvm-lang/blob/main/docs/lazy-definitions.md for more information. diff --git a/tests/snapshots/mutual_recursion__odd_even.hvm.snap b/tests/snapshots/mutual_recursion__odd_even.hvm.snap index 92ad0846..0c9f181a 100644 --- a/tests/snapshots/mutual_recursion__odd_even.hvm.snap +++ b/tests/snapshots/mutual_recursion__odd_even.hvm.snap @@ -2,4 +2,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/odd_even.hvm --- +Mutual recursion cycle detected in compiled funcions: Cycle 1: isEven -> isOdd +This program will expand infinitely in strict evaluation mode. +Read https://github.com/HigherOrderCO/hvm-lang/blob/main/docs/lazy-definitions.md for more information.