Iota Collection Classes

The Iota Collection Classes are similar to the Java Collection Classes.  They are a substantial test case that no final compiler from CS412-SP00 could successfully compile.  So you'll want to be sure to test your compiler on lots of smaller cases before trying this one.

Disclaimer

These haven't been completely tested, especially the ListIterator and the HashEntrySet classes.


Collection.ii:

// Iota collections classes
// Author: Nathaniel Nystrom
// Date: 1 May 2000

interface Collection
{
	equator(): Equator

	// Add an object to the collection (at the end if ordered).
	// Return true if added.
	add(x: object): bool

	// Add all elements of a collection to the collection
	// (at the end if ordered).  Return true if added.
	addAll(x: Collection): bool

	// Remove all elements of the collection.
	clear()

	// Return true iff the collection contains x.
	contains(x: object): bool

	// Return true iff the collection contains all elements of x.
	containsAll(x: Collection): bool

	// Returns true iff the collection and x have the same elements.
	equals(x: Collection): bool

	// Return true iff the collection is empty.
	isEmpty(): bool

	// Get an iterator over the collection.
	iterator(): Iterator

	// Remove x from the collection, return true if removed.
	remove(x: object): bool

	// Remove all elements of x from the collection, return true if any
	// removed.
	removeAll(x: Collection): bool

	// Remove all but elements of x from the collection, return true if
	// any removed.
	retainAll(x: Collection): bool

	// Get the size of the collection.
	size(): int

	// Create an array containing all elements of the collection, in
	// iterator order.
	toArray(): array[object]
}

interface Iterator
{
	// Return true iff the iterator has another element to return.
	// This also returns false if the collection changed since the
	// iterator was created.
	hasNext(): bool

	// Return true iff the iterator has another element to return.
	// This returns null if the collection changed since the
	// iterator was created.
	next(): object

	// Remove the last element returned from the collection.
	remove()

	// This returns false iff the collection changed since the
	// iterator was created.
	valid(): bool
}

interface List extends Collection
{
	addAt(i: int, x: object): bool
	addAllAt(i: int, x: Collection): bool

	get(i: int): object

	listIterator(): ListIterator

	indexOf(x: object): int
	lastIndexOf(x: object): int

	removeAt(i: int): bool

	set(i: int, x: object)
}

interface ListIterator extends Iterator
{
	add(x: object)
}

interface Set extends Collection
{
}


interface MapEntry
{
	key(): object
	value(): object
}

interface Equatable
{
	equals(x: object): bool
}

interface Equator
{
	equals(x, y: object): bool
}

interface Hashable
{
	hash(): int
}

interface Hasher
{
	hash(x: object): int
}

interface Map
{
	keyEquator(): Equator
	valueEquator(): Equator

	clear()

	containsKey(k: object): bool
	containsValue(v: object): bool

	equals(x: Map): bool

	get(k: object): object
	put(k: object, v: object): object

	keys(): Set
	values(): Collection
	entries(): Set

	putAll(m: Map)

	remove(k: object)

	isEmpty(): bool

	size(): int
}

makeLinkedList(eq: Equator): List
makeArrayList(eq: Equator): List

makeHashSet(h: Hasher, eq: Equator): Set
makeHashMap(h: Hasher, keq: Equator, veq: Equator): Map

// Returns a Hasher that implements hash(x) as:
//	y: Hashable = cast(x, Hashable).hash();
//	if (y == null) 0 else y.hash()
makeDefaultHasher(): Hasher

// Returns a Hasher that implements hash(x) as:
//	y: Hashable = cast(x, Hashable).hash();
//	if (y == null) 0 else y.hash()
makeStringHasher(): Hasher

// Returns an Equator that implements equals(x,y) as x == y
makeDefaultEquator(): Equator

// Returns an Equator that implements equals(x,y) as x == y
makeStringEquator(): Equator

back to top


Collection.im:

// Iota collections classes implementation
// Author: Nathaniel Nystrom
// Date: 1 May 2000
//

uses io.print

// Constructor functions
makeLinkedList(eq: Equator): List = (
	l: LinkedList = new LinkedList;
	l.init(eq);
	l
)

makeArrayList(eq: Equator): List = (
	l: ArrayList = new ArrayList;
	l.init(eq);
	l
)

makeDefaultEquator(): Equator = new DefaultEquator
makeStringEquator(): Equator = new StringEquator
makeDefaultHasher(): Hasher = new DefaultHasher
makeStringHasher(): Hasher = new StringHasher

makeHashMap(h: Hasher, keq: Equator, veq: Equator): Map = (
	m: HashMap = new HashMap;
	m.init(h, keq, veq);
	m
)

makeHashSet(h: Hasher, eq: Equator): Set = (
	s: HashSet = new HashSet;
	s.init(h, eq);
	s
)

class DefaultEquator implements Equator
{
	equals(x: object, y: object): bool = (x == y)
}

class StringEquator implements Equator
{
	equals(x: object, y: object): bool = (
		if (x == y)
			true
		else if (x == null | y == null)
			false
		else (
			xx: string = cast(x, string);
			yy: string = cast(y, string);
			xx == yy
		)
	)
}

class DefaultHasher implements Hasher
{
	hash(x: object): int = (
		a: Hashable = cast(x, Hashable);
		if (a) a.hash() else 0
	)
}

class StringHasher implements Hasher
{
	hash(x: object): int = (
		a: string = cast(x, string);
		if (a) (
		    h: int = 0;
		    i: int = 0;
		    while (i < length(a)) (
			h = h + a[i] * (a[i] + i);
			i++
		    );
		    h
		)
		else 0
	)
}

// A linked list implementation
class LinkedList implements List
{
	nil: Link
	len: int
	version: int
        eq: Equator

	init(e: Equator) = (
		eq = e;
		nil = new Link;
		nil.prev = nil;
		nil.next = nil;
		nil.data = null;
		len = 0;
		version = 0
	)

	// From Collection.int

	add(x: object): bool = (
		newLink: Link = new Link;
		newLink.data = x;
		newLink.next = nil;
		newLink.prev = nil.prev;
		nil.prev.next = newLink;
		nil.prev = newLink;
		len++;
		version++;
		true
	)

	addAll(x: Collection): bool = sharedAddAll(this, x)

	clear() = (
		nil.next = nil;
		nil.prev = nil;
		len = 0;
		version++
	)

	contains(x: object): bool = sharedContains(this, x)
	containsAll(x: Collection): bool = sharedContainsAll(this, x)
	equals(x: Collection): bool = sharedEquals(this, x)

	equator(): Equator = eq

	isEmpty(): bool = (len == 0)

	listIterator(): ListIterator = (
		i: LinkedListIterator = new LinkedListIterator;
		i.init(this);
		i
	)

	listIteratorAt(j: int): ListIterator = (
		i: LinkedListIterator = new LinkedListIterator;
		i.init(this);
		while (j >= 0) (
			if (! i.hasNext()) break;
			i.next();
			j--
		);
		i
	)

	iterator(): Iterator = listIterator()

	remove(x: object): bool = (
		p: Link = nil.next;

		while (p != nil) (
			if (eq.equals(p.data, x)) (
				p.prev.next = p.next;
				p.next.prev = p.prev;
				len--;
				version++;
				return true
			);
			p = p.next
		);
		false
	)

	removeAll(x: Collection): bool = sharedRemoveAll(this, x)

	retainAll(x: Collection): bool = (
		r: bool = false;
		p: Link = nil.next;

		while (p != nil) (
			if (! x.contains(p.data)) (
				p.prev.next = p.next;
				p.next.prev = p.prev;
				len--;
				version++;
				r = true
			);
			p = p.next
		);
		r
	)

	size(): int = len

	toArray(): array[object] = sharedToArray(this)

	// From List.int

	addAt(i: int, x: object): bool = (
		if (i == len) (
			return add(x)
		)
		else if (i > len | i < 0) (
			return false
		);

		j: int = 0;
		p: Link = nil.next;

		while (p != nil) (
			if (j == i) (
				// insert before p
				newLink: Link = new Link;
				newLink.data = x;
				newLink.next = p;
				newLink.prev = p.prev;
				p.prev.next = newLink;
				p.prev = newLink;
				len++;
				version++;
				break
			);
			p = p.next
		);

		true
	)

	addAllAt(i: int, x: Collection): bool = (
		if (i == len) (
			return addAll(x)
		)
		else if (i > len | i < 0) (
			return false
		);

		j: int = 0;
		p: Link = nil.next;

		while (p != nil) (
			if (j == i) (
				p = p.prev;

				// insert after p

				k: Iterator = x.iterator();
				while (k.hasNext()) (
					newLink: Link = new Link;
					newLink.data = k.next();
					newLink.next = p.next;
					newLink.prev = p;
					p.next.prev = newLink;
					p.next = newLink;
					len++;
					version++
				);
				break
			);
			p = p.next
		);

		true
	)

	get(i: int): object = (
		a: object = null;
		j: int = 0;
		k: Iterator = iterator();
		while (k.hasNext()) (
			a = k.next();
			if (i == j) break;
			j++
		);
		a
	)

	indexOf(x: object): int = (
		j: int = 0;
		i: Iterator = iterator();
		while (i.hasNext()) (
			a: object = i.next();
			if (a == x) return j;
			j++;
		);
		-1
	)

	lastIndexOf(x: object): int = (
		last: int = -1;
		j: int = 0;
		i: Iterator = iterator();
		while (i.hasNext()) (
			a: object = i.next();
			if (a == x) last = j;
			j++;
		);
		last
	)

	removeAt(i: int): bool = (
		if (i >= len | i < 0) (
			return false
		);

		j: int = 0;
		p: Link = nil.next;

		while (p != nil) (
			if (j == i) (
				p.prev.next = p.next;
				p.next.prev = p.prev;
				len--;
				version++;
				return true
			);
			p = p.next
		);
		false
	)

	set(i: int, x: object) = (
		if (i >= len | i < 0) (
			return
		);

		j: int = 0;
		p: Link = nil.next;

		while (p != nil) (
			if (j == i) (
				p.data = x;
				break
			)
		)
	)
}

// A link in a linked list
class Link
{
	data: object
	prev: Link
	next: Link
}

// Iterator for linked lists
class LinkedListIterator implements ListIterator
{
	list: LinkedList
	curr: Link	// Always points to the last element returned.
	version: int

	init(l: LinkedList) = (
		list = l;
		curr = list.nil;
		version = list.version
	)

	hasNext(): bool = (
		valid() & curr.next != list.nil
	)

	hasPrevious(): bool = (
		valid() & curr.prev != list.nil
	)

	next(): object = (
		if (valid() & curr.next != list.nil) (
			a: object = curr.next.data;
			curr = curr.next;
			a
		)
		else
			null
	)

	previous(): object = (
		if (valid() & curr.prev != list.nil) (
			a: object = curr.prev.data;
			curr = curr.prev;
			a
		)
		else
			null
	)

	// Remove the last element returned (curr), updating curr to its
	// next element.
	remove() = (
		nuke: Link = curr;
		curr = curr.next;
		if (valid() & nuke != list.nil) (
			nuke.prev.next = nuke.next;
			nuke.next.prev = nuke.prev;
			list.len--;
			list.version++;
			version = list.version;
		)
	)

	valid(): bool = (version == list.version)

	set(x: object) = (
		if (valid() & curr != list.nil)
			curr.data = x
	)

	// Add before the next element to be returned by next() and before
	// the next element to be returned by prev().  The new element
	// is inserted before the last element returned (curr).
	// curr is NOT updated, so the next call to next() will NOT
	// return the new element, but the next call to previous() will.
	add(x: object) = (
		if (valid() & curr != list.nil) (
			newLink: Link = new Link;
			newLink.data = x;
			newLink.next = curr;
			newLink.prev = curr.prev;
			curr.prev.next = newLink;
			curr.prev = newLink;
			list.len++;
			list.version++;
			version = list.version
		)
	)
}

// A vector implementation
class ArrayList implements List
{
	len: int
	data: array[object]
	version: int
	equ: Equator

	equator(): Equator = equ

	init(e: Equator) = (
		data = new object[10](null);
		equ = e;
		len = 0;
		version = 0
	)

	grow(newlen: int) = (
		if (length(data) < newlen) (
			d: array[object] = new object[newlen](null);
			i: int = 0;
			while (i < len) (
				d[i] = data[i];
				i++
			);
			data = d
		)
	)

	// From Collection.int

	add(x: object): bool = (
		grow(len+1);
		data[len] = x;
		len++;
		version++;
		true
	)

	addAll(x: Collection): bool = (
		grow(len+x.size());
		sharedAddAll(this, x)
	)

	clear() = (
		// realloc to let GC collect the old array elements
		data = new object[10](null);
		len = 0;
		version++
	)

	contains(x: object): bool = sharedContains(this, x)
	containsAll(x: Collection): bool = sharedContainsAll(this, x)
	equals(x: Collection): bool = sharedEquals(this, x)

	isEmpty(): bool = (len == 0)

	listIterator(): ListIterator = (
		i: ArrayListIterator = new ArrayListIterator;
		i.init(this);
		i
	)

	listIteratorAt(j: int): ListIterator = (
		i: ArrayListIterator = new ArrayListIterator;
		i.init(this);
		while (j >= 0) (
			if (! i.hasNext()) break;
			i.next();
			j--
		);
		i
	)

	iterator(): Iterator = listIterator()

	remove(x: object): bool = (
		i: int = sharedIndexOf(this, x);
		if (i >= 0) removeAt(i);
		true
	)

	removeAll(x: Collection): bool = sharedRemoveAll(this, x)
	retainAll(x: Collection): bool = sharedRetainAll(this, x)

	size(): int = len

	toArray(): array[object] = sharedToArray(this)

	// From List.int

	addAt(i: int, x: object): bool = (
		if (i == len) (
			return add(x)
		)
		else if (i > len | i < 0) (
			return false
		);

		grow(len+1);

		j: int = len;

		while (j > i) (
			data[j] = data[j-1]
		);

		data[i] = x;

		true
	)

	addAllAt(i: int, x: Collection): bool = (
		if (i == len) (
			return addAll(x)
		)
		else if (i > len | i < 0) (
			return false
		);

		n: int = x.size();

		grow(len + n);

		j: int = len + n;

		while (j > i) (
			data[j] = data[j-n];
		);

		k: Iterator = x.iterator();

		while (k.hasNext()) (
			a: object = k.next();
			data[i] = a;
			i++
		);

		true
	)

	get(i: int): object = (if (i > len | i < 0) null else data[i])

	indexOf(x: object): int = sharedIndexOf(this, x)
	lastIndexOf(x: object): int = sharedLastIndexOf(this, x)

	removeAt(i: int): bool = (
		if (i >= len | i < 0) (
			return false
		);

		len--;

		while (i < len) (
			data[i] = data[i+1];
			i++
		);

		version++;

		true
	)

	set(i: int, x: object) = (
		if (i >= len | i < 0) (
			return
		);

		data[i] = x
	)
}

// Iterator for ArrayLists
class ArrayListIterator implements ListIterator
{
	list: ArrayList
	curr: int
	version: int

	init(l: ArrayList) = (
		list = l;
		curr = -1;
		version = list.version
	)

	hasNext(): bool = (
		valid() & curr != list.len-1
	)

	hasPrevious(): bool = (
		valid() & curr != 0
	)

	next(): object = (
		if (valid() & curr != list.len-1) (
			a: object = list.data[curr+1];
			curr++;
			a
		)
		else
			null
	)

	previous(): object = (
		if (curr == -1) curr = list.len;
		if (valid() & curr != 0) (
			a: object = list.data[curr-1];
			curr--;
			a
		)
		else
			null
	)

	// Remove the last element returned (curr), updating curr to its
	// next element.
	remove() = (
		if (valid() & curr >= 0 & curr < list.len) (
			list.removeAt(curr);
			version = list.version
		)
	)

	valid(): bool = (version == list.version)

	set(x: object) = (
		if (valid() & curr >= 0 & curr < list.len)
			list.data[curr] = x
	)

	// Add before the next element to be returned by next() and before
	// the next element to be returned by prev().  The new element
	// is inserted before the last element returned (curr).
	// curr is NOT updated, so the next call to next() will NOT
	// return the new element, but the next call to previous() will.
	add(x: object) = (
		if (valid() & curr >= 0 & curr < list.len) (
			list.addAt(curr, x);
			curr++;
			version = list.version
		)
	)
}

// Methods shared between collections
sharedAddAll(self: Collection, x: Collection): bool = (
	added: bool = false;
	i: Iterator = x.iterator();
	while (i.hasNext()) (
		a: object = i.next();
		if (self.add(a)) added = true
	);
	added
)

sharedContainsAll(self: Collection, x: Collection): bool = (
	i: Iterator = x.iterator();
	while (i.hasNext()) (
		a: object = i.next();
		if (! self.contains(a)) return false
	);
	true
)

sharedEquals(self: Collection, x: Collection): bool = (
	if (self.size() != x.size())
		return false;

	i: Iterator = self.iterator();
	j: Iterator = x.iterator();

	while (i.hasNext()) (
		if (! j.hasNext()) return false;
		a: object = i.next();
		b: object = j.next();
		if (! self.equator().equals(a, b)) return false
	);

	return ! j.hasNext()
)

sharedRemoveAll(self: Collection, x: Collection): bool = (
	r: bool = false;
	i: Iterator = x.iterator();
	while (i.hasNext()) (
		a: object = i.next();
		if (self.remove(a)) r = true
	);
	r
)

sharedRetainAll(self: Collection, x: Collection): bool = (
	r: bool = false;
	i: Iterator = self.iterator();
	while (i.hasNext()) (
		a: object = i.next();
		if (! x.contains(a)) (
			i.remove();
			r = true
		)
	);
	r
)

sharedToArray(self: Collection): array[object] = (
	r: array[object] = new object[self.size()](null);

	j: int = 0;
	i: Iterator = self.iterator();
	while (i.hasNext()) (
		a: object = i.next();
		r[j] = a;
		j++
	);

	/* This shouldn't happen! */
	if (j != self.size()) return null;

	r
)

sharedContains(self: Collection, x: object): bool = (
	i: Iterator = self.iterator();
	while (i.hasNext()) (
		a: object = i.next();
		if (self.equator().equals(a, x)) return true
	);
	false
)

// Methods shared between lists
sharedIndexOf(self: List, x: object): int = (
	j: int = 0;
	i: Iterator = self.iterator();
	while (i.hasNext()) (
		a: object = i.next();
		if (self.equator().equals(a, x)) return j;
		j++;
	);
	-1
)

sharedLastIndexOf(self: List, x: object): int = (
	last: int = -1;
	j: int = 0;
	i: Iterator = self.iterator();
	while (i.hasNext()) (
		a: object = i.next();
		if (self.equator().equals(a, x)) last = j;
		j++;
	);
	last
)

class HashEntry implements MapEntry
{
	k: object
	v: object
	next: HashEntry

	key(): object = k
	value(): object = v
}

KEYS = 0
ENTRIES = 1

class HashEntrySetIterator implements Iterator
{
	curr: int
	entry: HashEntry
	set: HashEntrySet
	version: int

	init(s: HashEntrySet) = (
		set = s;
		version = s.version;
		curr = 0;
	        entry = null;
		advance()
	)

	advance() = (
		while (entry == null & curr < length(set.map.table)) (
			entry = set.map.table[curr];
			curr++
		)
	)
	
	valid(): bool = (version == set.version &
			 set.version == set.map.version)

	hasNext(): bool = (valid() & entry != null)

	next(): object = (
		if (valid() & entry != null) (
			x: object;

			if (set.type == ENTRIES) (
				x = entry
			)
			else if (set.type == KEYS) (
				x = entry.k
			);

			entry = entry.next;
			advance();

			x
		)
		else (
			null
		)
	)

	// Unimplemented
	remove(): bool = false
}

class MapEntryEquator implements Equator
{
	keyEquator: Equator
	valueEquator: Equator

	init(keq: Equator, veq: Equator) = (
	    keyEquator = keq;
	    valueEquator = veq
	)

	equals(x: object, y: object): bool = (
		xx: MapEntry = cast(x, MapEntry);
		yy: MapEntry = cast(y, MapEntry);
		if (xx & yy)
			keyEquator.equals(xx.key(), yy.key()) &
				valueEquator.equals(xx.value(), yy.value())
		else
			x == y
	)
}

class HashEntrySet implements Set
{
	map: HashMap
	version: int
	type: int

	init(m: HashMap, t: int) = (
		map = m;
		version = m.version;
		type = t;
	)

	valid(): bool = (version == map.version)

	equator(): Equator = (
		if (type == ENTRIES) (
		    eq: MapEntryEquator = new MapEntryEquator;
		    eq.init(map.keyEquator(), map.valueEquator());
		    eq
		)
		else if (type == KEYS) (
		    map.keyEquator()
		)
		else (
		    null
		)
	)

	// Add an object to the collection (at the end if ordered).
	// Return true if added.
	add(x: object): bool = (
		if (valid() & type == ENTRIES) (
		    e: MapEntry = cast(x, MapEntry);
		    if (e) (
			map.put(e.key(), e.value());
			version = map.version;
			return true
		    )
		);
		false
	)

	// Add all elements of a collection to the collection
	// (at the end if ordered).  Return true if added.
	addAll(x: Collection): bool = sharedAddAll(this, x)

	// Remove all elements of the collection.
	clear() = (
		if (valid()) (
			map.clear();
			version = map.version
		)
	)

	// Return true iff the collection contains x.
	contains(x: object): bool = (
		if (! valid()) return false;

		if (type == ENTRIES) (
		    e: MapEntry = cast(x, MapEntry);
		    if (e) (
			return map.valueEquator().
				equals(map.get(e.key()), e.value())
		    )
		)
		else if (type == KEYS) (
		    return map.containsKey(x)
		);
		false
	)

	// Return true iff the collection contains all elements of x.
	containsAll(x: Collection): bool = sharedContainsAll(this, x)

	// Returns true iff the collection and x have the same elements
	// in iterator order.
	equals(x: Collection): bool = sharedEquals(this, x)

	// Return true iff the collection is empty.
	isEmpty(): bool = map.isEmpty()

	// Get an iterator over the collection.
	iterator(): Iterator = (
		i: HashEntrySetIterator = new HashEntrySetIterator;
		i.init(this);
		i
	)

	// Remove x from the collection, return true if removed.
	remove(x: object): bool = (
		if (! valid()) return false;

		if (type == ENTRIES) (
		    e: MapEntry = cast(x, MapEntry);
		    if (e) (
			if (map.valueEquator().
				equals(map.get(e.key()), e.value())) (

				map.remove(e.key());
				version = map.version;
				return true
			)
		    )
		)
		else if (type == KEYS) (
		    e: MapEntry = cast(x, MapEntry);
		    if (map.containsKey(e.key())) (
		        map.remove(e.key());
		        return true
		    )
		);
		false
	)

	// Remove all elements of x from the collection, return true if any
	// removed.
	removeAll(x: Collection): bool = sharedRemoveAll(this, x)

	// Remove all but elements of x from the collection, return true if
	// any removed.
	retainAll(x: Collection): bool = sharedRetainAll(this, x)

	// Get the size of the collection.
	size(): int = map.count

	// Create an array containing all elements of the collection, in
	// iterator order.
	toArray(): array[object] = sharedToArray(this)
}

class HashMap implements Map
{
	table: array[HashEntry]
	count: int
	version: int
	hasher: Hasher
	keyEqu: Equator
	valueEqu: Equator

	keyEquator(): Equator = keyEqu
	valueEquator(): Equator = valueEqu

	init(h: Hasher, keq: Equator, veq: Equator) = (
		hasher = h;
		keyEqu = keq;
		valueEqu = veq;
		table = new HashEntry[101](null);
		count = 0;
		version = 0
	)

	clear() = (
		table = new HashEntry[101](null);
		count = 0;
		version++
	)

	containsKey(k: object): bool = (
		h: int = hasher.hash(k);
		e: HashEntry;
		e = table[h % length(table)];
		while (e) (
			if (keyEqu.equals(e.k, k))
				return true;
			e = e.next
		);
		false
	)

	containsValue(v: object): bool = (
		i: int;
		e: HashEntry;
		i = 0;
		while (i < length(table)) (
			e = table[i];
			while (e) (
				if (valueEqu.equals(e.v, v))
					return true;
				e = e.next
			);
			i++
		);
		false
	)
	
	// Unimplemented
	equals(x: Map): bool = false

	get(k: object): object = (
		h: int = hasher.hash(k);
		e: HashEntry;
		e = table[h % length(table)];
		while (e) (
			if (keyEqu.equals(e.k, k)) (
				return e.v
			) else (
				e = e.next
			)
		);
		null
	)

	put(k: object, v: object): object = (
		h: int = hasher.hash(k);
		e: HashEntry;
		e = table[h % length(table)];
		while (e) (
			if (keyEqu.equals(e.k, k)) (
				old: object = e.v;
				e.v = v;
				return old
			);
			e = e.next
		);

		// Will have more than 1 entry per bucket.  Rehash.
		if (count / length(table) >= 1) rehash();

		count++;
		e = new HashEntry;
		e.k = k;
		e.v = v;
		e.next = table[h % length(table)];
		table[h % length(table)] = e;
		null
	)

	rehash() = (
		newsize: int = count * 2;
		if (newsize < 101) newsize = 101;

		newtable: array[HashEntry] = new HashEntry[newsize](null);

		i: int = 0;

		while (i < length(table)) (
			e, n: HashEntry;
			e = table[i];
			while (e) (
				n = e.next;
				h: int = hasher.hash(e.k);
				e.next = newtable[h % length(newtable)];
				newtable[h % length(newtable)] = e;
				e = n
			);
			i++
		);

		table = newtable;
	)

	keys(): Set = (
		s: HashEntrySet = new HashEntrySet;
		s.init(this, KEYS);
		s
	)

	// Unimplemented
	values(): Set = null

	entries(): Set = (
		s: HashEntrySet = new HashEntrySet;
		s.init(this, ENTRIES);
		s
	)

	putAll(m: Map) = (
	    i: Iterator = m.keys().iterator();
	    while (i.hasNext()) (
		k: object = i.next();
		v: object = m.get(k);
		put(k, v)
	    )
	)

	remove(k: object) = (
		h: int = hasher.hash(k);
		e: HashEntry;
		e = table[h % length(table)];
		if (e) (
		    if (keyEqu.equals(e.k, k)) (
			table[h % length(table)] = e.next;
			count--;
			return
		    )
		    else (
			while (e.next) (
			    if (keyEqu.equals(e.next.k, k)) (
				  e.next = e.next.next;
				  count--;
				  return
			    );
			    e = e.next
			)
		    )
		)
	)

	isEmpty(): bool = (count == 0)

	size(): int = count
}

class HashSet implements Set
{
	map: HashMap

	init(h: Hasher, eq: Equator) = (
		map = new HashMap;
		map.init(h, eq, eq)
	)

	equator(): Equator = map.keyEquator()

	// Add an object to the collection (at the end if ordered).
	// Return true if added.
	add(x: object): bool = (map.put(x, x); true)

	// Add all elements of a collection to the collection
	// (at the end if ordered).  Return true if added.
	addAll(x: Collection): bool = sharedAddAll(this, x)

	// Remove all elements of the collection.
	clear() = map.clear()

	// Return true iff the collection contains x.
	contains(x: object): bool = map.containsKey(x)

	// Return true iff the collection contains all elements of x.
	containsAll(x: Collection): bool = sharedContainsAll(this, x)

	// Returns true iff the collection and x have the same elements.
	equals(x: Collection): bool = (
		sharedContainsAll(this, x) &
		sharedContainsAll(x, this)
	)

	// Return true iff the collection is empty.
	isEmpty(): bool = map.isEmpty()

	// Get an iterator over the collection.
	iterator(): Iterator = map.keys().iterator()

	// Remove x from the collection, return true if removed.
	remove(x: object): bool = (
		r: bool = map.containsKey(x);
		if (r) map.remove(x);
		r
	)

	// Remove all elements of x from the collection, return true if any
	// removed.
	removeAll(x: Collection): bool = sharedRemoveAll(this, x)

	// Remove all but elements of x from the collection, return true if
	// any removed.
	retainAll(x: Collection): bool = sharedRetainAll(this, x)

	// Get the size of the collection.
	size(): int = map.size()

	// Create an array containing all elements of the collection, in
	// iterator order.
	toArray(): array[object] = sharedToArray(this)
}

back to top


HashTest.im:

uses Collection.makeHashMap,
     Collection.makeStringHasher,
     Collection.makeStringEquator,
     Collection.Map,
     Collection.Collection,
     Collection.Set,
     Collection.Iterator,
     Collection.MapEntry,
     Collection.Hasher,
     Collection.Equator,
     io.print,
     conv.itos

main(args: array[string]): int = (
	m: Map;

	m = makeHashMap(makeStringHasher(), makeStringEquator(),
					    makeStringEquator());
	
	testMap(m);

	0
)

SIZE = 10000

testMap(m: Map) = (
	x: string;
	xx: object;

	i: int = 0;

	while (i < SIZE) (
		k: string = itos(i);
		v: string = itos(i+1);
		m.put(k, v);
		i++
	);

	xx = m.get("3521");
	x = cast(xx, string);

	if (!xx)
	    print("oops: get failed (null)\N")
	else if (x != "3522")
	    print("oops: get failed\N")
	else
	    print("ok: get successful\N");

	size: int = m.size();

	// Re-map a key.
	m.put("0", "0");

	xx = m.get("0");
	x = cast(xx, string);

	if (!xx)
	    print("oops: get failed (null)\N")
	else if (x != "0")
	    print("oops: get failed\N")
	else
	    print("ok: get successful\N");

	if (m.size() == size)
	    print("ok: put idempotent\N")
	else
	    print("oops: put not idempotent\N");

	i = 1;

	while (i < SIZE) (
		k: string = itos(i);
		m.remove(k);
		i++
	);

	if (m.size() == 1)
	    print("ok: remove successful\N")
	else
	    print("oops: remove failed\N");

)

printCollection(c: Collection) = (
	i: Iterator;
	a: string;
	n: int = 0;

	i = c.iterator();

	while (i.hasNext()) (
		a = cast(i.next(), string);
 
		if (n > 64) (
			print("\N");
			n = 0
		);

		print(a);
		n = n + length(a) + 1;

		if (i.hasNext()) print(" ") else print("\N")
	)
)

printMap(m: Map) = (
	i: Iterator;
	e: MapEntry;
	a: string;
	b: string;
	n: int = 0;

	i = m.entries().iterator();

	while (i.hasNext()) (
		e = cast(i.next(), MapEntry);
		
		a = cast(e.key(), string);
		b = cast(e.value(), string);

		if (n > 64) (
			print("\N");
			n = 0
		);

		print("[" + a + " => " + b + "]");
		n = n + length(a) + length(b) + 7;

		if (i.hasNext()) print(" ") else print("\N")
	)
)

back to top