/* PyLog server:  Top-level predicate for interacting with the PyLog python
   module.
*/


/* The server is invoked under SWI prolog with the following command:
      pl -f pylogServer.pl -t pylog:server -g pylog:server 2> /dev/null

   The protocol for queries is very simple.  Basically, the client
   (pylog) initiates requests with a single line on stdin.  The pl
   server always responds with at least a single line of output.  Here is the
   outline:

Notes:                     SERVER                        Pylog
------                    --------                     --------
On startup:                 ready
---------------------------------------------------------------------------
The server now expects
a query to be sent.
---------------------------------------------------------------------------
query (e.g.):                                         append(X,Y,[1,2,3]).
---------------------------------------------------------------------------
Notice the query is sent
followed by a "." this 
prolog convention is
retained in the protocol.  
We will probably want Pylog 
to append a "." to any query 
string that does not already 
have it.
---------------------------------------------------------------------------
server parses query:        none
---------------------------------------------------------------------------
This indicates that there
 are no syntax errors in 
the query.  If there
are no errors, the server 
will go ahead and send 
the first solution.
---------------------------------------------------------------------------
server sends solution:     ["X = []","Y = [1, 2, 3]"]
---------------------------------------------------------------------------
The solution is returned
as a list of strings that
show the variable bindings.
---------------------------------------------------------------------------
Pylog asks for more:                                  next.
server sends next:         ["X = [1]","Y = [2, 3]"]
Pylog has enough:                                     abort.
response:                  ready
---------------------------------------------------------------------------
Actually, anything other
than a "next." results in
a reset for a new query.
___________________________________________________________________________
another query:                                        X is 3 + 4
                           none
                           ["X = 7"]
                                                      next.
                           no
                           ready
---------------------------------------------------------------------------
When there are no more
solutions, server sends 
"no" instead of a list and
immediately resets.
---------------------------------------------------------------------------
syntax error:                                          foo(.
                           $stream_position(4, -1, 0) : Unexpected end\
		                 of clause  
___________________________________________________________________________
The server spits back the
prolog error and is ready
for a corrected input.
Note: no "ready" is output.
---------------------------------------------------------------------------
run-time error:                                         X is 3 / 0.

                           none
                              [  8] _G188 is 3 / 0
                              [  7] get_solution(_G188 is 3 / 0, true)
                              [  5] server_loop
                              [  1] '$initialise'
                           ready
------------------------------------------------------------------------------
"none" because there is
no syntax error.  Prolog
dumps some stack info, but
it is indented, we can discard
lines that start with space.
Server restarts after error.
___________________________________________________________________________
special cases:                                           halt.
                           none
Prolog quits 
Force sane state:                                        ctrl-c
                          Action (h for help) ?
                                                         a
                          ready
----------------------------------------------------------------------
I don't really know if the "ctrl-c a" will work over a pipe or not.  Try
it and see.

----------------------------------------------------------------------
*/

:-module(pylog,[]).

:- nodebug.

exception(_,_,fail).

server:-
	prompt(_,''),
	server_loop.

server_loop:-
	write('ready'), nl, flush,
	repeat,
	read_term(Goal, [syntax_errors(Errs), variable_names(Vars)]),
	write(Errs), nl, flush,
	Errs = none,
	output_solution(Goal, Vars, More),
	More = false,
	!, 
	server_loop.
	
output_solution(Goal, Vars, More) :-
	get_solution(Goal, GotSolution),
	output_result(GotSolution, Vars, More).

get_solution(Goal, true) :-
	Goal.
get_solution(_, false).

output_result(true, Vars, More) :-
	!,
	write_bindings(Vars),
	read(R),
	( R = next ->
	    More = true
	;
	  More = false
        ).
output_result(false, _, false) :-
	write(no), nl, flush.

write_bindings(Vars):-
	write('['),
	write_each_binding(Vars),
	write(']'),
	nl,
	flush.

write_each_binding([]):- !.
write_each_binding([B]) :- 
	!,
	write_binding(B).
write_each_binding([B|Bs]) :-
	write_binding(B),
	write('\,'),
	write_each_binding(Bs).

write_binding(B) :-
	write('\"'),
	write(B),
	write('\"'),
	flush.
