Using ruby reflection to generate code

hello,

i’m curious if anyone out there is using ruby reflection to generate
code for other languages. i love using ruby to prototype classes and
their interactions, especially if i can’t decide on a design and need to
try a few different implementations. i’m writing lots of c++ and
objective c these days, and it’s much harder to turn around and quickly
refactor class designs.

has anyone tried using ruby’s reflection to prototype classes in ruby
and then render the class structure to other languages? i’ve started
working along these lines so that i can call #render_objc on any object
and get back two big strings, one for the header and one for the source.
i use reflection to pull out instance variables and check their type, so
a ruby array turns into a NSMutableArray *, hash to NSMutableDictionary
*, etc, etc. i just look at variables, classes and methods with
reflection, i don’t parse the ruby code or try to do anything smart with
it yet. the methods in the target language are just stubs.

eventually, i would like to take the ruby code inside my methods and
stick that as a comment inside the generated methods in my target
language. then i can use ruby for RAD and generate stubs in my target
language along with ruby code in comments so i can remember what each
method was supposed to do. then i can move through the methods, porting
the ruby code to my target language and getting a finished product more
quickly.

anyone else going down this road? perhaps you have some advice or
pointers to examples you’ve found? i’m not sure it’s going to work
100%, but i’m hoping it will allow me to save time. if anyone’s
interested, i can post code once i fix some bugs and clean it up. if i
get something useful, i’m going to try this for c++ and perl as well.

thanks,

doug

···


“Contrary to what most people say, the most dangerous animal in the
world is not the lion or the tiger or even the elephant. It’s a shark
riding on an elephant’s back, just trampling and eating everything they
see.” – Jack Handey

In article 20030413004111.A80880@beaver.net,

···

Doug Beaver doug@beaver.net wrote:

hello,

i’m curious if anyone out there is using ruby reflection to generate
code for other languages. i love using ruby to prototype classes and
their interactions, especially if i can’t decide on a design and need to
try a few different implementations. i’m writing lots of c++ and
objective c these days, and it’s much harder to turn around and quickly
refactor class designs.

has anyone tried using ruby’s reflection to prototype classes in ruby
and then render the class structure to other languages? i’ve started
working along these lines so that i can call #render_objc on any object
and get back two big strings, one for the header and one for the source.
i use reflection to pull out instance variables and check their type, so
a ruby array turns into a NSMutableArray *, hash to NSMutableDictionary
*, etc, etc. i just look at variables, classes and methods with
reflection, i don’t parse the ruby code or try to do anything smart with
it yet. the methods in the target language are just stubs.

eventually, i would like to take the ruby code inside my methods and
stick that as a comment inside the generated methods in my target
language. then i can use ruby for RAD and generate stubs in my target
language along with ruby code in comments so i can remember what each
method was supposed to do. then i can move through the methods, porting
the ruby code to my target language and getting a finished product more
quickly.

anyone else going down this road? perhaps you have some advice or
pointers to examples you’ve found? i’m not sure it’s going to work
100%, but i’m hoping it will allow me to save time. if anyone’s
interested, i can post code once i fix some bugs and clean it up. if i
get something useful, i’m going to try this for c++ and perl as well.

thanks,

doug

I’m not currently doing this, but I do kind of want to be able to convert
RHDL to VHDL and/or Verilog which would entail some similar effort
(actually, it would probalby be harder).

At any rate, I really would be interested in seeing your code to generate
objective C and/or C++, can you post this or submit it to the RAA?

Phil

ptkwt@shell1.aracnet.com (Phil Tomson) wrote in message news:b7c6an01vb3@enews4.newsguy.com

In article 20030413004111.A80880@beaver.net,

hello,

i’m curious if anyone out there is using ruby reflection to generate
code for other languages. i love using ruby to prototype classes and
their interactions, especially if i can’t decide on a design and need to
try a few different implementations. i’m writing lots of c++ and
objective c these days, and it’s much harder to turn around and quickly
refactor class designs.

has anyone tried using ruby’s reflection to prototype classes in ruby
and then render the class structure to other languages? i’ve started
working along these lines so that i can call #render_objc on any object
and get back two big strings, one for the header and one for the source.
i use reflection to pull out instance variables and check their type, so
a ruby array turns into a NSMutableArray *, hash to NSMutableDictionary
*, etc, etc. i just look at variables, classes and methods with
reflection, i don’t parse the ruby code or try to do anything smart with
it yet. the methods in the target language are just stubs.

eventually, i would like to take the ruby code inside my methods and
stick that as a comment inside the generated methods in my target
language. then i can use ruby for RAD and generate stubs in my target
language along with ruby code in comments so i can remember what each
method was supposed to do. then i can move through the methods, porting
the ruby code to my target language and getting a finished product more
quickly.

anyone else going down this road? perhaps you have some advice or
pointers to examples you’ve found? i’m not sure it’s going to work
100%, but i’m hoping it will allow me to save time. if anyone’s
interested, i can post code once i fix some bugs and clean it up. if i
get something useful, i’m going to try this for c++ and perl as well.

thanks,

doug

I’m not currently doing this, but I do kind of want to be able to convert
RHDL to VHDL and/or Verilog which would entail some similar effort
(actually, it would probalby be harder).

At any rate, I really would be interested in seeing your code to generate
objective C and/or C++, can you post this or submit it to the RAA?

Phil

Hi,
I’m using Ruby as a scripting tool for an OpenGL app, Would it be
(theroertically) possible to use reflection to ‘reconstruct’ the
original ruby script. The reason I ask is that I use rb_load() to
initialise a Scenegraph within my app. The user can then change the
Scenegraph which I then need to save out again as an updated script.
Has anyone done something similar?

···

Doug Beaver doug@beaver.net wrote:

here is a first version, i put some comments at the top to discuss its
limitations:

http://beaver.net/ruby/objc_render.rb

phil and i talked over private email about DumpNode, it looks promising,
at least for figuring out names and types of method arguments, maybe
even the return type. i also thought it might be possible to put
attr-like hints in the ruby code, so you could do:

class Song
def play(track=0, duration=0)
args :track, Fixnum, :duration, Fixnum
retval :didPlay

# try to play the track here, set didPlay to false if it didn't work
return didPlay

end
end

i think you have to end up using some sort of hint in your ruby code,
ruby is too dynamic. i’m attempting this because i’m trying to develop
a secret weapon, i want to use ruby to prototype designs and generate
boilerplate code for use at work. we have a large perl and c++ base,
and it will be quite a while (i think) until ruby is accepted at work,
but i’d still like to use it to help me write code there, if i can.
the objc rendering code is the first shot just because i’ve been writing
a lot of cocoa code lately and figured objc was closer to ruby than c++.

i might end up writing a ruby extension for the c++ frameworks we use
and then use ruby to glue things together, skipping the boilerplate
generation altogether. once i had a working product, i would then rip
out the ruby code (whose design had been well tested at this point) and
replace it with handwritten c++ code when it’s time to ship. i’m hoping
that having lots of good unit tests will cut down on errors when i port
the glue from ruby to c++. i’m interested to hear if anyone else is
doing something similar to this…

thanks,

doug

···

On Mon, Apr 14, 2003 at 02:55:07AM +0900, Phil Tomson wrote:

In article 20030413004111.A80880@beaver.net,

I’m not currently doing this, but I do kind of want to be able to
convert RHDL to VHDL and/or Verilog which would entail some similar
effort (actually, it would probalby be harder).

At any rate, I really would be interested in seeing your code to
generate objective C and/or C++, can you post this or submit it to the
RAA?


“Contrary to what most people say, the most dangerous animal in the
world is not the lion or the tiger or even the elephant. It’s a shark
riding on an elephant’s back, just trampling and eating everything they
see.” – Jack Handey

In article 20030414212552.A46129@beaver.net,

In article 20030413004111.A80880@beaver.net,

I’m not currently doing this, but I do kind of want to be able to
convert RHDL to VHDL and/or Verilog which would entail some similar
effort (actually, it would probalby be harder).

At any rate, I really would be interested in seeing your code to
generate objective C and/or C++, can you post this or submit it to the
RAA?

here is a first version, i put some comments at the top to discuss its
limitations:

http://beaver.net/ruby/objc_render.rb

Thanks for sharing.

phil and i talked over private email about DumpNode, it looks promising,
at least for figuring out names and types of method arguments, maybe
even the return type. i also thought it might be possible to put
attr-like hints in the ruby code, so you could do:

class Song
def play(track=0, duration=0)
args :track, Fixnum, :duration, Fixnum
retval :didPlay

try to play the track here, set didPlay to false if it didn’t work

return didPlay
end
end

i think you have to end up using some sort of hint in your ruby code,
ruby is too dynamic.

True. I’ve had similar thoughts for RHDL-> VHDL conversion.

However, Ruby being dynamic and ObjC being dynamic probably means that
Ruby->ObjC would be a lot easier and would require fewer (if any?) hints,
no?

i’m attempting this because i’m trying to develop
a secret weapon, i want to use ruby to prototype designs and generate
boilerplate code for use at work. we have a large perl and c++ base,
and it will be quite a while (i think) until ruby is accepted at work,
but i’d still like to use it to help me write code there, if i can.
the objc rendering code is the first shot just because i’ve been writing
a lot of cocoa code lately and figured objc was closer to ruby than c++.

i might end up writing a ruby extension for the c++ frameworks we use
and then use ruby to glue things together, skipping the boilerplate
generation altogether. once i had a working product, i would then rip
out the ruby code (whose design had been well tested at this point) and
replace it with handwritten c++ code when it’s time to ship. i’m hoping
that having lots of good unit tests will cut down on errors when i port
the glue from ruby to c++. i’m interested to hear if anyone else is
doing something similar to this…

Swig would probably be good for this. You could use it to develop
your C++ classes in both C++ and Ruby; sort of rapid prototyping where you
minimally define your class on the C++ side but then you fill in methods
on the Ruby side. As you figure out exactly what you want your class to
do and you have a good idea that things are working the way you
want, you can define these methods on the C++ side (and continue
iteratively until you’ve defined all the methods in C++ if that’s your
goal). As a side benefit you’ll be able to unit test your C++ code using
Ruby and Test::Unit. Your unit tests would be defined in Ruby and as you
move Ruby code to the C++ side the same tests can be used to ensure that
things still work the way they did in Ruby.

Phil

···

Doug Beaver doug@beaver.net wrote:

On Mon, Apr 14, 2003 at 02:55:07AM +0900, Phil Tomson wrote:

Perhaps you could even treat them as assertions, e.g.
assert(track.is_a? Fixnum)
assert(duration.is_a? Fixnum)

which are checked at runtime (in Ruby) but used as compile-time hints (for
more static languages)

Just a thought…

Brian.

···

On Tue, Apr 15, 2003 at 10:25:55AM +0900, Doug Beaver wrote:

phil and i talked over private email about DumpNode, it looks promising,
at least for figuring out names and types of method arguments, maybe
even the return type. i also thought it might be possible to put
attr-like hints in the ruby code, so you could do:

class Song
def play(track=0, duration=0)
args :track, Fixnum, :duration, Fixnum
retval :didPlay

# try to play the track here, set didPlay to false if it didn't work
return didPlay

end
end

In article 20030414212552.A46129@beaver.net,

i think you have to end up using some sort of hint in your ruby
code, ruby is too dynamic.

True. I’ve had similar thoughts for RHDL-> VHDL conversion.

However, Ruby being dynamic and ObjC being dynamic probably means that
Ruby->ObjC would be a lot easier and would require fewer (if any?)
hints, no?

i agree that objc requires fewer hints, but there’s still some stuff i
can’t look up just by using reflection. for instance, i can use
Method#arity to see how many args my methods take, but i don’t know what
the names of the args are. objc’s methods are smalltalky, so i end up
doing this, ignoring the types completely and autogenerating the
selectors:

  • (id)meth:(id)val1 arg2:(id)val2 arg3:(id)val3;

i thought i could set defaults for the args in the definition, but then
arity doesn’t work. i remember seeing threads on ruby-talk saying that
this is by design, so i’m trying to figure out other ways to look at
method args.

def meth(arg1, arg) → arity returns 2
def meth(arg1=0, arg2=) → arity returns -1

i think with hints, i can at least get the args named and typed
correctly, and just make all the methods return id. or maybe force
myself to declare a return type with a hint, and then overload return to
raise an exception if i attempt to return a value from the method that
doesn’t match that type:

def meth(stack = )
args :stack, Array
return_type Float

do some stuff

return false # throw InvalidReturnTypeException
end

i’m thinking now that i’m going to try to get something working with
hints, and if i get usable code out of it, then i’ll try to hook in
NodeDump or something similar so i don’t have to use hints at all.
ideally, you would write a bunch of code, load all the classes into the
translation module, and then it would DTRT and generate your objc for
you with no hassles.

brian candler suggested that i turn the hints into assert calls, which
would be checked at runtime in ruby and compile time in static
languages. that sounds really interesting, i might do that instead. i
love the idea of using assertions for that sort of thing.

i also noticed after searching for c++ generation on ruby-talk, that bob
calco was working on a framework called RuGen that would let you design
in ruby and generate different output languages. that looks cool!

i might end up writing a ruby extension for the c++ frameworks we
use and then use ruby to glue things together, skipping the
boilerplate generation altogether. once i had a working product, i
would then rip out the ruby code (whose design had been well tested
at this point) and replace it with handwritten c++ code when it’s
time to ship. i’m hoping that having lots of good unit tests will
cut down on errors when i port the glue from ruby to c++. i’m
interested to hear if anyone else is doing something similar to
this…

Swig would probably be good for this. You could use it to develop
your C++ classes in both C++ and Ruby; sort of rapid prototyping where
you minimally define your class on the C++ side but then you fill in
methods on the Ruby side. As you figure out exactly what you want
your class to do and you have a good idea that things are working the
way you want, you can define these methods on the C++ side (and
continue iteratively until you’ve defined all the methods in C++ if
that’s your goal). As a side benefit you’ll be able to unit test your
C++ code using Ruby and Test::Unit. Your unit tests would be defined
in Ruby and as you move Ruby code to the C++ side the same tests can
be used to ensure that things still work the way they did in Ruby.

this sounds very interesting, i didn’t think of involving swig. i
wouldn’t be creating that many new c++ classes, just using different
frameworks we already have for creating services, but i think it still
works well. it sounds like that with this method, i’d still have to
check in ruby code for the unit tests, which won’t work for me. i think
i could come up with something where i have the ruby tests on my
desktop, create a set of c++ unit tests that attempt to test the same
things, and then run them side by side until i get the same results,
checking in the c++ tests when i’m satisfied.

it makes me feel a little uneasy, though. i wish i could just check
ruby code in. i evangelize ruby at work, but we have hundreds of
developers, and the company has paid for many of them to be trained in
perl, so it’s a bit of an uphill battle. i think i can find a niche for
ruby in code generation and developer tools, but first i have to build a
community of people who are reasonably fluent in ruby so that we can
review each other’s code. nothing like the little details… :slight_smile:

doug

···

On Tue, Apr 15, 2003 at 01:02:05PM +0900, Phil Tomson wrote:

Doug Beaver doug@beaver.net wrote:


“Contrary to what most people say, the most dangerous animal in the
world is not the lion or the tiger or even the elephant. It’s a shark
riding on an elephant’s back, just trampling and eating everything they
see.” – Jack Handey

In article 20030415132450.A49913@beaver.net,

In article 20030414212552.A46129@beaver.net,

i think you have to end up using some sort of hint in your ruby
code, ruby is too dynamic.

True. I’ve had similar thoughts for RHDL-> VHDL conversion.

However, Ruby being dynamic and ObjC being dynamic probably means that
Ruby->ObjC would be a lot easier and would require fewer (if any?)
hints, no?

i agree that objc requires fewer hints, but there’s still some stuff i
can’t look up just by using reflection. for instance, i can use
Method#arity to see how many args my methods take, but i don’t know what
the names of the args are. objc’s methods are smalltalky, so i end up
doing this, ignoring the types completely and autogenerating the
selectors:

  • (id)meth:(id)val1 arg2:(id)val2 arg3:(id)val3;

i thought i could set defaults for the args in the definition, but then
arity doesn’t work. i remember seeing threads on ruby-talk saying that
this is by design, so i’m trying to figure out other ways to look at
method args.

def meth(arg1, arg) → arity returns 2
def meth(arg1=0, arg2=) → arity returns -1

i think with hints, i can at least get the args named and typed
correctly, and just make all the methods return id. or maybe force
myself to declare a return type with a hint, and then overload return to
raise an exception if i attempt to return a value from the method that
doesn’t match that type:

def meth(stack = )
args :stack, Array
return_type Float

do some stuff

return false # throw InvalidReturnTypeException
end

i’m thinking now that i’m going to try to get something working with
hints, and if i get usable code out of it, then i’ll try to hook in
NodeDump or something similar so i don’t have to use hints at all.
ideally, you would write a bunch of code, load all the classes into the
translation module, and then it would DTRT and generate your objc for
you with no hassles.

brian candler suggested that i turn the hints into assert calls, which
would be checked at runtime in ruby and compile time in static
languages. that sounds really interesting, i might do that instead. i
love the idea of using assertions for that sort of thing.

i also noticed after searching for c++ generation on ruby-talk, that bob
calco was working on a framework called RuGen that would let you design
in ruby and generate different output languages. that looks cool!

i might end up writing a ruby extension for the c++ frameworks we
use and then use ruby to glue things together, skipping the
boilerplate generation altogether. once i had a working product, i
would then rip out the ruby code (whose design had been well tested
at this point) and replace it with handwritten c++ code when it’s
time to ship. i’m hoping that having lots of good unit tests will
cut down on errors when i port the glue from ruby to c++. i’m
interested to hear if anyone else is doing something similar to
this…

Swig would probably be good for this. You could use it to develop
your C++ classes in both C++ and Ruby; sort of rapid prototyping where
you minimally define your class on the C++ side but then you fill in
methods on the Ruby side. As you figure out exactly what you want
your class to do and you have a good idea that things are working the
way you want, you can define these methods on the C++ side (and
continue iteratively until you’ve defined all the methods in C++ if
that’s your goal). As a side benefit you’ll be able to unit test your
C++ code using Ruby and Test::Unit. Your unit tests would be defined
in Ruby and as you move Ruby code to the C++ side the same tests can
be used to ensure that things still work the way they did in Ruby.

this sounds very interesting, i didn’t think of involving swig. i
wouldn’t be creating that many new c++ classes, just using different
frameworks we already have for creating services, but i think it still
works well. it sounds like that with this method, i’d still have to
check in ruby code for the unit tests, which won’t work for me. i think
i could come up with something where i have the ruby tests on my
desktop, create a set of c++ unit tests that attempt to test the same
things, and then run them side by side until i get the same results,
checking in the c++ tests when i’m satisfied.

What do you use for C++ unit testing now? I remember trying cppunit and
not being able to get it to work which led to using swig and
Ruby/Test::Unit (which in turn led to other benefits like being able to
script our app in Ruby).

it makes me feel a little uneasy, though. i wish i could just check
ruby code in. i evangelize ruby at work, but we have hundreds of
developers, and the company has paid for many of them to be trained in
perl, so it’s a bit of an uphill battle. i think i can find a niche for
ruby in code generation and developer tools, but first i have to build a
community of people who are reasonably fluent in ruby so that we can
review each other’s code. nothing like the little details… :slight_smile:

Sounds like you’ll need to find some allies. If you can demonstrate
productivity gains with your approach to prototyping in Ruby and then
translating to ObjC/C++ then that could be a win.

Phil

···

Doug Beaver doug@beaver.net wrote:

On Tue, Apr 15, 2003 at 01:02:05PM +0900, Phil Tomson wrote:

Doug Beaver doug@beaver.net wrote:

Have you considered creating an output generator for rdoc?

-austin
– Austin Ziegler, austin@halostatue.ca on 2003.04.15 at 21:23:44