Restrict et.Let, et.MutateVar to StorageLocation

Previously Let and MutateVar were using BoundValue which can be either a
storage location, Scheme primitive or bound syntax. Only storage
locations make sense for et.Let and et.MutateVar. For example, it's
meaningless to assign a value to previously bound syntax

This is mostly a type annotation and unit test change. However, we also
now explicitly prevent set! on anything but storage locations
Add IsPureExpression

IsPureExpression conservatively determines if an et.Expression is pure.
This will be required for further passes such as storage annotation and
tree shaking