// Effect System Test: Pure Recursive Functions
// =============================================
//
// What this test validates:
// - Recursive pure functions are correctly inferred as pure
// - Self-recursion maintains purity
// - Mutual recursion between pure functions maintains purity
// - Base cases and recursive cases both pure -> function is pure
//
// Expected effect inference results:
// - factorial(n) -> Pure
// - fibonacci(n) -> Pure
// - gcd(a, b) -> Pure (Euclidean algorithm)
// - is_even(n) -> Pure (mutual recursion)
// - is_odd(n) -> Pure (mutual recursion)
// - sum_range(start, end) -> Pure
gene Math.Recursive @0.1.0 {
"""
Recursive pure functions demonstrating that recursion
does not introduce effects when the function body is pure.
"""
// Pure: classic factorial with recursion
// Base case and recursive case both pure
fn factorial(n: Int) -> Int {
if n <= 1 {
1
} else {
n * factorial(n - 1)
}
}
// Pure: Fibonacci sequence
// Multiple recursive calls, still pure
fn fibonacci(n: Int) -> Int {
if n <= 0 {
0
} else if n == 1 {
1
} else {
fibonacci(n - 1) + fibonacci(n - 2)
}
}
// Pure: Greatest Common Divisor (Euclidean algorithm)
// Recursive with modulo operation
fn gcd(a: Int, b: Int) -> Int {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
// Pure: Mutual recursion - is_even
fn is_even(n: Int) -> Bool {
if n == 0 {
true
} else {
is_odd(n - 1)
}
}
// Pure: Mutual recursion - is_odd
fn is_odd(n: Int) -> Bool {
if n == 0 {
false
} else {
is_even(n - 1)
}
}
// Pure: Sum of range [start, end)
fn sum_range(start: Int, end: Int) -> Int {
if start >= end {
0
} else {
start + sum_range(start + 1, end)
}
}
// Pure: Ackermann function (deeply recursive)
fn ackermann(m: Int, n: Int) -> Int {
if m == 0 {
n + 1
} else if n == 0 {
ackermann(m - 1, 1)
} else {
ackermann(m - 1, ackermann(m, n - 1))
}
}
}
// Test assertions for effect inference
test effects {
assert_pure(Math.Recursive.factorial);
assert_pure(Math.Recursive.fibonacci);
assert_pure(Math.Recursive.gcd);
assert_pure(Math.Recursive.is_even);
assert_pure(Math.Recursive.is_odd);
assert_pure(Math.Recursive.sum_range);
assert_pure(Math.Recursive.ackermann);
}