an automatically parallel prolog system
  • C 81.1%
  • Prolog 13.4%
  • Shell 4%
  • Raku 1%
  • Perl 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-12 19:13:33 +01:00
bench fix and align benchmark argument ordering 2026-10-12 19:13:33 +01:00
docs fix and align benchmark argument ordering 2026-10-12 19:13:33 +01:00
lib add ISO reference versions of TOTP/HOTP 2026-05-19 23:44:40 +01:00
tests infer safe WAM/WAMVM AND-par prefixes automatically 2026-10-12 15:32:08 +01:00
.gitignore reduce stack usage 2026-01-12 22:56:42 +00:00
flowlog-logo.png new logo c: 2026-03-19 00:47:09 +00:00
flowlog.c infer safe WAM/WAMVM AND-par prefixes automatically 2026-10-12 15:32:08 +01:00
Makefile update conformity tests to fix simple errors in the test code 2026-05-04 18:34:29 +01:00
README.md infer safe WAM/WAMVM AND-par prefixes automatically 2026-10-12 15:32:08 +01:00
TODO.md split CLI arguments into system/application, and expose current_prolog_flag(argv, Argv) 2026-03-17 22:39:45 +00:00

Flowlog: an automatically parallel prolog system

flowlog git repo

Flowlog is an ISO-style Prolog system implemented as a single, portable C file (flowlog.c), with a focus on running unmodified Prolog search faster on multicore CPUs.

It provides:

  • A small, self-contained Prolog runtime (no external libraries required beyond libc + pthreads)
  • Multiple execution engines (wamvm, wam, interp/tree)
  • Optional OR-parallelism (parallel exploration of choicepoints) and conservative AND-parallelism (parallel execution of independent subgoals when safe)
  • Unbounded integers with automatic promotion (current_prolog_flag(bounded,false))
  • A practical REPL with history and line editing
  • An ISO conformance workflow (INRIA suite + regression tests)

Why it exists

Prolog is a great fit for search problems, constraint-style programming, and symbolic manipulation, but classic implementations tend to exploit only limited parallelism automatically. Flowlog's goal is to keep Prolog's familiar ISO semantics while also making it easy to:

  • Use all available CPU cores during nondeterministic search
  • Trade strict, classic "left-to-right" solution ordering for throughput when desired
  • Keep a simple "one C file" implementation that is easy to build and embed

Quick start

git clone:

git clone https://git.liminal.cafe/byakuren/flowlog.git

Build:

cd flowlog
make

Or compile directly:

cd flowlog
cc -O2 -Wall -Wextra -pthread flowlog.c -lm -o flowlog

Run the REPL:

./flowlog

Load a file and run a goal:

./flowlog -g 'main.' program.pl

Control the number of worker threads:

./flowlog --threads 12 -g 'goal(X).' program.pl

Engines (and defaults)

Flowlog ships three execution engines:

  • wamvm - bytecode WAM VM (default). Designed to be fast and parallel-friendly; may fall back to wam/interp if a feature is not supported in VM-only mode.
  • wam - a "WAM-lite" direct solver (still a Prolog engine, but not a classic WAM bytecode VM).
  • interp / tree - a full tree-walking interpreter (useful as the most conservative reference behavior).

Select an engine:

./flowlog --engine wamvm   -g 'goal.' program.pl
./flowlog --engine wam     -g 'goal.' program.pl
./flowlog --engine interp  -g 'goal.' program.pl

Parallelism

Flowlog's parallel features are opt-in/controllable so you can choose between classic behavior and maximum throughput:

  • OR-parallelism: splits choicepoints across workers (best for large search spaces)
  • AND-parallelism: runs proven-safe independent subgoals in parallel (conservative by design)

The main user-facing switch is the parallel profile:

  • fast - prefer throughput; may return solutions in a different order than classic Prolog
  • iso - prioritize classic ordering/behavior where possible
  • off - disable Flowlog parallelism features
./flowlog --parallel-profile fast -g 'goal.' program.pl
./flowlog --parallel-profile iso  -g 'goal.' program.pl
./flowlog --parallel-profile off  -g 'goal.' program.pl

Flowlog also supports the same controls as Prolog flags (so an ISO Prolog program can enable them explicitly when running under Flowlog):

:- set_prolog_flag(flowlog_parallel_profile, fast).
:- set_prolog_flag(flowlog_parallel_and_workers, 4).

AND-parallelism is inferred automatically for conservative safe cases. For pure deterministic predicates that the analysis cannot prove, Flowlog also accepts :- flowlog_and_safe([pure_predicate/2]). as an explicit promise.

Parse diagnostics (with context)

Flowlog's parser reports errors with file/line/column, a one-line source excerpt, and a caret pointing at the offending token:

flowlog: fatal error (240): flowlog: parse error: unexpected token after term: ) (TOK_RPAREN); expected '.' (TOK_DOT)
  at incorrect-syntax.pl:6:12
  (unexpected token after a complete term; check for a missing ',' between goals or a missing operator)
  6 | 	N is X + 1).
    | 	          ^

...

flowlog: fatal error (240): flowlog: unexpected token while parsing term: ) (TOK_RPAREN)
  at program.pl:1:6
  expected one of: '(', '[', atom, string, number, variable
  (')' closes a group/call; a term was expected before it)
  1 | p :- ).
    |      ^

See docs/TROUBLESHOOTING.md for more examples (including read_term/2,3 lexer errors like illegal_character_escape).

ISO conformance

Flowlog targets ISO/IEC 13211-1 behavior for the core language and built-in predicates. The recommended way to check conformance in this repo:

make test       # run regression tests
make inria      # run the inria test suite
make quad       # run all existing quad tests

To lock in that the INRIA suite runs entirely in the wamvm VM (no fallback):

make inria-wamvm-vmonly

Documentation

to-do file:

Start here:

Core references:

Parallel/runtime internals:

Contributing:

Benchmarks and tests:

  • BENCHMARKS.md - benchmark harnesses and reference programs (includes full source)
  • TESTS.md - regression tests and ISO suite runners (includes full source)
  • QUAD_TESTS.md - quad conformance tests (format, runners, logs)

Performance comparison

These tables are derived from the raw timing logs in this repo: magic_square_timings.txt and nqueens_timings.txt. Times are wall-clock real seconds (lower is better), sorted fastest -> slowest.

Magic square timings (magic_square(4, _)):

program engine profile time
magic_square(4) flowlog-wamvm fast 34.76s
magic_square(4) flowlog-wam fast 37.28s
magic_square(4) flowlog-wamvm iso 115.27s
magic_square(4) flowlog-wam iso 125.12s
magic_square(4) flowlog-tree fast 271.67s
magic_square(4) flowlog-tree iso 637.05s
magic_square(4) scryer-prolog - 1815.01s
magic_square(4) tpl - 2636.00s

N-queens timings (nqueens(13, _)):

program engine profile time
nqueens(13) flowlog-wamvm fast 1.82s
nqueens(13) flowlog-wam fast 6.95s
nqueens(13) flowlog-wamvm iso 7.57s
nqueens(13) flowlog-wam iso 7.71s
nqueens(13) flowlog-tree fast 14.19s
nqueens(13) flowlog-tree iso 25.00s
nqueens(13) scryer-prolog - 30.39s
nqueens(13) tpl - 41.42s

A short history of parallel Prolog (and what's different here)

Parallel execution in Prolog has a long research lineage:

  • OR-parallelism (splitting different clause alternatives/choicepoints across workers) appeared in systems like Muse and Aurora.
  • AND-parallelism (running independent subgoals in parallel) was explored in systems like &-Prolog and related work on dependency analysis.
  • Practical systems often combine these ideas with other features (tabling, indexing, compilation, constraints) but typically require either explicit parallel constructs or careful programming patterns to get consistent wins.

Flowlog's approach is:

  • Keep the surface language close to ISO Prolog.
  • Provide a fast-by-default runtime profile for search workloads (unordered when permitted).
  • Make parallelism a runtime policy (flags/profiles), not a separate language.
  • Keep the whole system small, hackable, and easy to build as a single C source file.

If you're new: start with QUICKSTART.md, then skim USER_GUIDE.md and PARALLELISM.md.

Version history

Flowlog has gone through a few distinct implementation phases. This is a high-level timeline of the ideas that shaped the current system:

  • v4 - WAMVM engine: Added a bytecode-based WAM VM (wamvm) as the default engine, aiming for higher instruction-cache locality and tighter inner loops while still supporting Flowlog's OR/AND parallel policies. VM-only conformance runs (no fallback) make it easier to track and close remaining feature gaps.
  • v2 - WAM-lite engine: Introduced a faster execution core than the interpreter, keeping the same surface language while improving clause selection, unification, and backtracking hot paths. This was the first "compiled-ish" step toward closing the performance gap with established Prolog systems while preserving Flowlog's parallel hooks.
  • v1 - tree-walking engine (pure C + pthreads): A standalone implementation that removed BMDFM constraints and made it easier to reason about performance, memory layout, and scheduling. This phase focused on correctness (ISO-style behavior), a practical REPL, and making OR-parallelism a first-class runtime policy.
  • v0 - BMDFM-based prototype: The original Flowlog experiments were built on top of the BMDFM runtime, using its flow/parallel model to explore how Prolog search could map onto a graph-like execution substrate (especially OR-parallel search and "run independent work at once" ideas).

Contact me c:

The best way to contact me with any feedback, or even just to chat is on IRC

  • server: irc.libera.chat
  • channel: #flowlog
  • my nick: byakuren

see you there! ^^