Ann: SWI-Prolog 9.3.25

Dear SWI-Prolog user,

It has been a while since the last release. That doesn’t mean nothing
happened as you can find in the long ChangeLog below. Highlights:

  • Fixed several reported issues

  • Improved clause indexing performance, in particular for predicates
    with a lot of clauses where some argument has only a few possible
    values. In such cases failure on a value that does not appear in
    any clause could be slow.

  • Many changes in (console) I/O handling, wait and (xpce) event
    dispatching.

  • Added library(editline), the BSD command line editor to the Windows
    version. This provides saved history and Prolog-sensitive completion
    to swipl.exe running in the console.

  • Dropped 32-bit Windows support. Everything has to end at some point.
    It is getting increasingly hard to get all dependencies (Python/Janus
    never existed for 32-bit). The upcoming SDL/Cairo/Pango based xpce
    no longer supports 32-bit systems.

  • Updated the build docker for the Windows version to use Fedora 42 as
    base image.

The last four changes are all related to upgrading xpce and replacing the
GUI versions (Qt and native Windows swipl-exe) by SWI-Prolog+xpce.

Enjoy --- Jan

SWI-Prolog Changelog since version 9.3.24

  • PORT: Discontinue 32-bit windows builds.

  • PORT: Support library(editline) (libedit) on Windows. This provides
    cross-platform commandline editing with Prolog-sensitive completion.

  • ADDED: Windows: tty_size/2 to also work on Windows consoles.

  • WASM: Deal with new PL_prompt_string() API

  • MODIFIED: Signature for PL_promot_string() and PL_prompt_next() These
    API functions now use the Prolog stream as argument to facilitate
    better support for Windows.

  • ADDED: IOSTREAM* control message to get the Windows HANDLE

  • FIXED: wait_for_input/3: use Swinsock() from pl-stream.c rather than
    a local macro This ensures proper error messages if the input is not
    a socket.

  • MODIFIED: PL_dispatch() and friends now use IOSTREAM* instead
    of int. This is a first step to merge simultaneous handling of
    console outout and GUI dispatching for POSIX systems and Windows to
    a common design.

  • WINE: Waiting for windows console input now works for wine.

  • PORT: Make installing INDEX.pl files work on Windows. Concurrency
    may cause sharing violations. This patch retries renaming the index
    file several times.

  • FIXED: Possible early reclaim of closure blob after unwrapping
    a predicate. PL_unregister_atom() was called twice.

  • ADDED: Incorporate epilog into the toplevel. These patches prepare
    for the XPCE based swipl-win. May be started by using the sdl
    branch of xpce and run as

    swipl -Depilog [arg ...]
    
  • ADDED: ‘$run_state’/1 to query the current run state Can be used to
    detect code is running as part of the cleanup hooks.

  • BUILD: Use SDL_VIDEODRIVER=dummy for running Prolog steps This
    makes sure the new SDL based xpce does not try to open graphics and
    is harmless on other targets.

  • FIXED: Move swipl-win history support to library(win_menu). This
    library is loaded as source and thus conditional compilation applies.
    library(prolog_history) is compiled to .qlf. Now the code is also
    where it belongs.

  • FIXED: When generating _X variable names, avoid query variable names.
    Consider the below example by Jan Burse. Using _A in the answer is
    at least confusing. We must not only skip variable names that appear
    in the projection, but also variable names from the query that are
    not in the projection.

    ?- length(L,2), f(L) = R, S = [_A].
    L = [_A, _B],
    R = f([_A, _B]),
    S = [_A].
    
  • FIXED: Terminal REPL loop using thread_exit(io_error) on an io_error
    during read.

  • FIXED: Termination of a REPL loop due to error state of the streams
    This did not properly close the query, crashing the system in the
    thread cleanup.

  • FIXED: thread_join/2: could leave L_THREAD mutex locked on error.

  • ADDED: Allow thread_signal/2 to raise native signals by number.
    This can be used to raise e.g. SIGINT in a thread to debug it.

  • FIXED: enable_line_editing/3 to avoid conditional compilation.
    This is needed to make library(threadutil) work as .qlf module.

  • FIXED: write/1,2 to take rational number syntax from module user.
    Before, only write_term/2,3 supported “natural” rational number syntax.

  • FIXED: Make the stream macros Suser_input safe when called from a
    non-Prolog thread Called from a non-Prolog thread caused these macros
    to crash. They now return NULL. The main-thread I/O can be obtained
    using Sinput, Soutput or Serror.

  • ADDED: Allow hooking into the terminal link generation.

  • FIXED: Various details for the sys app

  • ADDED: Prolog flag linux

  • FIXED: QLF format to store references to predicates in the current
    module by functor. Otherwise, if a predicate is imported the clause
    will point at the import location, bypassing the predicate resolution
    that happens when loading the source.

  • BUILD: Avoid cmake warnings.

  • ENHANCED: jiti_list/0,1 - Provide collision stats - Order predicates
    alphabetically - Use tty hyperlinks when supported to allow jumping
    to the definition

  • FIXED: ansi_hyperlink/3: Fix position logic Make sure the column admin
    is not updated when writing the escape sequences. This allows mixing
    with format/1-3 tag specifiers.

  • ENHANCED: Make sure that small clause index tables have no collisions.

  • ENHANCED: Use Fibonacci hashing for clause indexes.

  • ENHANCED: Index performance on common arguments. Given a predicate
    with many clauses that has one or more arguments with only a few
    possible values and (thus) many clauses in the hash buckets for each
    of these values force fast failure when using a query with a value
    that does not appear in that argument.

    For example, suppose we have a business database that records the legal
    status in one of the columns (arguments). A query with a non-existing
    lega status should fail quickly. In the old system, the small number
    of values could easily lead to a hash colission, causing the system to
    try all clauses with the legal status of the collision.

    This issue was reported by Abramo Bagnara

  • FIXED: #1364 nb_set_to_list/2 could skip elements.

  • FIXED: version/1: avoid redefined warning.

  • FIXED: ansi_get_color/2: avoid errors on swipl-win (Qt)

Package clib

  • COMPAT: Use new PL_dispatch() API.

  • ENHANCED: uri_file_name/2, mode (+,-): Allow for file://host/…
    If host is the same as gethostname/1 reports.

Package cpp

  • PORT: Deal with new PL_prompt_string() and PL_prompt_next() API.

  • COMPAT: Use new PL_dispatch() API.

Package http

  • ENHANCED: Use url(URL) for HTTP startup message.

  • FIXED: http_time_stamp/2 in mode (-,_+).

  • FIXED: json_skip_ws/3: Pass exception.

  • FIXED: http_open/3: when applying a transfer filter, do not close
    the output Instead, create a new stream pair from the transfer filter
    stream and the output stream.

  • SECURITY: Make http handlers read remaining request data for Keep-alive
    When using a Keep-alive connection the core HTTP infrastructure now
    ensures that, if the request has a request body (Content-length)
    exactly this number of bytes is read from the input before returning
    the stream to the Keep-alive mechanism.

    This prevents crafted content to generate additional HTTP requests.

  • FIXED: http_open/3: only catch error(Formal, Context).

  • FIXED: Multipart reader to update stream position data of
    parent stream. This is a tentative fix, lacking a test case.
    It still looses the line count/pos. That could be fixed by calling
    S__fupdatefilepos_getc() on all processed data.

    See
    Multipart_open does not advance the stream's pointer - #3 by matt.lilley

Package libedit

  • PORT: Support Windows

  • COMPAT: Update for new signature for PL_prompt_string() and
    PL_prompt_next()

  • COMPAT: Use new PL_dispatch() API.

  • ENHANCED: el_wrap/4 to raise an error if the stream is already wrapped.

  • FIXED: Avoid memory leak on FILE structs created by fdopen()

  • FIXED: el_history/2: handling of setsize() was undefined.

  • ADDED: Allow using the (integer) fd to specify the editline instance
    This allows accessing the history of other threads.

  • ENHANCED: Sync the positions of the terminal streams.

Package readline

  • PORT: Deal with new PL_promot_string() and PL_prompt_next() APIs

  • COMPAT: Use new PL_dispatch() API.

Package xpce

  • COMPAT: Changed dispatch handling to pass an IOSTREAM that must
    be watched.
2 Likes

I’m still seeing Terminal regression on 9.3.23, MacOS · Issue #1367 · SWI-Prolog/swipl-devel · GitHub on 9.3.25. Am I alone? Is there some piece of config that I’m missing?

As commented on github, this does not reproduce for me (MacBook Air, MacOS 15.5). What happens on

?- [library(editline)].

Where on github?

Not getting the point but (example with up-arrow key):

$ /Applications/SWI-Prolog9.3.25.app/Contents/MacOS/swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 9.3.25)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- [library(editline)].
true.

?- ^[[A^[[A^[[A^[[A

As noted this only happens to me on 9.3.23 and later.

Library editline provides the (default) commandline editor that makes e.g., the up-arrow key work. There has been no change to this stuff for 9.3.24. There have been a lot of changes for 9.3.25, fixing bugs (see Having all sorts of problems with libeditline - #13 by alanbur), supporting Windows and modifications to the APIs that handle GUI events while waiting for the console.

Now, are we only talking about the arrow keys, or does the whole library not work? Does TAB completion work? Can you edit in the history using Emacs keys ^B/^F for backward/forward, ^P^N for up/down?

Anyone else facing this? Relevant info could be the MacOS version (libedit.dylib comes from the OS) and the console/terminal you are using.

Edit There have been changes for 9.3.22 that modify the conditions on when the library is actually enabled. Try calling

 ?- el_wrap.

Does this enable the arrow keys and editing? If so, please trace through editline:el_wrap_if_ok to see why it is not enabled.

Lots of things don’t work:

  • arrow keys
  • forward delete
  • option-click for line cursor positioning
  • TAB completion (just outputs TAB, or 4 spaces)

Prior to running el_wrap arrow keys etc. generate some character sequences like:

?- ^[[A^[[B^[[C^[[D^[[D^[[Dl      

After executing el_wrap nothing gets output for these keys other than an audible beep. So something changed but not necessarily for the better.

All I know is that it worked on 9.3.22 and hasn’t worked since.

That is only mildly useful :frowning: For one thing, nothing changed to this package in version 9.3.23 and 9.3.24. For 9.3.22 changes where made to allow for creating editline.qlf, which implies we cannot enable/disable parts of the library using conditional compilation. That could affect whether or not the library is actually enabled.

It is really hard to say something sensible when behind a system where all works as expected. I’d read through the library and possibly trace a little to see what is going on. You can start Prolog ensuring this library is not loaded using

 swipl -Dno-readline

Now there should be no history editing. Now, I can load

?- [library(editline)].

And line editing should work. The library initializes itself by calling el_wrap_if_ok/0, so see why that does (not) work. I normally check it works by typing

?- statis<TAB>

which should expand to

?- statistics.

Not working arrow keys can have more reasons, such as the terminal capabilities not being detected properly. For that reason you can use ^P to get to the previous command. That should not depend on the terminal detection.

So this is progress. Following this procedure, arrow keys, forward delete, cursor positioning, and TAB completion all work. In fact everything I normally do seems to be back in working order. As to why, I have no idea.