I’m trying to build an interactive “expert system” in an html page with the wasm version of swi-prolog.
I have a textbox for the user input (that would normally come from the console), and a button to submit the text message.
I can write to the html page, and I can use bind/4 to add click events on the button, but is there a way I can suspend prolog until the value is read from the textbox?
Here is a snippet from my code.
add_message simply prints strings on screen, nothing more.
In the read_and_continue I can print the data read form the textbox, but ask_user does not wait for read_and_continue to end.
Good question. I think the answer is in creating a promise that waits for the (click) event and then use await/2. There are several code snippets on stack overflow for waiting for an event using a Promise. If you also want to process other stuff you should probably make sure that this “thread” runs in is own engine using Prolog.forEach() with the {engine: true} option as you find it (only) in the very latest (9.3.20) release.
So far, Prolog+WASM+JavaScript was mostly limited to using callbacks. With JavaScript Promise and Prolog engines we have something similar to JavaScript async functions. No example code and experience though. Please give it a try and share your experience!
I tried (copying some strange javascript code from stackoverflow for the js part).
The issue is if I run it with swipl-wasm I get the error in the picture. I’m not sure about what the input window is…
My understanding is that the prolog part should be something like this:
Sure. I made a few changes and included everything in the html file (prolog script included).
I’m not particularly familiar with Javascript, so that might very well be where the issue is.
This is basically the tweety code, with the addition of a user query tied to the html form.
The user is supposed to enter yes/no in the textfield.
There are two singleton variables. Apparently something goes wrong reporting these, causing the GC system error. If you fix these, you get a little further.
To run the query, you use Prolog.query().once(). But, this is synchronous. If you want async programming (which you need if you want to use Promises), you need Prolog.forEach(). That returns a promise, so you either need to add .then(...) or put it in an async function and add await.
With these two fixes it prints the answer to the question in the console, so that step works. I didn’t look at the rest.
Up to me is why printing compilation warnings leads to problems …
Probably. We should probably have a closer look at other browser based Prolog systems such as Tau Prolog. Note there seem to be three ways for Prolog in the browser:
Build it all in JavaScript (e.g., Tau)
Compile to WASM. As is, WASM is synchronous unless you compile it as async code, but Emscripten says there is a high price both wrt size and performance. WASM engine support seems to be on the way, which may change things. If not, we have two options
Put Prolog in a web worker and communicate with it using messages. That is what e.g. Ciao does (AFAIK)
Support yield from the VM, so you can return to the browser event loop, optionally wait for something and resume. That is what SWI-Prolog does.
The first and last allows quite direct manipulation of the DOM, something which is a lot harder when using a web worker. These two result (I think) in a different approach for integrating Prolog into the browser.
At least, that is my current understanding. I’m not a browser/JavaScript/WASM expert though. If I missed some useful path, I’d be glad to hear.
I’m no browser/javascript expert either. Far from it in fact.
I’m mainly trying to use it for simple demonstrations of user interaction aimed at students.
I have to admit that I’d also like something more robust to come out of this, but that’s a long term plan…