No description
  • Rust 98%
  • Just 1.5%
  • JavaScript 0.4%
  • Prolog 0.1%
Find a file
2026-07-13 11:59:39 -07:00
.forgejo/workflows ● Phase E — CI (both tiers) 2026-06-20 18:52:21 -07:00
crates chore: bump version to 0.4.4 2026-07-05 03:11:53 +00:00
docs Done. Tab cycling implemented, tested, documented, and the design doc moved to 2026-07-04 19:58:17 -07:00
examples example 2026-07-05 21:05:40 -07:00
scripts Summary of the wasm track 2026-07-04 06:30:57 -07:00
.gitignore CI green. The example works end-to-end. 2026-07-04 08:38:42 -07:00
book.toml ⏺ The docs site deploy is set up — adapted from the skill's GitHub-Pages 2026-06-16 22:42:30 -07:00
Cargo.lock lock 2026-07-13 11:59:39 -07:00
Cargo.toml chore: bump version to 0.4.4 2026-07-05 03:11:53 +00:00
justfile sync docs 2026-07-04 15:57:11 -07:00
LICENSE ● patch-prolog2 is up and running — and it's a real compiler this time. Summary of where things stand: 2026-06-04 10:51:51 -07:00
README.md sync docs 2026-07-04 15:57:11 -07:00
rust-toolchain.toml rust 2026-07-02 05:16:54 -07:00

patch-prolog

patch-prolog-compiler patch-prolog-repl patch-prolog-lsp

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.

Home Code Repository is at git.navicore.tech

PRs and issues welcome at codeberg.org mirror

Documentation

API docs (rustdoc) per crate on docs.rs: patch-prolog-shared · patch-prolog-frontend · patch-prolog-runtime · patch-prolog-compiler · patch-prolog-lsp · patch-prolog-repl

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

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.

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

Command Purpose
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 docs/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

The full documentation site is published at https://docs.navicore.tech/patch-prolog/ — built from docs/ with mdBook. Source pages: Getting Started · Compiler Usage · Language Guide · Operators · Builtin & Stdlib Reference · Semantics & ISO Conformance · REPL Guide · LSP & Editor Guide · Examples · Architecture

Build the site locally with just docs-serve (live reload) or just docs (one-shot into book/).

Releasing

Crates publish to crates.io from Forgejo Actions (.forgejo/workflows/release.yml) when a v* tag is pushed:

git tag v0.2.0 && git push origin v0.2.0

The workflow then, on the same navicore-rust runner CI uses (so the rust-toolchain.toml pin governs):

  1. sets the [workspace.package] version and the =-pinned inter-crate dependencies to the tag, regenerates Cargo.lock, and commits the bump back to main;
  2. publishes in dependency order with a pause between each so crates.io indexes it before the next depends on it: patch-prolog-shared-frontend-runtime-compiler-lsp-repl.

The crates.io package names are patch-prolog-*; the library and binary names are unchanged (use plg_shared; the binaries are plgc/plgl/plgr), so patch-prolog-runtime still builds the libplg_runtime.a the compiler embeds.

Required repo secrets (Forgejo → Settings → Actions → Secrets and Variables):

  • PAT — Forgejo token with write:repository, to push the version bump to main.
  • CRATES_IO_TOKEN — crates.io API token from https://crates.io/settings/tokens.
  • DOCS_CLIENT_ID — anz client ID for publishing the mdbook
  • DOCS_CLIENT_SECRET — anz client secret for publishing the mdbook