`compile_internal` generates the cache key

Passing a cache key to compile_internal is error prone and
laborious, so this PR changes `compile_internal` to generate the
cache key. This also enables caching for all calls to it, some of
which were previously not enabled because they passed no
`cache_key`.

This also adds a test for the caching, which checks the size of
the cache after the compilation of functions to determine whether
the cache is being used correctly.
Just add it on the end. To check that a different signature doesn't reuse the already cached version.