DanielR
DanielR

Reputation: 55

Tau-Prolog results visible in browser window

I'm fairly new to Tau-Prolog and Javascript. At the beginning I would like to show some results computed by the Tau-Prolog engine in a Browser.

So far, all I want to show is some information contained in my Prolog-database:

The prolog-output would be something like: "Robot A fits with Gripper C (Same interface Z)." I've programmed this in SWI-Prolog and it works fine so far.

Now I would like to show the results in a HTML-Element:

<div class="example-result" id="show_result1"></div>

This is what I've come up so far:

function queryRG() {   
    var session = pl.create(1000);
    var parsed = session.consult("code.pl");
    //if (parsed !== true) { console.log(pl.format_answer(parsed)) }


    var query1 = session.query("queryRG.");

    var callback = function(answer){

        var result1 = document.getElementById("show_result1");

        console.log( pl.format_answer( answer ));

        if (pl.type.is_substitution(answer)){

            var ab = answer.toString();

            result.innerHTML = result.innerHTML + ab;
        }   
    }
    session.answer(callback);
}

I can see all the (correct) results in the console, but I fail to make them visible on the website. Thanks for your help!

Edited:

After the the help of @CapelliC i came up with this version now. Still I have the problem that the expected result show up in the Console, but not on the site:

<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Playground</title>
</head>
<body>
    <script type="text/javascript" src="tau-prolog.js"></script>
    <h1>Playground4</h1>
<script>

    function queryRG() {
      var session = pl.create(1000)

      var code_pl = `
        robot('Robot1','A', 1, 550).
        robot('Robot2','C', 2, 340).
        robot('Robot3','A', 2, 200).
        robot('Robot4','B', 3, 260).

        gripper('Gripper1', 'B', 50).
        gripper('Gripper2', 'A', 60).
        gripper('Gripper3', 'C', 30).
        gripper('Gripper4', 'C', 80).
        gripper('Gripper5', 'A', 20).
        gripper('Gripper6', 'B', 30).
        gripper('Gripper7', 'C', 90).

        query_robots :-robot(Name,Interface,Size,Price), write('The database contains: '),write(Name), write(', with Interface: '), write(Interface), write(', Size: '), write(Size) , write(', Price: '), write(Price), nl, fail.
      `
      var parsed = session.consult(code_pl)
      var query = session.query('query_robots.')

      function inform(msg) {
        show_result1.innerHTML += '<div>' + msg + '</div>'
      }

      var count_answers = 0
      var callback = function(answer) {
        if (answer === false) {
          inform('DONE, #answers='+count_answers)
          return
        }
        if (answer === null) {
          inform('TIMEOUT, #answers='+count_answers)
          return
        }
        // loop
        ++count_answers
        inform(pl.format_answer(answer))
        session.answer(callback)
      }
      // start the query loop
      session.answer(callback)
    }
    </script>

    <div id=show_result1>
      <h3>results show here...</h3>
    </div>
    <button onclick="queryRG()">Click to run</button>
</body>
</html>

Upvotes: 3

Views: 539

Answers (1)

CapelliC
CapelliC

Reputation: 60034

Just an example of handling multiple result, I crafted it creating a page 'tau-prolog.html' in the same folder where had downloaded 'tau-prolog.js', and opened locally in my browser. Then using the developer tools (console, debugger) had a look at inner workings of Tau Prolog.

Beware of details, like

  • how do you load the Prolog file? in my example I opted for the simpler way, passing the 'program' into a string
  • how do you start the interaction with the interpreter? in my example I opted for a button, and the most basic handler onclick="..." that loops to extract all answers. Clearly not appropriate for every scenario, but it illustrate the peculiar recursion that Javascript allows. Specially note that the variable session remain in scope among calls.
  • when you get an answer, only then the callback can decide if looping or quitting...
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>test tau-prolog</title>
    <script src=tau-prolog.js></script>
  </head>
  <body>
    <script>
    function queryRG() {
      var session = pl.create(1000)

      var code_pl = `
        :- use_module(library(lists)).
        fruit(apple).
        fruit(pear).
        fruit(banana).
        fruits_in(Xs, X) :- member(X, Xs), fruit(X).
      `
      var parsed = session.consult(code_pl)
      var query = session.query('fruits_in([banana,lemon,apple],X).')

      function inform(msg) {
        show_result1.innerHTML += '<div>' + msg + '</div>'
      }

      var count_answers = 0
      var callback = function(answer) {
        if (answer === false) {
          inform('DONE, #answers='+count_answers)
          return
        }
        if (answer === null) {
          inform('TIMEOUT, #answers='+count_answers)
          return
        }
        // loop
        ++count_answers
        inform(pl.format_answer(answer))
        session.answer(callback)
      }
      // start the query loop
      session.answer(callback)
    }
    </script>

    <div id=show_result1>
      <h3>results show here...</h3>
    </div>
    <button onclick="queryRG()">Click to run</button>
  </body>
</html>

The result of click on [Click to run] is as expected:

results show here...
X = banana ;
X = apple ;
DONE, #answers=2

HTH

edit Your query is really a 'failure driven loop', typically used only for its 'side effects', since it undoes variables bindings at failure point. The problem becomes that, apparently, they didn't documented how to properly change IO handlers. At least, I haven't found anything useful. A quick hack then: rebind the put function, adding this line immediately after function inform(msg){...}

      session.current_output.stream.put = inform

Now, it's clear that inform(msg) should be rethinked, because it doesn't understand plain text streaming. Maybe you could change inform(msg){} to output a <span>msg</msg> instead of a <div>, inspect for \n and call flush on that, and then bind a flush handler (currently undefined) that group <span>s in a <div>.

Note: inspecting the code, it's rather clear that IO streams are not the main priority of Tau-Prolog. Indeed, at line 1670 of tau-prolog.js have found this typo:

        return new Stram( this.stream, this.mode, this.alias, this.type, this.reposition, this.eof_action );

Clearly, Stram should be Stream.

edit

A better idea to get readable output without handling flush(): simplify

    function inform(msg){
       show_result1.innerHTML += msg
    }

and change the markup:

    <h3>results show here...</h3>
    <pre id=show_result1>
    </pre>

Upvotes: 2

Related Questions