How can I override the functionality for accessing variables in an environment?

TL;DR: How can I make a subclass of the base R environment type so that I can make a record of anytime R asks if a value exists in this environment?

I'm working on a slightly smarter caching process to help me with a project I'm working on. My initial approach was to digest the function or function body when the function is run. However, this seems to be too fragile: a new cache entry needs to be added any time there is a new entry in the file with the function's source. I could do a character representation of the function body, but the problem is that this wouldn't update if the definition changes because of an update of a function called within the body.

My envisioned solution is to execute the function body within an environment that keeps track of which entries (most importantly, which other R functions I've written) are accessed, and when checking whether a cache result is valid, including a digest of those functions too. I've tried this with different functions ($, [[, names) but none seem to be called in the evalq expression at the end.

If it is the case that this is internal and can't be modified with R subclassing, then that is good to know too.

I'm trying to merely print out the name of the variable being looked for in this reprex:

cachingEnv <- setClass("cachingEnv", contains = "environment", slots = c(bodies = "list"))

setMethod("$", c("cachingEnv"),
          function(x, name) {
            cat(paste0("name is", name, "\n"))
            ev <- as(x, "environment")
            print(rlang::env_print(ev))
            ev[[name]]
          })

ce <- cachingEnv()

ce$x <- 3

ce$x
#> name isx
#> <environment: 0x5583674819f8>
#> parent: <environment: 0x55836747e338>
#> bindings:
#>  * x: <dbl>
#> <environment: 0x5583674819f8>
#> [1] 3

evalq({x}, envir = ce)
#> [1] 3                              <- This is where I'm wishing for results like with ce$x

Created on 2021-11-22 by the reprex package (v1.0.0)