[armedbear-cvs] r12965 - trunk/abcl/src/org/armedbear/lisp
Erik Huelsmann
ehuelsmann at common-lisp.net
Sat Oct 9 20:50:41 UTC 2010
Author: ehuelsmann
Date: Sat Oct 9 16:50:41 2010
New Revision: 12965
Log:
Reduce our number of hash table implementations to 1 (from 4)
by abstracting out the concept of "key equality" and "hash code
retrieval" into a Comparator class.
The other classes are left in place for now, but have been reduced
to simple wrappers around the HashTable class.
While at it, reformat HashTable.java (sorry about that -
it obfuscates the functional changes).
Modified:
trunk/abcl/src/org/armedbear/lisp/EqHashTable.java
trunk/abcl/src/org/armedbear/lisp/EqlHashTable.java
trunk/abcl/src/org/armedbear/lisp/EqualHashTable.java
trunk/abcl/src/org/armedbear/lisp/EqualpHashTable.java
trunk/abcl/src/org/armedbear/lisp/HashTable.java
Modified: trunk/abcl/src/org/armedbear/lisp/EqHashTable.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/EqHashTable.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/EqHashTable.java Sat Oct 9 16:50:41 2010
@@ -35,128 +35,10 @@
public final class EqHashTable extends HashTable
{
- private LispObject cachedKey;
- private int cachedIndex;
-
- private int mask;
-
public EqHashTable(int size, LispObject rehashSize,
LispObject rehashThreshold)
{
- super(calculateInitialCapacity(size), rehashSize, rehashThreshold);
- mask = buckets.length - 1;
- }
-
- @Override
- public Symbol getTest()
- {
- return Symbol.EQ;
- }
-
- @Override
- public synchronized LispObject get(LispObject key)
- {
- final int index;
- if (key == cachedKey) {
- index = cachedIndex;
- } else {
- index = key.sxhash() & mask;
- cachedKey = key;
- cachedIndex = index;
- }
- HashEntry e = buckets[index];
- while (e != null) {
- if (key == e.key)
- return e.value;
- e = e.next;
- }
- return null;
- }
-
- @Override
- public synchronized void put(LispObject key, LispObject value)
- {
- int index;
- if (key == cachedKey) {
- index = cachedIndex;
- } else {
- index = key.sxhash() & mask;
- cachedKey = key;
- cachedIndex = index;
- }
- HashEntry e = buckets[index];
- while (e != null) {
- if (key == e.key) {
- e.value = value;
- return;
- }
- e = e.next;
- }
- // Not found. We need to add a new entry.
- if (++count > threshold) {
- rehash();
- // Need a new hash value to suit the bigger table.
- index = key.sxhash() & mask;
- cachedKey = key;
- cachedIndex = index;
- }
- e = new HashEntry(key, value);
- e.next = buckets[index];
- buckets[index] = e;
- }
-
- @Override
- public LispObject remove(LispObject key)
- {
- final int index;
- if (key == cachedKey) {
- index = cachedIndex;
- } else {
- index = key.sxhash() & mask;
- cachedKey = key;
- cachedIndex = index;
- }
- HashEntry e = buckets[index];
- HashEntry last = null;
- while (e != null) {
- if (key == e.key) {
- if (last == null)
- buckets[index] = e.next;
- else
- last.next = e.next;
- --count;
- return e.value;
- }
- last = e;
- e = e.next;
- }
- return null;
- }
-
- @Override
- protected void rehash()
- {
- cachedKey = null; // Invalidate the cache!
- HashEntry[] oldBuckets = buckets;
- final int newCapacity = buckets.length * 2;
- threshold = (int) (newCapacity * loadFactor);
- buckets = new HashEntry[newCapacity];
- mask = buckets.length - 1;
- for (int i = oldBuckets.length; i-- > 0;) {
- HashEntry e = oldBuckets[i];
- while (e != null) {
- final int index = e.key.sxhash() & mask;
- HashEntry dest = buckets[index];
- if (dest != null) {
- while (dest.next != null)
- dest = dest.next;
- dest.next = e;
- } else
- buckets[index] = e;
- HashEntry next = e.next;
- e.next = null;
- e = next;
- }
- }
+ super(new Comparator(), calculateInitialCapacity(size),
+ rehashSize, rehashThreshold);
}
}
Modified: trunk/abcl/src/org/armedbear/lisp/EqlHashTable.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/EqlHashTable.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/EqlHashTable.java Sat Oct 9 16:50:41 2010
@@ -35,110 +35,10 @@
public final class EqlHashTable extends HashTable
{
- private int mask;
-
public EqlHashTable(int size, LispObject rehashSize,
LispObject rehashThreshold)
{
- super(calculateInitialCapacity(size), rehashSize, rehashThreshold);
- mask = buckets.length - 1;
- }
-
- @Override
- public Symbol getTest()
- {
- return Symbol.EQL;
- }
-
- @Override
- public synchronized LispObject get(LispObject key)
- {
- HashEntry e = buckets[key.sxhash() & mask];
- while (e != null)
- {
- if (key.eql(e.key))
- return e.value;
- e = e.next;
- }
- return null;
- }
-
- @Override
- public synchronized void put(LispObject key, LispObject value)
- {
- int index = key.sxhash() & mask;
- HashEntry e = buckets[index];
- while (e != null)
- {
- if (key.eql(e.key))
- {
- e.value = value;
- return;
- }
- e = e.next;
- }
- // Not found. We need to add a new entry.
- if (++count > threshold)
- {
- rehash();
- // Need a new hash value to suit the bigger table.
- index = key.sxhash() & mask;
- }
- e = new HashEntry(key, value);
- e.next = buckets[index];
- buckets[index] = e;
- }
-
- @Override
- public LispObject remove(LispObject key)
- {
- final int index = key.sxhash() & mask;
- HashEntry e = buckets[index];
- HashEntry last = null;
- while (e != null)
- {
- if (key.eql(e.key))
- {
- if (last == null)
- buckets[index] = e.next;
- else
- last.next = e.next;
- --count;
- return e.value;
- }
- last = e;
- e = e.next;
- }
- return null;
- }
-
- @Override
- protected void rehash()
- {
- HashEntry[] oldBuckets = buckets;
- int newCapacity = buckets.length * 2;
- threshold = (int) (newCapacity * loadFactor);
- buckets = new HashEntry[newCapacity];
- mask = buckets.length - 1;
- for (int i = oldBuckets.length; i-- > 0;)
- {
- HashEntry e = oldBuckets[i];
- while (e != null)
- {
- final int index = e.key.sxhash() & mask;
- HashEntry dest = buckets[index];
- if (dest != null)
- {
- while (dest.next != null)
- dest = dest.next;
- dest.next = e;
- }
- else
- buckets[index] = e;
- HashEntry next = e.next;
- e.next = null;
- e = next;
- }
- }
+ super(new EqlComparator(), calculateInitialCapacity(size),
+ rehashSize, rehashThreshold);
}
}
Modified: trunk/abcl/src/org/armedbear/lisp/EqualHashTable.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/EqualHashTable.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/EqualHashTable.java Sat Oct 9 16:50:41 2010
@@ -35,110 +35,10 @@
public final class EqualHashTable extends HashTable
{
- private int mask;
-
public EqualHashTable(int size, LispObject rehashSize,
LispObject rehashThreshold)
{
- super(calculateInitialCapacity(size), rehashSize, rehashThreshold);
- mask = buckets.length - 1;
- }
-
- @Override
- public Symbol getTest()
- {
- return Symbol.EQUAL;
- }
-
- @Override
- public synchronized LispObject get(LispObject key)
- {
- HashEntry e = buckets[key.sxhash() & mask];
- while (e != null)
- {
- if (key == e.key || key.equal(e.key))
- return e.value;
- e = e.next;
- }
- return null;
- }
-
- @Override
- public synchronized void put(LispObject key, LispObject value)
- {
- int index = key.sxhash() & mask;
- HashEntry e = buckets[index];
- while (e != null)
- {
- if (key == e.key || key.equal(e.key))
- {
- e.value = value;
- return;
- }
- e = e.next;
- }
- // Not found. We need to add a new entry.
- if (++count > threshold)
- {
- rehash();
- // Need a new hash value to suit the bigger table.
- index = key.sxhash() & mask;
- }
- e = new HashEntry(key, value);
- e.next = buckets[index];
- buckets[index] = e;
- }
-
- @Override
- public LispObject remove(LispObject key)
- {
- final int index = key.sxhash() & mask;
- HashEntry e = buckets[index];
- HashEntry last = null;
- while (e != null)
- {
- if (key == e.key || key.equal(e.key))
- {
- if (last == null)
- buckets[index] = e.next;
- else
- last.next = e.next;
- --count;
- return e.value;
- }
- last = e;
- e = e.next;
- }
- return null;
- }
-
- @Override
- protected void rehash()
- {
- HashEntry[] oldBuckets = buckets;
- int newCapacity = buckets.length * 2;
- threshold = (int) (newCapacity * loadFactor);
- buckets = new HashEntry[newCapacity];
- mask = buckets.length - 1;
- for (int i = oldBuckets.length; i-- > 0;)
- {
- HashEntry e = oldBuckets[i];
- while (e != null)
- {
- final int index = e.key.sxhash() & mask;
- HashEntry dest = buckets[index];
- if (dest != null)
- {
- while (dest.next != null)
- dest = dest.next;
- dest.next = e;
- }
- else
- buckets[index] = e;
- HashEntry next = e.next;
- e.next = null;
- e = next;
- }
- }
+ super(new EqualComparator(), calculateInitialCapacity(size),
+ rehashSize, rehashThreshold);
}
}
Modified: trunk/abcl/src/org/armedbear/lisp/EqualpHashTable.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/EqualpHashTable.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/EqualpHashTable.java Sat Oct 9 16:50:41 2010
@@ -38,104 +38,6 @@
public EqualpHashTable(int size, LispObject rehashSize,
LispObject rehashThreshold)
{
- super(size, rehashSize, rehashThreshold);
- }
-
- @Override
- public Symbol getTest()
- {
- return Symbol.EQUALP;
- }
-
- @Override
- public synchronized LispObject get(LispObject key)
- {
- final int index = key.psxhash() % buckets.length;
- HashEntry e = buckets[index];
- while (e != null)
- {
- if (key.equalp(e.key))
- return e.value;
- e = e.next;
- }
- return null;
- }
-
- @Override
- public synchronized void put(LispObject key, LispObject value)
- {
- int index = key.psxhash() % buckets.length;
- HashEntry e = buckets[index];
- while (e != null)
- {
- if (key.equalp(e.key))
- {
- e.value = value;
- return;
- }
- e = e.next;
- }
- // Not found. We need to add a new entry.
- if (++count > threshold)
- {
- rehash();
- // Need a new hash value to suit the bigger table.
- index = key.psxhash() % buckets.length;
- }
- e = new HashEntry(key, value);
- e.next = buckets[index];
- buckets[index] = e;
- }
-
- @Override
- public LispObject remove(LispObject key)
- {
- final int index = key.psxhash() % buckets.length;
- HashEntry e = buckets[index];
- HashEntry last = null;
- while (e != null)
- {
- if (key.equalp(e.key))
- {
- if (last == null)
- buckets[index] = e.next;
- else
- last.next = e.next;
- --count;
- return e.value;
- }
- last = e;
- e = e.next;
- }
- return null;
- }
-
- @Override
- protected void rehash()
- {
- HashEntry[] oldBuckets = buckets;
- int newCapacity = buckets.length * 2 + 1;
- threshold = (int) (newCapacity * loadFactor);
- buckets = new HashEntry[newCapacity];
- for (int i = oldBuckets.length; i-- > 0;)
- {
- HashEntry e = oldBuckets[i];
- while (e != null)
- {
- final int index = e.key.psxhash() % buckets.length;
- HashEntry dest = buckets[index];
- if (dest != null)
- {
- while (dest.next != null)
- dest = dest.next;
- dest.next = e;
- }
- else
- buckets[index] = e;
- HashEntry next = e.next;
- e.next = null;
- e = next;
- }
- }
+ super(new EqualpComparator(), size, rehashSize, rehashThreshold);
}
}
Modified: trunk/abcl/src/org/armedbear/lisp/HashTable.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/HashTable.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/HashTable.java Sat Oct 9 16:50:41 2010
@@ -30,276 +30,366 @@
* obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
-
package org.armedbear.lisp;
import static org.armedbear.lisp.Lisp.*;
-public abstract class HashTable extends LispObject
-{
- private static final int DEFAULT_SIZE = 16;
+public abstract class HashTable extends LispObject {
- protected static final float loadFactor = 0.75f;
+ private static final int DEFAULT_SIZE = 16;
+ protected static final float loadFactor = 0.75f;
+ protected final LispObject rehashSize;
+ protected final LispObject rehashThreshold;
+ // The rounded product of the capacity and the load factor. When the number
+ // of elements exceeds the threshold, the implementation calls rehash().
+ protected int threshold;
+ // Array containing the actual key-value mappings.
+ protected HashEntry[] buckets;
+ // The number of key-value pairs.
+ protected int count;
+ private int mask;
+ final Comparator comparator;
- protected final LispObject rehashSize;
- protected final LispObject rehashThreshold;
+ protected HashTable(int size, LispObject rehashSize,
+ LispObject rehashThreshold)
+ {
+ protected HashTable(Comparator c, int size, LispObject rehashSize,
+ LispObject rehashThreshold) {
+ this.rehashSize = rehashSize;
+ this.rehashThreshold = rehashThreshold;
+ buckets = new HashEntry[size];
+ threshold = (int) (size * loadFactor);
+ comparator = c;
+ mask = buckets.length - 1;
+ }
- // The rounded product of the capacity and the load factor. When the number
- // of elements exceeds the threshold, the implementation calls rehash().
- protected int threshold;
+ protected static int calculateInitialCapacity(int size) {
+ int capacity = 1;
+ while (capacity < size) {
+ capacity <<= 1;
+ }
+ return capacity;
+ }
- // Array containing the actual key-value mappings.
- protected HashEntry[] buckets;
+ public final LispObject getRehashSize() {
+ return rehashSize;
+ }
- // The number of key-value pairs.
- protected int count;
+ public final LispObject getRehashThreshold() {
+ return rehashThreshold;
+ }
- protected HashTable(int size, LispObject rehashSize,
- LispObject rehashThreshold)
- {
- this.rehashSize = rehashSize;
- this.rehashThreshold = rehashThreshold;
- buckets = new HashEntry[size];
- threshold = (int) (size * loadFactor);
- }
+ public int getSize() {
+ return buckets.length;
+ }
- protected static int calculateInitialCapacity(int size)
- {
- int capacity = 1;
- while (capacity < size)
- capacity <<= 1;
- return capacity;
- }
+ public int getCount() {
+ return count;
+ }
- public final LispObject getRehashSize()
- {
- return rehashSize;
- }
+ @Override
+ public LispObject typeOf() {
+ return Symbol.HASH_TABLE;
+ }
- public final LispObject getRehashThreshold()
- {
- return rehashThreshold;
- }
+ @Override
+ public LispObject classOf() {
+ return BuiltInClass.HASH_TABLE;
+ }
- public int getSize()
- {
- return buckets.length;
- }
+ @Override
+ public LispObject typep(LispObject type) {
+ if (type == Symbol.HASH_TABLE) {
+ return T;
+ }
+ if (type == BuiltInClass.HASH_TABLE) {
+ return T;
+ }
+ return super.typep(type);
+ }
- public int getCount()
- {
- return count;
- }
+ @Override
+ public boolean equalp(LispObject obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof HashTable) {
+ HashTable ht = (HashTable) obj;
+ if (count != ht.count) {
+ return false;
+ }
+ if (getTest() != ht.getTest()) {
+ return false;
+ }
+ LispObject entries = ENTRIES();
+ while (entries != NIL) {
+ LispObject entry = entries.car();
+ LispObject key = entry.car();
+ LispObject value = entry.cdr();
+ if (!value.equalp(ht.get(key))) {
+ return false;
+ }
+ entries = entries.cdr();
+ }
+ return true;
+ }
+ return false;
+ }
- public abstract Symbol getTest();
+ @Override
+ public LispObject getParts() {
+ LispObject parts = NIL;
+ for (int i = 0; i < buckets.length; i++) {
+ HashEntry e = buckets[i];
+ while (e != null) {
+ parts = parts.push(new Cons("KEY [bucket " + i + "]", e.key));
+ parts = parts.push(new Cons("VALUE", e.value));
+ e = e.next;
+ }
+ }
+ return parts.nreverse();
+ }
- @Override
- public LispObject typeOf()
- {
- return Symbol.HASH_TABLE;
- }
+ public synchronized void clear() {
+ for (int i = buckets.length; i-- > 0;) {
+ buckets[i] = null;
+ }
+ count = 0;
+ }
- @Override
- public LispObject classOf()
- {
- return BuiltInClass.HASH_TABLE;
- }
+ // gethash key hash-table &optional default => value, present-p
+ public synchronized LispObject gethash(LispObject key) {
+ LispObject value = get(key);
+ final LispObject presentp;
+ if (value == null) {
+ value = presentp = NIL;
+ } else {
+ presentp = T;
+ }
+ return LispThread.currentThread().setValues(value, presentp);
+ }
- @Override
- public LispObject typep(LispObject type)
- {
- if (type == Symbol.HASH_TABLE)
- return T;
- if (type == BuiltInClass.HASH_TABLE)
- return T;
- return super.typep(type);
- }
+ // gethash key hash-table &optional default => value, present-p
+ public synchronized LispObject gethash(LispObject key,
+ LispObject defaultValue) {
+ LispObject value = get(key);
+ final LispObject presentp;
+ if (value == null) {
+ value = defaultValue;
+ presentp = NIL;
+ } else {
+ presentp = T;
+ }
+ return LispThread.currentThread().setValues(value, presentp);
+ }
- @Override
- public boolean equalp(LispObject obj)
- {
- if (this == obj)
- return true;
- if (obj instanceof HashTable)
- {
- HashTable ht = (HashTable) obj;
- if (count != ht.count)
- return false;
- if (getTest() != ht.getTest())
- return false;
- LispObject entries = ENTRIES();
- while (entries != NIL)
- {
- LispObject entry = entries.car();
- LispObject key = entry.car();
- LispObject value = entry.cdr();
- if (!value.equalp(ht.get(key)))
- return false;
- entries = entries.cdr();
- }
- return true;
- }
- return false;
- }
+ public synchronized LispObject gethash1(LispObject key) {
+ final LispObject value = get(key);
+ return value != null ? value : NIL;
+ }
- @Override
- public LispObject getParts()
- {
- LispObject parts = NIL;
- for (int i = 0; i < buckets.length; i++)
- {
- HashEntry e = buckets[i];
- while (e != null)
- {
- parts = parts.push(new Cons("KEY [bucket " + i + "]", e.key));
- parts = parts.push(new Cons("VALUE", e.value));
- e = e.next;
- }
- }
- return parts.nreverse();
- }
+ public synchronized LispObject puthash(LispObject key, LispObject newValue) {
+ put(key, newValue);
+ return newValue;
+ }
- public synchronized void clear()
- {
- for (int i = buckets.length; i-- > 0;)
- buckets[i] = null;
- count = 0;
- }
+ // remhash key hash-table => generalized-boolean
+ public synchronized LispObject remhash(LispObject key) {
+ // A value in a Lisp hash table can never be null, so...
+ return remove(key) != null ? T : NIL;
+ }
- // gethash key hash-table &optional default => value, present-p
- public synchronized LispObject gethash(LispObject key)
+ @Override
+ public String writeToString() {
+ if (Symbol.PRINT_READABLY.symbolValue(LispThread.currentThread()) != NIL) {
+ error(new PrintNotReadable(list(Keyword.OBJECT, this)));
+ return null; // Not reached.
+ }
+ StringBuilder sb = new StringBuilder(getTest().writeToString());
+ sb.append(' ');
+ sb.append(Symbol.HASH_TABLE.writeToString());
+ sb.append(' ');
+ sb.append(count);
+ if (count == 1) {
+ sb.append(" entry");
+ } else {
+ sb.append(" entries");
+ }
+ sb.append(", ");
+ sb.append(buckets.length);
+ sb.append(" buckets");
+ return unreadableString(sb.toString());
+ }
- {
- LispObject value = get(key);
- final LispObject presentp;
- if (value == null)
- value = presentp = NIL;
- else
- presentp = T;
- return LispThread.currentThread().setValues(value, presentp);
- }
-
- // gethash key hash-table &optional default => value, present-p
- public synchronized LispObject gethash(LispObject key,
- LispObject defaultValue)
+ public Symbol getTest() {
+ return comparator.getTest();
+ }
- {
- LispObject value = get(key);
- final LispObject presentp;
- if (value == null)
- {
- value = defaultValue;
- presentp = NIL;
- }
- else
- presentp = T;
- return LispThread.currentThread().setValues(value, presentp);
- }
+ synchronized public LispObject get(LispObject key) {
+ int index = comparator.hash(key) & mask;
+ HashEntry e = buckets[index];
+ while (e != null) {
+ if (comparator.keysEqual(key, e.key)) {
+ return e.value;
+ }
+ e = e.next;
+ }
+ return null;
+ }
+
+ synchronized public void put(LispObject key, LispObject value) {
+ int index = comparator.hash(key) & mask;
+ for (HashEntry e = buckets[index]; e != null; e = e.next) {
+ if (comparator.keysEqual(key, e.key)) {
+ e.value = value;
+ return;
+ }
+ }
+ // Not found. We need to add a new entry.
+ if (++count > threshold) {
+ rehash();
+ // Need a new hash value to suit the bigger table.
+ index = comparator.hash(key) & mask;
+ }
+ buckets[index] = new HashEntry(key, value, buckets[index]);
+ }
- public synchronized LispObject gethash1(LispObject key)
+ synchronized public LispObject remove(LispObject key) {
+ int index = comparator.hash(key) & mask;
- {
- final LispObject value = get(key);
- return value != null ? value : NIL;
- }
+ HashEntry e = buckets[index];
+ HashEntry last = null;
+ while (e != null) {
+ if (comparator.keysEqual(key, e.key)) {
+ if (last == null) {
+ buckets[index] = e.next;
+ } else {
+ last.next = e.next;
+ }
+ --count;
+ return e.value;
+ }
+ last = e;
+ e = e.next;
+ }
+ return null;
+ }
- public synchronized LispObject puthash(LispObject key, LispObject newValue)
+ synchronized protected void rehash() {
+ final int newCapacity = buckets.length * 2;
+ threshold = (int) (newCapacity * loadFactor);
+ mask = newCapacity - 1;
+ HashEntry[] newBuckets = new HashEntry[newCapacity];
+
+ for (int i = buckets.length; i-- > 0;) {
+ HashEntry e = buckets[i];
+ while (e != null) {
+ final int index = comparator.hash(e.key) & mask;
+ newBuckets[index] = new HashEntry(e.key,e.value, newBuckets[index]);
+ e = e.next;
+ }
+ }
+ buckets = newBuckets;
+ }
- {
- put(key, newValue);
- return newValue;
- }
+ // Returns a list of (key . value) pairs.
+ public LispObject ENTRIES() {
+ LispObject list = NIL;
+ for (int i = buckets.length; i-- > 0;) {
+ HashEntry e = buckets[i];
+ while (e != null) {
+ list = new Cons(new Cons(e.key, e.value), list);
+ e = e.next;
+ }
+ }
+ return list;
+ }
- // remhash key hash-table => generalized-boolean
- public synchronized LispObject remhash(LispObject key)
+ public LispObject MAPHASH(LispObject function) {
+ for (int i = buckets.length; i-- > 0;) {
+ HashEntry e = buckets[i];
+ while (e != null) {
+ function.execute(e.key, e.value);
+ e = e.next;
+ }
+ }
+ return NIL;
+ }
- {
- // A value in a Lisp hash table can never be null, so...
- return remove(key) != null ? T : NIL;
- }
+ protected static class Comparator {
+ Symbol getTest() {
+ return Symbol.EQ;
+ }
+
+ boolean keysEqual(LispObject key1, LispObject key2) {
+ return key1 == key2;
+ }
+
+ int hash(LispObject key) {
+ return key.sxhash();
+ }
+ }
- @Override
- public String writeToString()
- {
- if (Symbol.PRINT_READABLY.symbolValue(LispThread.currentThread()) != NIL)
- {
- error(new PrintNotReadable(list(Keyword.OBJECT, this)));
- return null; // Not reached.
- }
- StringBuilder sb = new StringBuilder(getTest().writeToString());
- sb.append(' ');
- sb.append(Symbol.HASH_TABLE.writeToString());
- sb.append(' ');
- sb.append(count);
- if (count == 1)
- sb.append(" entry");
- else
- sb.append(" entries");
- sb.append(", ");
- sb.append(buckets.length);
- sb.append(" buckets");
- return unreadableString(sb.toString());
- }
-
- public abstract LispObject get(LispObject key);
-
- public abstract void put(LispObject key, LispObject value)
- ;
+ protected static class EqlComparator extends Comparator {
+ @Override
+ Symbol getTest() {
+ return Symbol.EQL;
+ }
+
+ @Override
+ boolean keysEqual(LispObject key1, LispObject key2) {
+ return key1.eql(key2);
+ }
+ }
- public abstract LispObject remove(LispObject key);
+ protected static class EqualComparator extends Comparator {
+ @Override
+ Symbol getTest() {
+ return Symbol.EQUAL;
+ }
+
+ @Override
+ boolean keysEqual(LispObject key1, LispObject key2) {
+ return key1.equal(key2);
+ }
+ }
- protected abstract void rehash();
+ protected static class EqualpComparator extends Comparator {
+ @Override
+ Symbol getTest() {
+ return Symbol.EQUALP;
+ }
+
+ @Override
+ boolean keysEqual(LispObject key1, LispObject key2) {
+ return key1.equalp(key2);
+ }
+
+ @Override
+ int hash(LispObject key) {
+ return key.psxhash();
+ }
+ }
- // Returns a list of (key . value) pairs.
- public LispObject ENTRIES()
- {
- LispObject list = NIL;
- for (int i = buckets.length; i-- > 0;)
- {
- HashEntry e = buckets[i];
- while (e != null)
- {
- list = new Cons(new Cons(e.key, e.value), list);
- e = e.next;
- }
- }
- return list;
- }
+ protected static class HashEntry {
- public LispObject MAPHASH(LispObject function)
- {
- for (int i = buckets.length; i-- > 0;)
- {
- HashEntry e = buckets[i];
- while (e != null)
- {
- function.execute(e.key, e.value);
- e = e.next;
- }
- }
- return NIL;
- }
+ LispObject key;
+ LispObject value;
+ HashEntry next;
+
+ HashEntry(LispObject key, LispObject value, HashEntry next) {
+ this.key = key;
+ this.value = value;
+ this.next = next;
+ }
+ }
- protected static class HashEntry
- {
- LispObject key;
- LispObject value;
- HashEntry next;
-
- HashEntry(LispObject key, LispObject value)
- {
- this.key = key;
- this.value = value;
- }
- }
-
- // For EQUALP hash tables.
- @Override
- public int psxhash()
- {
- long result = 2062775257; // Chosen at random.
- result = mix(result, count);
- result = mix(result, getTest().sxhash());
- return (int) (result & 0x7fffffff);
- }
+ // For EQUALP hash tables.
+ @Override
+ public int psxhash() {
+ long result = 2062775257; // Chosen at random.
+ result = mix(result, count);
+ result = mix(result, getTest().sxhash());
+ return (int) (result & 0x7fffffff);
+ }
}
More information about the armedbear-cvs
mailing list