The prolog command allows to call a Prolog predicate from Tcl, using Tcl syntax and arguments which have an equivalent representation in both languages. This is usually sufficient, however sometimes we might want to call Prolog using Prolog syntax. The ProTcXl command call_prolog provides this functionality. Since it is implemented using other ProTcXl primitives, its implementation is a good example how to use ProTcXl . Let us show how a simple version of call_prolog can be implemented:
The command is
call_prolog stringand its argument is a string which contains a Prolog term. call_prolog calls this term as Prolog goal and then it puts all its variables into the var array. We first define a Prolog predicate call_from_tcl(String, Res) which parses the contents of String, extracts its variables, calls the Prolog term and unifies Res with a list of name-value lists. We use readvar/3 to parse the string and return variables together with their names:
[eclipse 17]: [user]. call_from_tcl(String, Res) :- open(String, string, s), readvar(s, Goal, Vars), % parse and return variables close(s), call(Goal), return_vars(Vars, Res). % convert [N|V] to [N, V] because pairs do not exist in Tcl return_vars([], []). return_vars([[Name|Value]|L], [[Name, Value]|LR]) :- return_vars(L, LR). user compiled traceable 704 bytes in 0.00 seconds
Second, we define the Tcl call_prolog procedure: it calls the Prolog predicate call_from_tcl/2 and stores the returned list of variable-value lists in X. Then it sets the elements of the var array to the appropriate values:
proc call_prolog {goal} { global var prolog "tcl_call $goal X" set list $var(X) unset var(X) foreach pair $list { # we do: set var(Name) Value set var([lindex $pair 0]) [lindex $pair 1] } }
call_prolog can call arbitrary Prolog goals:
Note that although we can use arbitrary Prolog syntax in the argument of call_prolog, this string cannot contain any spaces, otherwise it would be interpreted by Tcl as a list with a space separator, because in Tcl there is no difference between a string containing spaces and a list.[eclipse 18]: tclsh. % call_prolog {append([1,2],[a,b],X),append(X,X,Y)} success % array get var; # list all array elements [X, [1, 2, a, b], Y, [1, 2, a, b, 1, 2, a, b]] % call_prolog {get_flag(hostarch,X),setval(arch1,X)} success % call_prolog {getval(arch1,X)}; puts $var(X) i386_linux