Status: Implemented (Phase 1 - Bash Wrapper Approach) Version: 1.0.0 Date: 2025-10-19
UnifyWeaver can now compile Prolog predicates to PowerShell scripts! This document explains how PowerShell compilation works, how to use it, and what to expect.
Instead of generating native PowerShell code, we generate bash scripts and wrap them in PowerShell compatibility layer invocations. This approach:
✅ Reuses all existing bash templates - No need to rewrite compilation logic
✅ Leverages the PowerShell compatibility layer - Uses uw-* commands
✅ Provides quick PowerShell support - Minimal new code required
✅ Maintains consistency - PowerShell and bash outputs are identical
Future (Phase 2): Native PowerShell code generation with object pipeline support
:- use_module(unifyweaver(core/powershell_compiler)).
?- compile_to_powershell(color/1, Code).
% Generates PowerShell script that wraps bash implementation
?- compile_to_powershell(
grandparent/2,
[output_file('grandparent.ps1')],
_
).
% Creates grandparent.ps1
# First, load the compatibility layer
. .\scripts\init_unify_compat.ps1
# Then run the generated script
.\grandparent.ps1
compile_to_powershell/2Signature:
compile_to_powershell(+Predicate, -PowerShellCode)
Description: Compiles a Prolog predicate to PowerShell code with default options.
Example:
?- compile_to_powershell(color/1, Code).
Code = "# Generated PowerShell Script\n...".
compile_to_powershell/3Signature:
compile_to_powershell(+Predicate, +Options, -PowerShellCode)
Description: Compiles a Prolog predicate to PowerShell code with custom options.
Parameters:
Predicate: Pred/Arity indicator (e.g., grandparent/2)Options: List of compilation options (see below)PowerShellCode: Generated PowerShell script as stringOptions:
compiler(stream|recursive) - Which bash compiler to use (default: stream)wrapper_style(inline|tempfile) - How to invoke bash (default: inline)compat_check(true|false) - Add compatibility layer check (default: true)output_file(Path) - Write to file instead of returning codescript_name(Name) - Name for generated script (default: derived from predicate)Examples:
% Basic compilation
?- compile_to_powershell(color/1, [], Code).
% Use recursive compiler
?- compile_to_powershell(factorial/2, [compiler(recursive)], Code).
% Tempfile wrapper style
?- compile_to_powershell(process_data/1, [wrapper_style(tempfile)], Code).
% Write to file
?- compile_to_powershell(
grandparent/2,
[output_file('output/grandparent.ps1'), script_name(grandparents)],
_
).
% Disable compatibility check (not recommended)
?- compile_to_powershell(color/1, [compat_check(false)], Code).
Pros:
Cons:
Example Output:
$bashScript = @'
#!/bin/bash
# bash implementation here
'@
uw-bash -c $bashScript
Pros:
Cons:
Example Output:
$tempFile = [System.IO.Path]::GetTempFileName() + ".sh"
$bashScript = @'
#!/bin/bash
# bash implementation here
'@
try {
Set-Content -Path $tempFile -Value $bashScript -Encoding UTF8
uw-bash $tempFile
} finally {
Remove-Item $tempFile -ErrorAction SilentlyContinue
}
# Generated PowerShell Script
# Script: grandparent.ps1
# Generated by UnifyWeaver PowerShell Compiler
# Generated: 2025-10-19 22:00:00
#
# This script wraps a bash implementation via the PowerShell compatibility layer.
# The bash code is executed using uw-bash from UnifyWeaver compatibility layer.
# Ensure compatibility layer is available
if (-not (Get-Command uw-bash -ErrorAction SilentlyContinue)) {
Write-Error "UnifyWeaver PowerShell compatibility layer not loaded"
Write-Host "Please run: . .\scripts\init_unify_compat.ps1" -ForegroundColor Yellow
exit 1
}
# Embedded bash implementation
$bashScript = @'
#!/bin/bash
# Bash code generated by stream_compiler
awk 'BEGIN {
# AWK implementation of grandparent/2
...
}' "$@"
'@
# Execute via compatibility layer
if ($Input) {
$Input | uw-bash -c $bashScript
} else {
uw-bash -c $bashScript
}
Prolog:
% Define facts
color(red).
color(green).
color(blue).
% Compile to PowerShell
?- compile_to_powershell(color/1, [output_file('colors.ps1')], _).
Generated PowerShell:
# colors.ps1
# (wrapper code omitted for brevity)
$bashScript = @'
#!/bin/bash
awk 'BEGIN {
print "red"
print "green"
print "blue"
}'
'@
uw-bash -c $bashScript
Usage:
. .\scripts\init_unify_compat.ps1
.\colors.ps1
# Output:
# red
# green
# blue
Prolog:
% Define relationships
parent(tom, bob).
parent(bob, ann).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
% Compile to PowerShell
?- compile_to_powershell(grandparent/2, [output_file('grandparent.ps1')], _).
Generated PowerShell:
# grandparent.ps1
# (includes join logic via AWK)
$bashScript = @'
#!/bin/bash
awk 'BEGIN {
# parent/2 facts
parent["tom","bob"] = 1
parent["bob","ann"] = 1
# Join logic
for (key in parent) {
split(key, xy, SUBSEP)
x = xy[1]; y = xy[2]
for (key2 in parent) {
split(key2, yz, SUBSEP)
if (yz[1] == y) {
z = yz[2]
print x "\t" z
}
}
}
}'
'@
uw-bash -c $bashScript
Usage:
.\grandparent.ps1
# Output:
# tom ann
Generated scripts support PowerShell pipelines:
# Read data from file and process
Get-Content users.csv | .\process_users.ps1
# Chain multiple scripts
.\get_users.ps1 | .\filter_active.ps1 | .\format_output.ps1
scripts/powershell-compat/stream_compiler or recursive_compilerpowershell_compiler (this module)# In PowerShell, one-time per session:
. .\scripts\init_unify_compat.ps1
# Now you can run generated scripts:
.\colors.ps1
.\grandparent.ps1
Add to your PowerShell profile ($PROFILE):
# Load UnifyWeaver compatibility layer
$UnifyWeaverPath = "C:\path\to\UnifyWeaver"
if (Test-Path "$UnifyWeaverPath\scripts\init_unify_compat.ps1") {
. "$UnifyWeaverPath\scripts\init_unify_compat.ps1"
}
If you’re sure the compatibility layer is always available:
?- compile_to_powershell(color/1, [compat_check(false)], Code).
This removes the compatibility check from generated scripts, but they’ll fail if uw-bash is not available.
Prolog:
color(red).
color(green).
color(blue).
Bash Output:
#!/bin/bash
awk 'BEGIN {
print "red"
print "green"
print "blue"
}'
PowerShell Output:
# Generated PowerShell Script
# (wrapper code)
$bashScript = @'
#!/bin/bash
awk 'BEGIN {
print "red"
print "green"
print "blue"
}'
'@
uw-bash -c $bashScript
Key Difference: PowerShell version wraps the same bash code in a PowerShell compatibility layer invocation.
Result: Identical output, different invocation mechanism.
PowerShell scripts have a small overhead compared to direct bash execution:
Direct Bash:
Prolog → Bash → AWK → Output
PowerShell (Phase 1):
Prolog → PowerShell → uw-bash → Bash → AWK → Output
(Extra layer: PowerShell compatibility wrapper)
Impact:
Mitigation:
❌ Not True Native PowerShell
❌ No PowerShell Object Pipeline
❌ Requires Bash
❌ Performance Overhead
✅ Text Processing
✅ PowerShell Integration
✅ Cross-Platform
Solution:
. .\scripts\init_unify_compat.ps1
Cause: Compatibility layer not properly initialized
Solution:
scripts/powershell-compat/init_unify_compat.ps1 exists. .\scripts\init_unify_compat.ps1bash --versionPossible Causes:
Debugging:
# Check if bash code works directly
$bashScript = @'
# ... paste bash code here ...
'@
# Run with uw-bash for debugging
uw-bash -c $bashScript
Solution:
# Set execution policy (one-time)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# Or bypass for single script
PowerShell -ExecutionPolicy Bypass -File .\script.ps1
Instead of wrapping bash, generate actual PowerShell code:
Example (Future):
# Native PowerShell (Phase 2)
function Get-Color {
return @('red', 'green', 'blue')
}
Get-Color
Convert between Prolog terms and PowerShell objects:
# Pipeline with objects (Phase 2)
$users | ConvertTo-Json | Invoke-PrologQuery | ConvertFrom-Json
?- [unifyweaver(core/powershell_compiler)].
?- test_powershell_compiler.
╔════════════════════════════════════════╗
║ PowerShell Compiler Tests ║
╚════════════════════════════════════════╝
[Test 1] Inline wrapper generation
[✓] Inline wrapper contains expected components
[Test 2] Tempfile wrapper generation
[✓] Tempfile wrapper contains expected components
[Test 3] Compilation with various options
[✓] compat_check(false) omits compatibility check
[✓] Default includes compatibility check
╔════════════════════════════════════════╗
║ All PowerShell Compiler Tests Passed ║
╚════════════════════════════════════════╝
?- [examples/powershell_compilation_demo].
?- main.
This will demonstrate all compilation features and generate example PowerShell scripts.
A: No (in Phase 1). The generated scripts require the compatibility layer to invoke bash. Phase 2 will support native PowerShell generation.
A: Yes, if you have PowerShell Core (pwsh) and bash installed. The compatibility layer works cross-platform.
A: Yes! Generated scripts are normal PowerShell scripts and can be called from other PowerShell code:
Import-Module MyModule
$data = Get-MyData
$data | .\process_prolog.ps1 | Export-Results
A: Phase 1 has ~50-100ms overhead for the PowerShell wrapper. For data processing, this is usually negligible. Phase 2 native generation will eliminate this.
A: Yes, but regenerating will overwrite your changes. Best practice: keep Prolog as source of truth, or copy generated script to a new file for customization.
✅ Compile Prolog predicates to PowerShell scripts ✅ Reuse all existing bash compilation templates ✅ Integrate with PowerShell workflows ✅ Cross-platform support (Windows/Linux/Mac with PowerShell Core) ✅ Text-based pipeline support
⭐ Native PowerShell code generation ⭐ PowerShell object pipeline support ⭐ No bash dependency ⭐ Better performance ⭐ PowerShell-specific optimizations
docs/POWERSHELL_COMPAT.mddocs/STREAM_COMPILER.mddocs/RECURSIVE_COMPILER.mdexamples/powershell_compilation_demo.plCreated: 2025-10-19 Authors: John William Creighton (@s243a), Claude Code (Sonnet 4.5)