Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

patch-prolog

A standalone Prolog compiler. plgc compiles an ISO-subset Prolog program to a single native binary with zero runtime dependencies — no Rust toolchain, no interpreter, no serialized clause database. Predicates become native code via LLVM.

plgc build rules.pl -o my-linter      # ~676K standalone binary
./my-linter --query "violation([field(id,integer)], Field, Reason)"
echo $?   # 0 = no solutions (clean), 1 = solutions found

The compiled binary contains no clause interpreter — control flow is generated per predicate as native code, and only primitive services (heap, trail, unification, builtins, query parsing, output) come from a small runtime statically linked in. The result runs anywhere with libc/libm and nothing else.

The language semantics (ISO subset, the full builtin vocabulary, the embedded list stdlib, safety guarantees) are pinned by a 200-assertion integration corpus. The execution model is built on the architecture proven by patch-seq: LLVM IR text generation, clang linking, and a Rust runtime staticlib embedded in the compiler binary.

The toolchain

Three binaries share the engine:

BinaryWhat it is
plgcThe compiler — build, run, and check your Prolog.
plgrAn interactive REPL that drives the compiler (never interprets).
plglA Language Server (diagnostics, completion, hover, go-to-definition).

Requirements

  • To build the compiler: Rust (see rust-toolchain.toml), just
  • To use plgc: clang ≥ 15 (for linking) — no Rust required
  • To run compiled binaries: nothing (libc/libm only)

Quick start

just build                 # builds libplg_runtime.a then plgc
target/release/plgc build examples/deps.pl -o deps
./deps --query "needs(app, X)"
./deps --query "findall(D, needs(app, D), Ds)" --format text

Scripts work too:

#!/usr/bin/env plgc
greet(hello, world).
chmod +x greet.pl && ./greet.pl --query "greet(X, Y)" --format text

Commands

CommandPurpose
plgc build <in.pl>... [-o out] [--keep-ir] [--debug]compile to a native executable (--debug: -O0 + DWARF)
plgc run <in.pl>... --query "g(X)"compile to a temp binary and run it (never interprets)
plgc check <in.pl>...parse + static analysis only
plgc completions <shell>shell completion scripts
plgc prog.pl [args...]script mode (shebang-friendly)

Compiled binaries take --query "goal", --limit N, --format json|text (default json) and exit with 0 no solutions · 1 solutions · 2 query parse error · 3 runtime error. The step ceiling (default 10,000, uncatchable) is tunable via PLG_MAX_STEPS.

The language

An ISO 13211-1 subset, with ISO conformance as the guide. A few minor, deliberate deviations and several safety extensions beyond ISO are documented in ISO_COMPLIANCE.md; the subset is defined by its omissions and its features.

Deliberate omissions: no modules, DCG, op/3, assert/retract, or postfix operators.

Features:

  • Full backtracking with first-argument indexing
  • Cut, transparent through ,/;/-> (ISO semantics)
  • ->/;/\+/once
  • catch/throw with the ISO error-term taxonomy
  • findall/3, call/N, between/3
  • Checked i64 arithmetic with floored mod
  • The standard order of terms
  • ~60 builtins, plus a compiled-in list stdlib (member, append, length, reverse, nth0/1, last)

Deep recursion is safe: all control transfers are guaranteed tail calls (musttail), so a million-deep recursive chain runs in constant C stack.

Documentation

Source pages: Getting Started · Compiler Usage · Language Guide · Operators · Builtin & Stdlib Reference · Semantics & ISO Conformance · REPL Guide · LSP & Editor Guide · Examples · Architecture