Use of `attribute_goals//1` to compose answers

I still don’t know. Except for debugging under SWISH, I see little use in that. More the opposite. A typical usage scenario for server maintenance is to embed the SSH server into Prolog such that you can login to the server, manage debug messages and optionally apply a hot-fix to resolve some issue. That works because debug message handling is shared over the threads.

But, if it can be made to work safely under SWISH, I see no reason not to support it. As I think of it, an alternative might be to have a second debug library (or some option to the primary one) that does only thread-local debugging. That way it would be a compile time option as to which debug topics are thread-local (and usable in SWISH) and which ones are shared (and protected in SWISH).

I use it just to enable additional diagnostic messages, as in a debug mode.
Of course, I could always leave the debug topic permanently enabled, and have another thread-local flag to turn message output (vs. using debugging/1). Sounds like that may be the easier way to go.

I have started a stripped down version of library(debug) for in SWISH. That seems like the right solution. It allows using debug/3 and debug/1 in SWISH code and allows pre-loaded libraries to load this alternative debug library. Need to finish some details to get a first version inside SWISH.

This approach provides safety as well as the ability to improve the integration with SWISH by using more HTML features.

Ok. Pull swish and see lib/swish_debug.pl. The file explains how it can be added to libraries. Only did some quick tests …

Thanks for responding to this issue so quickly, gives me the opportunity to sort things out before I push a new version.

I gave this a quick test, but I think I’m missing something basic. After updating the server and adding the conditional use_module directives, I see on the main server console:

?- listing(debug/1).
prolog_debug:debug(Topic) :-
    with_mutex(prolog_debug, debug(Topic, true)).

swish_debug:debug(Topic) :-
    debug(Topic, true).

Running the queries there:

?- debug(clpBNR),debugging(clpBNR,true).
true.

?- nodebug(clpBNR),debugging(clpBNR,true).
false.

So far, so good. Running the same queries from the SWISH UI, both succeed with a warning about “no matching debug topic (yet)”.

So should I be making any other source changes, or are debugging/2 and debug/3 expected to work as is? (I never call debug/1 directly in clpBNR).

Also how can I fix the warnings on SWISH queries?

If your code loads swish(lib/swish_debug) before the code using it, call calls to debug/3 should actually call swish_debug/3. You can verify that by listing one of the predicates that calls debug/3. Inside a SWISH toplevel, debug/1 resolves to the one on swish_debug.pl.

Worked for me using a simple example, e.g. test,pl

:- module(test,
          [ hello/1
          ]).
:- use_module(swish(lib/swish_debug)).

hello(X) :-
    debug(t1, 'Got ~p', [X]),
    format('Hello ~w~n', [X]).

Make this available in SWISH by, after swipl run.pl, using

?- [swish:test].

Now, inside SWISH you should be able to run

?- debug(t1), hello(world).

and see both the debug message and the format/2 output. No warnings should be printed. Listing hello/1 from the toplevel (not allowed inside SWISH) should say

hello(X) :-
    swish_debug(t1, 'Got ~p', [X]),
    format('Hello ~w~n', [X]).

Not sure what hole I was down, but basic operation seems to be working as advertised. One idiosyncrasy: this SWISH query:

?- debug(clpBNR),debugging(clpBNR).

succeeds, but:

?- debug(clpBNR),debugging(clpBNR,true).

fails. Will take a closer look tomorrow.

debugging/2 is not part of the swish vesion library. I don’t know why it is in library(debug). I don’t see much use for it.

But it is in library(debug), so if you want minimize source changes to also support swish, it should also be in the swish version. It also seems to be used in swish_debug:

swish_debugging(Topic) :-
    debugging(Topic, true).

I currently use it because it is the lowest cost check in performance critical code (every change to clpBNR attribute) for debug topic enabled, e.g.,

(debugging(clpBNR,true) -> debug_clpBNR_('Failed to unify ~w::(~w) with ~w',[Type,Val,V]))

I understand that this is not a very compelling argument for using it, but it was available in library(debug). If it isn’t available, I would probably add some conditional goal expansion for the swish case just to avoid multiple changes to the source.

Yes, but debugging(Topic, Var) or debugging(Topic, false) would be more complicated and slower as you can find in the code to list the active debug topics in the SWISH version. That is because we have a dual representation, one of known topics from static libraries and one that deals with active topics as well as known topics from user code in swish.

I tried to measure the difference in using

  ?- time(forall(between(1, 1000000, _), debugging(pengine(debug), true))).
  ?- time(forall(between(1, 1000000, _), debugging(pengine(debug)))).

The difference is simply not measurable. That i also to be expected as both make a call on the underlying predicate debugging/3, so it is either you adding the true or debugging/1. As both calls are subject to LCO, there are no costs for copying arguments around.

As the docs already state that debugging/2 is not for user code. It might be better to deprecate it.

Point taken. I’m going to use a conditional goal expansion, just to avoid making a lot of source changes and put a better cleanup on my TODO list.

For discussion, on another subject, I realize this is early days, but I think the debug messages just take up too much room, particularly when there are multiple such messages.

I would prefer a more compact scheme enabled by:

  • In swish_debug.pl:
debug_msg(Msg, Topic) -->
	{ atomics_to_string(['% ', Topic, ': ', Msg], DMsg) },
    html(div(class('debug-msg'),
             [ pre([class('msg'), title('Debug message')], DMsg)
             ])).
  • In answers.css:
		 /*******************************
		 *	      DEBUG		*
		 *******************************/
div.debug-msg pre
{ border: 0;
  background-color: #f5f5f5;
  margin: 0;
  padding: 0;
  color: blue;
}


		 /*******************************
		 *	       WFS		*
		 *******************************/

This is very similar to the toplevel output with the addition of the topic. It also uses the same background as print_message. Maybe there’s a case to be made for more consistency between print_message and debug/3, and between the toplevel and SWISH from a UI perspective. Any thoughts? I’ll dig into this a bit more if you think it’s worthy of some attention.

In any case, I have more than enough to go on - I need to examine the the safety implications in clpBNR now that debug topics can be locally supported in pengines.

The idea of SWISH is not to replicate the terminal. Instead, the idea is to use the facilities that browsers offer to get to a better user interface. So, the DOM for a debug message, separating the topic from the message (the topic is not displayed at all in the toplevel) is, IMO, good. I don’t know what you mean with “too much space”. A debug message is still a single line, but with the topic shown in smaller font flushed right. The idea is that this allows for some more user interaction, such as highlighting or hiding all messages with the same topic. We could further enrich this using time information and possibly source location information.

I don’t have much opinion on the color. It might be a little too bright. Having a distinct style compared to other print_message/2 output seems good, especially if we decide to extend the UI.

If the debug message is not a single line, you may need a shift-reload to properly update the style sheets (assuming you did not create the minimized versions of the JavaScript and CSS, in which case you have to rebuild these or remove them).

Having undone my experiment, it’s much better than it first appeared; perhaps old CSS got cached and I wasn’t seeing the new styles from server. (The first rendering had the topic on a separate line, standard font, with the message following in a border with significant padding so whole message took up about 3 equivalent console lines.) Had I seen the intended rendering, I probably wouldn’t have commented further.

As long as it’s better in some sense. If users are going to be in either the SWISH camp or the local SWIP camp, it doesn’t matter much. For those in both, differences in console output can be a little jarring. That particularly applies to cosmetics like borders, font styling, and not-so-subtle background colour changes, IMO. But I guess there’ll never be universal agreement on issues like this - that’s why UI themes were invented.

Anyway, I’m no ergonomics expert, so I’ll bow out at this point.

Neither am I :frowning: I’ve done a lot of UI programming. The programming part is fine, but designing the logic of the interaction and getting it to look nice is another matter. If anyone with experience feels he or she can contribute, please do! This applies to SWISH as well as a lot of the tooling and website.

Tried to run my local swish server on 9.1.21 and ended up with a bunch of load errors starting with:

$ /Applications/SWI-Prolog9.1.21.app/Contents/MacOS/swipl run.pl
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/crypto.pl:72:
ERROR:    /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/crypto.pl:72: Initialization goal raised exception:
ERROR:    open_shared_object/3: dlopen(/Applications/SWI-Prolog9.1.21.app/Contents/swipl/lib/fat-darwin/crypto4pl.so, 1): Library not loaded: /Users/jan/deps/lib/libcrypto.3.dylib
  Referenced from: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/lib/fat-darwin/crypto4pl.so
  Reason: image not found
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/ssl.pl:67:
ERROR:    Exported procedure crypto:rsa_public_decrypt/4 is not defined
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/ssl.pl:67:
ERROR:    Exported procedure crypto:rsa_private_encrypt/4 is not defined
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/ssl.pl:67:
ERROR:    Exported procedure crypto:rsa_public_encrypt/4 is not defined
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/ssl.pl:67:
ERROR:    Exported procedure crypto:crypto_n_random_bytes/2 is not defined
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/ssl.pl:67:
ERROR:    Exported procedure crypto:rsa_private_decrypt/4 is not defined
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/ssl.pl:67:
ERROR:    Exported procedure crypto:crypto_name_curve/2 is not defined
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/ssl.pl:69:
ERROR:    /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/ssl.pl:69: Initialization goal raised exception:
ERROR:    open_shared_object/3: dlopen(/Applications/SWI-Prolog9.1.21.app/Contents/swipl/lib/fat-darwin/ssl4pl.so, 1): Library not loaded: /Users/jan/deps/lib/libssl.3.dylib
  Referenced from: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/lib/fat-darwin/ssl4pl.so
  Reason: image not found
ERROR: /Applications/SWI-Prolog9.1.21.app/Contents/swipl/library/ext/ssl/http/http_ssl_plugin.pl:38:

SWIP 9.1.21 seems OK (both terminal and qt version).

I rebuilt swish (make yarn-zip) but that didn’t seem to make any difference. Any suggestions?

It seems that the script that copies dependencies into the app bundle stopped doing this for some of the dependencies. I’d assume that

 ?- [library(ssl)].

fails as well?

Turns out that an update to CMake caused the “bundle fixup script” not to be executed. This implies that most packages relying on non-MacOS shared libraries do not work. Uploaded a version that should fix this as “swipl-9.1.21-2”. Note the “-2”. It will take an hour or so for www.swi-prolog.org to update. If it still tells you “-1”, try eu.swi-prolog.org to bypass the CDN.

So, possibly the console working again is related to the CMake update, though it seems unlikely.

Correct.

I will test when it’s available.

Downloaded and tested - seems to work on all counts.

Just pushed a new version (0.11.4) of clpBNR to GitHub. Changes include:

  • redo answer generation to support SWISH (annotated bindings rather than separate global)
  • replace trace implementation based on debug hooks with one using module prolog_wrap (still unsafe, so actually can’t be used in SWISH).
  • support swish_debug topics
  • add html portray hook for ellipsis format in answers
  • other changes and cleanups as suggested in earlier feedback

To run additional examples (from “CLP(BNR) User Guide”), module clpBNR_toolkit (included with pack) must be available and enabled in SWISH.

Tested on local SWISH server with SWIP 9.1.21.

Let me know if you spot any more necessary fixes and/or improvements.

1 Like