Skip to content
Jan Wielemaker edited this page Mar 13, 2025 · 7 revisions

SWI-Tinker: A Prolog playground in your browser

About

SWI-Tinker is SWI-Prolog compiled using Emscripten to WASM. SWI-Prolog for your browser is available as the npm package swipl-wasm. This npm package allows for running Prolog inside the browser. It allows Prolog programs to interact with the browser, e.g., register events, manipulate the DOM, etc. SWI-Tinker uses this to provide an interactive Prolog system running inside the browser. The JavaScript module defines a number of classes that facilitate building other interactive Prolog components, e.g., pages using embedded Prolog source, etc.

Overview

Tinker provides a source view for managing files and a Prolog console for managing queries. Prolog has access to the WASM virtual file system. Prolog itself is installed in /swipl. User files are stored under /prolog, which is also the initial working directory. The initial and default file is called scratch.pl. The user may insert a Prolog program in this file, use the (Re)consult button to load the program and run queries against this program.

Tips and tricks

Dealing with files in SWI-Tinker

The WASM versions contains a virtual file system, i.e., a file system in memory. That contains the Prolog library and a directory /prolog where SWI-Tinker starts. Prolog can compile files from there as well as create files there. By default, these files do not persist. Files can be created and deleted using the menus above the editor. All entries that refer to files in /prolog are saved to your browser local store on page unload and restored when you return to the page.

  • Use the 📥 button (bottom-right) to download the file as it currently appears in the editor.
  • Use the 📤 button (bottom-right) to upload one or more files. First click opens a file input widget. After selecting the files, use 📤 again to upload the files. The uploaded files are places in the /prolog directory and visible in the file dropdown above the editor. That implies they persist!

In the REPL window (left), you can use commands such as ?- ls., ?- pwd. to examine the files and ?- [file]. to load (consult) them.

Loading files directly from the internet

SWI-Tinker can compile files using use_module/1 or one of the other file loading predicates using their URL, e.g.

?- use_module('https://raw.githubusercontent.com/JanWielemaker/chat80/refs/heads/master/prolog/chat80.pl').

After which we can start the program using

?- chat80:hi.

and ask e.g. "What rivers are there?"

Finding your way around

The ?- edit(What). command can be used to try and edit anything the system can find from the name What, e.g., ?- edit(member). to view the sources of the member/2 predicate.

Using ?- explain(Term). the system will print all information related to Term. Known locations are shown as hyperlinks.

Debugging

Using ?- trace, mygoal. you can trace the execution of mygoal. The debugger is still a bit primitive, but usable.

Reading from the user

Currently, SWI-Tinker supports the following predicates to read from the user: read/1, read/2, read_term/2, read_term/3, get_code/1, get_code/2, get/1, get0/1 and get_single_char/1. The versions without a stream argument are handled special when the current_input is user_input and the versions with an explicit stream argument if this argument is user_input.

Controlling the output

The preloaded library tinker.pl provides a couple of utilities to manage output. All normal Prolog output predicates work, e.g., write/1, put_char/1, etc. Color, bold and underline ANSI escape sequences are supported using ansi_format/3. Some Tinker specific utilities are:

  • cls
    Clear the console. This removes all completed queries and non-query relates output (e.g., the banner.

  • pp(@Term)
    Pretty print a term.

  • html(@Spec)
    Wrapper around html//1 to add HTML to the output of the current answer. For example

    ?- html(['What a ', b(nice), ' ', i(world), br([])]).
    

Using multiple open queries

SWI-Tinker demonstrates the capabilities of SWI-Prolog engines that allow for multiple asynchronous Prolog engines to coexist. This is similar to JavaScript async functions. From the Tinker interface you can cause a query to run in a new engine by using Shift-Enter to activate the query.