Use Java based table-switch for type switches

Predicates that use different clauses for different types of terms use
a type switch on the first argument/register.  Rewrite this as a
proper table switch in Java so the JVM can emit an efficient switch
statement.  Use a virtual method and lightweight ints enumerated from
0 to N in the order the switch was previously written in to get an
efficient implementation for the JIT.

Change-Id: If7274ec8776479afe70bbec0882768d7a28b4c64
diff --git a/src/lang/ClosureTerm.java b/src/lang/ClosureTerm.java
index 001f509..053035c 100644
--- a/src/lang/ClosureTerm.java
+++ b/src/lang/ClosureTerm.java
@@ -18,7 +18,11 @@
     /** Returns the Prolog goal of this <code>ClosureTerm</code>. */
     public Predicate getCode() { return code; }
 
-    /* Term */
+    @Override
+    public int type() {
+      return TYPE_CLOSURE;
+    }
+
     public boolean unify(Term t, Trail trail) {
 	//	t = t.dereference();
 	if (t instanceof VariableTerm)
diff --git a/src/lang/DoubleTerm.java b/src/lang/DoubleTerm.java
index 588d815..dbb80f7 100644
--- a/src/lang/DoubleTerm.java
+++ b/src/lang/DoubleTerm.java
@@ -33,7 +33,11 @@
      */
     public double value() { return val; }
 
-    /* Term */
+    @Override
+    public int type() {
+      return TYPE_DOUBLE;
+    }
+
     public boolean unify(Term t, Trail trail) {
 	if (t instanceof VariableTerm)
 	    return ((VariableTerm)t).unify(this, trail);
diff --git a/src/lang/IntegerTerm.java b/src/lang/IntegerTerm.java
index e64c9b0..d9e1596 100644
--- a/src/lang/IntegerTerm.java
+++ b/src/lang/IntegerTerm.java
@@ -29,6 +29,11 @@
      */
     public int value() { return val; }
 
+    @Override
+    public int type() {
+      return TYPE_INTEGER;
+    }
+
     /* Term */
     public boolean unify(Term t, Trail trail) {
 	if (t instanceof VariableTerm)
diff --git a/src/lang/JavaObjectTerm.java b/src/lang/JavaObjectTerm.java
index 3076f80..89c946f 100644
--- a/src/lang/JavaObjectTerm.java
+++ b/src/lang/JavaObjectTerm.java
@@ -37,7 +37,11 @@
 
     public String  toQuotedString() { return toString(); }
 
-    /* Term */
+    @Override
+    public int type() {
+      return TYPE_JAVA_OBJECT;
+    }
+
     public boolean unify(Term t, Trail trail) {
 	if (t instanceof VariableTerm)
 	    return ((VariableTerm)t).unify(this, trail);
diff --git a/src/lang/ListTerm.java b/src/lang/ListTerm.java
index 5d733db..e1ead71 100644
--- a/src/lang/ListTerm.java
+++ b/src/lang/ListTerm.java
@@ -75,6 +75,11 @@
      */
     public void setCdr(Term t) { cdr = t; }
 
+    @Override
+    public int type() {
+      return TYPE_LIST;
+    }
+
     /* Term */
     public boolean unify(Term t, Trail trail) {
 	t = t.dereference();
diff --git a/src/lang/Prolog.java b/src/lang/Prolog.java
index e3c059b..be73553 100644
--- a/src/lang/Prolog.java
+++ b/src/lang/Prolog.java
@@ -206,20 +206,22 @@
 				    Operation con, 
 				    Operation str, 
 				    Operation lis) {
-	Term arg1 = r1.dereference();
-	if (arg1 instanceof VariableTerm)
-	    return var;
-	if (arg1 instanceof IntegerTerm)
-	    return Int;
-	if (arg1 instanceof DoubleTerm)
-	    return flo;
-	if (arg1 instanceof SymbolTerm)
-	    return con;
-	if (arg1 instanceof StructureTerm)
-	    return str;
-	if (arg1 instanceof ListTerm)
-	    return lis;
-	return var;
+      switch (r1.dereference().type()) {
+        case Term.TYPE_VARIABLE:
+          return var;
+        case Term.TYPE_INTEGER:
+          return Int;
+        case Term.TYPE_DOUBLE:
+          return flo;
+        case Term.TYPE_SYMBOL:
+          return con;
+        case Term.TYPE_STRUCTURE:
+          return str;
+        case Term.TYPE_LIST:
+          return lis;
+        default:
+          return var;
+      }
     }
 
     /**
diff --git a/src/lang/StructureTerm.java b/src/lang/StructureTerm.java
index cfd9c12..17e8864 100644
--- a/src/lang/StructureTerm.java
+++ b/src/lang/StructureTerm.java
@@ -78,6 +78,11 @@
 
     public Term arg(int nth) { return args[nth]; }
 
+    @Override
+    public int type() {
+      return TYPE_STRUCTURE;
+    }
+
     public boolean unify(Term t, Trail trail) {
 	t = t.dereference();
 	if (t instanceof VariableTerm) {
diff --git a/src/lang/SymbolTerm.java b/src/lang/SymbolTerm.java
index 347a103..9c6e4cf 100644
--- a/src/lang/SymbolTerm.java
+++ b/src/lang/SymbolTerm.java
@@ -179,7 +179,11 @@
      */
     public String name() { return name; }
 
-    /* Term */
+    @Override
+    public int type() {
+      return TYPE_SYMBOL;
+    }
+
     public boolean unify(Term t, Trail trail) {
       t = t.dereference();
       if (t instanceof VariableTerm) {
diff --git a/src/lang/Term.java b/src/lang/Term.java
index 960e156..c3e86c1 100644
--- a/src/lang/Term.java
+++ b/src/lang/Term.java
@@ -17,6 +17,18 @@
     /** Holds an integer value <code>-1</code>. */
     public static final int BEFORE = -1;
 
+    public static final int TYPE_VARIABLE = 0;
+    public static final int TYPE_INTEGER = 1;
+    public static final int TYPE_DOUBLE = 2;
+    public static final int TYPE_SYMBOL = 3;
+    public static final int TYPE_STRUCTURE = 4;
+    public static final int TYPE_LIST = 5;
+    public static final int TYPE_CLOSURE = 6;
+    public static final int TYPE_JAVA_OBJECT = 7;
+
+    /** One of the {@code TYPE_*} constants from {@code Term}. */
+    public abstract int type();
+
     /**
      * Checks whether the argument term is unified with this one.
      * @param t the term to be unified with.
diff --git a/src/lang/VariableTerm.java b/src/lang/VariableTerm.java
index 3cfd339..5bb4085 100644
--- a/src/lang/VariableTerm.java
+++ b/src/lang/VariableTerm.java
@@ -42,7 +42,11 @@
     /** Returns a string representation of this object.*/
     protected String variableName() { return "_" + Integer.toHexString(hashCode()).toUpperCase(); }
 
-    /* Term */
+    @Override
+    public int type() {
+      return TYPE_VARIABLE;
+    }
+
     /** 
      * Checks whether the argument term is unified with this one.
      * If this is an unbound variable, the <code>unify</code> method binds this to