Change HashDict implementation to use tries with compound nodes

The new implementation is basically a tree of tuples (tries) but
they allow compond nodes (a node with a key-value pair and a
sub-tree). This removes the need for node-expansion and also simplifies
the design structure to not require multiple stages nor buckets.

The end result is a faster HashDict implementation (about 10% faster
on access, 30% on updates), which is still small for small dicts
but about 30% bigger for large dicts (in terms of memory) and with
a much simpler implementation.