A Gem to Rewrite Ruby code from a special syntax into an evented IO form.
Ruby
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.gitignore
Gemfile
Gemfile.lock
LICENSE
README.rdoc
Rakefile
console
step_rewrite.gemspec

README.rdoc

What is this for?

This gem tries to solve a very specific problem when working with evented I/O code. Ideally, I suppose it would work with something like EventMachine, but I havent worked enough with EventMachine to know if that's the case. Its meant for cases where blocks are passed to methods solely to sequence a set of steps. Like in this example.

writeFile(path, "hello") do
    File.open(path, "a") do |file|
        write(file, "\nworld") do
            close(file) do
                read(path) do |data|
                    puts data.last
                end
            end
        end
    end
end

Traditionally blocks have been a lightweight strategy pattern. Not so with evented I/O. While each function takes a block, this is merely to sequence the rest of the program to execute after the function is executed. To understand the context a little better read this

Installation

gem install step_rewrite

After installing the gem, the quick and dirty way to use it is to include the StepRewrite module in your code.

include StepRewrite
step do
    path = "fileio.txt"
    writeFile(path, "hello", &_)
    file = File.open(path, "a", &_)
    write(file, "\nworld", &_)
    close(file, &_)
    data = read(path, &_)
    puts data.last
end

The block passed to step is rewritten so that everywhere you have a method that takes &_ as a parameter, the rest of the code is passed as a block to it. So step rewrites this code into the code above and THEN evaluates it.

Rewrite Rules

Any code of the form

foo(&_)
bar
baz

gets rewritten to

foo do
  bar
  baz
end

return values from such functions are converted into arguments to the block

a = foo(&_)
bar(a)
baz

becomes

foo do |a|
  bar(a)
  baz
end

This allows an infinite degree of nesting

foo(&_)
bar(&_)
baz(&_)
qux

becomes

foo { bar { baz { qux } } }

existing blocks or lambda parameters are not touched.

Other execution methods

If the name step clashes with a method in your code, you can instead use the module method

StepRewrite.step do
    path = "fileio.txt"
    writeFile(path, "hello", &_)
    file = File.open(path, "a", &_)
    write(file, "\nworld", &_)
    close(file, &_)
    data = read(path, &_)
    puts data.last
end

if _ is a variable you are already using, you can configure the special callback identifier for rewriting.

StepRewrite.step(:cb) do
    path = "fileio.txt"
    writeFile(path, "hello", &cb)
    file = File.open(path, "a", &cb)
    write(file, "\nworld", &cb)
    close(file, &cb)
    data = read(path, &cb)
    puts data.last
end

Define Method

The problem with the above approach is that it does not cache the result of rewriting the code. If what you are writing is part of a long running server, the recommended style is to define a method instead.

require 'step_rewrite/module'

class IO
    define_step_method :hello_world do
        path = "fileio.txt"
        writeFile(path, "hello", &_)
        file = File.open(path, "a", &_)
        write(file, "\nworld", &_)
        close(file, &_)
        data = read(path, &_)
        puts data.last
    end
end

IO.new.hello_world

How does this work?

This gem makes use of the ParseTree gem to extract the sexp out of any block and then rewrites it using various rules. This code is converted back into Ruby using Ruby2Ruby and then evaled into a context

Copyright

Copyright © 2010 Vishnu Iyengar. See LICENSE for details.