Def if ; end - basically impossible?

I’m writing some code which needs to do something unusual when it
encounters an if, an else, or an end.

def if
“asdf”
end
=> nil
if
?> true
end
=> nil

The ?> line comes up because if appears to not be a method but an
operator or something similar, so my override does nada.

Is there any way to do this? It looks as if I have to either rethink
my strategy or write some kind of parser.


Giles B.

Podcast: http://hollywoodgrit.blogspot.com
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com

On Dec 28, 2007 11:21 AM, Giles B. [email protected] wrote:

=> nil

The ?> line comes up because if appears to not be a method but an
operator or something similar, so my override does nada.

Is there any way to do this? It looks as if I have to either rethink
my strategy or write some kind of parser.

If is not a method, it’s a reserved word.

Ruby doesn’t have many reserved words, but it has a few: FILE ,
LINE, alias. and ,begin, BEGIN, break, case, class, def
,defined?, do, else, elsif, end, END, ensure, false. for, if, in, or,
module, next, nil, not, redo, rescue, retry, return, self, super,
then, true, undef, unless, until, when, while, and yield


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

2007/12/28, Giles B. [email protected]:

end
=> nil

The ?> line comes up because if appears to not be a method but an
operator or something similar, so my override does nada.

Is there any way to do this? It looks as if I have to either rethink
my strategy or write some kind of parser.

You have defined a function namen “if”, and you can call this function
with
send(:if),
but this doesn’t override the if-else/elsif-end construct.

On Sat, Dec 29, 2007 at 01:21:04AM +0900, Giles B. wrote:

=> nil

The ?> line comes up because if appears to not be a method but an
operator or something similar, so my override does nada.

Is there any way to do this? It looks as if I have to either rethink
my strategy or write some kind of parser.

It works if you call #if on an object. I do something like this in
ruby-libjit:

class Function
def if(condition, &block)
# append code to:
# - if the condition is true, execute the code appended by the
# block
# - if the condition is false, branch to the end label
block.call
return If.new(self)
end

class If
  def initialize(function)
    @function = function
  end

  def end
    # append the end label here
  end
end

end

so I can write something like:

Function.compile do |f|
f.if() {
# true case
} .else {
# false case
} .end

end

(I’ve omitted the code for #else for simplicity, because it really makes
the code complicated)

Paul

(I’ve omitted the code for #else for simplicity, because it really makes
the code complicated)

Could I see it? It looks as if ruby-libjit has no releases (according
to RubyForge) and I think I’ll probably use your technique to make
this happen. Right now I’m passing blocks to a code generator, like
this:

Generator.module_eval(&block)

I could probably do something which treats the code as strings, and
either passes them off to module_eval(&block) like this, or passes
them to send(:if) instead. Even a simple case statement might work.


Giles B.

Podcast: http://hollywoodgrit.blogspot.com
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com

On Dec 28, 3:51 pm, Giles B. [email protected] wrote:

Generator.module_eval(&block)

If you’re passing the code as a block, the easiest solution may be
ParseTree? I haven’t toyed with it, but Ryan D. also just released
ruby_parser apparently, which seems to be a pure-ruby version of
ParseTree.

Generator.module_eval(&block)

If you’re passing the code as a block, the easiest solution may be
ParseTree? I haven’t toyed with it, but Ryan D. also just released
ruby_parser apparently, which seems to be a pure-ruby version of
ParseTree.

I think that’s correct; it’s either a Ruby port or a Ruby equivalent.
But it returns s-exps; what I really need is to catch ifs and send
them to an if method.


Giles B.

Podcast: http://hollywoodgrit.blogspot.com
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com

On Dec 28, 10:57 pm, Giles B. [email protected] wrote:

Generator.module_eval(&block)

If you’re passing the code as a block, the easiest solution may be
ParseTree? I haven’t toyed with it, but Ryan D. also just released
ruby_parser apparently, which seems to be a pure-ruby version of
ParseTree.

I think that’s correct; it’s either a Ruby port or a Ruby equivalent.
But it returns s-exps; what I really need is to catch ifs and send
them to an if method.

Right. I guess I meant it would seem like you could use ParseTree (or
something similar) to detect if/elsif/else/end constructs, and then re-
evaluate their interiors as a new proc (I think ParseTree can
compile a S-Exp to Ruby, but I haven’t tried that side personally).
That way, you could evaluate the condition, and then send the correct
branch along.

I guess my assumption is that you don’t necessarily need to have a
method called :if if you can properly detect/handle if keywords in
the blocks. But that assumption could be off base. Maybe your whole
point is building a DSL with :if methods to use. I dunno. Best of
luck. :slight_smile:

Giles B. wrote:

Could I see it? It looks as if ruby-libjit has no releases (according
to RubyForge) and I think I’ll probably use your technique to make
this happen.

You should be able to check the code out of svn.

Right now I’m passing blocks to a code generator, like this:

Generator.module_eval(&block)

I could probably do something which treats the code as strings, and
either passes them off to module_eval(&block) like this, or passes
them to send(:if) instead. Even a simple case statement might work.

I’m having a hard time imaging what you are describing.

You should be able to use self.if instead of send(:if).

Paul

Giles B. wrote:

generating_code(ForSomething) do
if variable != some_condition
do :stuff
else
do(:other => stuff)
end
end

The only way I know to make this work is to use parsetree or nodewrap to
build a custom parser for the block. I’ve tinkered with doing this, but
it always turns out too hard for the user (actually, everything’s easy
except for how Ruby handles local variables – I think need to build an
intermediate representation for the Ruby code that can be easily
transformed).

The solution you came up with is probably cleaner, at least for the time
being.

Paul

You should be able to check the code out of svn.

Whoops! Duh. Will do.

You should be able to use self.if instead of send(:if).
The thing is, I want to be able to do this:

generating_code(ForSomething) do
if variable != some_condition
do :stuff
else
do(:other => stuff)
end
end

And basically not use the if or else built into Ruby. I can do it
very easily if I do this:

gen_code(Etc) do
“if asdf == qwerty” # etc
end

but that’s cheating because it’s using strings and I want to use actual
code.

The solution I came up with is kinda booty. Basically it goes like this:

generating(Code) do |variable|
variable.> value do
stuff
end
variable.<= value do
other :stuff
end
end

it seems to be the best solution available to me at the moment but a
better solution would be better. obviously.


Giles B.

Podcast: http://hollywoodgrit.blogspot.com
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com