- Rust 98%
- Just 1.5%
- JavaScript 0.4%
- Prolog 0.1%
| .forgejo/workflows | ||
| crates | ||
| docs | ||
| examples | ||
| scripts | ||
| .gitignore | ||
| book.toml | ||
| Cargo.lock | ||
| Cargo.toml | ||
| justfile | ||
| LICENSE | ||
| README.md | ||
| rust-toolchain.toml | ||
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.
Home Code Repository is at git.navicore.tech
PRs and issues welcome at codeberg.org mirror
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) ->/;/\+/oncecatch/throwwith the ISO error-term taxonomyfindall/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):
- sets the
[workspace.package]version and the=-pinned inter-crate dependencies to the tag, regeneratesCargo.lock, and commits the bump back tomain; - 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 withwrite:repository, to push the version bump tomain.CRATES_IO_TOKEN— crates.io API token from https://crates.io/settings/tokens.DOCS_CLIENT_ID— anz client ID for publishing the mdbookDOCS_CLIENT_SECRET— anz client secret for publishing the mdbook