ruby2ruby-2.3.0/0000755000004100000410000000000012677057701013525 5ustar www-datawww-dataruby2ruby-2.3.0/Rakefile0000444000004100000410000000305212677057701015170 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' license "MIT" 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 task :bugs do sh "for f in bug*.rb ; do #{Gem.ruby} -S rake debug F=$f && rm $f ; done" end # vim: syntax=ruby ruby2ruby-2.3.0/bin/0000755000004100000410000000000012677057701014275 5ustar www-datawww-dataruby2ruby-2.3.0/bin/r2r_show0000555000004100000410000000106212677057701015765 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.3.0/Manifest.txt0000444000004100000410000000015412677057701016032 0ustar www-datawww-data.autotest History.txt Manifest.txt README.txt Rakefile bin/r2r_show lib/ruby2ruby.rb test/test_ruby2ruby.rb ruby2ruby-2.3.0/.autotest0000444000004100000410000000116612677057701015400 0ustar www-datawww-data# -*- ruby -*- require 'autotest/restart' Autotest.add_hook :initialize do |at| at.libs << ':../../minitest/dev/lib' 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.3.0/README.txt0000444000004100000410000000525312677057701015226 0ustar www-datawww-data= ruby2ruby home :: https://github.com/seattlerb/ruby2ruby rdoc :: http://docs.seattlerb.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.deep_clone) # Note: #process destroys its input, so # #deep_clone if you need to preserve it ## 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.3.0/ruby2ruby.gemspec0000644000004100000410000000651112677057701017042 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "ruby2ruby" s.version = "2.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Ryan Davis"] s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDPjCCAiagAwIBAgIBAzANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu\nZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB\nGRYDY29tMB4XDTE1MDkxOTIwNTEyMloXDTE2MDkxODIwNTEyMlowRTETMBEGA1UE\nAwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS\nJomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda\nb9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx\ntaCPaLmfYIaFcHHCSY4hYDJijRQkLxPeB3xbOfzfLoBDbjvx5JxgJxUjmGa7xhcT\noOvjtt5P8+GSK9zLzxQP0gVLS/D0FmoE44XuDr3iQkVS2ujU5zZL84mMNqNB1znh\nGiadM9GHRaDiaxuX0cIUBj19T01mVE2iymf9I6bEsiayK/n6QujtyCbTWsAS9Rqt\nqhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV\ngBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw\nHQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBBQUAA4IB\nAQB+Hx8xUgrpZa4P8H8gR8zme5kISwQrG80MbpqJV6/G3/ZicRFhN5sjwu0uHGue\nbd9Cymf6oIRwHVarJux2M32T6bL07Hmi07w2QaPc3MnMKB/D46SRZ2JSSGPFRBTc\nSilobMRoGs/7B15uGFUEnNrCB/ltMqhwwSx1r++UQPfeySHEV9uqu03E5Vb7J37O\n2Er6PLXHRiYsIycD1LkMi6YnixdITRHmrqJYE2rsjaIfpIehiusVAPHkNf7qbpHq\nqx3h45R1CAsObX0SQDIT+rRbQrtKz1GHIZTOFYvEJjUY1XmRTZupD3CJ8Q7sDqSy\nNLq5jm1fq6Y9Uolu3RJbmycf\n-----END CERTIFICATE-----\n"] s.date = "2016-02-19" s.description = "ruby2ruby provides a means of generating pure ruby code easily from\nRubyParser compatible Sexps. This makes making dynamic language\nprocessors in ruby easier than ever!" s.email = ["ryand-ruby@zenspider.com"] s.executables = ["r2r_show"] s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"] s.files = [".autotest", "History.txt", "Manifest.txt", "README.txt", "Rakefile", "bin/r2r_show", "lib/ruby2ruby.rb", "test/test_ruby2ruby.rb"] s.homepage = "https://github.com/seattlerb/ruby2ruby" s.licenses = ["MIT"] s.rdoc_options = ["--main", "README.txt"] s.require_paths = ["lib"] s.rubygems_version = "1.8.23" s.summary = "ruby2ruby provides a means of generating pure ruby code easily from RubyParser compatible Sexps" if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, ["~> 3.14"]) s.add_development_dependency(%q, ["~> 5.8"]) s.add_development_dependency(%q, ["~> 4.0"]) s.add_runtime_dependency(%q, ["~> 3.1"]) s.add_runtime_dependency(%q, ["~> 4.0"]) else s.add_dependency(%q, ["~> 3.14"]) s.add_dependency(%q, ["~> 5.8"]) s.add_dependency(%q, ["~> 4.0"]) s.add_dependency(%q, ["~> 3.1"]) s.add_dependency(%q, ["~> 4.0"]) end else s.add_dependency(%q, ["~> 3.14"]) s.add_dependency(%q, ["~> 5.8"]) s.add_dependency(%q, ["~> 4.0"]) s.add_dependency(%q, ["~> 3.1"]) s.add_dependency(%q, ["~> 4.0"]) end end ruby2ruby-2.3.0/data.tar.gz.sig0000444000004100000410000000040012677057701016336 0ustar www-datawww-data!<T' ,8O4@+$cvDT" *0wBbM(_;2:Jy$@X8ԉ뮢gZ*HŹ`3^۾!,@lb轔ղP:zzx '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.3.0" # :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, ] ## # Some sexp types are OK without parens when appearing as hash values. # This list can include `:call`s because they're always printed with parens # around their arguments. For example: # # { :foo => (bar("baz")) } # The outer parens are unnecessary # { :foo => bar("baz") } # This is the normal code style HASH_VAL_NO_PAREN = [ :call, :false, :lit, :lvar, :nil, :str, :true ] 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) when :kwarg then _, k, v = arg args << "#{k}: #{process v}" 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, safe_call = false) # :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 if safe_call "#{receiver}&.#{name}(#{args.join(', ')})" else "(#{receiver} #{name} #{args.join(', ')})" end 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 and not safe_call receiver = "#{receiver}&." if receiver and safe_call "#{receiver}#{name}#{args}" end ensure @calls.pop end def process_safe_call(exp) # :nodoc: process_call(exp, :safe) 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 << process(exp.shift) end body << "# do nothing" if body.empty? body = body.join("\n") body = body.lines.to_a[1..-2].join("\n") if body =~ /^\Abegin/ && body =~ /^end\z/ body = indent(body) unless body =~ /(^|\n)rescue/ 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? s = exp.shift t = s.sexp_type lhs = process s case t when :kwsplat then result << lhs else rhs = exp.shift t = rhs.first rhs = process rhs rhs = "(#{rhs})" unless HASH_VAL_NO_PAREN.include? t result << "#{lhs} => #{rhs}" end 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 " |#{process(args)[1..-2]}|" 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_kwsplat(exp) "**#{process exp.shift}" 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.size <= 3 && !exp.resbody.block && !exp.resbody.return 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_safe_attrasgn(exp) # :nodoc: receiver = process exp.shift name = exp.shift rhs = exp.pop args = exp.pop # should be nil exp.clear raise "dunno what to do: #{args.inspect}" if args 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 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.3.0/test/0000755000004100000410000000000012677057701014504 5ustar www-datawww-dataruby2ruby-2.3.0/test/test_ruby2ruby.rb0000444000004100000410000004232512677057701020041 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 =~ /(str_question|not|bang).*_(19|20|21|22|23)$/ 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_hash_parens_str inn = s(:hash, s(:lit, :k), s(:str, "banana")) out = '{ :k => "banana" }' util_compare inn, out end def test_hash_parens_lit inn = s(:hash, s(:lit, :k), s(:lit, 0.07)) out = "{ :k => 0.07 }" util_compare inn, out end def test_hash_parens_bool inn = s(:hash, s(:lit, :k), s(:true)) out = "{ :k => true }" util_compare inn, out end def test_hash_parens_nil inn = s(:hash, s(:lit, :k), s(:nil)) out = "{ :k => nil }" util_compare inn, out end def test_hash_parens_lvar inn = s(:hash, s(:lit, :k), s(:lvar, :x)) out = "{ :k => x }" util_compare inn, out end def test_hash_parens_call inn = s(:hash, s(:lit, :k), s(:call, nil, :foo, s(:lit, :bar))) out = "{ :k => foo(:bar) }" util_compare inn, out end def test_hash_parens_iter iter = s(:iter, s(:call, nil, :foo), 0, s(:str, "bar")) inn = s(:hash, s(:lit, :k), iter) out = '{ :k => (foo { "bar" }) }' util_compare inn, 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_kwsplat inn = s(:call, nil, :test_splat, s(:hash, s(:kwsplat, s(:call, nil, :testing)))) out = "test_splat(**testing)" util_compare inn, out end def test_call_arg_assoc_kwsplat inn = s(:call, nil, :f, s(:lit, 1), s(:hash, s(:lit, :kw), s(:lit, 2), s(:kwsplat, s(:lit, 3)))) out = "f(1, :kw => 2, **3)" util_compare inn, out end def test_call_kwsplat_x inn = s(:call, nil, :a, s(:hash, s(:kwsplat, s(:lit, 1)))) out = "a(**1)" util_compare inn, out end def test_defn_kwargs inn = s(:defn, :initialize, s(:args, :arg, s(:kwarg, :keyword, s(:nil)), :"**args"), s(:nil)) out = "def initialize(arg, keyword: nil, **args)\n # do nothing\nend" util_compare inn, out end def test_defn_kwargs2 inn = s(:defn, :initialize, s(:args, :arg, s(:kwarg, :kw1, s(:nil)), s(:kwarg, :kw2, s(:nil)), :"**args"), s(:nil)) out = "def initialize(arg, kw1: nil, kw2: nil, **args)\n # do nothing\nend" util_compare inn, out 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_defn_kwsplat inn = s(:defn, :test, s(:args, :"**testing"), s(:nil)) out = "def test(**testing)\n # do nothing\nend" assert_parse inn, out end def test_defn_rescue_return inn = s(:defn, :blah, s(:args), s(:rescue, s(:lasgn, :a, s(:lit, 1)), s(:resbody, s(:array), s(:return, s(:str, "a"))))) out = "def blah\n a = 1\nrescue\n return \"a\"\nend" assert_parse 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_safe_attrasgn inn = s(:safe_attrasgn, s(:call, nil, :x), :y=, s(:lit, 1)) out = "x&.y = 1" util_compare inn, out end def test_safe_call inn = s(:safe_call, s(:safe_call, s(:call, nil, :x), :y), :z, s(:lit, 1)) out ="x&.y&.z(1)" util_compare inn, out end def test_safe_call_binary inn = s(:safe_call, s(:call, nil, :x), :>, s(:lit, 1)) out = "x&.>(1)" 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 a = 1\nrescue\n log\n raise\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 assert_parse 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 alias util_compare assert_parse 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.3.0/checksums.yaml.gz.sig0000444000004100000410000000040012677057701017566 0ustar www-datawww-datay.ٻRC fMLͱ-c.26Ue*E7QRCt>3{IQ[M:n) ʈ$,A(.r@V:ݧߨ28ͪz3"h'n,~}2;|5 1yȜ5 ') Z4i5 d X¢<}c5c`Q&¨{2 M$"½?;S{+gj,bɕ0%ݓp> ~-Kwgruby2ruby-2.3.0/metadata.gz.sig0000444000004100000410000000040012677057701016420 0ustar www-datawww-data:A kP}sv:qҙFx?%@645_ARQiD6‡y W}O:[`3V_8 =8w8,} ؂\#n%Bu8\lV{yDi*}ma=a/M>3,m+59@Uqx{EUjtIڄ&^%aaNz)Q+0Ŀx%U0YꊞtyʸYn