# Ann: SWI-Prolog 9.3.21

**URL:** <https://swi-prolog.discourse.group/t/ann-swi-prolog-9-3-21/8879>\
**Category:** Releases\
**Created:** [March 12, 2025, 11:16am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-3-21/8879 "2025-03-12T11:16:08Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [March 12, 2025, 11:16am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-3-21/8879/1 "2025-03-12T11:16:08Z")

</div>

Dear SWI-Prolog user,

SWI-Prolog 9.3.21 is ready for download. There are a large number of  
changes, mostly involving the WASM (Web Assembly) version.

## Debugger

The internals of the debugger have been changed considerably, allowing  
the VM to _yield_ (return with the ability to resume) on trace events.  
Yield based and hook based (using `prolog_trace_interception/4`) reuse  
the same code to communicate how execution must be continued after  
prompting the user. The set of supported trace continuations has been  
extended to simplify writing your own debugger.

The debugger rules to decide with ports to hide (or show) was modified  
a little, notably tracing calls to built-in predicates called through  
`catch/3`, `findall/3`, etc. Exception ports are now always visible,  
trapping the debugger immediately on most exceptions. This notably  
makes `trap/1` more effective. `trap/1` has been updated to avoid  
trapping system calls immediately wrapped in catch/3. This implies  
that calls like this do not trap the debugger.

```
catch(number_codes(Num, Codes), error(_,_), fail).

```

## WASM version

Much improved support for dealing with SWI-Prolog engines. Support  
for yield based debugging (required to run SWI-Tinker)

## SWI-Tinker

Based on this, SWI-Tinker (the former SWI-Prolog WASM shell) now has  
a (simple) debugger. Its internals are completely rewritten. The  
JavaScript module `tinker.js` no exports five classes that provide  
building blocks for building web pages that provide embedded of  
interactive Prolog queries. SWI-Tinker can now exploit engines to  
manage multiple open queries. This is definitely not perfect yet.  
Help is welcome.

## Misc

A few minor bug fixes.

- `wrap_predicate/4`, used by tabling and `trace/2` (possible double free).
- SICStus `block/1` emulation calling undefined predicate
- `resource/3` embedding calling undefined predicate.
- PL\_put\_chars() added a reference to created atoms, preventing them  
from being garbage collected.
- `sparql_query/3` option `endpoint(url)` raised an exception
- XPCE paste of Unicode text is fixed (X11 version)

Some regression, notably in the debugger, is not unlikely. Please report.

```
Enjoy --- Jan

```

# SWI-Prolog Changelog since version 9.3.20

- WASM: Fixed abort handling.

- WASM: Fixed yieldable using Prolog.call() running in engine.

- ENHANCED: trap/1: stop trapping direct catch. Do not trap the debugger  
for `catch(SytemPred, _, _)`. Such calls are very unlikely interesting  
to the debugger.

- ENHANCED: logic to trace a call to a system predicate Consider system  
with a stack user ← meta ← system as a debug frame. For example,  
trace char\_code/2 in the code below.

- FIXED: finish command of GUI debugger. This fix adds skip(Frame)  
to the possible replies from prolog\_trace\_interception/4 and deletes  
prolog\_skip\_frame/1.

- FIXED: prompt1/1 called in mode (-) must fail if there is no “first”  
prompt.

- ADDED: Prolog.call(): allow passing the goal using Prolog.Compound()

- FIXED: Prolog.Compound() constructor

- ADDED: wasm\_query/1, support running a single query interactively.

- BUILD: Avoid CMake generating paths with double “/”

- BUILD: Updated cmake\_minimum\_required to 3.10 as adviced in CMake 3.31

- FIXED: Handling skip in the gui tracer. Incorrectly detected that  
an exit was from a skipped frame. We could also consider to move  
this into the exit port, e.g., present the port as exit(skip).

- CLEANUP: Remove restoring REDO port from tracePort() This is dealt  
with in the VM backtracing code and (thus) never reached.

- WASM: Fixed Prolog.consult() in strict mode

- FIXED: #1352 open\_resource/2: Unknown procedure: ‘$rc’:zip\_close/2

- ADDED: ansi\_hyperlink/3: better handling of URLs

- WASM: Rename shell to “tinker”. Tool will be named “SWI-Tinker”

- WASM: More URL handling.

- FIXED: PL\_put\_chars(): unregister atom when using `PL_ATOM`.

- WASM: Support single character input from the user (get\_code/1, etc.)

- ADDED: prompt1/1 can retrieve current prompt using a variable.

- BUILD: #1350 Auto-include utf8proc if documentation is requested.

- WASM: Support include/1 from files loaded using a URL

- FIXED: Sandbox: declare distinct/1,2 as safe (uses tries).

- WASM: Allow reusing a query in the shell.

- WASM: Added options to Prolog.consult() This allows for  
`Prolog.consult(file1, file2, ..., {module:"project"})`

- WASM: Give proper warning on `?- [user].`

- WASM: Added decoding of ansi hyperlink sequence

- WASM: Handle read/1 and friends in shell

- MODIFIED: (Undocumented) PL\_prompt\_string() now returns UTF-8

- WASM: Added tty\_size/2 and get\_single\_char/1 to shell

- WASM: Added upload and download buttons for WASM shell.

- WASM: Simple debugger for the browser shell.

- WASM: Added decoding of ANSI escape sequences

- WASM: Prolog.call() provides `nodebug` option. Also add Prolog.Term()  
class that allows for creating terms from term handles or strings.

- WASM: Split shell demo into multiple files.

- WASM: Reorganised directory

- WASM: Fixed dealing with heartbeat events.

- DEBUG: Use swipl-web.js rather than swipl-bundle.js for debugging

- WASM: Minimally working Prolog tracer in the browser

- WASM: Fixed standard I/O flushing. Notably writing to `user_error`  
was flushed on a newline.

- WASM: Fixed Prolog.write()

- ENHANCED: Error message when using WASM await/2 in synchronous query.

- FIXED: We must discard foreign environments While unwinding an  
exception, before we discard a frame, which may call the foreign  
cleanup handler, we must discard newer foreign environments.

- FIXED: Extended query solutions from `int` to `int64_t` Otherwise,  
PL\_new\_solution() is limited to 2G solutions.

- FIXED: PL\_yield\_address(): preserve foreign environment

- FIXED: State handling using PL\_yield\_address().

- FIXED: library(block) (SICStus emulation) warns about append/3.  
Reported by Peter Ludemann.

- FIXED: wrap\_predicate/4: possible double free after unwrapping The  
copy of the predicate held in the closure should not copy the lingering  
list and we must avoid lingering the wrapped supervisor as it becomes  
owned by the closure.

- ADDED: Yield based debugger support This patch introduces a large  
number of changes to the VM as well as the debugger code. It allows  
interacting with the Prolog debugger using _yield_, i.e., instead of  
calling a hook when a Prolog port is passed it makes PL\_next\_solution()  
return. The environment can examine the state, make calls on this  
Prolog engine and finally set how the session must be continued and  
resume PL\_next\_solution().

- ADDED: print\_prolog\_backtrace/3: show\_files(+How) option

- CLEANUP: Delete VMI profiling code. As we have VMI functions and  
much better profiling tools this merely complicates the sources.

- MODIFIED: abort/0: disable debug mode.

## Package semweb

- FIXED: sparql\_query/3 using option endpoint(URL) This raised an  
exception in select\_option/3 due to an insufficiently instantiated  
argument.

## Package xpce

- TRACER: Fixed “finish” to use new skip(Frame) reply.

- FIXED: X11 version: paste Unicode text

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [March 12, 2025, 5:45pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-3-21/8879/2 "2025-03-12T17:45:38Z")

</div>

Thanks for continuos work on updating SWI-Prolog, Jan.

When activating swipl from Emacs Ediprolog, since some point of time I had to insert a line  
`open -a XQuartz` like below. Otherwise `spy` command does not work  
in Ediprolog mode. I have checked git source swipl whether new swipl version still requires that line with hope not being necessary now, but found it is not the case.

```prolog
#! /bin/sh
SWIPL=${HOME}/bin/swipl
PACLIB=${HOME}/devel/zdd/prolog
PAC=${PACLIB}/pac.pl
ZDD=${PACLIB}/zdd/zdd.pl
open -a XQuartz
${SWIPL} -l $PAC -l $ZDD

```

Is there a way to omit the `open -a XQuartz` but `spy` command can be used ? I am afraid that the answer is NO knowing little about XQuartz.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [March 13, 2025, 7:35am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-3-21/8879/3 "2025-03-13T07:35:22Z")

</div>

> [@kuniaki.mukai](#):
>
> When activating swipl from Emacs Ediprolog, since some point of time I had to insert a line  
> `open -a XQuartz` like below. Otherwise `spy` command does not work

I don’t know why spy/1 needs graphics unless it is redefined by ediprolog. Anyway, if it needs graphics it needs `XQuartz` on MacOS. I guess your `open -a` resolves that or you can add `XQuartz` to the autostart applications. On my machine it starts automatically while I have not touched the `XQuartz` configuration.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [March 13, 2025, 9:12am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-9-3-21/8879/4 "2025-03-13T09:12:53Z")

</div>

> [@jan](#):
>
> I guess your `open -a` resolves that or you can add `XQuartz` to the autostart applications.

I have removed the line “open -a XQurtz”, and added `XQuartz ` application to Login items so that it starts automatically. And `spy` works. Thanks.

However, if remember correctly, I did the same fix, but it did not work at that time.  
And this time, as I happened to find that XQuratz was allowed as background in Privacy& Security setting. Also I remember that I changed XQuartz to a downloaded version from the one via Homebrew due to some reason which I don’t remember. Finally once I checked that the spy problem is not related to Ediprolog. Although I am curious of reason of the spy trouble, now it should be enough for me that auto-starting XQuartz seems to fix the trouble, Thanks again.

**EDIT**  
I asked chatGPT ways of passing environmental variables (PATH for example) to Emacs (as GUI). It suggested four ways, only one of which I know. Although I am not sure whether they are related to the spy trouble, as three of them are new to me, I am curious on trying thems. BTW, it was surprise to see how widely and much chatGPT knows.
