Simplify the main execution loop of the interpreter

Made the code easier to follow, and handle halt(N) as normally
happens in a Prolog implementation like SWI-Prolog.
diff --git a/src/builtin/PRED_$begin_exception_1.java b/src/builtin/PRED_$begin_exception_1.java
index 2d914e3..966e0cd 100644
--- a/src/builtin/PRED_$begin_exception_1.java
+++ b/src/builtin/PRED_$begin_exception_1.java
@@ -21,6 +21,7 @@
 
 	if (! a1.unify(new JavaObjectTerm(this), engine.trail))
 	    return engine.fail();
+	PrologControl ctl = engine.control;
 	Operation code = cont;
 	int B = engine.stack.top();
 	this.outOfScope = false;
@@ -28,26 +29,11 @@
 	engine.trail.push(new OutOfLoop(this));
 
 	try {
-	    main_loop:while(true) {
-		while (engine.exceptionRaised == 0) {
-		    if (engine.control.isEngineStopped())
-			break main_loop;
-		    if (outOfLoop)
-			break main_loop;
-		    code = code.exec(engine);
-		}
-		switch (engine.exceptionRaised) {
-		case 1:  // halt/0
-		    break main_loop;
-		case 2:  // freeze/2
-		    throw new SystemException("freeze/2 is not supported yet");
-		    // Do something here
-                    // engine.exceptionRaised = 0 ;
-		    // break
-		default:
-		    break main_loop;
-		}
-	    }
+	  do {
+	    if (ctl.isEngineStopped()) break;
+	    if (outOfLoop) break;
+	    code = code.exec(engine);
+	  } while (engine.halt == 0);
 	} catch (PrologException e) {
 	    if (outOfScope)
 		throw e;
diff --git a/src/builtin/PRED_$begin_sync_2.java b/src/builtin/PRED_$begin_sync_2.java
index 7822184..6f42d35 100644
--- a/src/builtin/PRED_$begin_sync_2.java
+++ b/src/builtin/PRED_$begin_sync_2.java
@@ -44,18 +44,8 @@
 	main_loop:while(true) {
 	    synchronized (o) {
 		while (! outOfScope) {
-		    if (engine.exceptionRaised != 0) {
-			switch (engine.exceptionRaised) {
-			case 1:  // halt/0
+		    if (engine.halt != 0) {
 			    break main_loop;
-			case 2:  // freeze/2
-			    throw new SystemException("freeze/2 is not supported yet");
-			    // Do something here
-			    // engine.exceptionRaised = 0 ;
-			    // break
-			default:
-			    break main_loop;
-			}
 		    }
 		    if (engine.control.isEngineStopped())
 			break main_loop;
@@ -66,18 +56,8 @@
 
 	    }
 	    while (outOfScope) {
-		if (engine.exceptionRaised != 0) {
-		    switch (engine.exceptionRaised) {
-		    case 1:  // halt/0
+		if (engine.halt != 0) {
 			break main_loop;
-		    case 2:  // freeze/2
-			throw new SystemException("freeze/2 is not supported yet");
-			// Do something here
-			// engine.exceptionRaised = 0 ;
-			// break
-		    default:
-			break main_loop;
-		    }
 		}
 		if (engine.control.isEngineStopped())
 		    break main_loop;
diff --git a/src/builtin/PRED_halt_1.java b/src/builtin/PRED_halt_1.java
index 2aa4b92..0290a54 100644
--- a/src/builtin/PRED_halt_1.java
+++ b/src/builtin/PRED_halt_1.java
@@ -22,7 +22,7 @@
 	    throw new PInstantiationException(this, 1);
 	if (! a1.isInteger())
 	    throw new IllegalTypeException(this, 1, "integer", a1);
-	engine.exceptionRaised = ((IntegerTerm)a1).intValue();
+	engine.halt = 1 + ((IntegerTerm)a1).intValue();
         return cont;
     }
 }
diff --git a/src/builtin/builtins.pl b/src/builtin/builtins.pl
index c71f3f3..1fa2405 100644
--- a/src/builtin/builtins.pl
+++ b/src/builtin/builtins.pl
@@ -1767,11 +1767,9 @@
 '$prolog_impl_flag'(print_stack_trace, [on,off], changeable(yes)).
 
 :- public halt/0.
-%:- public halt/1. (written in Java)
 :- public abort/0.
 
-halt :- halt(1).
-
+halt :- halt(0).
 abort :- raise_exception('Execution aborted').
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/src/lang/Failure.java b/src/lang/Failure.java
index 7a716a7..e8001ae 100644
--- a/src/lang/Failure.java
+++ b/src/lang/Failure.java
@@ -12,7 +12,7 @@
 
     public Operation exec(Prolog engine) {
 	engine.control.fail();
-	engine.exceptionRaised = 1; // halt
+	engine.halt = 1; // halt(0)
 	return null;
     }
 
diff --git a/src/lang/HaltException.java b/src/lang/HaltException.java
new file mode 100644
index 0000000..5dbd4ef
--- /dev/null
+++ b/src/lang/HaltException.java
@@ -0,0 +1,14 @@
+package com.googlecode.prolog_cafe.lang;
+
+public class HaltException extends SystemException {
+  private final int status;
+
+  public HaltException(int status) {
+    super("halt(" + status + ")");
+    this.status = status;
+  }
+
+  public int getStatus() {
+    return status;
+  }
+}
diff --git a/src/lang/Prolog.java b/src/lang/Prolog.java
index 8f97c30..204cf88 100644
--- a/src/lang/Prolog.java
+++ b/src/lang/Prolog.java
@@ -50,10 +50,10 @@
      * Exception level of continuation passing loop:
      * <li><code>0</code> for no exception,
      * <li><code>1</code> for <code>halt/0</code>,
-     * <li><code>2</code> for <code>freeze/2</code> (not supported yet)
+     * <li><code>1+N</code> for <code>halt(N)</code>.
      * </ul>
      */
-    public int exceptionRaised;
+    public int halt;
 
     /** <font color="red">Not supported yet</font>. Prolog implementation flag: <code>bounded</code>. */
     protected boolean bounded = false;
@@ -246,7 +246,7 @@
 	initialFrame.timeStamp = ++CPFTimeStamp;
 	stack.push(initialFrame);
 
-	exceptionRaised = 0;
+	halt = 0;
 
 	charConversion  = "off";
 	debug           = "off";
diff --git a/src/lang/PrologControl.java b/src/lang/PrologControl.java
index 2ee53da..fb3b87b 100644
--- a/src/lang/PrologControl.java
+++ b/src/lang/PrologControl.java
@@ -143,28 +143,24 @@
      * @throws PrologException
      * @throws JavaInterruptedException
      */
-    protected void executePredicate()
-      throws PrologException, JavaInterruptedException {
-	    engine.init();
-	    main_loop:while(true) {
-		while (engine.exceptionRaised == 0) {
-		    if (isEngineStopped())
-			break main_loop;
-		    code = code.exec(engine);
-		}
-		SymbolTerm.gc();
-		switch (engine.exceptionRaised) {
-		case 1:  // halt/0
-		    break main_loop;
-		case 2:  // freeze/2
-		    throw new SystemException("freeze/2 is not supported yet");
-		    // Do something here
-		    // engine.exceptionRaised = 0 ;
-		    // break;
-		default:
-		    throw new SystemException("Invalid value of exceptionRaised");
-		}
-	    }
+    protected void executePredicate() throws PrologException, JavaInterruptedException {
+      Prolog engine = this.engine;
+      Operation code = this.code;
+      try {
+        engine.init();
+
+        do {
+          if (isEngineStopped()) return;
+          code = code.exec(engine);
+        } while (engine.halt == 0);
+
+        if (engine.halt != 1) {
+            throw new HaltException(engine.halt - 1);
+        }
+      } finally {
+        this.code = code;
+        SymbolTerm.gc();
+      }
     }
 
     /** @param err stack trace to print (or log). */
diff --git a/src/lang/PrologMain.java b/src/lang/PrologMain.java
index 7ab9b05..1e41c38 100644
--- a/src/lang/PrologMain.java
+++ b/src/lang/PrologMain.java
@@ -51,6 +51,8 @@
 	    p.setPredicate(Prolog.BUILTIN, "initialization", arg1, arg2);
 	    for (boolean r = p.call(); r; r = p.redo()) {}
 	    System.exit(0);
+	} catch (HaltException e) {
+	    System.exit(e.getStatus());
 	} catch (Exception e){
 	    e.printStackTrace();
 	    System.exit(1);