ptkwt@shell1.aracnet.com (Phil Tomson) writes:
Hmmmm… interesting idea. So basically what you’re proposing would be
able to walk the AST of the currently running program (or any arbitrary
snippet that you send off to eval?)?
Yes. That’s what Perl’s B.pm does.
% perl -MB -le ‘$x= B::main_start; print $x->name while $x=$x->next’
nextstate
pushmark
gv
entersub
gvsv
sassign
…
(New statement, add a mark to the stack, add a symbol table entry
[B::main_start] to the stack, call it, put a variable on the stack,
assign the result of the call to the variable…)
I don’t think anyone has approached the problem in the way you propose.
Can you give some more details of how you’re thinking of doing it?
I can even give you some sample code, because I’ve already got a fair bit
of it working. 
It says a lot for Ruby’s ease of use, clarity of code and
well-developed extensions system that I’ve only been using the
bloody language for three days and I’ve already got most of a bytecode
walker constructed.
Here’s the core of it:
static VALUE
bytecode_get_root(VALUE class)
{
return Data_Wrap_Struct(class, 0, 0, ruby_eval_tree);
}
void Init_Bytecode () {
cByteNode = rb_define_class(“ByteNode”, rb_cObject);
rb_define_singleton_method(cByteNode, “root”, bytecode_get_root, 0);
rb_define_method(cByteNode, “type”, bytecode_nd_type, 0);
rb_define_method(cByteNode, “line”, bytecode_nd_line, 0);
rb_define_method(cByteNode, “head”, bytecode_nd_head, 0);
rb_define_method(cByteNode, “next”, bytecode_nd_next, 0);
…
}
The bytecode_nd_* functions just do a Data_Get_Struct, call the relevant
nd_* macro, and wrap the result.
Now I can say:
% ruby -e ‘require “Bytecode”; p ByteNode.root; p ByteNode.root.next.type’
#ByteNode:0x401a6550
4
Is this making more sense now?
Of course, it’ll make even more sense when I write something which converts
type back into a string rather than an enum, etc. 
···
–
Darn it, who spiked my coffee with water?!
– Larry Wall in 200002141819.KAA18235@kiev.wall.org