ruby2ruby-2.0.7/0000755000004100000410000000000012256407415013523 5ustar www-datawww-dataruby2ruby-2.0.7/Rakefile0000444000004100000410000000273712256407415015177 0ustar www-datawww-data# -*- ruby -*- require 'rubygems' require 'hoe' Hoe.add_include_dirs("lib", "../../ruby_parser/dev/lib", "../../sexp_processor/dev/lib") Hoe.plugin :seattlerb Hoe.plugin :isolate Hoe.spec 'ruby2ruby' do developer 'Ryan Davis', 'ryand-ruby@zenspider.com' self.rubyforge_name = 'seattlerb' dependency "sexp_processor", "~> 4.0" dependency "ruby_parser", "~> 3.1" end def process ruby, file="stdin" require "ruby_parser" require "ruby2ruby" parser = RubyParser.new ruby2ruby = Ruby2Ruby.new begin sexp = parser.process(ruby, file) ruby2ruby.process(sexp) rescue Interrupt => e raise e end end task :stress do $: << "lib" $: << "../../ruby_parser/dev/lib" require "pp" files = Dir["../../*/dev/**/*.rb"] warn "Stress testing against #{files.size} files" bad = {} files.each do |file| warn file begin process File.read(file), file rescue Interrupt => e raise e rescue Exception => e bad[file] = e end end pp bad end task :debug => :isolate do ENV["V"] ||= "18" $: << "lib" require 'ruby_parser' parser = if ENV["V"] == "18" then Ruby18Parser.new else Ruby19Parser.new end file = ENV["F"] || ENV["FILE"] ruby = if file then File.read(file) else file = "env" ENV["R"] || ENV["RUBY"] end puts process(ruby, file) end # vim: syntax=ruby ruby2ruby-2.0.7/.gemtest0000644000004100000410000000000012256407415015162 0ustar www-datawww-dataruby2ruby-2.0.7/bin/0000755000004100000410000000000012256407415014273 5ustar www-datawww-dataruby2ruby-2.0.7/bin/r2r_show0000555000004100000410000000106212256407415015763 0ustar www-datawww-data#!/usr/bin/ruby -ws require 'rubygems' require 'ruby2ruby' require 'ruby_parser' $h ||= false $s ||= false if $h then puts "usage: #{File.basename $0} [options] [file...]" puts "options:" puts "-h : display usage" puts "-s : print the sexp before displaying the translated ruby" exit 1 end ARGV.push "-" if ARGV.empty? parser = Ruby18Parser.new ruby2ruby = Ruby2Ruby.new ARGV.each do |file| ruby = file == "-" ? $stdin.read : File.read(file) sexp = parser.process(ruby, file) p sexp if $s puts ruby2ruby.process(sexp) end ruby2ruby-2.0.7/Manifest.txt0000444000004100000410000000015412256407415016030 0ustar www-datawww-data.autotest History.txt Manifest.txt README.txt Rakefile bin/r2r_show lib/ruby2ruby.rb test/test_ruby2ruby.rb ruby2ruby-2.0.7/.autotest0000444000004100000410000000114412256407415015372 0ustar www-datawww-data# -*- ruby -*- require 'autotest/restart' Autotest.add_hook :initialize do |at| at.order = :random at.testlib = "minitest/autorun" at.extra_files << "../../sexp_processor/dev/lib/pt_testcase.rb" at.libs << ":../../sexp_processor/dev/lib:../../ruby_parser/dev/lib" (1..4).each do |n| at.extra_class_map["TestRuby2Ruby#{n}"] = "test/test_ruby2ruby.rb" end at.add_mapping(/unified|pt_testcase/) do |f, _| at.files_matching(/test.*rb$/) end end if ENV['RCOV'] then require 'autotest/rcov' Autotest::RCov.command = 'rcov_info' Autotest::RCov.pattern = 'test/test_ruby2ruby.rb' end ruby2ruby-2.0.7/README.txt0000444000004100000410000000505712256407415015226 0ustar www-datawww-data= ruby2ruby home :: https://github.com/seattlerb/ruby2ruby rdoc :: http://seattlerb.rubyforge.org/ruby2ruby == DESCRIPTION: ruby2ruby provides a means of generating pure ruby code easily from RubyParser compatible Sexps. This makes making dynamic language processors in ruby easier than ever! == FEATURES/PROBLEMS: * Clean, simple SexpProcessor generates ruby code from RubyParser compatible sexps. == SYNOPSIS: require 'rubygems' require 'ruby2ruby' require 'ruby_parser' require 'pp' ruby = "def a\n puts 'A'\nend\n\ndef b\n a\nend" parser = RubyParser.new ruby2ruby = Ruby2Ruby.new sexp = parser.process(ruby) pp sexp p ruby2ruby.process(sexp) ## outputs: s(:block, s(:defn, :a, s(:args), s(:scope, s(:block, s(:call, nil, :puts, s(:arglist, s(:str, "A")))))), s(:defn, :b, s(:args), s(:scope, s(:block, s(:call, nil, :a, s(:arglist)))))) "def a\n puts(\"A\")\nend\ndef b\n a\nend\n" == REQUIREMENTS: + sexp_processor + ruby_parser == INSTALL: + sudo gem install ruby2ruby == How to Contribute: To get started all you need is a checkout, rake, and hoe. The easiest way is: % git clone seattlerb/ruby2ruby # assumes you use the `hub` wrapper. % gem i rake hoe % rake install_plugins # installs hoe-seattlerb & isolate % rake install_plugins # installs minitest (referenced from hoe-seattlerb) From here you should be good to go. We accept pull requests on github. == LICENSE: (The MIT License) Copyright (c) Ryan Davis, seattle.rb Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ruby2ruby-2.0.7/data.tar.gz.sig0000444000004100000410000000040012256407414016333 0ustar www-datawww-dataNcB|PnjpJTLJw=y@=m^ }YK0 +ܲQ$ PIx?`L/mQ給nPǮ=|,+>pݓ"&|3:qR?P/>J+(/mx;|#B+/l8?ϹD%AOMu7y!7?ymST䧧& 6 2؏!pLXmQVo_ .JM RGEgwS!d{ ruby2ruby-2.0.7/History.txt0000444000004100000410000002114012256407415015721 0ustar www-datawww-data=== 2.0.7 / 2013-12-13 * 4 minor enhancements: * Add != to list of binary operators. (camertron) *le sigh* * Clean out cruft from process_masgn that I can't reproduce anymore. * Extend process_args to deal with masgn (eg: a.b { |(c, d)| ... }). * Extend process_masgn to deal with both sexps and var lists. * 1 bug fix: * Ensure proper parens on rescue subexpressions. (Bocete) === 2.0.6 / 2013-06-20 * 2 bug fixes: * Fixed bug with complex rescue but short enough to trigger 1-liner. (Confusion) * Fixed multiple expressions inside sclass === 2.0.5 / 2013-04-25 * 2 bug fixes: * Fixed attrasgn w/ multiple keys: a[x, y] = z. (derula) * Fixed error w/ attr_* detection when more than 1 ivar/iasgn exist in body. === 2.0.4 / 2013-03-28 * 1 bug fix: * Fixed attr_* generators in cases where the body isn't idiomatic. (robertfeldt) === 2.0.3 / 2013-02-07 * 2 minor enhancements: * 1.9: Added support for ! call to go back to (not ...). * 2nd and 3rd order testing now uses RubyPraser.for_current_ruby for maximal carnage. * 1 bug fix: * On failure (eg ruby 2.0), fall back to compound RubyParser instance for 2nd & 3rd order testing === 2.0.2 / 2013-01-16 * 1 minor enhancement: * Updated to ruby_parser 3.1 and up === 2.0.1 / 2012-11-02 * 1 bug fix: * Fixed dependency on alpha ruby_parser. *sigh* === 2.0.0 / 2012-11-02 * 1 minor enhancement: * Only do phase 1 testing if $SIMPLE=1. * 1 bug fix: * Fixed block args processing for RP 3.0 sexp changes === 2.0.0.b1 / 2012-07-27 * 4 major enhancements: * Made it work without arglist in call. * Made it work without scope/block in class/module/defn/defs. * Removed block from resbody * Removed block from when node * 4 minor enhancements: * Added debug task to help isolate an error * Empty hash is now a proper {} * Refactored and added finish method. * Switched to new Ruby18Parser to avoid deprecation warnings * 4 bug fixes: * Fixed call with empty hash arg. (neilconway) * OMG WTF... removed long decrepit ParseTree dependency * Removed isolate/rake require to reduce minimum bootstrap to hoe + rake + rake install_plugins (*2) * Skip 1.9 tests for now. === 1.3.1 / 2011-09-22 * 1 minor enhancement: * Added parenthesize to add parens in certain contexts. * 10 bug fixes: * Add newline to 'do nothing' comment in a block... seems contrived. (andreacampi) * Binary operations not work properly with some complex statements. (smorss) * Fixed if statements with no body (smorss) * Fixed logic for call with hash args in various locations (smorss) * Fixed match3 on an assignment. (smorss) * Fixed multiple nested rescue/ensure exprs (larsch) * Fixed process_alias to parenthesize (smorss) * Fixed process_and to parenthenize only when it makes sense. * Fixed rescue with 2+ statements in resbody (smorss) * Regexps with options other than /o were not showing flags. (smorss) === 1.3.0 / 2011-09-01 * 1 minor enhancement: * output comments for class and method definitions. (pythonic) === 1.2.5 / 2010-09-01 * 4 minor enhancements: * Added braces to hash args surrounded if in a binary method call. * Added rewrite_resbody to double check structure and freak if necessary. * Added stress task * rewrite_rescue now detects rescue with multiple arguments. * 2 bug fixes: * Fixed dstr/dregex/d* roundtripping problem * Fixed up call arg processing to be more correct and to work with the new sexp form === 1.2.4 / 2009-08-14 * 2 bug fixes: * Fixed all doco to use ruby_praser * Fixed bin/r2r_show to use ruby_parser. oops === 1.2.3 / 2009-06-23 * 4 minor enhancements: * Overhauled 4-generation tests to use RubyParser. Much cleaner * Removed last of ParseTree. Fully switched to RubyParser. * Switched to minitest * Updated Rakefile to new hoe capabilities === 1.2.2 / 2009-01-20 * 3 minor enhancements: * Added -s to display sexp before printing r2r * Added a bunch of backslash and masgn tests. * Refactored tests. * 4 bug fixes: * Fixed iters to deal with empty bodies. * Fixed process_call for a number of cases incl [], []=, and args processing. * Fixed process_hash to always generate braces if in arglist. * Switched process_alias to producing alias again, needed for globals. === 1.2.1 / 2008-11-04 * 1 bug fix: * Don't freak out and die if passed a c function defn. stupid rails. === 1.2.0 / 2008-10-22 * 2 minor enhancements: * Removed all PT dependent code to PT project (see parse_tree_extensions.rb). * Revamped. Got working with new unified ruby output. Much much cleaner. === 1.1.9 / 2008-06-09 * 5 minor enhancements: * Added more defensive programming in the tests to make it work with 1.9 and rubinius better. * Converted r2r_show to more plain parse style, no more discover_new_classes. * Made Proc#to_sexp and #to_ruby more resiliant. * Started to work on fallback to ruby_parser code. Should prolly do flog first. * Updated rakefile and readme format for hoe. Much cleaner! * 6 bug fixes: * Added 1.9 fixes. * Added code to tests to isolate rubyinline builds. * Fixed miniunit-deprecated assertions * Fixes for const2/3, esp in class names * Renamed ProcStoreTmp#name to #new_name. dur. * Skip proc tests in 1.9 since they require ParseTree. === 1.1.8 / 2007-08-21 * 6 minor enhancements: * Added super awesome .autotest file. YAY! * Removed nil.method_missing... too many ppl bitching about it. * Renamed RubyToRuby (the class name) to Ruby2Ruby. * Restructured self-translation tests so they were friendlier when dying. * Strings are now always one line long only. * Fully in sync with ParseTree and ruby_parser. * 2 bug fixes: * Fixed a number of issues/bugs discovered via ruby_parser. * Cleaned out some dead code and hacks we don't need anymore. === 1.1.7 / 2007-08-21 * 2 major enhancements: * Switched to ParseTree's UnifiedRuby... much much cleaner now! * Made test_ruby2ruby MUCH more rigorous with circular testing. * 5 minor enhancements: * Add r2r_show command like parse_tree_show. * Add parens for :block nodes as appropriate. May be overzealous. * Make SexpAny work with #==. * Removed calls to processor_stack / caller in favor of self.context. * Some style differences, eschew rescue. * 6 bug fixes: * Fix R2R bug with masgn/argscat. * Fixed a bug with new resbody unification. * Fixes for changes to pt_testcase. * Fixes the rest of the tests under strict sexp checking. * Fixed some circular bugs, mostly by hacking them out, wrt operator precidence. * Fixed trinary operator. === 1.1.6 / 2007-06-05 * 2 minor enhancements: * Extended tests for dstr/dsym/drgx to test against embedded slashes and quotes. * Updated for dasgn_curr changes to PT. * 2 bug fixes: * Fixed a bug with begin/rescue/ensure. * Fixed argscat and blockpass bug. blah(42, *args, &block) handled. === 1.1.5 / 2007-02-13 * 3 minor enhancements: * Can now heckle ActiveRecord::Base in full. * Cleaned up 1-liner generating code. * Made clean/simple rescues 1-liners. * 7 bug fixes: * Finally got the rest of block_pass working. * Fixed block_pass on procs in iters. UGH! * Fixed attrasgn in masgn. * Fixed splat in masgn. * Fixed unary/prefix methods. * Fixed attrasgn for []= where there were multiple args inside []. * Fixed a couple resbody bugs. === 1.1.4 / 2007-01-15 * 4 minor enhancements: * Added some extra rewriting code and tests for various bmethods. Ugh. * Added support for splatted block args. * Refactored class/module and dsym/dstr. * Short if/unless statements are now post-conditional expressions. * 4 bug fixes: * Finally fixed eric's nebulous proc code-in-goalposts bug. * Fixed dasgn_curr so block's dasgn vars decl goes away (bug 7420). * Fixed dmethod. I think the tests were bogus before. * Fixed improper end in method rescues (bug 7396). === 1.1.3 / 2006-12-20 * 1 minor enhancement * Unit tests do self-translation and retesting for 3 generations! Solid. BAM! * 1 bug fixes * iasgn inside masgn was totally borked in ruby2ruby. === 1.1.2 / 2006-12-19 * 2 minor enhancements * Improved []= and [] to be more idiomatic. * Support for nested whens (from when case has no expression). * 3 bug fixes * Fixed case output when there is no case expression. * NEARLY have RubyToRuby self-cloning and passing tests again. * Minor cleanup === 1.1.1 / 2006-11-13 * 3 bug fixes * Fixed procs * Cleaned return when no return values. * Rewrote process_if. No more elsif but no more bugs. :) === 1.1.0 / 2006-10-11 * 2 major enhancements * Released separately from ZenHacks. * Major overhaul/audit from the new ParseTree test infrastructure. Very complete now. ruby2ruby-2.0.7/lib/0000755000004100000410000000000012256407415014271 5ustar www-datawww-dataruby2ruby-2.0.7/lib/ruby2ruby.rb0000555000004100000410000005753312256407415016601 0ustar www-datawww-data#!/usr/bin/env ruby -w require 'rubygems' require 'sexp_processor' # :stopdoc: # REFACTOR: stolen from ruby_parser class Regexp unless defined? ENC_NONE then ENC_NONE = /x/n.options ENC_EUC = /x/e.options ENC_SJIS = /x/s.options ENC_UTF8 = /x/u.options CODES = { EXTENDED => 'x', IGNORECASE => 'i', MULTILINE => 'm', ENC_NONE => 'n', ENC_EUC => 'e', ENC_SJIS => 's', ENC_UTF8 => 'u', } end end # :startdoc: ## # Generate ruby code from a sexp. class Ruby2Ruby < SexpProcessor VERSION = "2.0.7" # :nodoc: # cutoff for one-liners LINE_LENGTH = 78 # binary operation messages BINARY = [:<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :**, :'!='] ## # Nodes that represent assignment and probably need () around them. # # TODO: this should be replaced with full precedence support :/ ASSIGN_NODES = [ :dasgn, :flip2, :flip3, :lasgn, :masgn, :attrasgn, :op_asgn1, :op_asgn2, :op_asgn_and, :op_asgn_or, :return, :if, # HACK :rescue, ] def initialize # :nodoc: super @indent = " " self.auto_shift_type = true self.strict = true self.expected = String @calls = [] # self.debug[:defn] = /zsuper/ end ############################################################ # Processors def process_alias(exp) # :nodoc: parenthesize "alias #{process(exp.shift)} #{process(exp.shift)}" end def process_and(exp) # :nodoc: parenthesize "#{process exp.shift} and #{process exp.shift}" end def process_arglist(exp) # custom made node # :nodoc: code = [] until exp.empty? do arg = exp.shift to_wrap = arg.first == :rescue arg_code = process arg code << (to_wrap ? "(#{arg_code})" : arg_code) end code.join ', ' end def process_args(exp) # :nodoc: args = [] until exp.empty? do arg = exp.shift case arg when Symbol then args << arg when Sexp then case arg.first when :lasgn then args << process(arg) when :masgn then args << process(arg) else raise "unknown arg type #{arg.first.inspect}" end else raise "unknown arg type #{arg.inspect}" end end "(#{args.join ', '})" end def process_array(exp) # :nodoc: "[#{process_arglist(exp)}]" end def process_attrasgn(exp) # :nodoc: receiver = process exp.shift name = exp.shift rhs = exp.pop args = s(:array, *exp) exp.clear case name when :[]= then args = process args "#{receiver}#{args} = #{process rhs}" else raise "dunno what to do: #{args.inspect}" unless args.size == 1 # s(:array) name = name.to_s.sub(/=$/, '') if rhs && rhs != s(:arglist) then "#{receiver}.#{name} = #{process(rhs)}" else raise "dunno what to do: #{rhs.inspect}" end end end def process_back_ref(exp) # :nodoc: "$#{exp.shift}" end # TODO: figure out how to do rescue and ensure ENTIRELY w/o begin def process_begin(exp) # :nodoc: code = [] code << "begin" until exp.empty? src = process(exp.shift) src = indent(src) unless src =~ /(^|\n)(rescue|ensure)/ # ensure no level 0 rescues code << src end code << "end" return code.join("\n") end def process_block(exp) # :nodoc: result = [] exp << nil if exp.empty? until exp.empty? do code = exp.shift if code.nil? or code.first == :nil then result << "# do nothing\n" else result << process(code) end end result = parenthesize result.join "\n" result += "\n" unless result.start_with? "(" return result end def process_block_pass exp # :nodoc: raise "huh?: #{exp.inspect}" if exp.size > 1 "&#{process exp.shift}" end def process_break(exp) # :nodoc: val = exp.empty? ? nil : process(exp.shift) # HACK "break" + (val ? " #{val}" : "") if val then "break #{val}" else "break" end end def process_call(exp) # :nodoc: receiver_node_type = exp.first.nil? ? nil : exp.first.first receiver = process exp.shift receiver = "(#{receiver})" if ASSIGN_NODES.include? receiver_node_type name = exp.shift args = [] # this allows us to do both old and new sexp forms: exp.push(*exp.pop[1..-1]) if exp.size == 1 && exp.first.first == :arglist @calls.push name in_context :arglist do until exp.empty? do arg_type = exp.first.sexp_type is_empty_hash = (exp.first == s(:hash)) arg = process exp.shift next if arg.empty? strip_hash = (arg_type == :hash and not BINARY.include? name and not is_empty_hash and (exp.empty? or exp.first.sexp_type == :splat)) wrap_arg = Ruby2Ruby::ASSIGN_NODES.include? arg_type arg = arg[2..-3] if strip_hash arg = "(#{arg})" if wrap_arg args << arg end end case name when *BINARY then "(#{receiver} #{name} #{args.join(', ')})" when :[] then receiver ||= "self" "#{receiver}[#{args.join(', ')}]" when :[]= then receiver ||= "self" rhs = args.pop "#{receiver}[#{args.join(', ')}] = #{rhs}" when :"!" then "(not #{receiver})" when :"-@" then "-#{receiver}" when :"+@" then "+#{receiver}" else args = nil if args.empty? args = "(#{args.join(', ')})" if args receiver = "#{receiver}." if receiver "#{receiver}#{name}#{args}" end ensure @calls.pop end def process_case(exp) # :nodoc: result = [] expr = process exp.shift if expr then result << "case #{expr}" else result << "case" end until exp.empty? pt = exp.shift if pt and pt.first == :when result << "#{process(pt)}" else code = indent(process(pt)) code = indent("# do nothing") if code =~ /^\s*$/ result << "else\n#{code}" end end result << "end" result.join("\n") end def process_cdecl(exp) # :nodoc: lhs = exp.shift lhs = process lhs if Sexp === lhs unless exp.empty? then rhs = process(exp.shift) "#{lhs} = #{rhs}" else lhs.to_s end end def process_class(exp) # :nodoc: "#{exp.comments}class #{util_module_or_class(exp, true)}" end def process_colon2(exp) # :nodoc: "#{process(exp.shift)}::#{exp.shift}" end def process_colon3(exp) # :nodoc: "::#{exp.shift}" end def process_const(exp) # :nodoc: exp.shift.to_s end def process_cvar(exp) # :nodoc: "#{exp.shift}" end def process_cvasgn(exp) # :nodoc: "#{exp.shift} = #{process(exp.shift)}" end def process_cvdecl(exp) # :nodoc: "#{exp.shift} = #{process(exp.shift)}" end def process_defined(exp) # :nodoc: "defined? #{process(exp.shift)}" end def process_defn(exp) # :nodoc: type1 = exp[1].first type2 = exp[2].first rescue nil expect = [:ivar, :iasgn, :attrset] # s(name, args, ivar|iasgn|attrset) if exp.size == 3 and type1 == :args and expect.include? type2 then name = exp.first # don't shift in case we pass through case type2 when :ivar then ivar_name = exp.ivar.last meth_name = ivar_name.to_s[1..-1].to_sym expected = s(meth_name, s(:args), s(:ivar, ivar_name)) if exp == expected then exp.clear return "attr_reader #{name.inspect}" end when :attrset then # TODO: deprecate? this is a PT relic exp.clear return "attr_writer :#{name.to_s[0..-2]}" when :iasgn then ivar_name = exp.iasgn[1] meth_name = "#{ivar_name.to_s[1..-1]}=".to_sym arg_name = exp.args.last expected = s(meth_name, s(:args, arg_name), s(:iasgn, ivar_name, s(:lvar, arg_name))) if exp == expected then exp.clear return "attr_writer :#{name.to_s[0..-2]}" end else raise "Unknown defn type: #{exp.inspect}" end end comm = exp.comments name = exp.shift args = process exp.shift args = "" if args == "()" exp.shift if exp == s(s(:nil)) # empty it out of a default nil expression # REFACTOR: use process_block but get it happier wrt parenthesize body = [] until exp.empty? do body << indent(process(exp.shift)) end body << indent("# do nothing") if body.empty? body = body.join("\n") return "#{comm}def #{name}#{args}\n#{body}\nend".gsub(/\n\s*\n+/, "\n") end def process_defs(exp) # :nodoc: lhs = exp.shift var = [:self, :cvar, :dvar, :ivar, :gvar, :lvar].include? lhs.first name = exp.shift lhs = process(lhs) lhs = "(#{lhs})" unless var exp.unshift "#{lhs}.#{name}" process_defn(exp) end def process_dot2(exp) # :nodoc: "(#{process exp.shift}..#{process exp.shift})" end def process_dot3(exp) # :nodoc: "(#{process exp.shift}...#{process exp.shift})" end def process_dregx(exp) # :nodoc: options = re_opt exp.pop if Fixnum === exp.last "/" << util_dthing(:dregx, exp) << "/#{options}" end def process_dregx_once(exp) # :nodoc: process_dregx(exp) + "o" end def process_dstr(exp) # :nodoc: "\"#{util_dthing(:dstr, exp)}\"" end def process_dsym(exp) # :nodoc: ":\"#{util_dthing(:dsym, exp)}\"" end def process_dxstr(exp) # :nodoc: "`#{util_dthing(:dxstr, exp)}`" end def process_ensure(exp) # :nodoc: body = process exp.shift ens = exp.shift ens = nil if ens == s(:nil) ens = process(ens) || "# do nothing" ens = "begin\n#{ens}\nend\n" if ens =~ /(^|\n)rescue/ body.sub!(/\n\s*end\z/, '') body = indent(body) unless body =~ /(^|\n)rescue/ return "#{body}\nensure\n#{indent ens}" end def process_evstr(exp) # :nodoc: exp.empty? ? '' : process(exp.shift) end def process_false(exp) # :nodoc: "false" end def process_flip2(exp) # :nodoc: "#{process(exp.shift)}..#{process(exp.shift)}" end def process_flip3(exp) # :nodoc: "#{process(exp.shift)}...#{process(exp.shift)}" end def process_for(exp) # :nodoc: recv = process exp.shift iter = process exp.shift body = exp.empty? ? nil : process(exp.shift) result = ["for #{iter} in #{recv} do"] result << indent(body ? body : "# do nothing") result << "end" result.join("\n") end def process_gasgn(exp) # :nodoc: process_iasgn(exp) end def process_gvar(exp) # :nodoc: return exp.shift.to_s end def process_hash(exp) # :nodoc: result = [] until exp.empty? lhs = process(exp.shift) rhs = exp.shift t = rhs.first rhs = process rhs rhs = "(#{rhs})" unless [:lit, :str].include? t # TODO: verify better! result << "#{lhs} => #{rhs}" end return result.empty? ? "{}" : "{ #{result.join(', ')} }" end def process_iasgn(exp) # :nodoc: lhs = exp.shift if exp.empty? then # part of an masgn lhs.to_s else "#{lhs} = #{process exp.shift}" end end def process_if(exp) # :nodoc: expand = Ruby2Ruby::ASSIGN_NODES.include? exp.first.first c = process exp.shift t = process exp.shift f = process exp.shift c = "(#{c.chomp})" if c =~ /\n/ if t then unless expand then if f then r = "#{c} ? (#{t}) : (#{f})" r = nil if r =~ /return/ # HACK - need contextual awareness or something else r = "#{t} if #{c}" end return r if r and (@indent+r).size < LINE_LENGTH and r !~ /\n/ end r = "if #{c} then\n#{indent(t)}\n" r << "else\n#{indent(f)}\n" if f r << "end" r elsif f unless expand then r = "#{f} unless #{c}" return r if (@indent+r).size < LINE_LENGTH and r !~ /\n/ end "unless #{c} then\n#{indent(f)}\nend" else # empty if statement, just do it in case of side effects from condition "if #{c} then\n#{indent '# do nothing'}\nend" end end def process_iter(exp) # :nodoc: iter = process exp.shift args = exp.shift body = exp.empty? ? nil : process(exp.shift) args = case args when 0 then " ||" else a = process(args)[1..-2] a = " |#{a}|" unless a.empty? a end b, e = if iter == "END" then [ "{", "}" ] else [ "do", "end" ] end iter.sub!(/\(\)$/, '') # REFACTOR: ugh result = [] result << "#{iter} {" result << args if body then result << " #{body.strip} " else result << ' ' end result << "}" result = result.join return result if result !~ /\n/ and result.size < LINE_LENGTH result = [] result << "#{iter} #{b}" result << args result << "\n" if body then result << indent(body.strip) result << "\n" end result << e result.join end def process_ivar(exp) # :nodoc: exp.shift.to_s end def process_lasgn(exp) # :nodoc: s = "#{exp.shift}" s += " = #{process exp.shift}" unless exp.empty? s end def process_lit(exp) # :nodoc: obj = exp.shift case obj when Range then "(#{obj.inspect})" else obj.inspect end end def process_lvar(exp) # :nodoc: exp.shift.to_s end def process_masgn(exp) # :nodoc: # s(:masgn, s(:array, s(:lasgn, :var), ...), s(:to_ary, , ...)) # s(:iter, , s(:args, s(:masgn, :a, :b)), ) case exp.first when Sexp then lhs = exp.shift rhs = exp.empty? ? nil : exp.shift case lhs.first when :array then lhs.shift # node type lhs = lhs.map do |l| case l.first when :masgn then "(#{process(l)})" else process(l) end end else raise "no clue: #{lhs.inspect}" end unless rhs.nil? then t = rhs.first rhs = process rhs rhs = rhs[1..-2] if t == :array # FIX: bad? I dunno return "#{lhs.join(", ")} = #{rhs}" else return lhs.join(", ") end when Symbol then # block arg list w/ masgn result = exp.join ", " exp.clear "(#{result})" else raise "unknown masgn: #{exp.inspect}" end end def process_match(exp) # :nodoc: "#{process(exp.shift)}" end def process_match2(exp) # :nodoc: lhs = process(exp.shift) rhs = process(exp.shift) "#{lhs} =~ #{rhs}" end def process_match3(exp) # :nodoc: rhs = process(exp.shift) left_type = exp.first.sexp_type lhs = process(exp.shift) if ASSIGN_NODES.include? left_type then "(#{lhs}) =~ #{rhs}" else "#{lhs} =~ #{rhs}" end end def process_module(exp) # :nodoc: "#{exp.comments}module #{util_module_or_class(exp)}" end def process_next(exp) # :nodoc: val = exp.empty? ? nil : process(exp.shift) if val then "next #{val}" else "next" end end def process_nil(exp) # :nodoc: "nil" end def process_not(exp) # :nodoc: "(not #{process exp.shift})" end def process_nth_ref(exp) # :nodoc: "$#{exp.shift}" end def process_op_asgn1(exp) # :nodoc: # [[:lvar, :b], [:arglist, [:lit, 1]], :"||", [:lit, 10]] lhs = process(exp.shift) index = process(exp.shift) msg = exp.shift rhs = process(exp.shift) "#{lhs}[#{index}] #{msg}= #{rhs}" end def process_op_asgn2(exp) # :nodoc: # [[:lvar, :c], :var=, :"||", [:lit, 20]] lhs = process(exp.shift) index = exp.shift.to_s[0..-2] msg = exp.shift rhs = process(exp.shift) "#{lhs}.#{index} #{msg}= #{rhs}" end def process_op_asgn_and(exp) # :nodoc: # a &&= 1 # [[:lvar, :a], [:lasgn, :a, [:lit, 1]]] exp.shift process(exp.shift).sub(/\=/, '&&=') end def process_op_asgn_or(exp) # :nodoc: # a ||= 1 # [[:lvar, :a], [:lasgn, :a, [:lit, 1]]] exp.shift process(exp.shift).sub(/\=/, '||=') end def process_or(exp) # :nodoc: "(#{process exp.shift} or #{process exp.shift})" end def process_postexe(exp) # :nodoc: "END" end def process_redo(exp) # :nodoc: "redo" end def process_resbody exp # :nodoc: args = exp.shift body = finish(exp) body << "# do nothing" if body.empty? name = args.lasgn true name ||= args.iasgn true args = process(args)[1..-2] args = " #{args}" unless args.empty? args += " => #{name[1]}" if name "rescue#{args}\n#{indent body.join("\n")}" end def process_rescue exp # :nodoc: body = process(exp.shift) unless exp.first.first == :resbody els = process(exp.pop) unless exp.last.first == :resbody body ||= "# do nothing" simple = exp.size == 1 && !exp.resbody.block && exp.resbody.size <= 3 resbodies = [] until exp.empty? do resbody = exp.shift simple &&= resbody[1] == s(:array) simple &&= resbody[2] != nil && resbody[2].node_type != :block resbodies << process(resbody) end if els then "#{indent body}\n#{resbodies.join("\n")}\nelse\n#{indent els}" elsif simple then resbody = resbodies.first.sub(/\n\s*/, ' ') "#{body} #{resbody}" else "#{indent body}\n#{resbodies.join("\n")}" end end def process_retry(exp) # :nodoc: "retry" end def process_return(exp) # :nodoc: # HACK return "return" + (exp.empty? ? "" : " #{process exp.shift}") if exp.empty? then return "return" else return "return #{process exp.shift}" end end def process_sclass(exp) # :nodoc: "class << #{process(exp.shift)}\n#{indent(process_block(exp))}\nend" end def process_self(exp) # :nodoc: "self" end def process_splat(exp) # :nodoc: if exp.empty? then "*" else "*#{process(exp.shift)}" end end def process_str(exp) # :nodoc: return exp.shift.dump end def process_super(exp) # :nodoc: args = finish exp "super(#{args.join(', ')})" end def process_svalue(exp) # :nodoc: code = [] until exp.empty? do code << process(exp.shift) end code.join(", ") end def process_to_ary(exp) # :nodoc: process(exp.shift) end def process_true(exp) # :nodoc: "true" end def process_undef(exp) # :nodoc: "undef #{process(exp.shift)}" end def process_until(exp) # :nodoc: cond_loop(exp, 'until') end def process_valias(exp) # :nodoc: "alias #{exp.shift} #{exp.shift}" end def process_when(exp) # :nodoc: src = [] if self.context[1] == :array then # ugh. matz! why not an argscat?!? val = process(exp.shift) exp.shift # empty body return "*#{val}" end until exp.empty? cond = process(exp.shift).to_s[1..-2] code = indent(finish(exp).join("\n")) code = indent "# do nothing" if code =~ /\A\s*\Z/ src << "when #{cond} then\n#{code.chomp}" end src.join("\n") end def process_while(exp) # :nodoc: cond_loop(exp, 'while') end def process_xstr(exp) # :nodoc: "`#{process_str(exp)[1..-2]}`" end def process_yield(exp) # :nodoc: args = [] until exp.empty? do args << process(exp.shift) end unless args.empty? then "yield(#{args.join(', ')})" else "yield" end end def process_zsuper(exp) # :nodoc: "super" end ############################################################ # Rewriters: def rewrite_attrasgn exp # :nodoc: if context.first(2) == [:array, :masgn] then exp[0] = :call exp[2] = exp[2].to_s.sub(/=$/, '').to_sym end exp end def rewrite_ensure exp # :nodoc: exp = s(:begin, exp) unless context.first == :begin exp end def rewrite_resbody exp # :nodoc: raise "no exception list in #{exp.inspect}" unless exp.size > 2 && exp[1] raise exp[1].inspect if exp[1][0] != :array # for now, do nothing, just check and freak if we see an errant structure exp end def rewrite_rescue exp # :nodoc: complex = false complex ||= exp.size > 3 complex ||= exp.resbody.block complex ||= exp.resbody.size > 3 complex ||= exp.find_nodes(:resbody).any? { |n| n[1] != s(:array) } complex ||= exp.find_nodes(:resbody).any? { |n| n.last.nil? } complex ||= exp.find_nodes(:resbody).any? { |n| n[2] and n[2].node_type == :block } handled = context.first == :ensure exp = s(:begin, exp) if complex unless handled exp end def rewrite_svalue(exp) # :nodoc: case exp.last.first when :array s(:svalue, *exp[1][1..-1]) when :splat exp else raise "huh: #{exp.inspect}" end end ############################################################ # Utility Methods: ## # Generate a post-or-pre conditional loop. def cond_loop(exp, name) cond = process(exp.shift) body = process(exp.shift) head_controlled = exp.shift body = indent(body).chomp if body code = [] if head_controlled then code << "#{name} #{cond} do" code << body if body code << "end" else code << "begin" code << body if body code << "end #{name} #{cond}" end code.join("\n") end ## # Utility method to escape something interpolated. def dthing_escape type, lit lit = lit.gsub(/\n/, '\n') case type when :dregx then lit.gsub(/(\A|[^\\])\//, '\1\/') when :dstr, :dsym then lit.gsub(/"/, '\"') when :dxstr then lit.gsub(/`/, '\`') else raise "unsupported type #{type.inspect}" end end ## # Process all the remaining stuff in +exp+ and return the results # sans-nils. def finish exp # REFACTOR: work this out of the rest of the processors body = [] until exp.empty? do body << process(exp.shift) end body.compact end ## # Indent all lines of +s+ to the current indent level. def indent(s) s.to_s.split(/\n/).map{|line| @indent + line}.join("\n") end ## # Wrap appropriate expressions in matching parens. def parenthesize exp case self.context[1] when nil, :defn, :defs, :class, :sclass, :if, :iter, :resbody, :when, :while then exp else "(#{exp})" end end ## # Return the appropriate regexp flags for a given numeric code. def re_opt options bits = (0..8).map { |n| options[n] * 2**n } bits.delete 0 bits.map { |n| Regexp::CODES[n] }.join end ## # Return a splatted symbol for +sym+. def splat(sym) :"*#{sym}" end ## # Utility method to generate something interpolated. def util_dthing(type, exp) s = [] # first item in sexp is a string literal s << dthing_escape(type, exp.shift) until exp.empty? pt = exp.shift case pt when Sexp then case pt.first when :str then s << dthing_escape(type, pt.last) when :evstr then s << '#{' << process(pt) << '}' # do not use interpolation here else raise "unknown type: #{pt.inspect}" end else raise "unhandled value in d-thing: #{pt.inspect}" end end s.join end ## # Utility method to generate ether a module or class. def util_module_or_class(exp, is_class=false) result = [] name = exp.shift name = process name if Sexp === name result << name if is_class then superk = process(exp.shift) result << " < #{superk}" if superk end result << "\n" body = [] begin code = process(exp.shift) unless exp.empty? body << code.chomp unless code.nil? or code.chomp.empty? end until exp.empty? unless body.empty? then body = indent(body.join("\n\n")) + "\n" else body = "" end result << body result << "end" result.join end end ruby2ruby-2.0.7/metadata.yml0000644000004100000410000001045312256407415016031 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: ruby2ruby version: !ruby/object:Gem::Version version: 2.0.7 platform: ruby authors: - Ryan Davis autorequire: bindir: bin cert_chain: - | -----BEGIN CERTIFICATE----- MIIDPjCCAiagAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB GRYDY29tMB4XDTEzMDkxNjIzMDQxMloXDTE0MDkxNjIzMDQxMlowRTETMBEGA1UE AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx taCPaLmfYIaFcHHCSY4hYDJijRQkLxPeB3xbOfzfLoBDbjvx5JxgJxUjmGa7xhcT oOvjtt5P8+GSK9zLzxQP0gVLS/D0FmoE44XuDr3iQkVS2ujU5zZL84mMNqNB1znh GiadM9GHRaDiaxuX0cIUBj19T01mVE2iymf9I6bEsiayK/n6QujtyCbTWsAS9Rqt qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBBQUAA4IB AQCFZ7JTzoy1gcG4d8A6dmOJy7ygtO5MFpRIz8HuKCF5566nOvpy7aHhDDzFmQuu FX3zDU6ghx5cQIueDhf2SGOncyBmmJRRYawm3wI0o1MeN6LZJ/3cRaOTjSFy6+S6 zqDmHBp8fVA2TGJtO0BLNkbGVrBJjh0UPmSoGzWlRhEVnYC33TpDAbNA+u39UrQI ynwhNN7YbnmSR7+JU2cUjBFv2iPBO+TGuWC+9L2zn3NHjuc6tnmSYipA9y8Hv+As Y4evBVezr3SjXz08vPqRO5YRdO3zfeMT8gBjRqZjWJGMZ2lD4XNfrs7eky74CyZw xx3n58i0lQkBE1EpKE0lFu/y -----END CERTIFICATE----- date: 2013-12-14 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: sexp_processor requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '4.0' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '4.0' - !ruby/object:Gem::Dependency name: ruby_parser requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '3.1' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '3.1' - !ruby/object:Gem::Dependency name: minitest requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '5.2' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '5.2' - !ruby/object:Gem::Dependency name: rdoc requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '4.0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '4.0' - !ruby/object:Gem::Dependency name: hoe requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '3.7' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '3.7' description: |- ruby2ruby provides a means of generating pure ruby code easily from RubyParser compatible Sexps. This makes making dynamic language processors in ruby easier than ever! email: - ryand-ruby@zenspider.com executables: - r2r_show extensions: [] extra_rdoc_files: - History.txt - Manifest.txt - README.txt files: - .autotest - History.txt - Manifest.txt - README.txt - Rakefile - bin/r2r_show - lib/ruby2ruby.rb - test/test_ruby2ruby.rb - .gemtest homepage: https://github.com/seattlerb/ruby2ruby licenses: - MIT metadata: {} post_install_message: rdoc_options: - --main - README.txt require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: seattlerb rubygems_version: 2.1.10 signing_key: specification_version: 4 summary: ruby2ruby provides a means of generating pure ruby code easily from RubyParser compatible Sexps test_files: - test/test_ruby2ruby.rb ruby2ruby-2.0.7/test/0000755000004100000410000000000012256407415014502 5ustar www-datawww-dataruby2ruby-2.0.7/test/test_ruby2ruby.rb0000444000004100000410000003407112256407415020036 0ustar www-datawww-data#!/usr/local/bin/ruby -w $TESTING = true $: << 'lib' require 'minitest/autorun' require 'ruby2ruby' require 'pt_testcase' require 'fileutils' require 'tmpdir' require 'ruby_parser' if ENV["CHECK_SEXPS"] class R2RTestCase < ParseTreeTestCase def self.previous key "ParseTree" end def self.generate_test klass, node, data, input_name, output_name output_name = data.has_key?('Ruby2Ruby') ? 'Ruby2Ruby' : 'Ruby' return if node.to_s =~ /19$/ klass.class_eval <<-EOM def test_#{node} pt = #{data[input_name].inspect} rb = #{data[output_name].inspect} refute_nil pt, \"ParseTree for #{node} undefined\" refute_nil rb, \"Ruby for #{node} undefined\" assert_equal rb, @processor.process(pt) end EOM end end start = __LINE__ class TestRuby2Ruby < R2RTestCase def setup super @check_sexp = ENV["CHECK_SEXPS"] @processor = Ruby2Ruby.new end def do_not_check_sexp! @check_sexp = false end def test_util_dthing_dregx inn = util_thingy(:dregx) inn.shift out = '/a"b#{(1 + 1)}c"d\/e/' exp = /a"b2c"d\/e/ assert_equal exp, eval(out) assert_equal out[1..-2], @processor.util_dthing(:dregx, inn) end def test_util_dthing_dstr inn = util_thingy(:dstr) inn.shift out = '"a\"b#{(1 + 1)}c\"d/e"' exp = 'a"b2c"d/e' assert_equal exp, eval(out) assert_equal out[1..-2], @processor.util_dthing(:dstr, inn) end def test_util_dthing_dregx_bug? inn = s(:dregx, '[\/\"]', s(:evstr, s(:lit, 42))) inn.shift out = '/[\/\"]#{42}/' exp = /[\/\"]42/ assert_equal out[1..-2], @processor.util_dthing(:dregx, inn) assert_equal exp, eval(out) end def test_and_alias inn = s(:and, s(:true), s(:alias, s(:lit, :a), s(:lit, :b))) out = "true and (alias :a :b)" util_compare inn, out end def test_attr_reader_diff inn = s(:defn, :same, s(:args), s(:ivar, :@diff)) out = "def same\n @diff\nend" util_compare inn, out end def test_attr_reader_same do_not_check_sexp! inn = s(:defn, :same, s(:args), s(:ivar, :@same)) out = "attr_reader :same" util_compare inn, out end def test_attr_reader_double inn = s(:defn, :same, s(:args), s(:ivar, :@same), s(:ivar, :@diff)) out = "def same\n @same\n @diff\nend" util_compare inn, out end def test_attr_reader_same_name_diff_body do_not_check_sexp! inn = s(:defn, :same, s(:args), s(:not, s(:ivar, :@same))) out = "def same\n (not @same)\nend" util_compare inn, out end def test_attr_writer_diff inn = s(:defn, :same=, s(:args, :o), s(:iasgn, :@diff, s(:lvar, :o))) out = "def same=(o)\n @diff = o\nend" util_compare inn, out end def test_attr_writer_double inn = s(:defn, :same=, s(:args, :o), s(:iasgn, :@same, s(:lvar, :o)), s(:iasgn, :@diff, s(:lvar, :o))) out = "def same=(o)\n @same = o\n @diff = o\nend" util_compare inn, out end def test_attr_writer_same_name_diff_body inn = s(:defn, :same=, s(:args, :o), s(:iasgn, :@same, s(:lit, 42))) out = "def same=(o)\n @same = 42\nend" util_compare inn, out end def test_attr_writer_same do_not_check_sexp! inn = s(:defn, :same=, s(:args, :o), s(:iasgn, :@same , s(:lvar, :o))) out = "attr_writer :same" util_compare inn, out end def test_dregx_slash do_not_check_sexp! inn = util_thingy(:dregx) out = '/a"b#{(1 + 1)}c"d\/e/' util_compare inn, out, /a"b2c"d\/e/ end def test_dstr_quote inn = util_thingy(:dstr) out = '"a\"b#{(1 + 1)}c\"d/e"' util_compare inn, out, 'a"b2c"d/e' end def test_dsym_quote inn = util_thingy(:dsym) out = ':"a\"b#{(1 + 1)}c\"d/e"' util_compare inn, out, :'a"b2c"d/e' end def test_lit_regexp_slash do_not_check_sexp! # dunno why on this one util_compare s(:lit, /blah\/blah/), '/blah\/blah/', /blah\/blah/ end def test_call_self_index util_compare s(:call, nil, :[], s(:lit, 42)), "self[42]" end def test_call_self_index_equals util_compare(s(:attrasgn, s(:self), :[]=, s(:lit, 42), s(:lit, 24)), "self[42] = 24") end def test_call_self_index_equals_array util_compare(s(:attrasgn, s(:self), :[]=, s(:lit, 1), s(:lit, 2), s(:lit, 3)), "self[1, 2] = 3") end def test_call_arglist_hash_first inn = s(:call, nil, :method, s(:hash, s(:lit, :a), s(:lit, 1)), s(:call, nil, :b)) out = "method({ :a => 1 }, b)" util_compare inn, out end def test_call_arglist_hash_first_last inn = s(:call, nil, :method, s(:hash, s(:lit, :a), s(:lit, 1)), s(:call, nil, :b), s(:hash, s(:lit, :c), s(:lit, 1))) out = "method({ :a => 1 }, b, :c => 1)" util_compare inn, out end def test_call_arglist_hash_last inn = s(:call, nil, :method, s(:call, nil, :b), s(:hash, s(:lit, :a), s(:lit, 1))) out = "method(b, :a => 1)" util_compare inn, out end def test_call_arglist_if inn = s(:call, s(:call, nil, :a), :+, s(:if, s(:call, nil, :b), s(:call, nil, :c), s(:call, nil, :d))) out = "(a + (b ? (c) : (d)))" util_compare inn, out end def test_masgn_block_arg inn = s(:iter, s(:call, s(:nil), :x), s(:args, s(:masgn, :a, :b)), s(:dstr, "", s(:evstr, s(:lvar, :a)), s(:str, "="), s(:evstr, s(:lvar, :b)))) out = 'nil.x { |(a, b)| "#{a}=#{b}" }' util_compare inn, out end def test_masgn_wtf inn = s(:block, s(:masgn, s(:array, s(:lasgn, :k), s(:lasgn, :v)), s(:splat, s(:call, s(:call, nil, :line), :split, s(:lit, /\=/), s(:lit, 2)))), s(:attrasgn, s(:self), :[]=, s(:lvar, :k), s(:call, s(:lvar, :v), :strip))) out = "k, v = *line.split(/\\=/, 2)\nself[k] = v.strip\n" util_compare inn, out end def test_masgn_splat_wtf inn = s(:masgn, s(:array, s(:lasgn, :k), s(:lasgn, :v)), s(:splat, s(:call, s(:call, nil, :line), :split, s(:lit, /\=/), s(:lit, 2)))) out = 'k, v = *line.split(/\\=/, 2)' util_compare inn, out end def test_match3_asgn inn = s(:match3, s(:lit, //), s(:lasgn, :y, s(:call, nil, :x))) out = "(y = x) =~ //" # "y = x =~ //", which matches on x and assigns to y (not what sexp says). util_compare inn, out end def test_splat_call inn = s(:call, nil, :x, s(:splat, s(:call, s(:call, nil, :line), :split, s(:lit, /\=/), s(:lit, 2)))) out = 'x(*line.split(/\=/, 2))' util_compare inn, out end def test_resbody_block inn = s(:rescue, s(:call, nil, :x1), s(:resbody, s(:array), s(:call, nil, :x2), s(:call, nil, :x3))) out = "begin\n x1\nrescue\n x2\n x3\nend" util_compare inn, out end def test_resbody_short_with_begin_end # "begin; blah; rescue; []; end" inn = s(:rescue, s(:call, nil, :blah), s(:resbody, s(:array), s(:array))) out = "blah rescue []" util_compare inn, out end def test_resbody_short_with_begin_end_multiple # "begin; blah; rescue; []; end" inn = s(:rescue, s(:call, nil, :blah), s(:resbody, s(:array), s(:call, nil, :log), s(:call, nil, :raise))) out = "begin\n blah\nrescue\n log\n raise\nend" util_compare inn, out end def test_resbody_short_with_defn_multiple inn = s(:defn, :foo, s(:args), s(:rescue, s(:lasgn, :a, s(:lit, 1)), s(:resbody, s(:array), s(:call, nil, :log), s(:call, nil, :raise)))) out = "def foo\n begin\n a = 1\n rescue\n log\n raise\n end\nend" util_compare inn, out end def test_regexp_options inn = s(:match3, s(:dregx, "abc", s(:evstr, s(:call, nil, :x)), s(:str, "def"), 4), s(:str, "a")) out = '"a" =~ /abc#{x}def/m' util_compare inn, out end def test_resbody_short_with_rescue_args inn = s(:rescue, s(:call, nil, :blah), s(:resbody, s(:array, s(:const, :A), s(:const, :B)), s(:array))) out = "begin\n blah\nrescue A, B\n []\nend" util_compare inn, out end def test_call_binary_call_with_hash_arg # if 42 # args << {:key => 24} # end inn = s(:if, s(:lit, 42), s(:call, s(:call, nil, :args), :<<, s(:hash, s(:lit, :key), s(:lit, 24))), nil) out = "(args << { :key => 24 }) if 42" util_compare inn, out end def test_binary_operators # (1 > 2) Ruby2Ruby::BINARY.each do |op| inn = s(:call, s(:lit, 1), op, s(:lit, 2)) out = "(1 #{op} 2)" util_compare inn, out end end def test_call_empty_hash inn = s(:call, nil, :foo, s(:hash)) out = "foo({})" util_compare inn, out end def test_if_empty inn = s(:if, s(:call, nil, :x), nil, nil) out = "if x then\n # do nothing\nend" util_compare inn, out end def test_interpolation_and_escapes # log_entry = " \e[#{message_color}m#{message}\e[0m " inn = s(:lasgn, :log_entry, s(:dstr, " \e[", s(:evstr, s(:call, nil, :message_color)), s(:str, "m"), s(:evstr, s(:call, nil, :message)), s(:str, "\e[0m "))) out = "log_entry = \" \e[#\{message_color}m#\{message}\e[0m \"" util_compare inn, out end def test_class_comments inn = s(:class, :Z, nil) inn.comments = "# x\n# y\n" out = "# x\n# y\nclass Z\nend" util_compare inn, out end def test_module_comments inn = s(:module, :Z) inn.comments = "# x\n# y\n" out = "# x\n# y\nmodule Z\nend" util_compare inn, out end def test_method_comments inn = s(:defn, :z, s(:args), s(:nil)) inn.comments = "# x\n# y\n" out = "# x\n# y\ndef z\n # do nothing\nend" util_compare inn, out end def test_basic_ensure inn = s(:ensure, s(:lit, 1), s(:lit, 2)) out = "begin\n 1\nensure\n 2\nend" util_compare inn, out end def test_nested_ensure inn = s(:ensure, s(:lit, 1), s(:ensure, s(:lit, 2), s(:lit, 3))) out = "begin\n 1\nensure\n begin\n 2\n ensure\n 3\n end\nend" util_compare inn, out end def test_nested_rescue inn = s(:ensure, s(:lit, 1), s(:rescue, s(:lit, 2), s(:resbody, s(:array), s(:lit, 3)))) out = "begin\n 1\nensure\n 2 rescue 3\nend" util_compare inn, out end def test_nested_rescue_exception inn = s(:ensure, s(:lit, 1), s(:rescue, s(:lit, 2), s(:resbody, s(:array, s(:const, :Exception)), s(:lit, 3)))) out = "begin\n 1\nensure\n begin\n 2\n rescue Exception\n 3\n end\nend" util_compare inn, out end def test_nested_rescue_exception2 inn = s(:ensure, s(:rescue, s(:lit, 2), s(:resbody, s(:array, s(:const, :Exception)), s(:lit, 3))), s(:lit, 1)) out = "begin\n 2\nrescue Exception\n 3\nensure\n 1\nend" util_compare inn, out end def test_rescue_block inn = s(:rescue, s(:call, nil, :alpha), s(:resbody, s(:array), s(:call, nil, :beta), s(:call, nil, :gamma))) out = "begin\n alpha\nrescue\n beta\n gamma\nend" util_compare inn, out end def test_array_adds_parens_around_rescue inn = s(:array, s(:call, nil, :a), s(:rescue, s(:call, nil, :b), s(:resbody, s(:array), s(:call, nil, :c)))) out = "[a, (b rescue c)]" util_compare inn, out end def test_call_arglist_rescue inn = s(:call, nil, :method, s(:rescue, s(:call, nil, :a), s(:resbody, s(:array), s(:call, nil, :b)))) out = "method((a rescue b))" util_compare inn, out end def test_unless_vs_if_not rb1 = "a unless b" rb2 = "a if (not b)" rb3 = "a if ! b" util_compare Ruby18Parser.new.parse(rb1), rb1 util_compare Ruby19Parser.new.parse(rb1), rb1 util_compare Ruby18Parser.new.parse(rb2), rb1 util_compare Ruby19Parser.new.parse(rb2), rb2 util_compare Ruby18Parser.new.parse(rb3), rb1 util_compare Ruby19Parser.new.parse(rb3), rb2 end def util_compare sexp, expected_ruby, expected_eval = nil assert_equal sexp, RubyParser.new.process(expected_ruby), "ruby -> sexp" if @check_sexp assert_equal expected_ruby, @processor.process(sexp), "sexp -> ruby" assert_equal expected_eval, eval(expected_ruby) if expected_eval end def util_thingy(type) s(type, 'a"b', s(:evstr, s(:call, s(:lit, 1), :+, s(:lit, 1))), s(:str, 'c"d/e')) end end #################### # impl # old new # # t old 0 1 # e # s # t new 2 3 tr2r = File.read(__FILE__).split(/\n/)[start+1..__LINE__-2].join("\n") ir2r = File.read("lib/ruby2ruby.rb") require 'ruby_parser' def silent_eval ruby old, $-w = $-w, nil eval ruby $-w = old end def morph_and_eval src, from, to, processor parser = RubyParser.for_current_ruby rescue RubyParser.new new_src = processor.new.process(parser.process(src.sub(from, to))) silent_eval new_src new_src end unless ENV["SIMPLE"] then ____ = morph_and_eval tr2r, /TestRuby2Ruby/, 'TestRuby2Ruby2', Ruby2Ruby ruby = morph_and_eval ir2r, /Ruby2Ruby/, 'Ruby2Ruby2', Ruby2Ruby ____ = morph_and_eval ruby, /Ruby2Ruby2/, 'Ruby2Ruby3', Ruby2Ruby2 class TestRuby2Ruby1 < TestRuby2Ruby def setup super @processor = Ruby2Ruby2.new end end class TestRuby2Ruby3 < TestRuby2Ruby2 def setup super @processor = Ruby2Ruby2.new end end class TestRuby2Ruby4 < TestRuby2Ruby2 def setup super @processor = Ruby2Ruby3.new end end end ruby2ruby-2.0.7/checksums.yaml.gz.sig0000444000004100000410000000040012256407414017563 0ustar www-datawww-datai)׀q:JܡGquR3 idv' x /U19 ~rg$ 6 ~g؄ʻE8\9% zs[Xw 0/'.86&'> {W|0GEJ]|f(y߇qɊdVTJ@1$XH3JΝnoìUHAY=Um)jT~shI;+Z1{ӔTAOruby2ruby-2.0.7/metadata.gz.sig0000444000004100000410000000040012256407414016415 0ustar www-datawww-datawr`]N{5oY+;UQc>g?vdkBͣvp@9YL['RhVtl%#4dBz8 +[2E~'졕ix&z5Hh)/h~~52nrgKyQs~X<<*'r,$Di^[e虤Ծ2n^61g!3>r 0zuƑ{'nf2>e#=s]g[M}Ggruby2ruby-2.0.7/checksums.yaml.gz0000444000004100000410000000041612256407414017011 0ustar www-datawww-datauRe;@EYl`,Ě۾Pc~^x>;NˏO?;xl RBU h>wT:,ƥZ5VP ʒV]?ZH.us=7ޏ9>b;䁜!qҍ76&XaDg A}DmsBAu鹡ef =w)(4q;#)`ZW~zZzgjɵ<ac