Skip to content

s243a/UnifyWeaver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5,140 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

UnifyWeaver

A Prolog transpiler that turns logic programs into LINQ-style data pipelines.

One codebase → Bash streams, C# queries, Go binaries, SQL views, and more.

📚 Extended Documentation | 🎓 Educational Materials


Why UnifyWeaver?

Write your data relationships and queries once in Prolog, then compile to the target that fits your environment:

  • Shell scripts for Unix pipelines and automation
  • Native binaries for portable, dependency-free deployment
  • SQL views for database integration
  • .NET assemblies for enterprise applications
  • Multi-language pipelines via cross-target glue

UnifyWeaver handles the hard parts—recursion, transitive closures, cycle detection, deduplication—so your generated code is correct and efficient.


Compilation Approaches

UnifyWeaver supports multiple compilation strategies depending on the target and predicate complexity:

Approach Description Targets
Stream/Procedural Direct template-based code generation with Unix pipes or LINQ iterators Bash, Go, Rust, C# Stream, PowerShell
Fixed-Point (Query Engine) IR + runtime with semi-naive evaluation for complex recursion C# Query Runtime
Generator-Based Lazy evaluation via Python generators with memoization Python
Declarative Output SQL queries for external database execution SQL
Symbolic WAM Low-level abstract machine instructions for complex unification/backtracking WAM (Hub)
WAM Transpilation WAM instructions compiled to target-language WAM virtual machine implementations C, Rust, Go, LLVM, JVM, ILAsm, Elixir

WAM Transpilation Targets

Several targets support a hybrid WAM compilation path: Prolog is first compiled to WAM (Warren Abstract Machine) instructions, then those instructions are transpiled into a complete WAM virtual machine implementation in the target language. This provides full unification and backtracking semantics.

Target WAM Module Format State Representation Run Loop
C wam_c_target Single Structs + tagged unions, manual memory while loop
Rust wam_rust_target Single HashMap/Vec, enum WamValue loop + match
Go wam_go_target Single map[string]interface{}, slices for loop + switch
LLVM wam_llvm_target Single SSA registers, stack alloca Basic blocks + br
JVM wam_jvm_target Dual (Jamaica / Krakatau) HashMap/ArrayList fields while + tableswitch
ILAsm (.NET) wam_ilasm_target Single Dictionary/List fields br loop + switch
Elixir wam_elixir_target Single %WamState{} struct, immutable maps Recursive run/1

Each WAM target includes:

  • 26 instruction arms covering head unification, body construction, control flow, and choice points
  • Helper functions: run loop, backtrack, trail unwinding, unification, builtin dispatch
  • Full project generation: source files, headers/configs, and build files
  • Dedicated test suite validating instruction coverage, code idioms, and runtime assembly

Recursion Pattern Support

Different targets support different recursion patterns. Choose based on your needs:

Pattern Bash C# Query Go Rust Python SQL PowerShell AWK Prolog
Linear Recursion
Tail Recursion
Tree Recursion
Transitive Closure
Mutual Recursion
Aggregations
Advanced Aggregations

Aggregations = dynamic fold expression extraction for list/numeric linear recursion (e.g., extracting * from F is N * F1). Advanced Aggregations = full aggregate_all/3 support with grouping, having filters, and multiple aggregation operations (sum, count, max, min, avg).

Functional Language Targets

Targets for functional / FP-oriented languages with pattern matching and immutability:

Pattern Haskell F# Scala Clojure Elixir
Linear Recursion
Tail Recursion
Tree Recursion
Transitive Closure
Mutual Recursion
Aggregations

JVM & OOP Targets

Pattern Java Kotlin Scala Clojure Jython
Linear Recursion
Tail Recursion
Tree Recursion
Transitive Closure
Mutual Recursion
Aggregations

Scala and Clojure also appear in the Functional table above.

Web & Managed Language Targets

Pattern WASM TypeScript VB.NET
Linear Recursion
Tail Recursion
Tree Recursion
Transitive Closure
Mutual Recursion
Aggregations

Scripting & Native Targets

Pattern C C++ Ruby Perl Lua R
Linear Recursion
Tail Recursion
Tree Recursion
Transitive Closure
Mutual Recursion
Aggregations

Assembly & IR Targets

Low-level assembly and intermediate representation targets:

Pattern Jamaica (JVM) Krakatau (JVM) ILAsm (.NET) WAT (WASM) LLVM IR WAM
Linear Recursion
Tail Recursion
Tree Recursion
Transitive Closure
Mutual Recursion
Aggregations

UI Framework Targets

Pattern Flutter React Native SwiftUI Vue
Linear Recursion
Tail Recursion
Tree Recursion
Transitive Closure
Mutual Recursion
Aggregations

Python Family Targets

All Python variants share the core python_target recursion support and add specialized compilation:

Variant Runtime Specialty Standalone Binary
CPython CPython 3.x Full-featured, generators, streaming JSONL
Jython JVM Java interop, JVM libraries
IronPython .NET/CLR C# interop, in-process .NET hosting
Cython C extension cdef typed functions, C-speed inner loops
MypyC Compiled Strict type annotations → native extensions
Numba LLVM JIT @jit/@njit decorators, vectorized, parallel
Codon LLVM AOT Static subset of Python, @par parallel loops
Nuitka C compiled Full Python → standalone executable, webapp mode
Pyodide WASM Browser-side Python via WebAssembly, packages([numpy])
Fuzzy CPython Fuzzy string matching, semantic search integration

Key:

  • ✅ Full support with optimizations (BFS, loops, memoization, semi-naive)
  • — Not supported or limited

Target Selection Guide

If you need... Use
Shell scripts for Unix pipelines Bash
Standalone binary, no runtime deps Go, Rust, or C
Complex recursion in .NET apps C# Query Runtime
Database views and analytics SQL
Python ecosystem integration Python
Windows/.NET orchestration PowerShell
BEAM VM with OTP concurrency Elixir
Lightweight text processing AWK
Prolog dialect transpilation Prolog
JVM bytecode (assembler-level) Jamaica or Krakatau
.NET IL bytecode ILAsm
WebAssembly (text format) WAT
LLVM IR for custom backends LLVM
Full WAM unification/backtracking Any WAM hybrid target

Type Annotations

UnifyWeaver supports optional predicate type metadata through Prolog facts.

Argument types:

uw_type(edge/2, 1, atom).
uw_type(edge/2, 2, atom).

Return types:

uw_return_type(lower_name/2, atom).

Typed targets such as typr consume this metadata directly.

The plain r target does not require type metadata, but if uw_return_type/2 is present it will use it by default for:

  • better fallback/result-shape generation
  • simple compile-time compatibility checks

This behavior can be disabled per compile call:

compile_predicate_to_r(lower_name/2, [type_constraints(false)], Code).

Optional diagnostics are also available:

compile_predicate_to_r(lower_name/2, [type_diagnostics(warn)], Code).
compile_predicate_to_r(lower_name/2, [type_diagnostics(error)], Code).
  • off (default): silent fallback/filtering
  • warn: emit a warning and continue
  • error: throw on a type-constraint violation

Structured diagnostics can also be collected without warning or throwing:

compile_predicate_to_r(lower_name/2, [type_diagnostics_report(Report)], Code).

Report is bound to a list of dicts with keys such as:

  • target
  • predicate
  • action
  • expected
  • inferred
  • body

TypR now uses the same shared return-type metadata and conservative inference layer. For simple binding-shaped predicates and literal-guarded multi-clause branches it lowers directly to native TypR syntax. That native subset now includes:

  • simple output-producing binding chains
  • simple alias or arithmetic assignment tails after an earlier native string-transform or length-producing step
  • simple alias tails after native conversion, list, and path producers such as to_numeric/2, reverse/2, dirname/2, atom_string/2, narrowed sub_atom/5, string_substr/4, and representative extra-parameter string producers such as string_replace/4, string_sub/4, string_format/3, and string_grepl/3
  • guard-style command predicates such as is_character/1
  • unary TypR-safe I/O commands such as cat/1 and print/1, emitted as native fixed-arity TypR calls
  • multi-argument output should still be composed explicitly, e.g. cat(paste("x =", x))
  • multi-step native control-flow chains where an earlier output feeds a later guard and output
  • simple comparison and boolean guard expressions over already-bound intermediates
  • structured fan-out chains where one earlier bound value feeds multiple later derived outputs or conditions
  • structured split-and-recombine chains where guarded derived values are later combined into a final native output
  • guarded disjunction-style alternative-assignment chains where each native alternative may introduce different branch-local intermediates before binding either the same later intermediate or the final output directly, and later native steps continue from the selected result
  • guarded disjunction-style multi-result chains where each native alternative may introduce different branch-local intermediates before binding the same later variables, and later native steps continue from those selected results
  • multiple sequential branch/rejoin segments in the same native body, including multi-result rejoin chains that continue through later native steps after each rejoin
  • asymmetric partial-rejoin chains where alternatives first converge on only part of the later state, subsequent native steps derive additional shared values, and a later rejoin still stays native
  • Prolog if -> then ; else chains where the branches bind either the same later intermediate, the final output directly, the same later result set, or guard-only control flow before later native steps continue from the selected values, including cases where one branch introduces additional branch-local intermediates before producing that shared later result set
  • Prolog if -> then chains where the then branch either contributes guard-only control flow for later native steps or binds a later intermediate, the final output directly, or the later result set needed by subsequent native steps
  • transitive-closure generation where BFS control flow, seeded adjacency storage, vector-parameter runtime query helpers, explicit input(stdin|file|vfs|function) loader wrappers, and declared scalar or conservative pair-shaped runtime node parsing all stay in native TypR syntax
  • conservative per-path visited recursion like category_ancestor/4, moved-input variants, and category_ancestor_weight/5, where a compile-time- seeded step relation and detected Visited position lower to a native TypR recursive worker that returns nested pair results with one direct node output and one or more additive numeric outputs; this path now supports one recursion-driving input plus conservative invariant non-visited inputs, including one helper/guard segment between the step relation and recursive call, and it also emits a native *_from_vectors runtime helper, native input(stdin|file|vfs|function) wrappers, and declared scalar or conservative pair-shaped runtime node parsing such as integer, number, pair(integer, integer), and pair(number, number) over the same step-relation shape; the first conservative path-aware aggregation slice also now stays native for aggregate_all(count, per_path_goal, N) wrappers over that supported per-path worker path
  • accumulator-style tail-recursive predicates such as factorial_acc/3, lowered to TypR functions that use native TypR loop bodies instead of relabeled standalone R scripts
  • conservative single-recursive-call numeric linear-recursive predicates with one recursion-driving argument and invariant context args, such as factorial_linear/2 and power/3, lowered to TypR functions that use native TypR fold/loop bodies instead of wrapped-R fallback
  • conservative single-recursive-call list linear-recursive predicates with one recursion-driving list argument and invariant context args, such as list_length/2 and list_length_from/3, lowered to TypR functions that use native TypR fold/loop bodies instead of wrapped-R fallback
  • conservative arity-2 numeric multi-call tree-recursive predicates such as fib/2, lowered to TypR functions that use native TypR memoized helper bodies instead of wrapped-R fallback
  • conservative boolean mutual-recursive predicate groups such as is_even/1 / is_odd/1, even_list/1 / odd_list/1, even_left_tree/1 / odd_left_tree/1, and even_tree/1 / odd_tree/1, plus conservative N-ary tree-structural SCCs with one tree-driving argument and one or more threaded context arguments, including dual-subtree tree SCCs with alias-style prework, shared computed context updates, or guarded shared context selection before the two recursive subtree calls, or direct recursive subtree calls inside supported guarded branch bodies with one nested branch-local control point around those calls and limited branch-local alias or guard state around those calls, including one nested branch-local control point around those calls before the shared boolean rejoin, one nested branch-local control point between the two direct recursive subtree calls with limited alias or guard state, one nested post-call control point after the shared dual-subtree calls before the shared boolean rejoin, inter-call symbolic context or alias state before the second call combined with that shared post-call control, nested non-recursive boolean post-call control after the shared dual-subtree calls, shared branch-local guard prework before a nested mutual branch, and the same conservative guarded branch-body family with one invariant context argument threaded through the subtree calls, including branch bodies where one shared subtree call happens before guarded control that contains the second subtree call plus nested non-recursive post-call control, shared context updates before that first subtree call, or branch-local context updates before the second subtree call, plus conservative integer-return tree-structural SCCs with one-subtree or shared dual-subtree descent, guarded branch-local alias selection before those shared subtree calls or direct recursive subtree calls inside supported guarded branch bodies, and simple post-call arithmetic recombination, including branch-local post-call arithmetic steps inside those supported guarded branch bodies, over value, left_result, right_result, and any threaded context args, including mixed-shape SCCs where different predicates in the same group use different supported one-subtree, shared-call, or guarded branch-body forms, and mixed tree/list structural SCCs where tree-shaped predicates recurse through paired-forest helpers, including guarded branch-local paired-forest call selection on the tree side, while list-shaped predicates recurse through head/tail decomposition or fixed two-element forest-pair decomposition or fixed pair-tail forest decomposition like [A, B|Ts], plus mixed list/numeric SCCs where list-shaped predicates recurse through head/tail or pair-tail decomposition like [A, B|Ts] while numeric predicates recurse through scalar step descent, singleton-list re-entry, or fixed pair-list re-entry, plus mixed tree/numeric SCCs where tree-shaped predicates recurse through current-value and one- subtree descent while numeric predicates recurse through scalar step descent or constructed tree re-entry, plus mixed tree/list/numeric SCCs where tree-shaped predicates recurse through current-value and paired- forest helpers while list-shaped predicates recurse through head/tail decomposition and numeric predicates recurse through scalar step descent or constructed tree re-entry, including mixed tree/numeric and mixed tree/list/numeric SCCs where the tree-shaped predicate uses the same supported guarded full-body forms after an earlier recursive group- call prefix, plus integer-return and threaded-context variants, lowered to TypR functions that use native TypR helper bodies instead of wrapped-R fallback
  • the first SCC IR-backed helper-goal slice is now in place: mixed tree/numeric SCCs with a local nonrecursive helper goal between recursive group calls now stay native in TypR instead of falling out with No mutual recursion support for target typr
  • the next confirmed SCC gap is broader than another structural micro-slice: broader helper-goal nodes and richer branch/result structure still point to a shared SCC IR as the next compiler step rather than more matcher families
  • conservative N-ary structural tree-recursive predicates with one tree-driving argument and invariant context args, such as tree_sum/2, tree_height/2, weighted_tree_sum/3, weighted_tree_affine_sum/4, weighted_tree_sum_scale_step/3, weighted_tree_sum_scale_branch/3, tree_sum_branch_calls/2, weighted_tree_branch_calls/3, tree_sum_recursive_branch/2, weighted_tree_recursive_branch/3, tree_sum_nested_recursive_branch/2, weighted_tree_nested_recursive_branch/3, tree_sum_nested_branch_recombine/2, weighted_tree_nested_branch_recombine/3, tree_sum_nested_branch_prework/2, weighted_tree_nested_branch_prework/3, tree_sum_double_nested_calls/2, weighted_tree_double_nested_calls/3, weighted_tree_sum_subtree_scale/3, weighted_tree_sum_subtree_branch/3, tree_sum_prework/2, weighted_tree_sum_prework/3, tree_sum_branch/2, weighted_tree_sum_branch/3, tree_sum_asym_branch/2, and weighted_tree_sum_asym_branch/3, lowered to TypR functions that use native TypR structural helper bodies over [] / [V, L, R] trees, including limited native guards, local is steps, threaded invariant-context updates before the two subtree calls, per-subtree invariant-context updates for the left and right recursive calls, nested branch-local subtree-context selection before shared recursive subtree calls, branch-local recursive-call aliases before the two subtree calls, guarded pre-recursive branching before the two subtree calls, recursive subtree calls inside supported branch bodies, nested recursive subtree calls inside supported branch bodies, shared pre-recursive local work before nested recursive branch bodies, nested branch-local post-recursive recombination before a later shared result expression, multiple nested branch-local control points around the two subtree calls, and asymmetric branch-local prework that is reconciled later by a guarded result expression, instead of wrapped-R fallback
  • guarded post-recursive recombination in those same linear-recursive shapes, including multi-state branch-local recombination such as power_if/3, count_occ/3, power_multistate/3, and count_weighted/3, where the recursive result and later selected intermediate values are recombined through native TypR if expressions instead of wrapped-R fallback
  • asymmetric post-recursive recombination in those same linear-recursive shapes, such as asym_rec_a/3 and asym_rec_c/3, where different branch-local intermediates feed a shared later result expression and still stay native in TypR
  • two-level nested guarded alternatives inside supported semicolon branches, including nested multi-result selections, where each nested branch still selects the same later result set natively
  • supported literal-headed branch bodies built from those chains, with let used for new intermediate TypR locals
  • dataframe helpers such as filter/3, sort_by/3, and group_by/3

More complex generic bodies still fall back to the wrapped R path. The wrapped fallback boundary is now beyond the first native string-transform/output-tail slice; if this area is extended further, the next real audit target is the producer-goal family after the currently supported string_lower/2, string_upper/2, string_length/2, to_numeric/2, reverse/2, dirname/2, atom_string/2, broader constant-parameter substring slices such as sub_atom/5 and string_substr/4, and representative extra-parameter string producers such as string_replace/4, string_sub/4, string_format/3, and string_grepl/3 follow-on alias or arithmetic tails, and the first list-producing Prolog string helper slice split_string/4 with a constant separator and empty pad chars followed by a simple alias tail.

TypR annotation modes are regression-covered too:

  • typed_mode(explicit) emits available annotations
  • typed_mode(infer) keeps the current minimal scalar-annotation behavior
  • typed_mode(off) emits untyped function signatures
  • per-predicate uw_typed_mode/2 overrides per-call mode options
  • current CLI validation boundary: infer and off are covered with typr check; the current typr build path still expects typed function signatures more often than the checker does
  • per-path unique-path work also has a dedicated TypR design note: docs/design/TYPR_PER_PATH_UNIQUE_PATH_DESIGN.md which now records the first counted aggregation slice as landed and points next toward grouped or min-style path-aware aggregation

Worked example:


Target Features

Bash Target (v0.2)

Stream-based compilation to Unix shell scripts with pipes and process substitution.

  • BFS optimization for transitive closures
  • Cycle detection and duplicate prevention
  • Template-based code generation
  • Enhanced Chaining — Fan-out, merge, conditional routing, and filtering stages

Docs: Enhanced Chaining

Go Target (v0.6)

Standalone native binaries with no runtime dependencies.

  • JSON I/O with schemas and nested path extraction
  • Regex matching with capture groups
  • Embedded bbolt database storage
  • Parallel workers for high-throughput processing
  • Enhanced Chaining — Fan-out, merge, conditional routing, and filtering stages
  • Binding System — Map predicates to Go stdlib functions

Docs: Go Target Guide | Enhanced Chaining

Rust Target (v0.2)

Memory-safe native binaries via Cargo.

  • Serde JSON integration
  • Semantic crawling support
  • Full Cargo project scaffolding
  • Enhanced Chaining — Fan-out, merge, conditional routing, and filtering stages
  • Binding System — Map predicates to Rust stdlib and crates

C# Target Family (v0.2)

Two compilation modes for different needs:

  • Stream Target (csharp_codegen) — LINQ pipelines for simple predicates
  • Query Runtime (csharp_query) — IR + semi-naive fixpoint for complex recursion

Features: LiteDB integration, mutual recursion via SCC, arithmetic constraints.

  • Enhanced Chaining — Fan-out, merge, conditional routing, and filtering stages
  • Binding System — Map predicates to .NET APIs and LINQ

Docs: C# Compilation Guide | Enhanced Chaining

Python Target (v0.4)

Generator-based streaming with Python ecosystem integration and multi-runtime support.

  • Pipeline Mode — Streaming JSONL I/O with typed object output
  • Runtime Selection — Auto-select CPython, IronPython, PyPy, or Jython based on context
  • Pipeline Chaining — Connect multiple predicates with yield from composition
  • Enhanced Chaining — Fan-out, merge, conditional routing, and filtering stages
  • Cross-Runtime Pipelines — Stage-based orchestration for mixed Python/C# workflows
  • C# Hosting — IronPython in-process or CPython subprocess with JSONL glue
  • Binding System — Map predicates to Python built-ins and libraries
  • Native XML via lxml, semantic runtime with SQLite and vector search

Docs: Python Target Guide | Enhanced Chaining

SQL Target (v0.3)

Compiles predicates to SQL queries for database execution.

  • Recursive CTEs for hierarchical data
  • Window functions (RANK, ROW_NUMBER, LAG, LEAD)
  • All JOIN types, aggregations, subqueries
  • Works with SQLite, PostgreSQL, MySQL, SQL Server

Docs: SQL Target Design

PowerShell Target (v2.6)

Windows automation and .NET orchestration with full object pipeline support.

  • Dual-mode: pure PowerShell or Bash-as-a-Service via WSL
  • Cross-platform (PowerShell 7+)
  • Binding system: 68+ bindings for cmdlets, .NET methods, Windows automation
  • Auto-transpilation: Rules like sqrt(X, Y) compile directly to [Math]::Sqrt($X)
  • Enhanced Chaining — Fan-out, merge, conditional routing, and filtering stages
  • Object pipeline: ValueFromPipeline parameters, PSCustomObject output
  • Advanced joins: Hash-based and pipelined N-way joins with O(n+m) complexity
  • Firewall security: Per-predicate mode control (pure/baas/auto)
  • Ideal for orchestrating .NET targets (C#, IronPython)

Docs: PowerShell Target Guide | Enhanced Chaining

AWK Target (v0.2)

Lightweight, portable text processing.

  • Tail recursion to while loops
  • Aggregations (sum, count, max, min, avg)
  • Regex matching with capture groups
  • Enhanced Chaining — Fan-out, merge, conditional routing, and filtering stages
  • Runs on any POSIX system

Docs: Enhanced Chaining

Prolog Target

Prolog-to-Prolog transpilation for dialect compatibility.

  • SWI-Prolog and GNU Prolog support
  • Native binary compilation via gplc
  • Executable script generation

Elixir Target (v0.1)

BEAM VM compilation with native pattern matching and tail-call optimization.

  • Multi-clause def with pattern-matched function heads
  • snake_to_camel/2 for idiomatic CamelCase module names
  • Pipeline mode with Stream + Jason JSONL processing
  • Generator mode via Stream.unfold/2
  • Transitive closure via BFS with Map + MapSet
  • Binding System — Arithmetic, comparison, string, I/O mappings

Docs: Elixir Target Guide


Cross-Target Glue System

Compose predicates across multiple languages in unified pipelines:

  • Shell Integration — TSV/CSV/JSON I/O between AWK, Python, Bash
  • .NET Bridges — In-process C# ↔ PowerShell ↔ IronPython
  • Python/C# Glue — IronPython in-process hosting or CPython subprocess with JSONL
  • Pipeline Chaining — Multi-stage orchestration with automatic runtime grouping
  • Native Orchestration — Go/Rust compilation with parallel workers
  • Network Communication — HTTP servers/clients, TCP streaming
  • Service Registry — Distributed service routing

Docs: Cross-Target Glue Guide


Data Sources & ETL

Built-in data source plugins for real-world pipelines:

Source Description
CSV/TSV Auto-header detection, custom delimiters
JSON jq integration for filtering and transformation
HTTP REST APIs with caching and custom headers
Python Inline scripts, SQLite queries
AWK Pattern matching, field extraction
XML/YAML Via Python (lxml, PyYAML)

Control Plane

Security and configuration for production deployments:

  • Firewall — Multi-service security for external tools
  • Network ACLs — Host pattern matching and restrictions
  • Import Restrictions — Python module whitelisting
  • File Access Patterns — Read/write permission management
  • Preferences — Layered configuration (global, rule-specific, runtime)

Installation

Requirements:

  • SWI-Prolog 8.0 or higher
  • Bash 4.0+ (for associative arrays)
git clone https://github.com/s243a/UnifyWeaver.git
cd UnifyWeaver

# Set up local data directories
./scripts/setup_local.sh

Local Data Directory

The .local/ directory holds project-specific data and tools that are not checked into git:

Directory Purpose
.local/bin/ Executable scripts
.local/data/ Cached API responses, scan results, embeddings
.local/lib/ Shared libraries/modules
.local/tools/ External tool repositories

For Pearltrees integration, clone the harvester tools:

git clone git@github.com:s243a/pt-harvester.git .local/tools/browser-automation

Quick Start

Test Environment

UnifyWeaver includes a convenient test environment with auto-discovery:

# Linux/WSL
cd scripts/testing
./init_testing.sh

# Windows (PowerShell)
cd scripts\testing
.\Init-TestEnvironment.ps1

Then in the test environment:

?- test_all.           % Run all tests
?- test_stream.        % Test stream compilation
?- test_recursive.     % Test basic recursion
?- test_advanced.      % Test advanced recursion patterns
?- test_constraints.   % Test constraint system

Manual Usage

?- use_module(unifyweaver(core/recursive_compiler)).
?- test_recursive_compiler.

This generates bash scripts in the output/ directory:

cd output
bash test_recursive.sh

Usage

Basic Example

Define your Prolog predicates:

% Facts
parent(alice, bob).
parent(bob, charlie).

% Rules
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).

Compile to bash:

?- compile_recursive(ancestor/2, [], BashCode).
?- write_bash_file('ancestor.sh', BashCode).

Use the generated script:

source parent.sh
source ancestor.sh

ancestor_all alice  # Find all descendants of alice
ancestor_check alice charlie && echo "Yes" || echo "No"  # Check specific relationship

See Extended Documentation for advanced recursion patterns, data sources, and complete examples.

Architecture

UnifyWeaver follows a modular compilation pipeline:

  1. Classification - Analyzes predicate to determine recursion pattern
  2. Constraint Analysis - Detects unique/ordering constraints
  3. Pattern Matching - Tries tail → linear → tree → mutual → basic recursion
  4. Optimization - Applies pattern-specific optimizations (BFS, loops, memoization)
  5. Target Selection - Chooses Bash, PowerShell, or C# backend based on requested target/1 preference
  6. Code Generation / Plan Emission - Renders shell templates, C# source, or query plans for the selected backend

See ARCHITECTURE.md and Extended Documentation for detailed architecture.

Mustache Template System

Large code templates (50+ lines) are stored as external .mustache files rather than inline format/2 strings. This eliminates Prolog escape sequence issues and makes templates easier to read and maintain.

Directory structure:

templates/targets/
├── c/transitive_closure.mustache
├── cpp/transitive_closure.mustache
├── rust/transitive_closure.mustache
├── go/transitive_closure.mustache
├── ruby/transitive_closure.mustache
├── perl/transitive_closure.mustache
├── python/transitive_closure.mustache
├── ... (18 target directories)

How it works:

Templates use {{placeholder}} syntax and are rendered via template_system:render_template/3:

%% Helper: load and render a target-specific mustache template
compile_tc_from_template(Target, Pred, BasePred, ExtraDict, Code) :-
    atom_string(Target, TargetStr),
    format(string(Path), 'templates/targets/~w/transitive_closure.mustache', [TargetStr]),
    read_file_to_string(Path, Template, []),
    append([pred=PredStr, base=BaseStr], ExtraDict, Dict),
    template_system:render_template(Template, Dict, Code).

Common placeholders: {{pred}} (predicate name), {{base}} (base relation name), {{pred_cap}} (capitalized predicate name for class/struct names).

Examples

Family Tree Queries

ancestor(X, Y)    % Transitive closure of parent
descendant(X, Y)  % Reverse of ancestor
sibling(X, Y)     % Same parent, different children

Data Source Integration

% CSV/TSV data processing
:- source(csv, users, [csv_file('data/users.csv'), has_header(true)]).

% AWK text processing
:- source(awk, extract_fields, [
    awk_program('$3 > 100 { print $1, $2 }'),
    input_file('data.txt')
]).

% HTTP API integration with caching
:- source(http, github_repos, [
    url('https://api.github.com/users/octocat/repos'),
    cache_duration(3600)
]).

% Python with SQLite
:- source(python, get_users, [
    sqlite_query('SELECT name, age FROM users WHERE active = 1'),
    database('app.db')
]).

% JSON processing with jq
:- source(json, extract_names, [
    jq_filter('.users[] | {name, email} | @tsv'),
    json_file('data.json')
]).

See Extended Documentation for complete examples.

Python Pipeline Example

% Compile predicates to a chained Python pipeline
compile_pipeline(
    [parse_user/2, filter_adult/2, format_output/3],
    [runtime(cpython), pipeline_name(user_pipeline)],
    PythonCode
).

Generated Python uses efficient generator chaining:

def user_pipeline(input_stream):
    """Chained pipeline: [parse_user, filter_adult, format_output]"""
    yield from format_output(filter_adult(parse_user(input_stream)))

For cross-runtime workflows (Python + C#):

compile_pipeline(
    [python:extract/1, csharp:validate/1, python:transform/1],
    [pipeline_name(data_processor)],
    Code
).

Current Limitations

  • Divide-and-conquer patterns (quicksort, mergesort) not yet supported
  • Tree recursion uses list representation only

Testing

cd scripts/testing
./init_testing.sh  # or Init-TestEnvironment.ps1 on Windows

In SWI-Prolog:

?- test_all.          % Run all tests
?- test_stream.       % Stream compilation
?- test_recursive.    % Basic recursion
?- test_advanced.     % Advanced patterns

See TESTING_GUIDE.md for adding tests.

Documentation

Resource Description
Educational Materials 13-book series covering all targets and patterns
Extended Documentation Tutorials and advanced examples
Architecture System design and compilation pipeline
Enhanced Pipeline Chaining Fan-out, merge, routing, and filter stages
Cross-Target Glue Multi-language pipeline composition
Advanced Recursion Recursion patterns deep dive
Testing Guide Testing infrastructure

Contributing

Issues and pull requests welcome! See CONTRIBUTING.md for details.

Key areas:

  • Additional recursion patterns (divide-and-conquer, N-ary trees)
  • Performance optimizations
  • Additional data source plugins
  • Native PowerShell code generation (pure mode enhancements)

License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Acknowledgments

Developed as an exploration of compiling declarative logic to efficient executable code across multiple target languages—making Prolog's power accessible everywhere from shell scripts to native binaries to database queries.

Contributors:

  • John William Creighton (@s243a) - Core development
  • GPT-5/5.1-Codex (via OpenAI) - Fixed-point architecture, query engine, generator approaches
  • Gemini (via gemini-cli) - Constraint awareness features
  • Claude (via Claude Code) - Advanced recursion system, test infrastructure, educational materials

About

Prolog-to-Bash compiler for declarative automation, featuring BFS-optimized transitive closures and recursion support.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors