Skip to content

SWI-Prolog/tinker

Repository files navigation

SWI-Tinker: SWI-Prolog in your browser

Public demo at https://wasm.swi-prolog.org/wasm/tinker

This repository implements SWI-Tinker, a SWI-Prolog playground running in your browser based on SWI-Prolog compiled using Emscripten to WASM.

The current system is primarily a proof-of-concept. You are encouraged to help improving it. The TODO file in this repo gives a list of possible improvements.

Achieved functionality

  • Run SWI-Prolog in your browser
  • Basic REPL loop window
  • Basic editor support based on CodeMirror
  • Saves command history and programs to your browser local store. Use ?- tinker_reset. to clear this and start with a clean slate.
  • Allows uploading and downloading programs
  • Allows for loading (compiling) these programs as well a loading programs directly from the internet.
  • Load large programs quickly as .qlf files.
  • Support for a basic debugger using the common ?- trace, mygoal. command. Support for spy- and break-points.
  • Demonstrates async support using Prolog engines.
  • Preload programs from the page URL (see below), which allows for linking to a ready-to-run program.
  • Edit and reload programs that are loaded from a URL, including programs that load their dependencies from the same site.

Loading programs from the page URL

Adding a query string to the Tinker URL loads one or more programs into the editor and consults them. The accepted forms are

  • ?<url>
    The entire query string is a URL. It is not split at &, so the URL may have a query string of its own. For example

    https://wasm.swi-prolog.org/wasm/tinker?https://example.org/hello.pl
    
  • ?url=<url>
    URL to load. May be repeated to load several programs.

  • ?code=<text>
    Prolog text to load. May be repeated. The text is loaded into a file named code.pl.

  • ?name=<file>
    Name for the file created by the preceding code=.

  • ?optimise=true or ?optimise=false
    Compile in optimised mode. Default is true. Optimised compilation is faster, but removes assertion/1 and debug/3 calls from your program. The optimise checkbox next to the (Re)consult button shows and changes this setting. Note that it only affects programs that are loaded after it is changed.

The 🔗 button below the editor copies a link to the program you are editing. If this program was loaded from a URL and you have not changed it we copy a ?url= link. This keeps the link short and, as the program is loaded from its URL, files loaded by this program are found as well. Otherwise we copy a ?code= link that carries the text from the editor as well as the name of the file, which allows for sharing a small program without putting it on a server. Note that URLs carry a limited amount of text.

Both relative and absolute URLs are accepted. Values of url= and code= must be encoded using JavaScript's encodeURIComponent(). Note that this does not encode +, which we therefore do not interpret as a space. Files are added as normal user files, overwriting a file with the same name if that exists. Loading from another site requires the server to allow this using the header Access-Control-Allow-Origin. Sites such as GitHub (using the raw content URL) do so. A .qlf file is consulted from its URL and, as it is not source, not shown in the editor.

Note that loading a program also runs its directives and thus an untrusted link can run arbitrary Prolog code in your browser.

Editing programs that came from a URL

A file that was loaded from a URL remembers where it came from. The file menu shows this URL as a tooltip. Such a file is consulted using its URL, e.g.

?- consult('https://example.org/dir/run.pl').

As a result, :- include(...), :- ensure_loaded(...) and library aliases inside the file are resolved against https://example.org/dir/, while the text that is compiled is the text you see in the editor. In other words, you can edit a program that was loaded from the web and reload it, including programs that load their dependencies from the same site.

Clicking an error location, edit/1 and the debugger download and add a local copy of files that were loaded indirectly, so you can fix and reload those too. Your changes are not written back to the server.

The local copies are stored in a directory structure that reflects the URL, e.g., https://example.org/dir/run.pl is stored in the browser's file system as /prolog/web/example.org/dir/run.pl. This way, a program and the files it loads keep their relation and programs from different sites cannot collide.

Programs that read data files (e.g., using open/3) rather than loading Prolog source do not work: the WASM version cannot open a URL as a stream.

Limitations and alternatives

SWI-Tinker is about two times slower than native SWI-Prolog on the same hardware. SWI-Tinker lacks many libraries bundled with the native version, either for reducing the size or because required primitives are lacking. It also lacks important features of SWI-Prolog such as multi threading and access to a lot of system resources. To get a list of available and not-available libraries, run

?- check_installation.

Some alternatives for running Prolog in your browser are:

  • SWISH provides a server-based alternative, i.e., your queries are executed on a server. The SWISH environment is much more evolved, providing notebooks, file storage including version control, file sharing, etc. SWISH supports a different set of features. Queries on SWISH are executed stateless and are limited by a sandbox.
  • Ciao playground provides a WASM based version of Ciao Prolog.
  • Tau Prolog provides a Prolog version completely written in JavaScript.

Acknowledgements

Raivo Laanemets did most of the ground work getting SWI-Prolog to run using WASM. Jesse Wright provides the npm package swipl-wasm. Torbjörn Lager created the first version of SWISH.

About

SWI-Tinker: a browser playground for SWI-Prolog

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages