Use UnifyWeaver’s Prolog target to generate a GNU Prolog script from a factorial predicate, compile it to a native binary using gplc, and verify the binary executes correctly without requiring a Prolog interpreter.
This playbook demonstrates Prolog-to-Prolog transpilation with native compilation - a powerful feature that enables:
Why transpile Prolog to Prolog?
While it may seem circular, transpiling Prolog to GNU Prolog provides:
gplc compilerAssumptions:
$UNIFYWEAVER_HOMEswipl) is availablegprolog) is installedgplc) is available in PATH/tmp/ and current directoryBackground: The Prolog target (covered in book-prolog-target) handles:
:- initialization(Goal).)See Book: Prolog Target for implementation details.
Heuristic: Use Strategy A for development, Strategy B for production releases.
Create /tmp/factorial_gnu.pl with a simple factorial predicate:
cat > /tmp/factorial_gnu.pl <<'EOF'
% factorial(+N, -Result) - Compute factorial of N
factorial(0, 1) :- !.
factorial(N, Result) :-
N > 0,
N1 is N - 1,
factorial(N1, PrevResult),
Result is N * PrevResult.
% test_factorial/0 - Test with known values
test_factorial :-
factorial(5, F5),
format('Factorial of 5 is ~w~n', [F5]),
factorial(10, F10),
format('Factorial of 10 is ~w~n', [F10]).
EOF
Verification: File should exist with 14 lines
test -f /tmp/factorial_gnu.pl && wc -l /tmp/factorial_gnu.pl
# Expected: 14 /tmp/factorial_gnu.pl
Always verify your Prolog code works before transpiling:
swipl -q -f /tmp/factorial_gnu.pl -g "test_factorial, halt"
Expected output:
Factorial of 5 is 120
Factorial of 10 is 3628800
[!tip] Development Best Practice
Test in SWI-Prolog first! It has better error messages and debugging tools than GNU Prolog.
Use UnifyWeaver’s Prolog target to generate a GNU Prolog script:
cd $UNIFYWEAVER_HOME
swipl -q <<'PROLOG_SCRIPT'
% Load Prolog target
asserta(file_search_path(unifyweaver, 'src/unifyweaver')),
use_module(unifyweaver(targets/prolog_target)),
% Load our factorial predicate
['/tmp/factorial_gnu.pl'],
% Generate GNU Prolog script with compilation enabled
generate_prolog_script(
[factorial/2, test_factorial/0],
[
dialect(gnu),
compile(true),
entry_point(test_factorial)
],
Code
),
% Write script with automatic compilation
write_prolog_script(
Code,
'factorial_gnu',
[dialect(gnu), compile(true)]
),
format('~n✓ Generation complete~n'),
halt.
PROLOG_SCRIPT
Expected output:
[PrologTarget] Generated script: factorial_gnu.pl
[PrologTarget] Compiling with gnu: gplc --no-top-level factorial_gnu.pl -o factorial_gnu
[PrologTarget] Compilation complete
✓ Generation complete
Verification: Both script and binary should exist
ls -lh factorial_gnu factorial_gnu.pl
# Should show both files
[!note] The
.plextension is added automatically to the script. The binary has no extension.
Examine the generated GNU Prolog code:
head -n 50 factorial_gnu.pl
Key elements to look for:
#!/usr/bin/env gprolog --consult-file:- initialization(test_factorial). for compiled mode[!tip] Understanding Initialization
For compiled binaries (
gplc --no-top-level), GNU Prolog requires::- initialization(Goal).NOT just
:- Goal.(which works for interpreted mode).UnifyWeaver automatically generates the correct directive based on the
compile(true)option.
Run the standalone binary:
./factorial_gnu
Expected output:
Factorial of 5 is 120
Factorial of 10 is 3628800
Verification: Check exit code
./factorial_gnu && echo "Exit code: $?"
# Expected: Exit code: 0
[!tip] Fast Startup
Notice how fast the binary starts! No interpreter loading.
time ./factorial_gnu # Typically <5ms on modern hardware
For comparison, run the generated script in interpreted mode:
gprolog --consult-file factorial_gnu.pl
Expected: Same output as binary, but slower startup.
The binary is portable within the same architecture:
file factorial_gnu
# Example: factorial_gnu: ELF 64-bit LSB executable, x86-64
ldd factorial_gnu
# Shows dynamic library dependencies (or "not a dynamic executable" if statically linked)
[!output] language: prolog purpose: GNU Prolog script with correct initialization format: executable_script location: factorial_gnu.pl
#!/usr/bin/env gprolog --consult-file % Generated by UnifyWeaver v0.1 % Target: Prolog (GNU Prolog) % Compilation: interpreted % Generated: 2025-11-17 22:00:00 % === User Code (Transpiled) === factorial(0, 1) :- !. factorial(A, B) :- A>0, C is A+ -1, factorial(C, D), B is A*D. test_factorial :- factorial(5, A), format('Factorial of 5 is ~w~n', [A]), factorial(10, B), format('Factorial of 10 is ~w~n', [B]). % === Entry Point === main :- test_factorial, halt(0). main :- format(user_error, 'Error: Execution failed~n', []), halt(1). % Entry point (for compiled binary) :- initialization(test_factorial).
[!output] language: binary purpose: Native GNU Prolog executable format: executable_binary location: factorial_gnu expected_size: ~800KB-2MB
# Test 1: Run binary
./factorial_gnu
# Expected: Output with factorials, exit 0
# Test 2: Check it's truly a binary (not a script)
file factorial_gnu | grep -q "executable" && echo "✓ Is executable binary"
# Test 3: Measure startup time
time ./factorial_gnu > /dev/null
# Expected: Real time <10ms
# Test with interpreter (for comparison)
time gprolog --consult-file factorial_gnu.pl > /dev/null
# Expected: Real time ~50-100ms (slower startup)
✅ All of the following must be true:
/tmp/factorial_gnu.pl exists with valid Prolog codefactorial_gnu.pl generated in current directoryfactorial_gnu binary exists and is executable:- initialization(test_factorial). directiveCause: GNU Prolog compiler not installed
Solution:
# Ubuntu/Debian
sudo apt-get install gprolog
# macOS
brew install gnu-prolog
# Verify installation
gplc --version
Cause: Wrong initialization directive in generated code
Solution: This should not happen with UnifyWeaver v0.1+, which automatically generates :- initialization(Goal). for compiled mode. If you see this error:
grep "initialization" factorial_gnu.pl
# Should show: :- initialization(test_factorial).
:- test_factorial. instead, you may be using an old version:
cd $UNIFYWEAVER_HOME
git pull origin main
Cause: Syntax error in generated Prolog code
Solution:
gprolog --consult-file factorial_gnu.pl
gprolog < factorial_gnu.pl
Cause: Entry point not called or output buffering
Solution:
gprolog --consult-file factorial_gnu.pl -g "main"
tail -5 factorial_gnu.pl
# Should end with: :- initialization(test_factorial).
If compilation fails, UnifyWeaver logs a warning but continues with the interpreted script:
[PrologTarget] WARNING: gnu compilation failed (exit 1)
[PrologTarget] Continuing with interpreted script: factorial_gnu.pl
What to do: You can still use the script in interpreted mode:
gprolog --consult-file factorial_gnu.pl
For strict mode (fail on compilation errors):
# Add fail_on_compile_error(true) option
write_prolog_script(Code, 'factorial_gnu', [
dialect(gnu),
compile(true),
fail_on_compile_error(true)
])
After completing this playbook:
gplc --no-top-level --static factorial_gnu.pl -o factorial_gnu_static
# Creates binary with no external dependencies
[!tip] Development Workflow
Best practice for production deployments:
- Develop and debug in SWI-Prolog (better tools)
- Validate with
validate_for_dialect(gnu, [your_pred/arity], Issues)- Generate and test GNU Prolog interpreted version
- Compile to binary for final deployment
- Test binary on target platform
[!warning] Binary Compatibility
Compiled binaries are platform-specific:
- x86_64 Linux binary won’t run on ARM or macOS
- Recompile on each target platform
- Or use static linking for better portability
[!tip] When Compilation is Worth It
Use compiled binaries when:
- Deployment to end users (no Prolog installation needed)
- Fast startup is critical (command-line tools)
- Want single-file distribution
- Running on resource-constrained systems
Stick with interpreted when:
- Rapid development and testing
- Debugging needed
- Code changes frequently
- Using SWI-specific features (HTTP, databases, etc.)
[!note] The v0.1 Improvements
The Prolog target in UnifyWeaver v0.1 includes critical fixes:
- ✅ Correct initialization directives for compiled binaries
- ✅ Exit code checking with error detection
- ✅ Graceful fallback when compilation fails
See Chapter 15: Case Study for the full story of how these were discovered and fixed.
Playbook Version: 1.0 Last Updated: 2025-11-17 Tested With: UnifyWeaver v0.1, SWI-Prolog 8.x, GNU Prolog 1.5.0
Execution Time: ~10 minutes Success Rate: 95%+ with correct prerequisites Platform: Linux, macOS (with GNU Prolog), WSL