simsym: Fix struct and map equality testing

Previously, these translated directly to Z3 equality of their
contents, bypassing any overridden __eq__ methods of the field and
value types.  Rewrite equality testing to work in terms of field/value
type equality.  This eliminates the notion of compound equality
testing, since that was fundamentally broken.

This affected the file system model because class Fs is itself a
struct, so testing for state equality bypassed the overridden __eq__
methods in state components like lists.  However, it shouldn't matter
for the correctness of most things; I think only file truncation and
pipes should ultimately be affected by the semantics of overridden
__eq__ methods.  It does, however, increase the number of testgen
enumeration failures on write/write from ~3 to ~9.
simsym: Correct and robust Symbolic.eq

Previously, Symbolic.eq assumed that compound dictionaries would have
the same keys and would iterate in the same order and didn't properly
handle compounds with concrete values.  In practice, it was never
called with anything that would violate these, but this depended on
subtle aspects of our implementation and CPython itself.  Fix these
problems to make Symbolic.eq robust.
simsym: Implement structural equality optimization universally

Previously, this was only done at the compound level.  Instead, make
Symbolic.__eq__ itself perform the optimization and require subclasses
to override _eq_internal instead of __eq__.
simsym: Getter for concrete integer values

This will be used for optimizations shortly.
symtypes: New "small" bounded list type

This new list type avoids the use of extensional arrays in the regular
list type, instead replacing them by a fixed set of fields plus a
length.  This is intended to be easier for Z3 to solve, since
extensional arrays are tricky.
simsym: Precisely type the result of symif

Previously, symif used a generic wrap call on its result, which works
for obvious types, but falls back to SExpr in harder cases like
tuinterpreted.  Prior to small lists, we had limited use of symif, so
this didn't cause problems, but small lists stress symif much more.

Modify symif to wrap its result in the type of its consequent (or
alternate, which must match).
fs: Use small list for file/pipe data

This brings the number of testgen errors for write/write down to 0.