import gnu.prolog.database.*; import gnu.prolog.io.*; import gnu.prolog.term.*; import gnu.prolog.vm.*; import gnu.prolog.vm.interpreter.*; import java.io.*; public class Predicate_setup_call_catcher_cleanup extends ExecuteOnlyCode { public int execute(Interpreter interpreter, boolean backtrackMode, gnu.prolog.term.Term args[]) throws PrologException { Environment environment = interpreter.getEnvironment(); int rc = SUCCESS; // Only call setup the first time if (!backtrackMode) rc = Predicate_call.staticExecute(interpreter, false, args[0]); if (rc == SUCCESS || rc == SUCCESS_LAST) { try { rc = Predicate_call.staticExecute(interpreter, backtrackMode, args[1]); } catch(PrologException q) { rc = interpreter.unify(args[2], new CompoundTerm(CompoundTermTag.get(AtomTerm.get("exception"), 1), q.getTerm())); if (rc == SUCCESS || rc == SUCCESS_LAST) return Predicate_call.staticExecute(interpreter, false, args[3]); // re-throw exception if unification fails else { throw(q); } } if (rc != SUCCESS) { // Call cleanup if the 2nd arg fails, has an exception or is finished // But first, unify the port with args[3] if (rc == FAIL) rc = interpreter.unify(args[2], AtomTerm.get("fail")); else if (rc == SUCCESS_LAST) { rc = interpreter.unify(args[2], AtomTerm.get("exit")); } if (rc == SUCCESS || rc == SUCCESS_LAST) return Predicate_call.staticExecute(interpreter, false, args[3]); else return rc; } else { // Choicepoint has been left. BacktrackInfo bt = interpreter.popBacktrackInfo(); interpreter.pushBacktrackInfo(new BacktrackInfoWithCatcherCleanup(bt, args[2], args[3])); return rc; } } else return rc; } public class BacktrackInfoWithCatcherCleanup extends BacktrackInfoWithCleanup { Term catcher; public BacktrackInfoWithCatcherCleanup(BacktrackInfo bt, Term catcher, Term cleanup) { super(bt, cleanup); this.catcher = catcher; } public void cleanup(Interpreter interpreter) { try { if (interpreter.unify(catcher, AtomTerm.get("!")) == SUCCESS_LAST) super.cleanup(interpreter); } catch(PrologException anything) { } } } }