// $G $F.go && $L $F.$A && ./$A.out

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

// ----------------------------------------------------------------------------
// Helper functions

func ASSERT(p bool) {
	if !p {
		// panic 0;
	}
}


// ----------------------------------------------------------------------------
// Implementation of the HashMap

type KeyType interface {
	Hash() uint32;
	Match(other *KeyType) bool
}


type ValueType interface {
	// empty interface
}


type Entry struct {
	key *KeyType;
	value *ValueType;
}


// Using the Array type below doesn't seem to work
//type Array array [1024] Entry;

type HashMap struct {
	map_ *[1024] Entry;
	log2_capacity_ uint32;
	occupancy_ uint32;
}


func (m *HashMap) capacity() uint32 {
	return 1 << m.log2_capacity_;
}


func (m *HashMap) Clear() {
	// Mark all entries as empty.
	var i uint32 = m.capacity() - 1;
	for i > 0 {
		m.map_[i].key = nil;
		i = i - 1
	}
	m.occupancy_ = 0
}


func (m *HashMap) Initialize (initial_log2_capacity uint32) {
	m.log2_capacity_ = initial_log2_capacity;
	m.map_ = new([1024] Entry);
	m.Clear();
}


func (m *HashMap) Probe (key *KeyType) *Entry {
	ASSERT(key != nil);

	var i uint32 = key.Hash() % m.capacity();
	ASSERT(0 <= i && i < m.capacity());
	
	ASSERT(m.occupancy_ < m.capacity());	// guarantees loop termination
	for m.map_[i].key != nil && !m.map_[i].key.Match(key) {
		i++;
		if i >= m.capacity() {
			i = 0;
		}
	}
	
	return &m.map_[i];
}


func (m *HashMap) Resize();


func (m *HashMap) Lookup (key *KeyType, insert bool) *Entry {
	// Find a matching entry.
	var p *Entry = m.Probe(key);
		if p.key != nil {
		return p;
	}

	// No entry found; insert one if necessary.
	if insert {
		p.key = key;
		p.value = nil;
		m.occupancy_++;
	
		// Grow the map if we reached >= 80% occupancy.
		if m.occupancy_ + m.occupancy_/4 >= m.capacity() {
			m.Resize();
			p = m.Probe(key);
		}
		
		return p;
	}

	// No entry found and none inserted.
	return nil;
}


func (m *HashMap) Resize() {
	var hmap *[1024] Entry = m.map_;
	var n uint32 = m.occupancy_;
	
	// Allocate a new map of twice the current size.
	m.Initialize(m.log2_capacity_ << 1);
	
	// Rehash all current entries.
	var i uint32 = 0;
	for n > 0 {
		if hmap[i].key != nil {
			m.Lookup(hmap[i].key, true).value = hmap[i].value;
			n = n - 1;
		}
		i++;
	}
}


// ----------------------------------------------------------------------------
// Test code

type Number struct {
	x uint32;
}


func (n *Number) Hash() uint32 {
	return n.x * 23;
}


func (n *Number) Match(other *KeyType) bool {
	// var y *Number = other;
	// return n.x == y.x;
	return false;
}


func MakeNumber (x uint32) *Number {
	var n *Number = new(Number);
	n.x = x;
	return n;
}


func main() {
	//f unc (n int) int { return n + 1; }(1);

	//print "HashMap - gri 2/8/2008\n";
	
	var hmap *HashMap = new(HashMap);
	hmap.Initialize(0);
	
	var x1 *Number = MakeNumber(1001);
	var x2 *Number = MakeNumber(2002);
	var x3 *Number = MakeNumber(3003);
	
	// this doesn't work I think...
	//hmap.Lookup(x1, true);
	//hmap.Lookup(x2, true);
	//hmap.Lookup(x3, true);
	
	//print "done\n";
}
