% % An almost portable implementation of logial assignment. % Distributed from http://www.kprolog.com/en/logical_assignment/ % % Copyright(C) 2003-2005 Nobukuni Kino, KLS Research, Inc. % kino@kprolog.com % % Licensed under the Open Software License version 2.1 % http://opensource.org/licenses/osl-2.1.php % % 01/03/2005 Error checking, and <+ compatibility % (Suggested by Paulo Moura, Thanks) % 12/31/2004 First distribution % :-module assignable. % :-public assignable/1,assignable/2. % :-public (<=)/2,(<+)/2,(=>)/2. :-op(700,xfy, '<='). :-op(700,xfy, '<+'). :-op(700,xfy, '=>'). % setarg(I,Term,Value):-$setarg(I,Term,Value). % for K-Prolog % clearargument(I,Term,Value). % for K-Prolog clearargument(I,Term,Value):-nb_setarg(I,Term,Value). % for SWI-Prolog % clearargument(I,Term,Value):-setarg(I,Term,Value,false). % for GNU-Prolog assignable(Assig):- Assig='}{'(_,_). assignable(Assig,Init):- Tail=[Init|_], Assig='}{'(Tail,Tail). check_assig(Assig):- nonvar(Assig), Assig='}{'(_,_),!. check_assig(Assig):- var(Assig),!, throw(instantiation_error). check_assig(Assig):- throw(domain_error(assignable,Assig)). Assig<=Value :- check_assig(Assig), poke_assig(Assig,Value). poke_assig(Assig,Value):- arg(1,Assig,Cache), arg(2,Assig,Body), compound(Body), compound(Cache),!, arg(2,Cache,Tail), % Cache points at the Tail Tail = [Value|_], % _ makes the new Tail setarg(1,Assig,Tail),!. % set the Cache as Tail poke_assig(Assig,Value):- arg(2,Assig,Body), compound(Body),!, findtail(Body,[_|Tail]), Tail = [Value|_], % _ makes the new Tail setarg(1,Assig,Tail),!. % set the Cache as Tail poke_assig(Assig,Value):- Tail=[Value|_], setarg(1,Assig,Tail), % set the Cache as Tail setarg(2,Assig,Tail),!. % set the Body as Tail Assig=>Value :- check_assig(Assig), peek_assig(Assig,Value). peek_assig(Assig,Value):- arg(1,Assig,Cache), compound(Body), compound(Cache),!, arg(1,Cache,Value). % Cache points at the Tail peek_assig(Assig,Value):- arg(2,Assig,Body), compound(Body), findtail(Body,Tail), arg(1,Tail,Value), setarg(1,Assig,Tail). % set Cache as Tail Assig<+Value:- check_assig(Assig), commit_assig(Assig,Value). commit_assig(Assig,Value):- clearargument(1,Assig,[]), % [] as \+compound. clearargument(2,Assig,[]), % this is dirty trick Tail=[Value|_], setarg(1,Assig,Tail), % set Cache as Tail setarg(2,Assig,Tail),!. % set Body as Tail findtail([_|Y],Tail):- nonvar(Y),!, findtail(Y,Tail). findtail(Tail,Tail). % We found the Tail value