On 1/19/07, gwtmp01 / mac.com <gwtmp01 / mac.com> wrote:

> I don't think this is technically possible because of the dynamic
> nature of Ruby.  That is to say that I think the task you describe
> is equivalent to the halting problem as it requires the ability to
> divine the intent of executable code by simply examining the code
> as opposed to running it and seeing what happens.

I think you are right, so let me amend my request a bit.

* I don't need to get the exact signature of every method provided or
required. File-based provides should be enough for what we need.
Anything more complex can be synthesized manually. In most cases, Ruby
provide would essentially be the filepath, with the $LOAD_PATH chopped
off the front and the extension removed. Thus,
/usr/lib/ruby/1.8/yaml.rb provides 'yaml'.

* Requires could be whatever was required at require time. I wrote a
quick and dirty requires generator that essentially overrode
Kernel.require to stuff the argument to require into a Set. Thus, for
yaml:

/usr/lib/ruby/1.8/yaml.rb requires the following modules:
"yaml/constants"
"yaml/ypath"
"yaml/error"
"yaml/rubytypes"
"stringio"
"date"
"rational"
"syck"
"yaml/syck"
"yaml/basenode"
"date/format"
"yaml/tag"
"yaml/stream"
"yaml/types"

The big question is whether Ruby C extensions are always required by
filename (i.e. if you have a C extension called big/foo.so, require
'big/foo' will load it). In Python, this is tricky, as the shared
library name may not be the thing you use with import at all.

The bottom line is to have a "good enough" provides/requires mechanism
that automates packaging information. It's obviously not perfect, as
two foo.rb's might do wildly different things.

Here's the code snippet, so far (quick and dirty is probably a vast
understatement):

require 'set'
$required = Set.new

module Kernel
    alias_method :old_require, :require
    def require(m)
        begin
            result = old_require(m)
        rescue LoadError => blargh
            print "warning: #{blargh}\n"
        rescue NameError
            true
        end
        $required = $required.add(m)
        result
    end
end

require(ARGV[0])

print "#{ARGV[0]} requires the following modules:\n"
$required.each { |file| p file }


-- 
scott parkerson. geek, erstwhile prophet and fool.
just a cog in the machinery: http://www.smerpology.org/sprocket/