This is Lua 5.1. It won’t work in 5.2 because they’re taking out
`getfenv` and `setfenv`. I don’t know whether that’s a bad thing, but
I’m pretty sure this particular use of that feature isn’t important
enough to count as an argument one way or the other.

To use it as it is:

    : kra...@inexorable:~/devel/inexorable-misc ; lua
    Lua 5.1.3  Copyright (C) 1994-2008 Lua.org, PUC-Rio
    > dofile('dependencies.lua')
    > demo()
    calling is_consonant with @; dependencies: 
            string
    calling is_consonant with x; dependencies: 
            vowels
            string
    calling is_consonant with a; dependencies: 
            vowels
            string
    > 

Here's the code for `dependencies.lua`, which is also available on
<http://canonical.org/~kragen/sw/inexorable-misc/> and by 
`git clone http://canonical.org/~kragen/sw/inexorable-misc.git`.

    #!/usr/bin/lua
    -- List the dependencies of a function, i.e. the values it uses from
    -- outside its own scope. Not sure if this works for upvalues.
    -- by Kragen Javier Sitaker, written 2009, dedicated to the public domain
    -- (i.e. I abandon all copyright in the work 
    -- so that anyone may use it for any purpose)

    function dependency_grabbing_metatable(target)
       local metatable = {}
       local dependencies = {}

       function metatable.__index(_, key) 
          dependencies[key] = true
          return target[key] 
       end

       function metatable.__newindex(_, key, value)
          dependencies[key] = true
          target[key] = value 
       end

       return metatable, dependencies
    end

    function read_logging_proxy(target)
       local proxy = {}
       local metatable, dependencies = dependency_grabbing_metatable(target)
       setmetatable(proxy, metatable)
       return proxy, dependencies
    end

    -- Return a table of the global variables accessed by calling a function.
    function get_dependencies(func, ...)
       local orig_env = getfenv(func)
       new_env, dependencies = read_logging_proxy(orig_env)
       setfenv(func, new_env)
       func(...)
       setfenv(func, orig_env)
       return dependencies
    end

    -- for demo:
    vowels = { a=true, e=true, i=true, o=true, u=true }
    function is_consonant(char)
       char = string.lower(char)
       if char < 'a' or char > 'z' then return false end
       return not vowels[char]
    end      

    function demo()
       for _, char in ipairs {'@', 'x', 'a'} do
          print('calling is_consonant with '..char..'; dependencies: ')
          for var in pairs(get_dependencies(is_consonant, char)) do
             print('', var)
          end
       end
    end

-- 
To unsubscribe: http://lists.canonical.org/mailman/listinfo/kragen-hacks

Reply via email to