[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

def if ; end - basically impossible?

Giles Bowkett

12/28/2007 4:21:00 PM

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 Bowkett

Podcast: http://hollywoodgrit.bl...
Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles....

10 Answers

Rick DeNatale

12/28/2007 4:44:00 PM

0

On Dec 28, 2007 11:21 AM, Giles Bowkett <gilesb@gmail.com> wrote:
> 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.

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.denh...

Johan Veenstra

12/28/2007 4:51:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

2007/12/28, Giles Bowkett <gilesb@gmail.com>:
>
> 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.
>
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.

Paul Brannan

12/28/2007 6:37:00 PM

0

On Sat, Dec 29, 2007 at 01:21:04AM +0900, Giles Bowkett wrote:
> 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.

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(<condition>) {
# true case
} .else {
# false case
} .end

end

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

Paul


Giles Bowkett

12/28/2007 9:51:00 PM

0

> (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 Bowkett

Podcast: http://hollywoodgrit.bl...
Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles....

Sam Smoot

12/29/2007 3:49:00 AM

0

On Dec 28, 3:51 pm, Giles Bowkett <gil...@gmail.com> 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 Davis also just released
ruby_parser apparently, which seems to be a pure-ruby version of
ParseTree.

Giles Bowkett

12/29/2007 4:57:00 AM

0

> > 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 Davis 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 Bowkett

Podcast: http://hollywoodgrit.bl...
Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles....

Sam Smoot

12/29/2007 3:46:00 PM

0

On Dec 28, 10:57 pm, Giles Bowkett <gil...@gmail.com> 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 Davis 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. :-)

Paul Brannan

12/29/2007 9:23:00 PM

0

Giles Bowkett 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 Bowkett

1/1/2008 3:15:00 AM

0

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

Whoops! Duh. Will do.

> > 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).

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 Bowkett

Podcast: http://hollywoodgrit.bl...
Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles....

Paul Brannan

1/1/2008 1:46:00 PM

0

Giles Bowkett 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