The Prolog target follows a well-defined pipeline that transforms your source code into executable Prolog scripts. Understanding this architecture helps you:
The Prolog target consists of three main modules:
prolog_target.pl - Main OrchestratorLocation: src/unifyweaver/targets/prolog_target.pl
Responsibilities:
Key Predicates:
% Main entry point
generate_prolog_script(+UserPredicates, +Options, -ScriptCode)
% Dependency analysis
analyze_dependencies(+Predicates, -Dependencies)
% Output handling
write_prolog_script(+ScriptCode, +OutputPath, +Options)
% Compilation (with error checking)
compile_script(+Dialect, +ScriptPath)
compile_script_safe(+Dialect, +ScriptPath, +Options)
prolog_dialects.pl - Dialect AbstractionLocation: src/unifyweaver/targets/prolog_dialects.pl
Responsibilities:
Key Predicates:
% Dialect support
supported_dialect(+Dialect)
dialect_capabilities(+Dialect, -Capabilities)
% Code generation
dialect_shebang(+Dialect, -ShebangLine)
dialect_header(+Dialect, +Options, -HeaderCode)
dialect_imports(+Dialect, +Dependencies, -ImportCode)
dialect_initialization(+Dialect, +Goal, +Options, -InitCode)
% Compilation
dialect_compile_command(+Dialect, +ScriptPath, -Command)
% Validation
validate_for_dialect(+Dialect, +Predicates, -Issues)
prolog_service_target.pl - Service IntegrationLocation: src/unifyweaver/targets/prolog_service_target.pl
Responsibilities:
Let’s walk through what happens when you call generate_prolog_script/3:
generate_prolog_script([factorial/2],
[dialect(gnu), compile(true), entry_point(test_factorial)],
ScriptCode)
% Extract dialect from options (default: swi)
option(dialect(Dialect), Options, swi),
% Validate it's supported
supported_dialect(Dialect),
% Check code compatibility
validate_for_dialect(Dialect, UserPredicates, Issues)
What happens: Ensures the requested dialect exists and that your code is compatible with it.
analyze_dependencies(UserPredicates, Dependencies)
What happens: Scans your predicates to find:
Example output:
Dependencies = [
module(unifyweaver(core/partitioner)),
ensure_loaded(unifyweaver(core/partitioners/fixed_size)),
plugin_registration(partitioner, fixed_size, fixed_size_partitioner)
]
dialect_shebang(Dialect, ShebangCode)
What happens: Creates the executable shebang line.
SWI-Prolog:
#!/usr/bin/env swipl
GNU Prolog:
#!/usr/bin/env gprolog --consult-file
dialect_header(Dialect, EnhancedOptions, HeaderCode)
What happens: Creates metadata comments about the script.
Example output:
% Generated by UnifyWeaver v0.1
% Target: Prolog (GNU Prolog)
% Compilation: interpreted
% Generated: 2025-11-17 22:13:14
% Predicates: 2
dialect_imports(Dialect, Dependencies, ImportsCode)
What happens: Converts dependency list into dialect-specific import statements.
SWI-Prolog example:
:- use_module(unifyweaver(core/partitioner)).
:- ensure_loaded(unifyweaver(core/partitioners/fixed_size)).
GNU Prolog: May use different syntax or skip unsupported features.
generate_user_code(UserPredicates, Options, UserCode)
What happens: Extracts and formats your actual predicate definitions.
Input: [factorial/2]
Output:
factorial(0, 1) :-
!.
factorial(A, B) :-
A>0,
C is A+ -1,
factorial(C, D),
B is A*D.
generate_main_predicate(Options, MainCode)
What happens: Creates the main/0 predicate that serves as the script’s entry point.
Output:
main :-
test_factorial,
halt(0).
main :-
format(user_error, 'Error: Execution failed~n', []),
halt(1).
dialect_initialization(Dialect, EntryGoal, Options, InitCode)
What happens: Generates dialect-specific initialization directives.
GNU Prolog (compiled):
% Entry point (for compiled binary)
:- initialization(test_factorial).
GNU Prolog (interpreted):
% Entry point (called on load)
:- test_factorial.
SWI-Prolog:
:- initialization(test_factorial, main).
atomic_list_concat([
ShebangCode,
HeaderCode,
ImportsCode,
UserCode,
'\n% === Entry Point ===',
MainCode,
InitCode
], '\n\n', ScriptCode)
What happens: Combines all pieces into the final script with proper spacing.
After generation, the script goes through output processing:
write_prolog_script(ScriptCode, OutputPath, Options)
This predicate:
open(OutputPath, write, Stream, [encoding(utf8)]),
write(Stream, ScriptCode),
close(Stream)
shell('chmod +x OutputPath')
( option(compile(true), Options)
-> compile_script_safe(Dialect, OutputPath, Options)
; true
)
The compilation step uses a safe wrapper:
compile_script_safe(Dialect, ScriptPath, Options) :-
catch(
compile_script(Dialect, ScriptPath),
error(compilation_failed(FailedDialect, ExitCode), Context),
handle_compilation_failure(...)
)
Behavior:
fail_on_compile_error(true))src/unifyweaver/targets/
│
├── prolog_target.pl # Main orchestrator
│ ├── generate_prolog_script/3
│ ├── analyze_dependencies/2
│ ├── write_prolog_script/3
│ └── compile_script_safe/3
│
├── prolog_dialects.pl # Dialect abstraction
│ ├── supported_dialect/1
│ ├── dialect_*/* (code generation)
│ └── validate_for_dialect/3
│
└── prolog_service_target.pl # Service integration
└── (service-specific logic)
User Predicates ──┐
│
Options ──────────┼──► generate_prolog_script/3
│ │
│ ├─► analyze_dependencies/2
│ │ └─► Dependencies
│ │
│ ├─► dialect_shebang/2
│ ├─► dialect_header/3
│ ├─► dialect_imports/3
│ ├─► generate_user_code/3
│ ├─► generate_main_predicate/2
│ └─► dialect_initialization/4
│ │
└─────────────────────┘
▼
ScriptCode (atom)
│
▼
write_prolog_script/3
│
├─► Write file
├─► chmod +x
└─► compile_script_safe/3
│
└─► gplc (if compile=true)
prolog_dialects.plprolog_dialects.planalyze_dependencies/2In Chapter 3, we’ll explore Prolog dialects in detail, understanding the capabilities and constraints of SWI-Prolog and GNU Prolog, and when to use each.
Key Takeaways:
| ← Previous: Chapter 1: Introduction to the Prolog Target | 📖 Book 11: Prolog Target | Next: Chapter 3: Understanding Prolog Dialects → |