If the following prolog code is saved in a file called interp.pl, then it can be executed with SWI-Prolog [1] with the command line
plcon -s interp.pl -t main -q
(plcon is the name of the console executable on windows--On Unix use pl, on MacOSX use swipl).
The code will issue the prompt prompt: to stdout. Prolog terms will be read from stdin. The terms are allow to either be assertions via the assert functor, or queries that contain either 0 or one variable. If there are no variables then the result of a successful query will be displayed as a single line containing "1". A failed query will display "0". If there is one variable, then the results will be displayed as a Tcl list using curly braces. A failed query will display the empty list {}.
The Tcl code follows the prolog code.
displayListAsTcl([]).
displayListAsTcl([H|T]):-
writef('{%w} ', [H]),
displayListAsTcl(T).
% mycall is a wrapper around call that will display results of queries
% as a Tcl list
% No variables means simple true (1) or false (0) output
mycall(Goal,[]):-
call(Goal),
write('1\n').
mycall(_Goal,[]):-
write('0\n').
% If there is a single variable then return a list of the results
mycall(Goal,[Var]):-
%free_variables(Goal,Var),
findall(Var,Goal,List),
write('{'),
displayListAsTcl(List),
write('}\n').
mycall(_Goal,[_Var]):-
write('{}\n').
% More than one variable is not allowed
mycall(_Goal,[_Var1,_Var2|_Tail]):-
write('ERROR: Queries cannot have more than one unbound variable\n').
% Database insertions are also allowed
mycall(assert(X)):-
assert(X),
write('asserted\n').
mycall(Goal):-
free_variables(Goal,_Vars),
mycall(Goal,_Vars).
handleError(Error):-
writef('ERROR: %w\n',[Error]),
main.
main:-
prompt(_Old,'prompt:\n'),
read(Term),
catch(mycall(Term),Error,handleError(Error)),
main.
% Prevent the above main to exit
% when the call fails
main:-
main.The Tcl code:
namespace eval prolog {
proc init {} {
variable prologInterp
set prologInterp [open "|c:/apps/prolog/bin/plcon -s interp.pl -t main -q" r+]
set prompt [gets $prologInterp]
fconfigure $prologInterp -blocking 0 -buffering none
fileevent $prologInterp readable [list prolog::unexpectedPrologOutput $prologInterp]
return
}
proc close {} {
variable prologInterp
fileevent $prologInterp readable ""
puts $prologInterp "halt."
::close $prologInterp
}
proc unexpectedPrologOutput {interp} {
set result [gets $interp]
if {[string length $result] == 0} {
error "Prolog interpreter closed unexpectedly"
close $interp
} else {
error "Received unexpected output from interpreter: $result"
}
}
proc getPrologResults {interp} {
variable prologResult
variable pendingResult
set result [gets $interp]
if {[string length $result] == 0} {
close $interp
} else {
#puts "Read line: $result"
switch -glob $result {
prompt:* {set prologResult $pendingResult}
ERROR:* {set pendingResult $result}
asserted {set pendingResult ""}
default {set pendingResult [lindex $result 0]}
}
}
}
proc prolog {prologTerm} {
variable prologInterp
variable prologResult
fileevent $prologInterp readable [list prolog::getPrologResults $prologInterp]
puts $prologInterp $prologTerm
set prologResult {}
vwait prolog::prologResult
fileevent $prologInterp readable [list prolog::unexpectedPrologOutput $prologInterp]
return $prologResult
}
}Example use (assuming the above Tcl code is stored in a file call prolog.tcl):
% source prolog.tcl
% prolog::init
% prolog::prolog assert(child(a,b)).
% prolog::prolog assert(child(a,c)).
% prolog::prolog child(a,b).
1
% prolog::prolog child(a,X).
{b} {c}
% prolog::prolog child(X,b).
{a}
% | Updated 30 Jun 2003, 15:22 GMT Search - Recent Changes - Reference - About WiKit - Go to Tkoutline - Help |