{"id":13503853,"url":"https://github.com/mthom/scryer-prolog","last_synced_at":"2026-02-23T05:02:11.279Z","repository":{"id":37686718,"uuid":"72257883","full_name":"mthom/scryer-prolog","owner":"mthom","description":"A modern Prolog implementation written mostly in Rust.","archived":false,"fork":false,"pushed_at":"2026-01-15T05:07:10.000Z","size":11163,"stargazers_count":2361,"open_issues_count":503,"forks_count":161,"subscribers_count":52,"default_branch":"master","last_synced_at":"2026-01-22T12:09:51.857Z","etag":null,"topics":["iso-prolog-standard","prolog","prolog-implementation","prolog-interpreter","prolog-programming-language","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mthom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-10-29T01:44:10.000Z","updated_at":"2026-01-22T11:16:06.000Z","dependencies_parsed_at":"2024-04-08T01:26:22.400Z","dependency_job_id":"ef4f88c5-b558-4c78-a7eb-15b59175736f","html_url":"https://github.com/mthom/scryer-prolog","commit_stats":{"total_commits":2368,"total_committers":34,"mean_commits":69.6470588235294,"dds":"0.33783783783783783","last_synced_commit":"4ee6a7bfb828474cbcab51695f24b120b1e35314"},"previous_names":["mthom/rusty-wam"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/mthom/scryer-prolog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthom%2Fscryer-prolog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthom%2Fscryer-prolog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthom%2Fscryer-prolog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthom%2Fscryer-prolog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mthom","download_url":"https://codeload.github.com/mthom/scryer-prolog/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthom%2Fscryer-prolog/sbom","scorecard":{"id":666591,"data":{"date":"2025-08-11","repo":{"name":"github.com/mthom/scryer-prolog","commit":"87f5295bd01e59c0387083b2de2b38e48ad1e310"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":6,"reason":"Found 8/12 approved changesets -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: topLevel 'checks' permission set to 'write': .github/workflows/ci.yml:16","Warn: no topLevel permission defined: .github/workflows/docker-publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:147: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:166: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:171: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:185: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:199: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:208: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:59: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:92: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:103: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:110: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:127: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:132: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:137: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docker-publish.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/docker-publish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker-publish.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/docker-publish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker-publish.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/docker-publish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker-publish.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/docker-publish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docker-publish.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/mthom/scryer-prolog/docker-publish.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:4","Warn: containerImage not pinned by hash: Dockerfile:10","Warn: containerImage not pinned by hash: Dockerfile:16","Warn: containerImage not pinned by hash: Dockerfile:24","Info:   0 out of  11 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   9 third-party GitHubAction dependencies pinned","Info:   0 out of   4 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.9.3 not signed: https://api.github.com/repos/mthom/scryer-prolog/releases/127771590","Warn: release artifact v0.9.2 not signed: https://api.github.com/repos/mthom/scryer-prolog/releases/118998398","Warn: release artifact v0.9.3 does not have provenance: https://api.github.com/repos/mthom/scryer-prolog/releases/127771590","Warn: release artifact v0.9.2 does not have provenance: https://api.github.com/repos/mthom/scryer-prolog/releases/118998398"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/docker-publish.yml:11"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 27 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: RUSTSEC-2024-0436","Warn: Project is vulnerable to: GHSA-gw5w-5j7f-jmjj","Warn: Project is vulnerable to: RUSTSEC-2024-0408","Warn: Project is vulnerable to: RUSTSEC-2024-0370"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T18:14:43.109Z","repository_id":37686718,"created_at":"2025-08-21T18:14:43.109Z","updated_at":"2025-08-21T18:14:43.109Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29738083,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T04:51:08.365Z","status":"ssl_error","status_checked_at":"2026-02-23T04:49:15.865Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["iso-prolog-standard","prolog","prolog-implementation","prolog-interpreter","prolog-programming-language","rust"],"created_at":"2024-07-31T23:00:47.664Z","updated_at":"2026-02-23T05:02:11.253Z","avatar_url":"https://github.com/mthom.png","language":"Rust","readme":"# Scryer Prolog\n\nScryer Prolog aims to become to ISO Prolog what GHC is to Haskell: an open\nsource industrial strength production environment that is also a\ntestbed for bleeding edge research in logic and constraint\nprogramming, which is itself written in a high-level language.\n\n**Scryer Prolog passes all tests** of\n[syntactic\u0026nbsp;conformity](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing),\n[`variable_names/1`](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/variable_names) and\n[`dif/2`](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/dif).\n\nThe homepage of the project is: [**https://www.scryer.pl**](https://www.scryer.pl)\n\n![Scryer Logo: Cryer](logo/scryer.png)\n\n## Phase 1\n\nProduce an implementation of the Warren Abstract Machine in Rust, done\naccording to the progression of languages in [Warren's Abstract\nMachine: A Tutorial Reconstruction](https://github.com/mthom/scryer-prolog/blob/master/wambook/wambook.pdf).\n\nPhase 1 has been completed in that Scryer Prolog implements in some form\nall of the WAM book, including lists, cuts, Debray allocation, first\nargument indexing, last call optimization and conjunctive queries.\n\n## Phase 2\n\nExtend Scryer Prolog to include the following, among other features:\n\n- [x] call/N as a built-in meta-predicate.\n- [x] ISO Prolog compliant throw/catch.\n- [x] Built-in and user-defined operators of all fixities, with custom\n      associativity and precedence.\n- [x] Bignum, rational number and floating point arithmetic.\n- [x] Built-in control operators (`,`, `;`, `-\u003e`, etc.).\n- [x] A revised, not-terrible module system.\n- [x] Built-in predicates for list processing and top-level declarative\n      control (`setup_call_cleanup/3`, `call_with_inference_limit/3`,\n      etc.)\n- [x] ~~Default representation of strings as lists of characters, using a packed\n      internal representation.~~\n- [x] `term_expansion/2` and `goal_expansion/2`.\n- [x] Definite Clause Grammars.\n- [x] Attributed variables using the SICStus Prolog interface and\n      semantics. Adding coroutines like `dif/2`, `freeze/2`, etc.\n      is straightforward with attributed variables.\n  - [x] Support for `verify_attributes/3`\n  - [x] Support for `attribute_goals/2` and `project_attributes/2`\n  - [x] `call_residue_vars/2`\n- [x] `if_/3` and related predicates, following the developments of the\n      paper \"[Indexing `dif/2`](https://arxiv.org/abs/1607.01590)\".\n- [x] All-solutions predicates (`findall/{3,4}`, `bagof/3`, `setof/3`, `forall/2`).\n- [x] Clause creation and destruction (`asserta/1`, `assertz/1`,\n      `retract/1`, `abolish/1`) with logical update semantics.\n- [x] Backtrackable and non-backtrackable global variables via `bb_get/2`\n      `bb_put/2` (non-backtrackable) and `bb_b_put/2`\n      (backtrackable).\n- [x] Delimited continuations based on reset/3, shift/1 (documented in\n      \"[Delimited Continuations for Prolog](https://biblio.ugent.be/publication/5646080/file/5646081)\").\n- [x] Tabling library based on delimited continuations\n      (documented in \"[Tabling as a Library with Delimited Control](https://biblio.ugent.be/publication/6880648/file/6885145.pdf)\").\n- [x] A _redone_ representation of strings as difference lists of\n      characters, using a packed internal representation.\n- [x] clp(B) and clp(ℤ) as builtin libraries.\n- [x] Streams and predicates for stream control.\n  - [x] A simple sockets library representing TCP connections as streams.\n- [x] Incremental compilation and loading process, newly written,\n      primarily in Prolog.\n- [ ] Improvements to the WAM compiler and heap representation:\n  - [ ] Replacing choice points pivoting on inlined semi-deterministic predicates\n        (`atom`, `var`, etc) with if/else ladders. (_in progress_)\n  - [ ] Inlining all built-ins and system call instructions.\n  - [x] Greatly reducing the number of instructions used to compile disjunctives.\n  - [x] Storing short atoms to heap cells without writing them to the atom table.\n- [ ] A compacting garbage collector satisfying the five properties of\n      \"[Precise Garbage Collection in Prolog](https://www.complang.tuwien.ac.at/ulrich/papers/PDF/2008-ciclops.pdf).\" (_in progress_)\n- [ ] Mode declarations.\n\n## Phase 3\n\nUse the WAM code produced by the completed code generator to get\nJIT-compiled and -executed Prolog programs. The question of how to get\nassembly from WAM code is something I'm still considering.\n\nIt's my hope to use Scryer Prolog as the logic engine of a low level (and\nideally, very fast) [Shen](http://shenlanguage.org) implementation.\n\n## Nice to have features\n\nThere are no current plans to implement any of these, but they might be\nnice to have in the future. They'd make a good project for anyone wanting\nto contribute code to Scryer Prolog.\n\n1. Implement the global analysis techniques described in Peter van\nRoy's thesis, \"[Can Logic Programming Execute as Fast as Imperative\nProgramming?](https://www.info.ucl.ac.be/~pvr/Peter.thesis/Peter.thesis.html)\"\n\n2. Add unum representation and arithmetic, using either an existing\nunum implementation or an ad hoc one. Unums are described in\nGustafson's book \"[The End of Error](http://www.johngustafson.net/unums.html).\"\n\n3. Add concurrent tables to manage shared references to atoms and\nstrings.\n\n4. Add some form of JIT predicate indexing.\n\n## Installing Scryer Prolog\n\n### Binaries\n\nPrecompiled binaries for several platforms are available for download\nat:\n\n**https://github.com/mthom/scryer-prolog/releases/latest**\n\n### Native Compilation\n\nFirst, install the latest stable version of\n[Rust](https://www.rust-lang.org/tools/install) using your\npreferred method. Scryer tends to use features from newer Rust\nreleases, whereas Rust packages in Linux distributions, Macports,\netc. tend to lag behind. [rustup](http://rustup.rs) will keep your\nRust updated to the latest stable release; any existing Rust\ndistribution should be uninstalled from your system before rustup is\nused.\n\n\n\u003e [!NOTE]\n\u003e The minimum rust toolchain version required can be found in the [Cargo.toml](https://github.com/mthom/scryer-prolog/blob/master/Cargo.toml#L13)\nunder the `package.rust-version` key.\n\u003e The accuracy of this value is validated in CI\n\n### From a local git checkout\n\n```\n$\u003e git clone https://github.com/mthom/scryer-prolog\n$\u003e cd scryer-prolog\n$\u003e cargo build --release\n```\n\nThe `--release` flag performs various optimizations, producing a\nfaster executable.\n\nAfter compilation, the executable `scryer-prolog` is available in the\ndirectory\u0026nbsp;`target/release` and can be invoked to run the system.\n\n### Via `cargo install`\n\n#### From git\n\n```\ncargo install --locked --git https://github.com/mthom/scryer-prolog.git\n```\n\nAfterwards the `scryer-prolog` binary will be in the `$HOME/.cargo/bin` directory which is usually added to your PATH \nduring the installation of the rust toolchain.\n\n#### From Crates.io [![Crates.io Version](https://img.shields.io/crates/v/scryer-prolog)](https://crates.io/crates/scryer-prolog) ![Crates.io MSRV](https://img.shields.io/crates/msrv/scryer-prolog)\n\n\u003e [!NOTE]\n\u003e The latest crates.io release can be significantly behind the version available in the git repository\n\u003e The crates.io badge in this sections title is a link to the crates.io page.\n\u003e The msrv badge in the section title references the minimum rust toolchain version required to compile the latest crates.io release\n\n`scryer-prolog` is also release on crates.io and can be installed with\n\n```\ncargo install --locked scryer-prolog\n```\n\n### Caveats for Windows\n\nOn Windows, Scryer Prolog is easier to build inside a [MSYS2](https://www.msys2.org/)\nenvironment as some crates may require native C compilation. However,\nthe resulting binary does not need MSYS2 to run. When executing Scryer in a shell, it is recommended to use a more advanced shell than mintty (the default MSYS2 shell). The [Windows Terminal](https://github.com/microsoft/terminal) works correctly.\n\nTo build a Windows Installer, you'll need first Scryer Prolog compiled in release mode, then, with WiX Toolset installed, execute:\n```\ncandle.exe scryer-prolog.wxs\nlight.exe scryer-prolog.wixobj\n```\nIt will generate a very basic MSI file which installs the main executable and a shortcut in the Start Menu. It can be installed with a double-click. To uninstall, go to the Control Panel and uninstall as usual.\n\n### Building WebAssembly\n\nScryer Prolog has basic WebAssembly support. You can follow `wasm-pack`'s [official instructions](https://rustwasm.github.io/docs/wasm-pack/quickstart.html) to install `wasm-pack` and build it in any way you like.\n\nHowever, none of the [default features](https://doc.rust-lang.org/cargo/reference/features.html#the-default-feature) are currently supported. The preferred way of disabling them is passing [extra options](https://rustwasm.github.io/wasm-pack/book/commands/build.html#extra-options) to `wasm-pack`.\n\nFor example, if you want a minimal working package without using any bundler like `webpack`, you can do this:\n```\nwasm-pack build --target web -- --no-default-features\n```\nThen a `pkg` directory will be created, containing everything you need for a webapp. You can test whether the package is successfully built by creating an html file, adapted from `wasm-bindgen`'s [official example](https://rustwasm.github.io/wasm-bindgen/examples/without-a-bundler.html) like this:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\" /\u003e\n    \u003ctitle\u003eScryer Prolog - Sudoku Solver Example\u003c/title\u003e\n    \u003cscript type=\"module\"\u003e\n        import initScryer, { MachineBuilder } from \"./pkg/scryer_prolog.js\";\n\n        // Initialize Scryer Prolog with WASM\n        const wasm = await fetch(\"./pkg/scryer_prolog_bg.wasm\");\n        const module = await WebAssembly.compile(await wasm.arrayBuffer());\n        await initScryer(module);\n\n        // Set up the Prolog machine\n        const machine = new MachineBuilder().build();\n\n        // Knowledge base: Sudoku rules and problem definition\n        const kb = `\n        :- use_module(library(format)).\n        :- use_module(library(clpz)).\n        :- use_module(library(lists)).\n\n        sudoku(Rows) :-\n          length(Rows, 9), maplist(same_length(Rows), Rows),\n          append(Rows, Vs), Vs ins 1..9,\n          maplist(all_distinct, Rows),\n          transpose(Rows, Columns),\n          maplist(all_distinct, Columns),\n          Rows = [A,B,C,D,E,F,G,H,I],\n          blocks(A, B, C),\n          blocks(D, E, F),\n          blocks(G, H, I).\n\n        blocks([], [], []).\n        blocks([A,B,C|T1], [D,E,F|T2], [G,H,I|T3]) :-\n          all_distinct([A,B,C,D,E,F,G,H,I]),\n          blocks(T1, T2, T3).\n\n        problem(1, [[_,_,_,_,_,_,_,_,_],\n                    [_,_,_,_,_,3,_,8,5],\n                    [_,_,1,_,2,_,_,_,_],\n                    [_,_,_,5,_,7,_,_,_],\n                    [_,_,4,_,_,_,1,_,_],\n                    [_,9,_,_,_,_,_,_,_],\n                    [5,_,_,_,_,_,_,7,3],\n                    [_,_,2,_,1,_,_,_,_],\n                    [_,_,_,_,4,_,_,_,9]]).\n      `;\n\n        machine.consultModuleString(\"user\", kb);\n\n        // Run the query\n        const query = \"problem(1, Rows), sudoku(Rows), maplist(portray_clause, Rows).\";\n        const answers = machine.runQuery(query);\n\n        const formattedSolutions = [];\n\n        // Format the answers\n        for (const solution of answers) {\n            const rows = solution.bindings[\"Rows\"].list;\n\n            const grid = rows.map(row =\u003e\n                row.list.map(cell =\u003e cell.integer)\n            );\n\n            const formatted = grid.map(row =\u003e `[${row.join(\", \")}]`).join(\"\\n\");\n            formattedSolutions.push(formatted);\n        }\n\n        // Output results\n        const solutionDiv = document.querySelector(\"#soduku-solution\");\n        for (const solution of formattedSolutions) {\n            const newPre = document.createElement(\"pre\");\n            newPre.textContent = solution;\n            solutionDiv.appendChild(newPre);\n        }\n    \u003c/script\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n    \u003cp\u003eSudoku solver returns:\u003c/p\u003e\n    \u003cdiv id=\"soduku-solution\"\u003e\n\n    \u003c/div\u003e\n\u003c/body\u003e\n\n\u003c/html\u003e\n```\n\nThen you can serve it with your favorite http server like `python -m http.server` or `npx serve`, and access the page with your browser.\n\n### Docker Install\n\nPre-built [Docker images are available on Docker Hub](https://hub.docker.com/r/mjt128/scryer-prolog/tags).\nThe `latest` tag reflects the state on `master`, which might be unstable. \nThere are also tags for Scryer releases 0.9.2 and up. \nNote though, that the base images are not kept up to date at the moment, \nso be wary of security vulnerabilities (see [#2646](https://github.com/mthom/scryer-prolog/issues/2646)).\n\nFirst, install [Docker](https://docs.docker.com/get-docker/) on Linux,\nWindows, or Mac.\n\nOnce Docker is installed, you can download and run Scryer Prolog with a single\ncommand:\n```\n$\u003e docker run -it mjt128/scryer-prolog\n```\n\nTo consult your Prolog files, bind mount your programs folder as a\n[Docker volume](https://docs.docker.com/storage/volumes/):\n\n```\n$\u003e docker run -v /home/user/prolog:/mnt -it mjt128/scryer-prolog\n?- consult('/mnt/program.pl').\ntrue.\n```\n\nThis works on Windows too:\n\n```\n$\u003e docker run -v C:\\Users\\user\\Documents\\prolog:/mnt -it mjt128/scryer-prolog\n?- consult('/mnt/program.pl').\ntrue.\n```\n\n## Tutorial\n\nProlog files are loaded by specifying them as arguments on the command\nline. For example, to load `program.pl`, use:\n\n```\n$\u003e scryer-prolog program.pl\n```\n\nLoading a Prolog file is also called “consulting” it. The built-in\npredicate `consult/1` can be used to consult a file from within\nProlog:\n\n```\n?- consult('program.pl').\n```\n\nAs an abbreviation for `consult/1`, you can specify a *list* of\nprogram files, given as *atoms*:\n\n```\n?- ['program.pl'].\n```\n\nThe special notation `[user]` is used to read Prolog\u0026nbsp;text from\nstandard input. For example,\n\n```\n?- [user].\nhello(declarative_world).\nhello(pure_world).\n```\n\nPressing `RETURN` followed by `Ctrl-d` stops reading from\nstandard\u0026nbsp;input and consults the entered Prolog\u0026nbsp;text.\n\nAfter a program is consulted, you can ask *queries* about the\npredicates it defines. For example, with the program shown above:\n\n```\n?- hello(What).\n   What = declarative_world\n;  What = pure_world.\n```\n\nPress `SPACE` to show further answers, if any exist. Press `RETURN`\nor\u0026nbsp;`.` to abort the search and return to the\ntoplevel\u0026nbsp;prompt. Press\u0026nbsp;`f` to see up to the next multiple of\n5 answers, and `a` to see all answers. Press\u0026nbsp;`h` to show a help\nmessage.\n\nUse `TAB` to complete atoms and predicate names in queries. For\ninstance, after consulting the program above, typing `decl` followed\nby\u0026nbsp;`TAB` yields `declarative_world`. Press\u0026nbsp;`TAB` repeatedly\nto cycle through alternative completions.\n\nTo quit Scryer Prolog, use the standard predicate `halt/0`:\n\n```\n?- halt.\n```\n\n### Starting Scryer Prolog\n\nScryer Prolog can be started from the command line by specifying\noptions, files and additional arguments. All components are optional:\n\n\u003cpre\u003e\nscryer-prolog [OPTIONS] [FILES] [-- ARGUMENTS]\n\u003c/pre\u003e\n\nThe supported options are:\n\n```\n   -h, --help             Display help message\n   -v, --version          Print version information and exit\n   -g, --goal GOAL        Run the query GOAL after consulting files\n   -f                     Fast startup. Do not load initialization file (~/.scryerrc)\n   --no-add-history       Prevent adding input to history file (~/.scryer_history)\n```\n\nAll specified Prolog files are consulted.\n\nAfter Prolog files, application-specific arguments can be specified on\nthe command line. These arguments can be accessed from within Prolog\napplications with the predicate\u0026nbsp;`argv/1`, which yields the list\nof arguments represented as strings.\n\nProlog files can also be turned into *shell\u0026nbsp;scripts* as explained in\nhttps://github.com/mthom/scryer-prolog/issues/2170#issuecomment-1821713993.\n\n### Dynamic operators\n\nScryer supports dynamic operators. Using the built-in\narithmetic operators with the usual precedences,\n\n```\n?- write_canonical(-5 + 3 - (2 * 4) // 8), nl.\n-(+(-5,3),//(*(2,4),8))\n   true.\n```\n\nNew operators can be defined using the `op` declaration.\n\n### First instantiated argument indexing\n\nScryer Prolog indexes on the leftmost argument that is not a variable\nin all clauses of a predicate's\u0026nbsp;definition. We call this strategy\nfirst *instantiated* argument indexing.\n\nA key motivation for first instantiated argument indexing is to enable\nindexing for meta-predicates such as `maplist/N` and `foldl/N`, whose\nfirst argument is a partial goal that is a variable in the definition\nof these predicates and therefore cannot be used for indexing.\n\nFor example, a natural definition of `maplist/2` reads:\n\n```\nmaplist(_, []).\nmaplist(Goal_1, [L|Ls]) :-\n        call(Goal_1, L),\n        maplist(Goal_1, Ls).\n```\n\nIn this case, first instantiated argument indexing automatically uses\nthe *second* argument for indexing, and thus prevents choicepoints for\ncalls with lists of fixed lengths (and deterministic goals).\nConveniently, no auxiliary predicates with reordered arguments are\nneeded to benefit from indexing in such cases.\n\nConventional first argument\u0026nbsp;indexing naturally arises as a\nspecial case of this strategy, if the first argument is instantiated\nin any clause of a predicate's definition.\n\n### Strings and partial strings\n\nA very compact internal representation of *strings* is one of the key\ninnovations of Scryer Prolog. This means that terms which appear as\nlists of characters to Prolog programs are stored in packed\nUTF-8\u0026nbsp;encoding by the engine.\n\nWithout this innovation, storing a list of characters in memory would\nuse one WAM memory\u0026nbsp;cell per character, one cell per list\nconstructor, and one cell for each tail that occurs in the list. Since\none cell takes 8\u0026nbsp;bytes in the WAM as implemented by\nScryer\u0026nbsp;Prolog, the packed representation yields an up\u0026nbsp;to\n**24-fold\u0026nbsp;reduction** of memory usage, and corresponding\nreduction of memory\u0026nbsp;accesses when creating and processing\nstrings.\n\nScryer Prolog's compact internal string representation makes it\nideally suited for the use case Prolog was originally developed for:\nefficient and convenient text processing, especially with definite\nclause grammars (DCGs) as provided by\n[`library(dcgs)`](src/lib/dcgs.pl) and\n[`library(pio)`](src/lib/pio.pl) to transparently apply DCGs to files.\n\nIn Scryer Prolog, the default value of the Prolog flag `double_quotes`\nis `chars`, which is also the recommended setting. This means that\nlists of characters can be written as double-quoted strings, in the\ntradition of Marseille\u0026nbsp;Prolog.\n\nFor example, the following query succeeds:\n\n```\n?- \"abc\" = [a,b,c].\n   true.\n```\n\nThis shows that the string `\"abc\"`, which is represented as a sequence\nof 3\u0026nbsp;bytes internally, appears to Prolog programs as a list of\ncharacters.\n\nScryer Prolog uses the same efficient encoding for *partial* strings,\nwhich appear to Prolog code as partial lists of characters. The\npredicate `partial_string/3` from `library(iso_ext)` lets you\nconstruct partial\u0026nbsp;strings explicitly. For example:\n\n```\n?- partial_string(\"abc\", Ls0, Ls).\n   Ls0 = [a,b,c|Ls].\n```\n\nIn this case, and as the answer illustrates, `Ls0` is\nindistinguishable from a partial\u0026nbsp;list with tail\u0026nbsp;`Ls`, while\nthe efficient packed representation is used internally.\n\nAn important design goal of Scryer Prolog is to *automatically* use\nthe efficient string representation whenever possible. Therefore, it\nis only very rarely necessary to use `partial_string/3` explicitly. In\nthe above example, posting \u003ctt\u003eLs0\u0026nbsp;=\u0026nbsp;[a,b,c|Ls]\u003c/tt\u003e yields\nthe exact same internal representation, and has the advantage that\nonly the standard predicate\u0026nbsp;`(=)/2` is used.\n\nThe efficient internal representation of strings and partial strings\nwas first proposed and explained by Ulrich Neumerkel in\nissues\u0026nbsp;[#24](https://github.com/mthom/scryer-prolog/issues/24)\nand\u0026nbsp;[#95](https://github.com/mthom/scryer-prolog/issues/95), and\nScryer\u0026nbsp;Prolog is the first Prolog\u0026nbsp;system that implements it.\n\n### Occurs check and cyclic terms\n\nThe *occurs\u0026nbsp;check* is an element of algorithms that perform\nsyntactic unification, causing the unification to fail if a variable\nis unified with a term that contains that variable as a proper\nsubterm. For efficiency, the *occurs\u0026nbsp;check* is omitted by default\nin Scryer\u0026nbsp;Prolog and many other Prolog systems.\n\nIn Scryer Prolog, unifications which succeed only if the\n*occurs\u0026nbsp;check* is omitted yield *cyclic\u0026nbsp;terms*, also called\n*rational\u0026nbsp;trees*. For example:\n\n```\n?- X = f(X), Y = g(X,Y).\n   X = f(X), Y = g(f(X),Y).\n```\n\nThe creation of cyclic terms often indicates a programming mistake in\nthe formulation of Prolog predicates, and to obtain logically sound\nresults it is desirable to either perform all unifications with\n*occurs\u0026nbsp;check* enabled, or let Prolog throw an error if enabling\nthe *occurs\u0026nbsp;check* is necessary to prevent a unification.\n\nScryer Prolog supports this via the Prolog flag `occurs_check`. It can\nbe set to one of the following values to obtain the desired behaviour:\n\n- `false`\n  Do not perform the *occurs\u0026nbsp;check*. This is the default.\n- `true`\n  Perform all unifications with the *occurs\u0026nbsp;check* enabled.\n- `error`\n  Yield an error if a unification is performed that the\n  *occurs\u0026nbsp;check* would have prevented.\n\nEspecially when starting with Prolog, we recommend to add the\nfollowing directive to the `~/.scryerrc` configuration file so that\nprogramming mistakes in predicates that lead to the creation of cyclic\nterms are indicated by errors:\n\n```\n:- set_prolog_flag(occurs_check, error).\n```\n\nScryer Prolog implements specialized reasoning to make unifications\nfast in many frequently occurring situations also if the\n*occurs\u0026nbsp;check* is enabled.\n\n### Tabling (SLG resolution)\n\nOne of the foremost attractions of Prolog is that logical consequences\nof pure\u0026nbsp;programs can be derived by various execution strategies\nthat differ regarding essential properties such as termination,\ncompleteness and efficiency.\n\nThe default execution strategy of Prolog is depth-first search with\nchronological backtracking. This strategy is very efficient. Its main\ndrawback is that it is *incomplete*: It may fail to find any solution\neven if one exists.\n\nScryer Prolog supports an alternative execution strategy which is\ncalled *tabling* and also known as tabled\u0026nbsp;execution and\nSLG\u0026nbsp;resolution. To enable tabled execution for a predicate, use\n[`library(tabling)`](src/lib/tabling.pl) and add a `(table)/1`\ndirective for the desired predicate indicator. For example, if we\nwrite:\n\n```\n:- use_module(library(tabling)).\n:- table a/0.\n\na :- a.\n```\n\nThen the query `?- a.` *terminates* (and fails), whereas it\ndoes\u0026nbsp;not terminate with the default execution strategy.\n\nScryer Prolog implements tabling via *delimited continuations* as\ndescribed in [*Tabling as a Library with Delimited\nControl*](https://biblio.ugent.be/publication/6880648/file/6885145.pdf)\nby Desouter\u0026nbsp;et.\u0026nbsp;al.\n\n### Constraint Logic Programming (CLP)\n\nScryer Prolog provides excellent support for Constraint Logic\nProgramming\u0026nbsp;(CLP), which is the amalgamation of\nLogic\u0026nbsp;Programming\u0026nbsp;(LP) and Constraints.\n\nIn addition to built-in support for [`dif/2`](src/lib/dif.pl),\n[`freeze/2`](src/lib/freeze.pl),\n[CLP(B)](src/lib/clpb.pl) and [CLP(ℤ)](src/lib/clpz.pl),\nScryer provides a convenient way to implement new user-defined\nconstraints: *Attributed variables* are available via\n[`library(atts)`](src/lib/atts.pl) as in SICStus\u0026nbsp;Prolog,\nwhich is one of the most sophisticated and fastest constraint systems\nin existence. In [`library(iso_ext)`](src/lib/iso_ext.pl),\nScryer provides predicates for backtrackable (`bb_b_put/2`) and\nnon-backtrackable (`bb_put/2`) global variables, which are needed to\nimplement certain types of constraint\u0026nbsp;solvers.\n\nThese features make Scryer Prolog an ideal platform for teaching,\nlearning and developing portable CLP\u0026nbsp;applications.\n\n### Modules\n\nScryer has a simple predicate-based module system. It provides a\nway to separate units of code into distinct namespaces, for both\npredicates and operators. See the files\n[`src/lib/*.pl`](src/lib) for\nexamples.\n\nAt the time of this writing, many predicates reside in their own\nmodules that need to be imported before they can be used.\nThe modules that ship with Scryer\u0026nbsp;Prolog are also called\n*library*\u0026nbsp;modules or *libraries*, and include:\n\n* [`lists`](src/lib/lists.pl)\n  providing `length/2`, `member/2`, `select/3`, `append/[2,3]`,\n  `foldl/[4,5]`, `maplist/[2-9]`, `same_length/2`, `transpose/2` etc.\n* [`dcgs`](src/lib/dcgs.pl)\n  Definite Clause Grammars (DCGs), a built-in grammar mechanism\n  that uses the operator `(--\u003e)/2` to define grammar rules,\n  and the predicates `phrase/[2,3]` to invoke them.\n* [`dif`](src/lib/dif.pl)\n  The predicate `dif/2` provides declarative disequality:\n  It is true if and only if its arguments are different, and\n  delays the test until a sound decision can be made.\n* [`reif`](src/lib/reif.pl)\n  providing `if_/3`, `tfilter/3` and related predicates\n  as described in *Indexing\u0026nbsp;dif/2*.\n* [`clpz`](src/lib/clpz.pl)\n  CLP(ℤ): Constraint Logic Programming over Integers,\n  providing declarative integer arithmetic via `(#=)/2`, `(#\\=)/2`,\n  `(#\u003e=)/2` etc., and various global constraints and\n  enumeration predicates for solving combinatorial tasks.\n* [`pairs`](src/lib/pairs.pl)\n  By convention, *pairs* are Prolog terms with\n  principal\u0026nbsp;functor `(-)/2`, written as `Key-Value`.\n  This library provides `pairs_keys_values/3`,\n  `pairs_keys/2`, and other predicates to reason about pairs.\n* [`si`](src/lib/si.pl)\n  The predicates `atom_si/1`, `integer_si/1`, `atomic_si/1`\n  and `list_si/1` implement sound type checks. They raise\n  instantiation errors if no decision can be made.\n  They are declarative replacements for logically flawed\n  lower-level type tests. For instance, instead of `integer(X)`,\n  write `integer_si(X)` to ensure soundness of your programs.\n  \"si\" stands for *sufficiently instantiated*, and also for\n  *sound\u0026nbsp;inference*.\n* [`debug`](src/lib/debug.pl)\n  Various predicates that allow for declarative debugging.\n* [`pio`](src/lib/pio.pl)\n  `phrase_from_file/2` applies a DCG nonterminal to the contents of a\n  file, reading lazily only as much as is needed. Due to the compact\n  internal string representation, also extremely large files can be\n  efficiently processed with Scryer\u0026nbsp;Prolog in this way.\n  `phrase_to_file/2` and `phrase_to_stream/2` write lists of\n  characters described by DCGs to files and streams, respectively.\n* [`lambda`](src/lib/lambda.pl)\n  Lambda expressions to simplify higher order programming.\n* [`charsio`](src/lib/charsio.pl) Various predicates that are useful\n  for parsing and reasoning about characters, notably `char_type/2` to\n  classify characters according to their type, and conversion\n  predicates for different encodings of strings.\n* [`error`](src/lib/error.pl)\n  `must_be/2` and `can_be/2` complement the type checks provided by\n  [`library(si)`](src/lib/si.pl), and are especially useful for\n  Prolog library authors.\n* [`tabling`](src/lib/tabling.pl)\n  The operator `(table)/1` is used in directives that prepare\n  predicates for tabled execution (SLG\u0026nbsp;resolution).\n* [`format`](src/lib/format.pl)\n  The nonterminal `format_//2` is used to describe formatted output,\n  arranging arguments according to a given format\u0026nbsp;string.\n  The predicates `format/[2,3]`, `portray_clause/[1,2]` and `listing/1`\n  provide formatted *impure* output.\n* [`assoc`](src/lib/assoc.pl)\n  providing `empty_assoc/1`, `get_assoc/3`, `put_assoc/4` etc.\n  to manage elements in AVL\u0026nbsp;trees which ensure\n  *O*(log(*N*))\u0026nbsp;access.\n* [`ordsets`](src/lib/ordsets.pl)\n  represents ordered sets as lists.\n* [`clpb`](src/lib/clpb.pl)\n  CLP(B): Constraint Logic Programming over Boolean variables,\n  a BDD-based SAT\u0026nbsp;solver provided via the predicates\n  `sat/1`, `taut/2`, `labeling/1` etc.\n* [`arithmetic`](src/lib/arithmetic.pl)\n  Arithmetic predicates such as `lsb/2`, `msb/2` and\n  `number_to_rational/2`.\n* [`time`](src/lib/time.pl) Predicates for reasoning about\n  time, including `time/1` to measure the CPU\u0026nbsp;time of a goal,\n  `current_time/1` to obtain the current system time, the nonterminal\n  `format_time//2` to describe strings with dates and times, and\n  `sleep/1` to slow down a computation.\n* [`files`](src/lib/files.pl)\n  Predicates for reasoning about files and directories, such as\n  `directory_files/2`, `file_exists/1` and `file_size/2`.\n* [`cont`](src/lib/cont.pl)\n  Provides *delimited continuations* via `reset/3` and `shift/1`.\n* [`random`](src/lib/random.pl)\n  Probabilistic predicates and random number generators.\n* [`http/http_open`](src/lib/http/http_open.pl) Open a stream to\n  read answers from web\u0026nbsp;servers. HTTPS is also supported.\n* [`http/http_server`](src/lib/http/http_server.pl) Runs a HTTP/1.1 and HTTP/2.0 web server. Uses [Warp](https://github.com/seanmonstar/warp) as a backend. Supports some query and form handling.\n* [`sgml`](src/lib/sgml.pl)\n  `load_html/3` and `load_xml/3` represent HTML and XML\u0026nbsp;documents\n  as Prolog\u0026nbsp;terms for convenient and efficient reasoning. Use\n  [`library(xpath)`](src/lib/iso_ext.pl) to extract information from\n  parsed documents.\n* [`csv`](src/lib/csv.pl)\n  `parse_csv//1` and `parse_csv//2` can be used with [`phrase_from_file/2`](src/lib/pio.pl)\n  or [`phrase/2`](src/lib/dcgs.pl) to parse csv\n* [`serialization/abnf`](src/lib/serialization/abnf.pl)\n  DCGs describing the\n  [ABNF grammar core (RFC 5234)](https://tools.ietf.org/html/rfc5234#appendix-B.1),\n  which is used to describe many [IETF](https://www.ietf.org/standards/rfcs/)\n  syntaxes, such as [HTTP v1.1](https://www.rfc-editor.org/rfc/rfc7230.html#page-82),\n  [SMTP](https://www.rfc-editor.org/rfc/rfc5321.html),\n  [iCalendar](https://www.rfc-editor.org/rfc/rfc5545.html), and more.\n* [`serialization/json`](src/lib/serialization/json.pl)\n  `json_chars//1` can be used with [`phrase_from_file/2`](src/lib/pio.pl)\n  or [`phrase/2`](src/lib/dcgs.pl) to parse and generate\n  [JSON](https://www.json.org/json-en.html).\n* [`xpath`](src/lib/xpath.pl)\n  The predicate `xpath/3` is used for convenient reasoning about HTML\n  and XML\u0026nbsp;documents, inspired by the XPath language. This library\n  is often used together with [`library(sgml)`](src/lib/sgml.pl).\n* [`sockets`](src/lib/sockets.pl)\n  Predicates for opening and accepting TCP connections as streams.\n* [`os`](src/lib/os.pl)\n  Predicates for reasoning about environment\u0026nbsp;variables.\n* [`iso_ext`](src/lib/iso_ext.pl)\n  Conforming extensions to and candidates for inclusion in the Prolog\n  ISO\u0026nbsp;standard, such as `setup_call_cleanup/3`, `call_nth/2` and\n  `call_with_inference_limit/3`.\n* [`crypto`](src/lib/crypto.pl)\n  Cryptographically secure random numbers and hashes, HMAC-based key\n  derivation\u0026nbsp;(HKDF), password-based key derivation\u0026nbsp;(PBKDF2),\n  public key signatures and signature verification with\u0026nbsp;Ed25519,\n  ECDH key\u0026nbsp;exchange over Curve25519 (X25519), authenticated symmetric\n  encryption with ChaCha20-Poly1305, and reasoning about elliptic curves.\n* [`process`](src/lib/process.pl)\n  Create and manage parallel processes.\n* [`uuid`](src/lib/uuid.pl) UUIDv4 generation and hex representation\n* [`tls`](src/lib/tls.pl)\n  Predicates for negotiating TLS connections explicitly.\n* [`numerics/special_functions`](src/lib/numerics/special_functions.pl)\n  Predicates for erf, gamma, beta, and related special functions.\n* [`ugraphs`](src/lib/ugraphs.pl) Graph manipulation library\n* [`simplex`](src/lib/simplex.pl) Providing `assignment/2`,\n  `transportation/4` and other predicates for solving linear\n  programming problems.\n\nTo use predicates provided by the `lists` library, write:\n\n```\n?- use_module(library(lists)).\n```\n\nTo load modules contained in files, the `library` functor can be\nomitted, prompting Scryer to search for the file (specified as an\natom) from its working directory:\n\n```\n?- use_module('file.pl').\n```\n\n`use_module` directives can be qualified by adding a list of imports:\n\n```\n?- use_module(library(lists), [member/2]).\n```\n\nA qualified `use_module` can be used to remove imports from the\ntoplevel by calling it with an empty import list.\n\nThe `(:)/2` operator resolves calls to predicates that might not be\nimported to the current working namespace:\n\n```\n?- lists:member(X, Xs).\n```\n\nThe [user] prompt can also be used to define modules inline at the\nREPL:\n\n```\n?- [user].\n:- module(test, [local_member/2]).\n:- use_module(library(lists)).\n\nlocal_member(X, Xs) :- member(X, Xs).\n```\n\nThe user listing can also be terminated by placing `end_of_file.` at\nthe end of the stream.\n\n### Configuration file\n\nAt startup, Scryer Prolog consults the file `~/.scryerrc`, if the file\nexists. This file is useful to automatically load libraries and define\npredicates that you need often.\n\nFor example, a sensible starting point for `~/.scryerrc` is:\n\n```\n:- use_module(library(lists)).\n:- use_module(library(dcgs)).\n:- use_module(library(reif)).\n```\n\n### Development environment\n\nTo write and edit Prolog programs, we recommend\n[GNU\u0026nbsp;Emacs](https://www.gnu.org/software/emacs/) with the\n[Prolog\u0026nbsp;mode](https://bruda.ca/emacs/prolog_mode_for_emacs)\nmaintained by Stefan Bruda.\n\nUse [ediprolog](https://www.metalevel.at/ediprolog/) to consult\nProlog\u0026nbsp;code and evaluate Prolog queries in arbitrary\nEmacs\u0026nbsp;buffers.\n\nEmacs definitions that show Prolog terms as trees are available\nin\u0026nbsp;[tools](tools).\n\nTo *debug* Prolog code, we recommend the predicates from\n[**`library(debug)`**](src/lib/debug.pl), most notably:\n\n- `(*)/1` to *\"generalize\u0026nbsp;away\"* a Prolog goal. Use it to debug\n  unexpected failures by generalizing your definitions until they\n  succeed. Simply place\u0026nbsp;`*` in front of a goal to generalize it away.\n- `($)/1` to emit a *trace* of the execution, showing when a goal\n  is invoked, and when it has succeeded. Place\u0026nbsp;`$` in front of a goal\n  to emit this information for that goal.\n\nThis way of debugging Prolog code has several major benefits, such as:\nIt stays close to the actual Prolog code under consideration, it does\nnot need additional tools and formalisms for its application, and\nfurther, it encourages declarative reasoning that can in principle\nalso be performed automatically.\n\n## Applications\n\nScryer Prolog's strong commitment to the Prolog ISO standard makes it\nideally suited for use in corporations and government\u0026nbsp;agencies\nthat are subject to strict regulations pertaining to interoperability,\nstandards\u0026nbsp;compliance and warranty.\n\nSuccessful existing applications of Scryer Prolog include:\n\n- [DocLog](https://github.com/aarroyoc/doclog) which generates\n  Scryer's own documentation and homepage\n- [Grants4Companies](https://arxiv.org/abs/2406.15293): reasoning\n  about business\u0026nbsp;grants in the Austrian public\u0026nbsp;administration\n- parts of the [precautionary](https://github.com/dcnorris/precautionary/tree/main/exec/prolog)\n  package for the analysis of dose-escalation trials in the\n  safety-critical and highly regulated domain of oncology\n  trial\u0026nbsp;design, described in [*An Executable Specification of\n  Oncology Dose-Escalation Protocols with\u0026nbsp;Prolog*](https://arxiv.org/abs/2402.08334)\n  and culminating in\u0026nbsp;[**DEDUCTION**](https://codeberg.org/dcnorris/DEDUCTION)\n- semantic reasoning and queries in [AD4M](https://github.com/coasys/ad4m),\n  an agent-centric distributed application meta-ontology.\n\nScryer Prolog is also very well suited for teaching and learning\nProlog, and for testing syntactic conformance and hence portability of\nexisting Prolog\u0026nbsp;programs.\n\n## Scryer Prolog Meetups\n\nScryer Prolog Meetups are an excellent opportunity to present and get\nto know the latest developments in Scryer\u0026nbsp;Prolog and its\napplications, to exchange ideas about current\u0026nbsp;plans and\nfuture\u0026nbsp;directions, and to discuss projects and visions\nin\u0026nbsp;person.\n\n- [Scryer Prolog Meetup 2023](https://hsd-pbsa.de/veranstaltung/scryer-prolog-meetup-2023/)\n  in Düsseldorf, Germany. Its [announcement](https://github.com/mthom/scryer-prolog/discussions/1813)\n  and [discussion](https://github.com/mthom/scryer-prolog/discussions/2160).\n- [Scryer Prolog Meetup 2024](https://www.digitalaustria.gv.at/wissenswertes/events/scryerprologmeetup2024)\n  in Vienna, Austria. Its [announcement and discussion](https://github.com/mthom/scryer-prolog/discussions/2377).\n- [Scryer Prolog Meetup 2025](https://hsd-pbsa.de/veranstaltung/scryer-prolog-meetup-2025/)\n  in Düsseldorf, Germany. Its [announcement and discussion](https://github.com/mthom/scryer-prolog/discussions/2948).\n- **Save the date:** The Scryer Prolog Meetup 2026\n  will take place on Oct.\u0026nbsp;24th and 25th\u0026nbsp;2026 in Vienna, Austria.\n  More information to follow.\n\n## Support and discussions\n\nIf Scryer Prolog crashes or yields unexpected errors, consider filing\nan\u0026nbsp;[issue](https://github.com/mthom/scryer-prolog/issues).\n\nTo get in touch with the Scryer Prolog community, participate in\n[discussions](https://github.com/mthom/scryer-prolog/discussions)\nor visit our #scryer IRC channel on [Libera](https://libera.chat)!\n","funding_links":[],"categories":["Programming Language","Development tools","Rust","Logic Programming","Interpreters"],"sub_categories":["Libraries","FFI"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmthom%2Fscryer-prolog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmthom%2Fscryer-prolog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmthom%2Fscryer-prolog/lists"}