def if ; end - basically impossible?

Discussion in 'Ruby' started by Giles Bowkett, Dec 28, 2007.

  1. 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.blogspot.com
    Blog: http://gilesbowkett.blogspot.com
    Portfolio: http://www.gilesgoatboy.org
    Tumblelog: http://giles.tumblr.com
    Giles Bowkett, Dec 28, 2007
    #1
    1. Advertising

  2. On Dec 28, 2007 11:21 AM, 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.


    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/
    Rick DeNatale, Dec 28, 2007
    #2
    1. Advertising

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

    2007/12/28, Giles Bowkett <>:
    >
    > 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.
    Johan Veenstra, Dec 28, 2007
    #3
  4. Giles Bowkett

    Paul Brannan Guest

    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
    Paul Brannan, Dec 28, 2007
    #4
  5. > (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.blogspot.com
    Blog: http://gilesbowkett.blogspot.com
    Portfolio: http://www.gilesgoatboy.org
    Tumblelog: http://giles.tumblr.com
    Giles Bowkett, Dec 28, 2007
    #5
  6. Giles Bowkett

    Sam Smoot Guest

    On Dec 28, 3:51 pm, Giles Bowkett <> 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.
    Sam Smoot, Dec 29, 2007
    #6
  7. > > 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.blogspot.com
    Blog: http://gilesbowkett.blogspot.com
    Portfolio: http://www.gilesgoatboy.org
    Tumblelog: http://giles.tumblr.com
    Giles Bowkett, Dec 29, 2007
    #7
  8. Giles Bowkett

    Sam Smoot Guest

    On Dec 28, 10:57 pm, Giles Bowkett <> 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. :)
    Sam Smoot, Dec 29, 2007
    #8
  9. Giles Bowkett

    Paul Brannan Guest

    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
    Paul Brannan, Dec 29, 2007
    #9
  10. > 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.blogspot.com
    Blog: http://gilesbowkett.blogspot.com
    Portfolio: http://www.gilesgoatboy.org
    Tumblelog: http://giles.tumblr.com
    Giles Bowkett, Jan 1, 2008
    #10
  11. Giles Bowkett

    Paul Brannan Guest

    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
    Paul Brannan, Jan 1, 2008
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jiong Feng
    Replies:
    0
    Views:
    819
    Jiong Feng
    Nov 19, 2003
  2. HED
    Replies:
    10
    Views:
    732
    James Kanze
    Oct 11, 2007
  3. Sean Ross
    Replies:
    3
    Views:
    122
    Aredridel
    Dec 25, 2003
  4. Kyung won Cheon
    Replies:
    1
    Views:
    105
    Pit Capitain
    Aug 18, 2008
  5. Replies:
    5
    Views:
    258
    Michele Dondi
    Jun 30, 2006
Loading...

Share This Page