func hashString(s string) uint32 {
	if len(s) >= 12 {
		return uint32(goStringHash(s, 0))
	}
	return softHashString(s)
}
hashString computes the hash of s.
package skylark
import (
	"fmt"
	_ "unsafe"  
)
type hashtable struct {
	table     []bucket   
	bucket0   [1]bucket  
	len       uint32
	itercount uint32   
	head      *entry   
	tailLink  **entry  
	frozen    bool
}
const bucketSize = 8
type bucket struct {
	entries [bucketSize]entry
	next    *bucket  
}
type entry struct {
	hash       uint32  
	key, value Value
	next       *entry   
	prevLink   **entry  
}
func (ht *hashtable) freeze() {
	if !ht.frozen {
		ht.frozen = true
		for i := range ht.table {
			for p := &ht.table[i]; p != nil; p = p.next {
				for i := range p.entries {
					e := &p.entries[i]
					if e.hash != 0 {
						e.key.Freeze()
						e.value.Freeze()
					}
				}
			}
		}
	}
}
func (ht *hashtable) insert(k, v Value) error {
	if ht.frozen {
		return fmt.Errorf("cannot insert into frozen hash table")
	}
	if ht.itercount > 0 {
		return fmt.Errorf("cannot insert into hash table during iteration")
	}
	if ht.table == nil {
		ht.table = ht.bucket0[:1]
		ht.tailLink = &ht.head
	}
	h, err := k.Hash()
	if err != nil {
		return err
	}
	if h == 0 {
		h = 1  
	}
retry:
	var insert *entry
	p := &ht.table[h&(uint32(len(ht.table)-1))]
	for {
		for i := range p.entries {
			e := &p.entries[i]
			if e.hash != h {
				if e.hash == 0 {
					insert = e
				}
				continue
			}
			if eq, err := Equal(k, e.key); err != nil {
				return err  
			} else if !eq {
				continue
			}
			e.value = v
			return nil
		}
		if p.next == nil {
			break
		}
		p = p.next
	}
	if overloaded(int(ht.len), len(ht.table)) {
		ht.grow()
		goto retry
	}
	if insert == nil {
		b := new(bucket)
		p.next = b
		insert = &b.entries[0]
	}
	insert.hash = h
	insert.key = k
	insert.value = v
	insert.prevLink = ht.tailLink
	*ht.tailLink = insert
	ht.tailLink = &insert.next
	ht.len++
	return nil
}
func overloaded(elems, buckets int) bool {
	const loadFactor = 6.5  
	return elems >= bucketSize && float64(elems) >= loadFactor*float64(buckets)
}
func (ht *hashtable) grow() {
	ht.table = make([]bucket, len(ht.table)<<1)
	oldhead := ht.head
	ht.head = nil
	ht.tailLink = &ht.head
	ht.len = 0
	for e := oldhead; e != nil; e = e.next {
		ht.insert(e.key, e.value)
	}
	ht.bucket0[0] = bucket{}  
}
func (ht *hashtable) lookup(k Value) (v Value, found bool, err error) {
	h, err := k.Hash()
	if err != nil {
		return nil, false, err  
	}
	if h == 0 {
		h = 1  
	}
	if ht.table == nil {
		return None, false, nil  
	}
	for p := &ht.table[h&(uint32(len(ht.table)-1))]; p != nil; p = p.next {
		for i := range p.entries {
			e := &p.entries[i]
			if e.hash == h {
				if eq, err := Equal(k, e.key); err != nil {
					return nil, false, err  
				} else if eq {
					return e.value, true, nil  
				}
			}
		}
	}
	return None, false, nil  
}
func (ht *hashtable) items() []Tuple {
	items := make([]Tuple, 0, ht.len)
	array := make([]Value, ht.len*2)  
	for e := ht.head; e != nil; e = e.next {
		pair := Tuple(array[:2:2])
		array = array[2:]
		pair[0] = e.key
		pair[1] = e.value
		items = append(items, pair)
	}
	return items
}
func (ht *hashtable) first() (Value, bool) {
	if ht.head != nil {
		return ht.head.key, true
	}
	return None, false
}
func (ht *hashtable) keys() []Value {
	keys := make([]Value, 0, ht.len)
	for e := ht.head; e != nil; e = e.next {
		keys = append(keys, e.key)
	}
	return keys
}
func (ht *hashtable) delete(k Value) (v Value, found bool, err error) {
	if ht.frozen {
		return nil, false, fmt.Errorf("cannot delete from frozen hash table")
	}
	if ht.itercount > 0 {
		return nil, false, fmt.Errorf("cannot delete from hash table during iteration")
	}
	if ht.table == nil {
		return None, false, nil  
	}
	h, err := k.Hash()
	if err != nil {
		return nil, false, err  
	}
	if h == 0 {
		h = 1  
	}
	for p := &ht.table[h&(uint32(len(ht.table)-1))]; p != nil; p = p.next {
		for i := range p.entries {
			e := &p.entries[i]
			if e.hash == h {
				if eq, err := Equal(k, e.key); err != nil {
					return nil, false, err
				} else if eq {
					*e.prevLink = e.next
					if e.next == nil {
						ht.tailLink = e.prevLink  
					} else {
						e.next.prevLink = e.prevLink
					}
					v := e.value
					*e = entry{}
					ht.len--
					return v, true, nil  
				}
			}
		}
	}
	return None, false, nil  
}
func (ht *hashtable) clear() error {
	if ht.frozen {
		return fmt.Errorf("cannot clear frozen hash table")
	}
	if ht.itercount > 0 {
		return fmt.Errorf("cannot clear hash table during iteration")
	}
	if ht.table != nil {
		for i := range ht.table {
			ht.table[i] = bucket{}
		}
	}
	ht.head = nil
	ht.tailLink = &ht.head
	ht.len = 0
	return nil
}
func (ht *hashtable) dump() {
	fmt.Printf("hashtable %p len=%d head=%p tailLink=%p",
		ht, ht.len, ht.head, ht.tailLink)
	if ht.tailLink != nil {
		fmt.Printf(" *tailLink=%p", *ht.tailLink)
	}
	fmt.Println()
	for j := range ht.table {
		fmt.Printf("bucket chain %d\n", j)
		for p := &ht.table[j]; p != nil; p = p.next {
			fmt.Printf("bucket %p\n", p)
			for i := range p.entries {
				e := &p.entries[i]
				fmt.Printf("\tentry %d @ %p hash=%d key=%v value=%v\n",
					i, e, e.hash, e.key, e.value)
				fmt.Printf("\t\tnext=%p &next=%p prev=%p",
					e.next, &e.next, e.prevLink)
				if e.prevLink != nil {
					fmt.Printf(" *prev=%p", *e.prevLink)
				}
				fmt.Println()
			}
		}
	}
}
func (ht *hashtable) iterate() *keyIterator {
	if !ht.frozen {
		ht.itercount++
	}
	return &keyIterator{ht: ht, e: ht.head}
}
type keyIterator struct {
	ht *hashtable
	e  *entry
}
func (it *keyIterator) Next(k *Value) bool {
	if it.e != nil {
		*k = it.e.key
		it.e = it.e.next
		return true
	}
	return false
}
func (it *keyIterator) Done() {
	if !it.ht.frozen {
		it.ht.itercount--
	}
}