Compile a factorial predicate from Prolog to optimized Bash, generate a test runner, and verify the compiled script produces correct results for inputs 0 through 10.
This playbook demonstrates linear recursion compilation - one of the most fundamental and straightforward patterns in UnifyWeaver. The factorial function serves as an excellent introduction to the compilation pipeline because it has:
0! = 1)Assumptions:
$UNIFYWEAVER_HOMEswipl) is available in PATH/tmp/ and education/output/$UNIFYWEAVER_HOMEBackground: Linear recursion is automatically optimized by UnifyWeaver’s compiler. The system:
$((...)) syntaxCreate the factorial predicate in /tmp/factorial.pl:
cat > /tmp/factorial.pl <<'EOF'
% factorial(+N, -F) - F is the factorial of N
% Computes the factorial of a non-negative integer
factorial(0, 1).
factorial(N, F) :-
N > 0,
N1 is N - 1,
factorial(N1, F1),
F is N * F1.
EOF
Verification: File should exist and contain exactly 8 lines
test -f /tmp/factorial.pl && wc -l /tmp/factorial.pl
# Expected: 8 /tmp/factorial.pl
[!note] The predicate includes comments for documentation. UnifyWeaver preserves these in the generated Bash scripts.
Ensure you’re in the correct directory:
cd $UNIFYWEAVER_HOME
pwd
# Expected: /path/to/UnifyWeaver
Verification: Check that core files exist
test -d src/unifyweaver && test -f src/unifyweaver/core/compiler_driver.pl && echo "✓ UnifyWeaver found"
# Expected: ✓ UnifyWeaver found
Run the compiler_driver to transpile Prolog to Bash:
swipl -q -g "
asserta(file_search_path(unifyweaver, 'src/unifyweaver')),
['/tmp/factorial.pl'],
use_module(unifyweaver(core/compiler_driver)),
compile(factorial/2, [
output_dir('education/output/advanced')
], Scripts),
format('Generated scripts: ~w~n', [Scripts]),
halt"
Expected output:
Generated scripts: [education/output/advanced/factorial.sh]
Verification: Script should exist and be executable
ls -lh education/output/advanced/factorial.sh
# Should show executable permissions (-rwxr-xr-x)
[!tip] If the script isn’t executable, run:
chmod +x education/output/advanced/factorial.sh
Test with a few known values:
echo "0" | bash education/output/advanced/factorial.sh
# Expected: 1
echo "5" | bash education/output/advanced/factorial.sh
# Expected: 120
echo "10" | bash education/output/advanced/factorial.sh
# Expected: 3628800
[!note] Math Check:
- 0! = 1 (by definition)
- 5! = 5 × 4 × 3 × 2 × 1 = 120
- 10! = 3,628,800
Use UnifyWeaver’s test runner inference to create a comprehensive test suite:
swipl -q -g "
asserta(file_search_path(unifyweaver, 'src/unifyweaver')),
use_module(unifyweaver(core/advanced/test_runner_inference)),
generate_test_runner_inferred('education/output/advanced/test_runner.sh', [
mode(explicit),
output_dir('education/output/advanced')
]),
halt"
Expected output:
Generated test runner: education/output/advanced/test_runner.sh
Verification: Test runner should exist
test -f education/output/advanced/test_runner.sh && echo "✓ Test runner created"
# Expected: ✓ Test runner created
Execute the test suite:
chmod +x education/output/advanced/test_runner.sh
./education/output/advanced/test_runner.sh
Expected output:
Testing factorial.sh...
Test 1: factorial 0 → 1
Result: PASS
Test 2: factorial 1 → 1
Result: PASS
Test 3: factorial 5 → 120
Result: PASS
Test 4: factorial 10 → 3628800
Result: PASS
All tests passed! ✓
[!output] language: bash purpose: Compiled factorial function format: executable location: education/output/advanced/factorial.sh
#!/bin/bash # Generated by UnifyWeaver # Pattern: Linear Recursion # Source: /tmp/factorial.pl factorial() { local N=$1 local F if [ "$N" -eq 0 ]; then echo 1 else local N1=$((N - 1)) local F1=$(factorial $N1) F=$((N * F1)) echo $F fi } # Main execution while IFS= read -r line; do result=$(factorial "$line") echo "$result" done
[!note] The actual generated code may vary slightly depending on UnifyWeaver optimizations.
Run all manual tests and verify outputs:
for n in 0 1 5 10; do
result=$(echo "$n" | bash education/output/advanced/factorial.sh)
echo "factorial($n) = $result"
done
Expected:
factorial(0) = 1
factorial(1) = 1
factorial(5) = 120
factorial(10) = 3628800
./education/output/advanced/test_runner.sh && echo "Exit code: $?"
# Expected: All tests PASS, Exit code: 0
✅ All of the following must be true:
/tmp/factorial.pl exists with valid Prolog codeeducation/output/advanced/factorial.sh exists and is executablefactorial 0 returns 1factorial 5 returns 120factorial 10 returns 3628800education/output/advanced/test_runner.shCause: file_search_path(unifyweaver, ...) not set correctly
Solution:
# Verify you're in UnifyWeaver root
cd $UNIFYWEAVER_HOME
# Verify the path exists
ls src/unifyweaver/core/compiler_driver.pl
# If $UNIFYWEAVER_HOME not set:
export UNIFYWEAVER_HOME=$(pwd)
Cause: Prolog file not loaded before compilation
Solution: Ensure the square bracket load statement ['/tmp/factorial.pl'] appears before the compile(...) call in the swipl command.
Cause: Script not executable
Solution:
chmod +x education/output/advanced/factorial.sh
Cause: Logic error in Prolog source or compilation issue
Solution:
swipl -q -f /tmp/factorial.pl -g "factorial(5, F), writeln(F), halt"
# Should output: 120
Cause: Test runner generation failed or predicates changed
Solution:
# Regenerate test runner
swipl -q -g "
asserta(file_search_path(unifyweaver, 'src/unifyweaver')),
use_module(unifyweaver(core/advanced/test_runner_inference)),
generate_test_runner_inferred('education/output/advanced/test_runner.sh', [
mode(explicit),
output_dir('education/output/advanced')
]),
halt"
chmod +x education/output/advanced/test_runner.sh
After completing this playbook successfully:
[!tip] Performance Consideration
For large N (>20), consider adding memoization to avoid redundant calculations. UnifyWeaver can automatically apply memoization optimizations with the
optimize(memoize)option.
[!tip] Debugging Generated Bash
To see the generated Bash code, run:
cat education/output/advanced/factorial.shThis helps understand how UnifyWeaver translates Prolog to Bash.
[!warning] Arithmetic Limits
Bash uses 64-bit signed integers. Factorials grow rapidly:
- 20! = 2,432,902,008,176,640,000 (fits in 64-bit)
- 21! overflows
For larger factorials, consider using arbitrary-precision arithmetic or a different target language (Python, arbitrary-precision C#).
Playbook Version: 1.0 Last Updated: 2025-11-17 Tested With: UnifyWeaver v0.1, SWI-Prolog 8.x
Execution Time: ~5 minutes Success Rate: Should be 100% with correct setup