Marc Chung
OpenRain
blog.marcchung.com
blog.openrain.com
@heisenthought
Hacking with ruby2ruby
Marc Chung
OpenRain
blog.marcchung.com
blog.openrain.com
@heisenthought
ruby2ruby
Ruby2Ruby
Walks the Ruby AST
To emit Ruby
sudo gem install ruby2ruby
Limitations
Rhino, rocks!
js> rhino_rocks.toString();
function rhino_rocks() {
return “Rhino, rocks!”;
}
js> eval(rhino_rocks.toString()).call();
Rhino, rocks!
ruby_rocks = proc {
return “Ruby, rocks”;
}
irb> ruby_rocks.call;
Ruby, rocks!
irb> require “ruby2ruby”
irb> require “parse_tree_extensions”
irb> ruby_rocks.to_ruby
Ruby, rocks!
define_method
class Voice
define_method(:shout) do |word|
word.upcase!
end
end
puts Ruby2Ruby.translate(Voice)
class Voice < Object
def yell(word)
word.upcase!
end
end
alias
class AliasClass
def old_busted
"42"
end
puts Ruby2Ruby.translate(AliasClass)
class AliasClass < Object
def new_hotness
"42"
end
def old_busted
"42"
end
end
#module_function
module HelperModule
def help
puts "Help me"
end
module_function : help
end
puts Ruby2Ruby.translate(HelperModule)
module HelperModule
def help
puts("Help me")
end
• Drmap
• git clone git://github.com/mchung/drmap.git
• Optionally, install Journeta
Under the hood
break;
case NODE_YIELD:
if (node->nd_stts)
add_to_parse_tree(self, current, node->nd_stts, locals);
if (node->nd_stts
&& (nd_type(node->nd_stts) == NODE_ARRAY
|| nd_type(node->nd_stts) == NODE_ZARRAY)
&& !node->nd_state)
rb_ary_push(current, Qtrue);
break;
[:class, :Book,
[:const, :Object],
[:defn, :title, [:scope, [:block,
[:args], [:str, "Ruby programming"]]]]]
class Book < Object
def title
“Ruby programming”
end
end
/opt/local/usr/bin
• parse_tree_show
• r2r_show
class Book
def title
“Ruby programming”
end
end
$ parse_tree_show book.rb
s(:class, :Book,
nil,
s(:scope,
s(:defn, :title,
s(:args),
s(:scope, s(:block,
s(:str, "Ruby programming"))))))
$ r2r_show book.rb
class Book
def title()
“Ruby programming”
end
end
Operator Precedence
with Guy Decoux: a b c, d
[[:fcall, :a,
[:array,
[:fcall, :b,
[:array,
[:vcall, :c],
[:vcall, :d]]]]]]
ParseTree.new.parse_tree_for_string(“a b c, d”)
ruby2java
class JavaClass
def self.main
puts “Java, rocks!”
end
end
[:class, :JavaClass,
[:const, :Object],
[:defs, [:self], :main,
[:scope,
[:block, [:args],
[:fcall, :puts, [:array, [:str, "Hello, Java"]]]]]]]
class Ruby2Java < SexpProcessor
def process_class(exp)
“public class #{exp.shift} #{next_token(exp, true)}”
end
def process_const(exp)
“extends #{exp.shift}”
end
....
end
public class JavaClass {
public static void main(String argv[]) {
return “Hello, Java”;
}
}
Distributing Ruby
def drmap(&block)
pool = Drmap::BeanstalkPool.new
jid = rand(100)
each_with_index do |element, idx|
pool.put_job(jid, block.to_ruby, element)
end
results = []
while results.size < length
results << pool.next_result(jid)
end
results
end
end
def process
loop do
begin
job_payload = next_job
fn = job_payload[:proc]
data = job_payload[:data]
result = eval(fn).call(data)
save(job_payload[:jid], result)
success!
rescue => e
fail!(e)
end
end
end
drmap
• Trivial
• Distributed
• Powerful
Demo time!
Gisting
• MapReduce in Ruby
• http://github.com/mchung/gisting
map / reduce
• Functional programming
• Iterating over collections
• (5..10).map {|x| x+1} #=> [6, 7, 8, 9, 10, 11]
• (5..10).reduce(:+) #=> 45
Google MapReduce
result = MapReduce(spec)
pp result
Gisting
My Git Repo
github.com/mchung
Marc Chung
blog.marcchung.com
Ruby::AZ
rubyaz.org
Resources
Code Generation: The Safety Scissors Of Metaprogramming
mwrc2008.confreaks.com/03bowkett.html
Ruby2Ruby
seattlerb.rubyforge.org/ruby2ruby/
ParseTree
parsetree.rubyforge.org