/* File: flrcontrol.P ** ** Author(s): Michael Kifer ** Guizhen Yang ** ** Contact: flora-users@lists.sourceforge.net ** ** Copyright (C) The Research Foundation of SUNY, 2001 ** ** FLORA-2 is free software; you can redistribute it and/or modify it under the ** terms of the GNU Library General Public License as published by the Free ** Software Foundation; either version 2 of the License, or (at your option) ** any later version. ** ** FLORA-2 is distributed in the hope that it will be useful, but WITHOUT ANY ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ** FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for ** more details. ** ** You should have received a copy of the GNU Library General Public License ** along with FLORA-2; if not, write to the Free Software Foundation, ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** $Id: flrcontrol.P,v 1.17 2003/06/18 07:01:20 kifer Exp $ ** */ :- compiler_options([xpp_on]). #include "flora_terms.flh" #include "flora_porting.flh" :- import flora_commit_storage/0 from flrutils. /*************************************************************************** if-then-else statement ***************************************************************************/ FLLIBIFTHENELSE(Cond,Then,_Else) :- call(Cond), call(Then). FLLIBIFTHENELSE(Cond,_Then,Else) :- FLORA_TNOT(Cond), call(Else). /*************************************************************************** if-then statement The semantics is such that the entire statement succeeds when the condition part fails. ***************************************************************************/ FLLIBIFTHEN(Cond,Then) :- call(Cond), call(Then). FLLIBIFTHEN(Cond,_Then) :- FLORA_TNOT(Cond). %% UNLESS ... DO ... is like IF...THEN true ELSE ... FLLIBUNLESSDO(Cond,_Action) :- call(Cond). FLLIBUNLESSDO(Cond,Action) :- FLORA_TNOT(Cond), call(Action). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% while-do and do-until loops commit storage after each iteration %%%% so they are not backtrackable (backtracking over updates can occur %%%% only within the condition or action parts, but not after an iteration %%%% is finished) %%%% These loops fail only if Action fails. %%%% Variables that were unbound at the time of the call stay unbound %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This should fail ONLY if Cond is true, but Action fails. %% We use catch/throw to achieve this FLLIBWHILEDO(Cond,Action) :- FLORA_SYMBOL('catch')((call(Cond), (call(Action) -> flora_commit_storage, fail ; throw(quitLoop) ) ; true ), quitLoop, % catcher fail). % fail, if condition was thrown %% Fails only if Action becomes false before Cond becomes true FLLIBDOUNTIL(Action,Cond) :- call(Action), flora_commit_storage, call(Cond). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% while-loop and loop-until %%%% These loops are fully backtrackable, but they are more expensive, %%%% since they are recursive. %%%% These loops fail only if Action fails. %%%% Variables that were unbound at the time of the call stay unbound %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FLLIBWHILELOOP(Cond,Action) :- %% Must copy_term Action&Cond together so the variables %% will be preserved copy_term((Action,Cond),(Action1,Cond1)), (call(Cond1) -> (call(Action1), !, FLLIBWHILELOOP(Cond,Action) ; fail ) ; true ). /* FLORA_SYMBOL('catch')( (call(Cond1) -> (call(Action1), ! ; throw(quitLoop)), FLLIBWHILELOOP(Cond,Action) ; true ), quitLoop, % catcher fail % fail if action failed ). */ %% Cond shouldn't be tabled!!! Otherwise "not" barks!!! %% We can't use FLORA_TNOT instead of "not" because FLORA_TNOT %% would table Cond and cause more iterations than necessary. %% We could call abolish_all_tables from within FLORA_TNOT, %% but this is dangerous: %% If there is a recursive dependency on Cond then abolishing tables %% while computing them can crash XSB FLLIBLOOPUNTIL(Action,Cond) :- %% Must copy_term Action&Cond together so the variables %% will be preserved copy_term((Action,Cond),(Action1,Cond1)), FLORA_SYMBOL('catch')( ((call(Action1), ! ; throw(quitLoop)), (not(call(Cond1)) -> FLLIBLOOPUNTIL(Action,Cond) ; true ) ), quitLoop, % catcher fail % fail if action failed ). %% These exist in order to be able to hide the calls %% to catch/throw in the debugger FLORA_SYMBOL('catch')(X,Y,Z) :- catch(X,Y,Z).