sexp_processor-4.4.1/0000755000004100000410000000000012256477515014644 5ustar www-datawww-datasexp_processor-4.4.1/Rakefile0000444000004100000410000000033012256477515016303 0ustar www-datawww-data# -*- ruby -*- require 'rubygems' require 'hoe' Hoe.plugin :seattlerb Hoe.spec 'sexp_processor' do developer 'Ryan Davis', 'ryand-ruby@zenspider.com' self.rubyforge_name = 'parsetree' end # vim: syntax=ruby sexp_processor-4.4.1/.gemtest0000644000004100000410000000000012256477515016303 0ustar www-datawww-datasexp_processor-4.4.1/Manifest.txt0000444000004100000410000000037512256477515017156 0ustar www-datawww-dataHistory.txt Manifest.txt README.txt Rakefile lib/composite_sexp_processor.rb lib/pt_testcase.rb lib/sexp.rb lib/sexp_processor.rb lib/unique.rb test/test_composite_sexp_processor.rb test/test_environment.rb test/test_sexp.rb test/test_sexp_processor.rb sexp_processor-4.4.1/README.txt0000444000004100000410000000341312256477515016341 0ustar www-datawww-data= SexpProcessor home :: https://github.com/seattlerb/sexp_processor rdoc :: http://docs.seattlerb.org/sexp_processor == DESCRIPTION: sexp_processor branches from ParseTree bringing all the generic sexp processing tools with it. Sexp, SexpProcessor, Environment, etc... all for your language processing pleasure. == FEATURES/PROBLEMS: * Includes SexpProcessor and CompositeSexpProcessor. * Allows you to write very clean filters. == SYNOPSIS: class MyProcessor < SexpProcessor def initialize super self.strict = false end def process_lit(exp) val = exp.shift return val end end == REQUIREMENTS: * rubygems == INSTALL: * sudo gem install sexp_processor == 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. sexp_processor-4.4.1/data.tar.gz.sig0000444000004100000410000000040012256477515017455 0ustar www-datawww-data]i\#H5.!x* 5 avωP;_uf@ɘ2x,!|( ;Z2 xM~R]xZ Z h2*#ڤpǾ密9=}x# =}nq!B+r)NU-ֱy;$eG /c9с6t"Z)ԁYc6) ed:iej$n'ѽR~s(:lit, 1) # SexpProcessor will call #process_lit, if it is defined. # # You can also specify a default method to call for any Sexp types # without a process_ method or use the default processor provided to # skip over them. # # Here is a simple example: # # class MyProcessor < SexpProcessor # def initialize # super # self.strict = false # end # # def process_lit(exp) # val = exp.shift # return val # end # end class SexpProcessor VERSION = "4.4.1" ## # Automatically shifts off the Sexp type before handing the # Sexp to process_ attr_accessor :auto_shift_type ## # Return a stack of contexts. Most recent node is first. attr_reader :context ## # A Hash of Sexp types and Regexp. # # Print a debug message if the Sexp type matches the Hash key # and the Sexp's #inspect output matches the Regexp. attr_accessor :debug ## # A default method to call if a process_ method is not found # for the Sexp type. attr_accessor :default_method ## # Expected result class attr_accessor :expected ## # Raise an exception if the Sexp is not empty after processing attr_accessor :require_empty ## # Raise an exception if no process_ method is found for a Sexp. attr_accessor :strict ## # An array that specifies node types that are unsupported by this # processor. SexpProcessor will raise UnsupportedNodeError if you try # to process one of those node types. attr_accessor :unsupported ## # Emit a warning when the method in #default_method is called. attr_accessor :warn_on_default ## # A scoped environment to make you happy. attr_reader :env ## # Creates a new SexpProcessor. Use super to invoke this # initializer from SexpProcessor subclasses, then use the # attributes above to customize the functionality of the # SexpProcessor def initialize @default_method = nil @warn_on_default = true @auto_shift_type = false @strict = false @unsupported = [:alloca, :cfunc, :cref, :ifunc, :last, :memo, :newline, :opt_n, :method] @unsupported_checked = false @debug = {} @expected = Sexp @require_empty = true @exceptions = {} # we do this on an instance basis so we can subclass it for # different processors. @processors = {} @rewriters = {} @context = [] public_methods.each do |name| case name when /^process_(.*)/ then @processors[$1.to_sym] = name.to_sym when /^rewrite_(.*)/ then @rewriters[$1.to_sym] = name.to_sym end end end def assert_empty(meth, exp, exp_orig) unless exp.empty? then msg = "exp not empty after #{self.class}.#{meth} on #{exp.inspect}" msg += " from #{exp_orig.inspect}" if $DEBUG raise NotEmptyError, msg end end def rewrite(exp) type = exp.first if @debug.has_key? type then str = exp.inspect puts "// DEBUG (original ): #{str}" if str =~ @debug[type] end in_context type do exp.map! { |sub| Array === sub ? rewrite(sub) : sub } end begin meth = @rewriters[type] exp = self.send(meth, exp) if meth break unless Sexp === exp if @debug.has_key? type then str = exp.inspect puts "// DEBUG (rewritten): #{str}" if str =~ @debug[type] end old_type, type = type, exp.first end until old_type == type exp end ## # Default Sexp processor. Invokes process_ methods matching # the Sexp type given. Performs additional checks as specified by # the initializer. def process(exp) return nil if exp.nil? if self.context.empty? then p :rewriting unless debug.empty? exp = self.rewrite(exp) p :done_rewriting unless debug.empty? end unless @unsupported_checked then m = public_methods.grep(/^process_/) { |o| o.to_s.sub(/^process_/, '').to_sym } supported = m - (m - @unsupported) raise UnsupportedNodeError, "#{supported.inspect} shouldn't be in @unsupported" unless supported.empty? @unsupported_checked = true end result = self.expected.new type = exp.first raise "type should be a Symbol, not: #{exp.first.inspect}" unless Symbol === type in_context type do if @debug.has_key? type then str = exp.inspect puts "// DEBUG:(original ): #{str}" if str =~ @debug[type] end exp_orig = nil exp_orig = exp.deep_clone if $DEBUG or @debug.has_key? type or @exceptions.has_key?(type) raise UnsupportedNodeError, "'#{type}' is not a supported node type" if @unsupported.include? type # now do a pass with the real processor (or generic) meth = @processors[type] || @default_method if meth then if @warn_on_default and meth == @default_method then warn "WARNING: Using default method #{meth} for #{type}" end exp.shift if @auto_shift_type and meth != @default_method result = error_handler(type, exp_orig) do self.send(meth, exp) end if @debug.has_key? type then str = exp.inspect puts "// DEBUG (processed): #{str}" if str =~ @debug[type] end raise SexpTypeError, "Result must be a #{@expected}, was #{result.class}:#{result.inspect}" unless @expected === result self.assert_empty(meth, exp, exp_orig) if @require_empty else unless @strict then until exp.empty? do sub_exp = exp.shift sub_result = nil if Array === sub_exp then sub_result = error_handler(type, exp_orig) do process(sub_exp) end raise "Result is a bad type" unless Array === sub_exp raise "Result does not have a type in front: #{sub_exp.inspect}" unless Symbol === sub_exp.first unless sub_exp.empty? else sub_result = sub_exp end result << sub_result end # NOTE: this is costly, but we are in the generic processor # so we shouldn't hit it too much with RubyToC stuff at least. #if Sexp === exp and not exp.sexp_type.nil? then begin result.sexp_type = exp.sexp_type rescue Exception # nothing to do, on purpose end else msg = "Bug! Unknown node-type #{type.inspect} to #{self.class}" msg += " in #{exp_orig.inspect} from #{caller.inspect}" if $DEBUG raise UnknownNodeError, msg end end end result end ## # Raises unless the Sexp type for +list+ matches +typ+ def assert_type(list, typ) raise SexpTypeError, "Expected type #{typ.inspect} in #{list.inspect}" if not Array === list or list.first != typ end def error_handler(type, exp=nil) # :nodoc: begin return yield rescue StandardError => err if @exceptions.has_key? type then return @exceptions[type].call(self, exp, err) else warn "#{err.class} Exception thrown while processing #{type} for sexp #{exp.inspect} #{caller.inspect}" if $DEBUG raise end end end ## # Registers an error handler for +node+ def on_error_in(node_type, &block) @exceptions[node_type] = block end ## # A fairly generic processor for a dummy node. Dummy nodes are used # when your processor is doing a complicated rewrite that replaces # the current sexp with multiple sexps. # # Bogus Example: # # def process_something(exp) # return s(:dummy, process(exp), s(:extra, 42)) # end def process_dummy(exp) result = @expected.new(:dummy) rescue @expected.new until exp.empty? do result << self.process(exp.shift) end result end ## # Add a scope level to the current env. Eg: # # def process_defn exp # name = exp.shift # args = process(exp.shift) # scope do # body = process(exp.shift) # # ... # end # end # # env[:x] = 42 # scope do # env[:x] # => 42 # env[:y] = 24 # end # env[:y] # => nil def scope &block env.scope(&block) end def in_context type self.context.unshift type yield self.context.shift end ## # I really hate this here, but I hate subdirs in my lib dir more... # I guess it is kinda like shaving... I'll split this out when it # itches too much... class Environment def initialize @env = [] @env.unshift({}) end def all @env.reverse.inject { |env, scope| env.merge scope } end def depth @env.length end # TODO: depth_of def [] name hash = @env.find { |closure| closure.has_key? name } hash[name] if hash end def []= name, val hash = @env.find { |closure| closure.has_key? name } || current hash[name] = val end def current @env.first end def scope @env.unshift({}) begin yield ensure @env.shift raise "You went too far unextending env" if @env.empty? end end end end ## # A simple subclass of SexpProcessor that defines a pattern I commonly # use: non-mutative and strict process that return assorted values; # AKA, an interpreter. class SexpInterpreter < SexpProcessor def initialize super self.expected = Object self.require_empty = false self.strict = true end end ## # A simple subclass of SexpProcessor that tracks method and class # stacks for you. Use #method_name, #klass_name, or #signature to # refer to where you're at in processing. If you have to subclass # process_(class|module|defn|defs) you _must_ call super. class MethodBasedSexpProcessor < SexpProcessor @@no_class = :main @@no_method = :none attr_reader :class_stack, :method_stack, :sclass, :method_locations def initialize super @sclass = [] @class_stack = [] @method_stack = [] @method_locations = {} self.require_empty = false end ## # Adds name to the class stack, for the duration of the block def in_klass name if Sexp === name then name = case name.first when :colon2 then name = name.flatten name.delete :const name.delete :colon2 name.join("::") when :colon3 then name.last.to_s else raise "unknown type #{name.inspect}" end end @class_stack.unshift name yield ensure @class_stack.shift end ## # Adds name to the method stack, for the duration of the block def in_method(name, file, line) method_name = Regexp === name ? name.inspect : name.to_s @method_stack.unshift method_name @method_locations[signature] = "#{file}:#{line}" yield ensure @method_stack.shift end ## # Tracks whether we're in a singleton class or not. Doesn't track # actual receiver. def in_sklass @sclass.push true yield ensure @sclass.pop end ## # Returns the first class in the list, or @@no_class if there are # none. def klass_name name = @class_stack.first if Sexp === name then raise "you shouldn't see me" elsif @class_stack.any? @class_stack.reverse.join("::").sub(/\([^\)]+\)$/, '') else @@no_class end end ## # Returns the first method in the list, or "#none" if there are # none. def method_name m = @method_stack.first || @@no_method m = "##{m}" unless m =~ /::/ m end ## # Process a class node until empty. Tracks all nesting. If you have # to subclass and override this method, you can clall super with a # block. def process_class(exp) exp.shift unless auto_shift_type # node type in_klass exp.shift do if block_given? then yield else process_until_empty exp end end s() end ## # Process a method node until empty. Tracks your location. If you # have to subclass and override this method, you can clall super # with a block. def process_defn(exp) exp.shift unless auto_shift_type # node type name = @sclass.empty? ? exp.shift : "::#{exp.shift}" in_method name, exp.file, exp.line do if block_given? then yield else process_until_empty exp end end s() end ## # Process a singleton method node until empty. Tracks your location. # If you have to subclass and override this method, you can clall # super with a block. def process_defs(exp) exp.shift unless auto_shift_type # node type process exp.shift # recv in_method "::#{exp.shift}", exp.file, exp.line do if block_given? then yield else process_until_empty exp end end s() end ## # Process a module node until empty. Tracks all nesting. If you have # to subclass and override this method, you can clall super with a # block. def process_module(exp) exp.shift unless auto_shift_type # node type in_klass exp.shift do if block_given? then yield else process_until_empty exp end end s() end ## # Process a singleton class node until empty. Tracks all nesting. If # you have to subclass and override this method, you can clall super # with a block. def process_sclass(exp) exp.shift unless auto_shift_type # node type in_sklass do if block_given? then yield else process_until_empty exp end end s() end ## # Process each element of #exp in turn. def process_until_empty exp until exp.empty? sexp = exp.shift process sexp if Sexp === sexp end end ## # Returns the method signature for the current method. def signature "#{klass_name}#{method_name}" end end class Object ## # deep_clone is the usual Marshalling hack to make a deep copy. # It is rather slow, so use it sparingly. Helps with debugging # SexpProcessors since you usually shift off sexps. def deep_clone Marshal.load(Marshal.dump(self)) end end ## # SexpProcessor base exception class. class SexpProcessorError < StandardError; end ## # Raised by SexpProcessor if it sees a node type listed in its # unsupported list. class UnsupportedNodeError < SexpProcessorError; end ## # Raised by SexpProcessor if it is in strict mode and sees a node for # which there is no processor available. class UnknownNodeError < SexpProcessorError; end ## # Raised by SexpProcessor if a processor did not process every node in # a sexp and @require_empty is true. class NotEmptyError < SexpProcessorError; end ## # Raised if assert_type encounters an unexpected sexp type. class SexpTypeError < SexpProcessorError; end sexp_processor-4.4.1/lib/pt_testcase.rb0000444000004100000410000040310712256477515020260 0ustar www-datawww-data# encoding: US-ASCII $TESTING = true require 'minitest/unit' require 'sexp_processor' # for deep_clone # key: # wwtt = what were they thinking? class Examples attr_reader :reader attr_writer :writer def a_method(x); x+1; end alias an_alias a_method define_method(:bmethod_noargs) do x + 1 end define_method(:unsplatted) do |x| x + 1 end define_method :splatted do |*args| y = args.first y + 42 end define_method :dmethod_added, instance_method(:a_method) if RUBY_VERSION < "1.9" end class ParseTreeTestCase < Minitest::Test attr_accessor :processor # to be defined by subclass def setup super @processor = nil end def after_process_hook klass, node, data, input_name, output_name end def before_process_hook klass, node, data, input_name, output_name end def self.add_test name, data, klass = self.name[4..-1] name = name.to_s klass = klass.to_s if testcases.has_key? name then if testcases[name].has_key? klass then warn "testcase #{klass}##{name} already has data" else testcases[name][klass] = data end else warn "testcase #{name} does not exist" end end def self.add_tests name, hash name = name.to_s hash.each do |klass, data| warn "testcase #{klass}##{name} already has data" if testcases[name].has_key? klass testcases[name][klass] = data end end def self.add_18tests name, hash add_tests "#{name}__18", hash end def self.add_19tests name, hash add_tests "#{name}__19", hash end def self.add_19edgecases ruby, sexp, cases cases.each do |name, code| add_19tests name, "Ruby" => code, "ParseTree" => sexp, "Ruby2Ruby" => ruby end end def self.clone_same @@testcases.each do |node, data| data.each do |key, val| if val == :same then prev_key = self.previous(key) data[key] = data[prev_key].deep_clone end end end end def self.copy_test_case nonverbose, klass verbose = nonverbose + "_mri_verbose_flag" testcases[verbose][klass] = testcases[nonverbose][klass] end def self.generate_test klass, node, data, input_name, output_name klass.send :define_method, "test_#{node}" do flunk "Processor is nil" if processor.nil? if node =~ /(1[89])$/ then version = $1 skip "version specific test" unless self.class.name =~ /#{version}/ end assert data.has_key?(input_name), "Unknown input data" assert data.has_key?(output_name), "Missing test data" $missing[node] << output_name unless data.has_key? output_name input = data[input_name].deep_clone expected = data[output_name].deep_clone case expected when :unsupported then assert_raises(UnsupportedNodeError) do processor.process(input) end else extra_expected = [] extra_input = [] _, expected, extra_expected = *expected if Array === expected and expected.first == :defx _, input, extra_input = *input if Array === input and input.first == :defx # OMG... I can't believe I have to do this this way. these # hooks are here instead of refactoring this define_method # body into an assertion. It'll allow subclasses to hook in # and add behavior before or after the processor does it's # thing. If you go the body refactor route, some of the # RawParseTree test cases fail for completely bogus reasons. before_process_hook klass, node, data, input_name, output_name refute_nil data[input_name], "testcase does not exist?" @result = processor.process input assert_equal(expected, @result, "failed on input: #{data[input_name].inspect}") after_process_hook klass, node, data, input_name, output_name extra_input.each do |extra| processor.process(extra) end extra = processor.extra_methods rescue [] assert_equal extra_expected, extra end end end def self.generate_tests klass install_missing_reporter clone_same output_name = klass.name.to_s.sub(/^Test/, '') input_name = self.previous(output_name) @@testcases.each do |node, data| next if [:skip, :unsupported].include? data[input_name] next if data[output_name] == :skip generate_test klass, node, data, input_name, output_name end end def self.inherited klass super generate_tests klass unless klass.name =~ /TestCase/ end def self.install_missing_reporter unless defined? $missing then $missing = Hash.new { |h,k| h[k] = [] } at_exit { at_exit { warn "" $missing.sort.each do |name, klasses| warn "add_tests(#{name.inspect}," klasses.map! { |klass| " #{klass.inspect} => :same" } warn klasses.join("\n") + ")" end warn "" } } end end def self.previous(key, extra=0) # FIX: remove R2C code idx = @@testcase_order.index(key) raise "Unknown class #{key} in @@testcase_order" if idx.nil? case key when "RubyToRubyC" then idx -= 1 end @@testcase_order[idx - 1 - extra] end def self.testcase_order; @@testcase_order; end def self.testcases; @@testcases; end def self.unsupported_tests *tests tests.flatten.each do |name| add_test name, :unsupported end end ############################################################ # Shared TestCases: @@testcase_order = %w(Ruby ParseTree) @@testcases = Hash.new { |h,k| h[k] = {} } ### # 1.8 specific tests add_18tests("call_arglist_norm_hash_splat", "Ruby" => "o.m(42, :a => 1, :b => 2, *c)", "ParseTree" => s(:call, s(:call, nil, :o), :m, s(:lit, 42), s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2)), s(:splat, s(:call, nil, :c)))) add_18tests("call_arglist_space", "Ruby" => "a (1,2,3)", "ParseTree" => s(:call, nil, :a, s(:lit, 1), s(:lit, 2), s(:lit, 3)), "Ruby2Ruby" => "a(1, 2, 3)") add_18tests("fcall_arglist_norm_hash_splat", "Ruby" => "m(42, :a => 1, :b => 2, *c)", "ParseTree" => s(:call, nil, :m, s(:lit, 42), s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2)), s(:splat, s(:call, nil, :c)))) add_18tests("if_args_no_space_symbol", "Ruby" => "x if y:z", "ParseTree" => s(:if, s(:call, nil, :y, s(:lit, :z)), s(:call, nil, :x), nil), "Ruby2Ruby" => "x if y(:z)") add_18tests("if_post_not", "Ruby" => "a if not b", "ParseTree" => s(:if, s(:call, nil, :b), nil, s(:call, nil, :a)), "Ruby2Ruby" => "a unless b") add_18tests("if_pre_not", "Ruby" => "if not b then a end", "ParseTree" => s(:if, s(:call, nil, :b), nil, s(:call, nil, :a)), "Ruby2Ruby" => "a unless b") add_18tests("iter_args_ivar", "Ruby" => "a { |@a| 42 }", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args, :@a), s(:lit, 42))) add_18tests("iter_masgn_args_ivar", "Ruby" => "a { |a, @b| 42 }", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args, :a, :@b), s(:lit, 42))) add_18tests("not", "Ruby" => "(not true)", "ParseTree" => s(:not, s(:true))) add_18tests("str_question_control", "Ruby" => '?\M-\C-a', "ParseTree" => s(:lit, 129), "Ruby2Ruby" => "129") add_18tests("str_question_escape", "Ruby" => '?\n', "ParseTree" => s(:lit, 10), "Ruby2Ruby" => "10") add_18tests("str_question_literal", "Ruby" => '?a', "ParseTree" => s(:lit, 97), "Ruby2Ruby" => "97") add_18tests("unless_post_not", "Ruby" => "a unless not b", "ParseTree" => s(:if, s(:call, nil, :b), s(:call, nil, :a), nil), "Ruby2Ruby" => "a if b") add_18tests("unless_pre_not", "Ruby" => "unless not b then a end", "ParseTree" => s(:if, s(:call, nil, :b), s(:call, nil, :a), nil), "Ruby2Ruby" => "a if b") add_18tests("until_post_not", "Ruby" => "begin\n (1 + 1)\nend until not true", "ParseTree" => s(:while, s(:true), s(:call, s(:lit, 1), :+, s(:lit, 1)), false), "Ruby2Ruby" => "begin\n (1 + 1)\nend while true") add_18tests("until_pre_not", "Ruby" => "until not true do\n (1 + 1)\nend", "ParseTree" => s(:while, s(:true), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "while true do\n (1 + 1)\nend") add_18tests("until_pre_not_mod", "Ruby" => "(1 + 1) until not true", "ParseTree" => s(:while, s(:true), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "while true do\n (1 + 1)\nend") add_18tests("while_post_not", "Ruby" => "begin\n (1 + 1)\nend while not true", "ParseTree" => s(:until, s(:true), s(:call, s(:lit, 1), :+, s(:lit, 1)), false), "Ruby2Ruby" => "begin\n (1 + 1)\nend until true") add_18tests("while_pre_not", "Ruby" => "while not true do\n (1 + 1)\nend", "ParseTree" => s(:until, s(:true), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "until true do\n (1 + 1)\nend") add_18tests("while_pre_not_mod", "Ruby" => "(1 + 1) while not true", "ParseTree" => s(:until, s(:true), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "until true do\n (1 + 1)\nend") # FIX ### # 1.9 specific tests add_19edgecases("lambda { (x + 1) }", s(:iter, s(:call, nil, :lambda), 0, s(:call, s(:call, nil, :x), :+, s(:lit, 1))), "stabby_args_0" => "->() { (x + 1) }", "stabby_args_0_doend" => "->() do (x + 1) end", "stabby_args_0_no_parens" => "-> { (x + 1) }", "stabby_args_0_no_parens_doend" => "-> do (x + 1) end", "stabby_args_0_spacebar_broken" => "->{x+1}") # I hate you add_19edgecases("lambda { |x, y| (x + y) }", s(:iter, s(:call, nil, :lambda), s(:args, :x, :y), s(:call, s(:lvar, :x), :+, s(:lvar, :y))), "stabby_args_2" => "->(x, y) { (x + y) }", "stabby_args_2_doend" => "->(x, y) do (x + y) end", "stabby_args_2_no_parens" => "-> x, y { (x + y) }", "stabby_args_2_no_parens_doend" => "-> x, y do (x + y) end") add_19edgecases("lambda { |x| (x + 1) }", s(:iter, s(:call, nil, :lambda), s(:args, :x), s(:call, s(:lvar, :x), :+, s(:lit, 1))), "stabby_args_1" => "->(x) { (x + 1) }", "stabby_args_1_doend" => "->(x) do (x + 1) end", "stabby_args_1_no_parens" => "-> x { (x + 1) }", "stabby_args_1_no_parens_doend" => "-> x do (x + 1) end") add_19tests("array_bare_hash", "Ruby" => "[:a, :b => :c]", "ParseTree" => s(:array, s(:lit, :a), s(:hash, s(:lit, :b), s(:lit, :c)))) add_19tests("array_bare_hash_labels", "Ruby" => "[:a, b: :c]", "ParseTree" => s(:array, s(:lit, :a), s(:hash, s(:lit, :b), s(:lit, :c)))) add_19tests("call_arglist_norm_hash_colons", "Ruby" => "o.m(42, a: 1, b: 2)", "ParseTree" => s(:call, s(:call, nil, :o), :m, s(:lit, 42), s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2)))) add_19tests("call_arglist_trailing_comma", "Ruby" => "a(1,2,3,)", "ParseTree" => s(:call, nil, :a, s(:lit, 1), s(:lit, 2), s(:lit, 3))) add_19tests("call_bang", "Ruby" => "!a", "ParseTree" => s(:call, s(:call, nil, :a), :"!")) add_19tests("call_bang_empty", "Ruby" => "! ()", "ParseTree" => s(:call, s(:nil), :"!")) add_19tests("call_fonz", "Ruby" => "a.()", "ParseTree" => s(:call, s(:call, nil, :a), :call)) add_19tests("call_fonz_cm", "Ruby" => "a::()", "ParseTree" => s(:call, s(:call, nil, :a), :call)) add_19tests("call_not", "Ruby" => "not (42)", "ParseTree" => s(:call, s(:lit, 42), :"!")) # add_19tests("call_not_empty", # "Ruby" => "not ()", # "ParseTree" => s(:call, s(:lit, 42), :"!")) add_19tests("call_not_equal", "Ruby" => "a != b", "ParseTree" => s(:call, s(:call, nil, :a), :"!=", s(:call, nil, :b))) add_19tests("call_splat_mid", "Ruby" => "def f(a = nil, *b, c) end", "ParseTree" => s(:defn, :f, s(:args, s(:lasgn, :a, s(:nil)), :"*b", :c), s(:nil))) add_19tests("defn_args_mand_opt_mand", "Ruby" => "def f(mand1, opt = 42, mand2)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand1, s(:lasgn, :opt, s(:lit, 42)), :mand2), s(:nil))) add_19tests("defn_args_mand_opt_splat_mand", "Ruby" => "def f(mand1, opt = 42, *rest, mand2)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand1, s(:lasgn, :opt, s(:lit, 42)), :"*rest", :mand2), s(:nil))) add_19tests("defn_args_opt_mand", "Ruby" => "def f(opt = 42, mand)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, s(:lasgn, :opt, s(:lit, 42)), :mand), s(:nil))) add_19tests("defn_args_opt_splat_mand", "Ruby" => "def f(opt = 42, *rest, mand)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, s(:lasgn, :opt, s(:lit, 42)), :"*rest", :mand), s(:nil))) add_19tests("defn_args_splat_mand", "Ruby" => "def f(*rest, mand)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :"*rest", :mand), s(:nil))) add_19tests("defn_args_splat_middle", "Ruby" => "def f(first, *middle, last)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :first, :"*middle", :last), s(:nil))) add_19tests("fcall_arglist_hash_colons", "Ruby" => "m(a: 1, b: 2)", "ParseTree" => s(:call, nil, :m, s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2)))) add_19tests("hash_new", "Ruby" => "{ a: 1, b: 2 }", "ParseTree" => s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2))) add_19tests("hash_new_no_space", "Ruby" => "{a:1,b:2}", "ParseTree" => s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2))) add_19tests("hash_new_with_keyword", "Ruby" => "{ true: 1, b: 2 }", "ParseTree" => s(:hash, s(:lit, :true), s(:lit, 1), s(:lit, :b), s(:lit, 2))) add_19tests("if_post_not", "Ruby" => "a if not b", "ParseTree" => s(:if, s(:call, s(:call, nil, :b), :"!"), s(:call, nil, :a), nil), "Ruby2Ruby" => "a unless b") add_19tests("if_pre_not", "Ruby" => "if not b then a end", "ParseTree" => s(:if, s(:call, s(:call, nil, :b), :"!"), s(:call, nil, :a), nil), "Ruby2Ruby" => "a unless b") add_19tests("label_in_bare_hash_in_array_in_ternary", "Ruby" => "1 ? [:a, b: 2] : 1", "ParseTree" => s(:if, s(:lit, 1), s(:array, s(:lit, :a), s(:hash, s(:lit, :b), s(:lit, 2))), s(:lit, 1))) add_19tests("label_in_callargs_in_ternary", "Ruby" => "1 ? m(a: 2) : 1", "ParseTree" => s(:if, s(:lit, 1), s(:call, nil, :m, s(:hash, s(:lit, :a), s(:lit, 2))), s(:lit, 1))) add_19tests("not", "Ruby" => "(not true)", "ParseTree" => s(:call, s(:true), :"!")) add_19tests("splat_fcall_middle", "Ruby" => "meth(1, *[2], 3)", "ParseTree" => s(:call, nil, :meth, s(:lit, 1), s(:splat, s(:array, s(:lit, 2))), s(:lit, 3))) add_19tests("str_question_control", "Ruby" => '?\M-\C-a', "ParseTree" => s(:str, "\x81")) add_19tests("str_question_escape", "Ruby" => '?\n', "ParseTree" => s(:str, "\n")) add_19tests("str_question_literal", "Ruby" => '?a', "ParseTree" => s(:str, "a")) add_19tests("unless_post_not", "Ruby" => "a unless not b", "ParseTree" => s(:if, s(:call, s(:call, nil, :b), :"!"), nil, s(:call, nil, :a)), "Ruby2Ruby" => "a if b") add_19tests("unless_pre_not", "Ruby" => "unless not b then a end", "ParseTree" => s(:if, s(:call, s(:call, nil, :b), :"!"), nil, s(:call, nil, :a)), "Ruby2Ruby" => "a if b") add_19tests("until_post_not", "Ruby" => "begin\n (1 + 1)\nend until not true", "ParseTree" => s(:until, s(:call, s(:true), :"!"), s(:call, s(:lit, 1), :+, s(:lit, 1)), false), "Ruby2Ruby" => "begin\n (1 + 1)\nend while true") add_19tests("until_pre_not", "Ruby" => "until not true do\n (1 + 1)\nend", "ParseTree" => s(:until, s(:call, s(:true), :"!"), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "while true do\n (1 + 1)\nend") add_19tests("until_pre_not_mod", "Ruby" => "(1 + 1) until not true", "ParseTree" => s(:until, s(:call, s(:true), :"!"), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "while true do\n (1 + 1)\nend") add_19tests("while_post_not", "Ruby" => "begin\n (1 + 1)\nend while not true", "ParseTree" => s(:while, s(:call, s(:true), :"!"), s(:call, s(:lit, 1), :+, s(:lit, 1)), false), "Ruby2Ruby" => "begin\n (1 + 1)\nend until true") add_19tests("while_pre_not", "Ruby" => "while not true do\n (1 + 1)\nend", "ParseTree" => s(:while, s(:call, s(:true), :"!"), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "until true do\n (1 + 1)\nend") add_19tests("while_pre_not_mod", "Ruby" => "(1 + 1) while not true", "ParseTree" => s(:while, s(:call, s(:true), :"!"), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "until true do\n (1 + 1)\nend") # FIX ### # Shared tests: add_tests("alias", "Ruby" => "class X\n alias :y :x\nend", "ParseTree" => s(:class, :X, nil, s(:alias, s(:lit, :y), s(:lit, :x)))) add_tests("alias_ugh", "Ruby" => "class X\n alias y x\nend", "ParseTree" => s(:class, :X, nil, s(:alias, s(:lit, :y), s(:lit, :x))), "Ruby2Ruby" => "class X\n alias :y :x\nend") add_tests("and", "Ruby" => "a and b", "ParseTree" => s(:and, s(:call, nil, :a), s(:call, nil, :b))) add_tests("argscat_inside", "Ruby" => "a = [b, *c]", "ParseTree" => s(:lasgn, :a, s(:array, s(:call, nil, :b), s(:splat, s(:call, nil, :c))))) add_tests("argscat_svalue", "Ruby" => "a = b, c, *d", "ParseTree" => s(:lasgn, :a, s(:svalue, s(:array, s(:call, nil, :b), s(:call, nil, :c), s(:splat, s(:call, nil, :d)))))) add_tests("argspush", "Ruby" => "a[*b] = c", "ParseTree" => s(:attrasgn, s(:call, nil, :a), :[]=, s(:splat, s(:call, nil, :b)), s(:call, nil, :c))) add_tests("array", "Ruby" => "[1, :b, \"c\"]", "ParseTree" => s(:array, s(:lit, 1), s(:lit, :b), s(:str, "c"))) add_tests("array_pct_W", "Ruby" => "%W[a b c]", "ParseTree" => s(:array, s(:str, "a"), s(:str, "b"), s(:str, "c")), "Ruby2Ruby" => "[\"a\", \"b\", \"c\"]") add_tests("array_pct_W_dstr", "Ruby" => "%W[a #\{@b} c]", "ParseTree" => s(:array, s(:str, "a"), s(:dstr, "", s(:evstr, s(:ivar, :@b))), s(:str, "c")), "Ruby2Ruby" => "[\"a\", \"#\{@b}\", \"c\"]") add_tests("array_pct_w", "Ruby" => "%w[a b c]", "ParseTree" => s(:array, s(:str, "a"), s(:str, "b"), s(:str, "c")), "Ruby2Ruby" => "[\"a\", \"b\", \"c\"]") add_tests("array_pct_w_dstr", "Ruby" => "%w[a #\{@b} c]", "ParseTree" => s(:array, s(:str, "a"), s(:str, "#\{@b}"), s(:str, "c")), "Ruby2Ruby" => "[\"a\", \"\\\#{@b}\", \"c\"]") # TODO: huh? add_tests("attrasgn", "Ruby" => "y = 0\n42.method = y\n", "ParseTree" => s(:block, s(:lasgn, :y, s(:lit, 0)), s(:attrasgn, s(:lit, 42), :method=, s(:lvar, :y)))) add_tests("attrasgn_index_equals", "Ruby" => "a[42] = 24", "ParseTree" => s(:attrasgn, s(:call, nil, :a), :[]=, s(:lit, 42), s(:lit, 24))) add_tests("attrasgn_index_equals_space", "Ruby" => "a = []; a [42] = 24", "ParseTree" => s(:block, s(:lasgn, :a, s(:array)), s(:attrasgn, s(:lvar, :a), :[]=, s(:lit, 42), s(:lit, 24))), "Ruby2Ruby" => "a = []\na[42] = 24\n") add_tests("attrset", "Ruby" => [Examples, :writer=], "ParseTree" => s(:defn, :writer=, s(:args, :arg), s(:attrset, :@writer)), "Ruby2Ruby" => "attr_writer :writer") add_tests("back_ref", "Ruby" => "[$&, $`, $', $+]", "ParseTree" => s(:array, s(:back_ref, :&), s(:back_ref, :"`"), s(:back_ref, :"'"), s(:back_ref, :+))) add_tests("begin", "Ruby" => "begin\n (1 + 1)\nend", "ParseTree" => s(:call, s(:lit, 1), :+, s(:lit, 1)), "Ruby2Ruby" => "(1 + 1)") add_tests("begin_def", "Ruby" => "def m\n begin\n\n end\nend", "ParseTree" => s(:defn, :m, s(:args), s(:nil)), "Ruby2Ruby" => "def m\n # do nothing\nend") add_tests("begin_rescue_ensure", "Ruby" => "begin\n a\nrescue\n # do nothing\nensure\n # do nothing\nend", "ParseTree" => s(:ensure, s(:rescue, s(:call, nil, :a), s(:resbody, s(:array), nil)), s(:nil))) add_tests("begin_rescue_ensure_all_empty", "Ruby" => "begin\n # do nothing\nrescue\n # do nothing\nensure\n # do nothing\nend", "ParseTree" => s(:ensure, s(:rescue, s(:resbody, s(:array), nil)), s(:nil))) add_tests("begin_rescue_twice", "Ruby" => "begin\n a\nrescue => mes\n # do nothing\nend\nbegin\n b\nrescue => mes\n # do nothing\nend\n", "ParseTree" => s(:block, s(:rescue, s(:call, nil, :a), s(:resbody, s(:array, s(:lasgn, :mes, s(:gvar, :$!))), nil)), s(:rescue, s(:call, nil, :b), s(:resbody, s(:array, s(:lasgn, :mes, s(:gvar, :$!))), nil)))) copy_test_case "begin_rescue_twice", "Ruby" copy_test_case "begin_rescue_twice", "ParseTree" add_tests("block_attrasgn", "Ruby" => "def self.setup(ctx)\n bind = allocate\n bind.context = ctx\n return bind\nend", "ParseTree" => s(:defs, s(:self), :setup, s(:args, :ctx), s(:lasgn, :bind, s(:call, nil, :allocate)), s(:attrasgn, s(:lvar, :bind), :context=, s(:lvar, :ctx)), s(:return, s(:lvar, :bind)))) add_tests("block_lasgn", "Ruby" => "x = (y = 1\n(y + 2))", "ParseTree" => s(:lasgn, :x, s(:block, s(:lasgn, :y, s(:lit, 1)), s(:call, s(:lvar, :y), :+, s(:lit, 2))))) add_tests("block_mystery_block", "Ruby" => "a(b) do\n if b then\n true\n else\n c = false\n d { |x| c = true }\n c\n end\nend", "ParseTree" => s(:iter, s(:call, nil, :a, s(:call, nil, :b)), s(:args), s(:if, s(:call, nil, :b), s(:true), s(:block, s(:lasgn, :c, s(:false)), s(:iter, s(:call, nil, :d), s(:args, :x), s(:lasgn, :c, s(:true))), s(:lvar, :c))))) add_tests("block_pass_args_and_splat", "Ruby" => "def blah(*args, &block)\n other(42, *args, &block)\nend", "ParseTree" => s(:defn, :blah, s(:args, :"*args", :"&block"), s(:call, nil, :other, s(:lit, 42), s(:splat, s(:lvar, :args)), s(:block_pass, s(:lvar, :block))))) add_tests("block_pass_call_0", "Ruby" => "a.b(&c)", "ParseTree" => s(:call, s(:call, nil, :a), :b, s(:block_pass, s(:call, nil, :c)))) add_tests("block_pass_call_1", "Ruby" => "a.b(4, &c)", "ParseTree" => s(:call, s(:call, nil, :a), :b, s(:lit, 4), s(:block_pass, s(:call, nil, :c)))) add_tests("block_pass_call_n", "Ruby" => "a.b(1, 2, 3, &c)", "ParseTree" => s(:call, s(:call, nil, :a), :b, s(:lit, 1), s(:lit, 2), s(:lit, 3), s(:block_pass, s(:call, nil, :c)))) add_tests("block_pass_fcall_0", "Ruby" => "a(&b)", "ParseTree" => s(:call, nil, :a, s(:block_pass, s(:call, nil, :b)))) add_tests("block_pass_fcall_1", "Ruby" => "a(4, &b)", "ParseTree" => s(:call, nil, :a, s(:lit, 4), s(:block_pass, s(:call, nil, :b)))) add_tests("block_pass_fcall_n", "Ruby" => "a(1, 2, 3, &b)", "ParseTree" => s(:call, nil, :a, s(:lit, 1), s(:lit, 2), s(:lit, 3), s(:block_pass, s(:call, nil, :b)))) add_tests("block_pass_omgwtf", "Ruby" => "define_attr_method(:x, :sequence_name, &Proc.new { |*args| nil })", "ParseTree" => s(:call, nil, :define_attr_method, s(:lit, :x), s(:lit, :sequence_name), s(:block_pass, s(:iter, s(:call, s(:const, :Proc), :new), s(:args, :"*args"), s(:nil))))) add_tests("block_pass_splat", "Ruby" => "def blah(*args, &block)\n other(*args, &block)\nend", "ParseTree" => s(:defn, :blah, s(:args, :"*args", :"&block"), s(:call, nil, :other, s(:splat, s(:lvar, :args)), s(:block_pass, s(:lvar, :block))))) add_tests("block_pass_thingy", "Ruby" => "r.read_body(dest, &block)", "ParseTree" => s(:call, s(:call, nil, :r), :read_body, s(:call, nil, :dest), s(:block_pass, s(:call, nil, :block)))) add_tests("block_stmt_after", "Ruby" => "def f\n begin\n b\n rescue\n c\n end\n\n d\nend", "ParseTree" => s(:defn, :f, s(:args), s(:rescue, s(:call, nil, :b), s(:resbody, s(:array), s(:call, nil, :c))), s(:call, nil, :d)), "Ruby2Ruby" => "def f\n b rescue c\n d\nend") copy_test_case "block_stmt_after", "Ruby" copy_test_case "block_stmt_after", "ParseTree" copy_test_case "block_stmt_after", "Ruby2Ruby" add_tests("block_stmt_before", "Ruby" => "def f\n a\n begin\n b\n rescue\n c\n end\nend", "ParseTree" => s(:defn, :f, s(:args), s(:call, nil, :a), s(:rescue, s(:call, nil, :b), s(:resbody, s(:array), s(:call, nil, :c)))), "Ruby2Ruby" => "def f\n a\n b rescue c\nend") # oddly... this one doesn't HAVE any differences when verbose... new? copy_test_case "block_stmt_before", "Ruby" copy_test_case "block_stmt_before", "ParseTree" copy_test_case "block_stmt_before", "Ruby2Ruby" add_tests("block_stmt_both", "Ruby" => "def f\n a\n begin\n b\n rescue\n c\n end\n d\nend", "ParseTree" => s(:defn, :f, s(:args), s(:call, nil, :a), s(:rescue, s(:call, nil, :b), s(:resbody, s(:array), s(:call, nil, :c))), s(:call, nil, :d)), "Ruby2Ruby" => "def f\n a\n b rescue c\n d\nend") copy_test_case "block_stmt_both", "Ruby" copy_test_case "block_stmt_both", "ParseTree" copy_test_case "block_stmt_both", "Ruby2Ruby" add_tests("bmethod", "Ruby" => [Examples, :unsplatted], "ParseTree" => s(:defn, :unsplatted, s(:args, :x), s(:call, s(:lvar, :x), :+, s(:lit, 1))), "Ruby2Ruby" => "def unsplatted(x)\n (x + 1)\nend") add_tests("bmethod_noargs", "Ruby" => [Examples, :bmethod_noargs], "ParseTree" => s(:defn, :bmethod_noargs, s(:args), s(:call, s(:call, nil, :x), :"+", s(:lit, 1))), "Ruby2Ruby" => "def bmethod_noargs\n (x + 1)\nend") add_tests("bmethod_splat", "Ruby" => [Examples, :splatted], "ParseTree" => s(:defn, :splatted, s(:args, :"*args"), s(:lasgn, :y, s(:call, s(:lvar, :args), :first)), s(:call, s(:lvar, :y), :+, s(:lit, 42))), "Ruby2Ruby" => "def splatted(*args)\n y = args.first\n (y + 42)\nend") add_tests("break", "Ruby" => "loop { break if true }", "ParseTree" => s(:iter, s(:call, nil, :loop), s(:args), s(:if, s(:true), s(:break), nil))) add_tests("break_arg", "Ruby" => "loop { break 42 if true }", "ParseTree" => s(:iter, s(:call, nil, :loop), s(:args), s(:if, s(:true), s(:break, s(:lit, 42)), nil))) add_tests("call", "Ruby" => "self.method", "ParseTree" => s(:call, s(:self), :method)) add_tests("call_arglist", "Ruby" => "o.puts(42)", "ParseTree" => s(:call, s(:call, nil, :o), :puts, s(:lit, 42))) add_tests("call_arglist_hash", "Ruby" => "o.m(:a => 1, :b => 2)", "ParseTree" => s(:call, s(:call, nil, :o), :m, s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2)))) add_tests("call_arglist_norm_hash", "Ruby" => "o.m(42, :a => 1, :b => 2)", "ParseTree" => s(:call, s(:call, nil, :o), :m, s(:lit, 42), s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2)))) add_tests("call_command", "Ruby" => "1.b(c)", "ParseTree" => s(:call, s(:lit, 1), :b, s(:call, nil, :c))) add_tests("call_expr", "Ruby" => "(v = (1 + 1)).zero?", "ParseTree" => s(:call, s(:lasgn, :v, s(:call, s(:lit, 1), :+, s(:lit, 1))), :zero?)) add_tests("call_index", "Ruby" => "a = []\na[42]\n", "ParseTree" => s(:block, s(:lasgn, :a, s(:array)), s(:call, s(:lvar, :a), :[], s(:lit, 42)))) add_tests("call_index_no_args", "Ruby" => "a[]", "ParseTree" => s(:call, s(:call, nil, :a), :[])) add_tests("call_index_space", "Ruby" => "a = []\na [42]\n", "ParseTree" => s(:block, s(:lasgn, :a, s(:array)), s(:call, s(:lvar, :a), :[], s(:lit, 42))), "Ruby2Ruby" => "a = []\na[42]\n") add_tests("call_no_space_symbol", "Ruby" => "foo:bar", "ParseTree" => s(:call, nil, :foo, s(:lit, :bar)), "Ruby2Ruby" => "foo(:bar)") add_tests("call_unary_neg", "Ruby" => "-2**31", "ParseTree" => s(:call, s(:call, s(:lit, 2), :**, s(:lit, 31)), :-@), "Ruby2Ruby" => "-(2 ** 31)") add_tests("case", "Ruby" => "var = 2\nresult = \"\"\ncase var\nwhen 1 then\n puts(\"something\")\n result = \"red\"\nwhen 2, 3 then\n result = \"yellow\"\nwhen 4 then\n # do nothing\nelse\n result = \"green\"\nend\ncase result\nwhen \"red\" then\n var = 1\nwhen \"yellow\" then\n var = 2\nwhen \"green\" then\n var = 3\nelse\n # do nothing\nend\n", "ParseTree" => s(:block, s(:lasgn, :var, s(:lit, 2)), s(:lasgn, :result, s(:str, "")), s(:case, s(:lvar, :var), s(:when, s(:array, s(:lit, 1)), s(:call, nil, :puts, s(:str, "something")), s(:lasgn, :result, s(:str, "red"))), s(:when, s(:array, s(:lit, 2), s(:lit, 3)), s(:lasgn, :result, s(:str, "yellow"))), s(:when, s(:array, s(:lit, 4)), nil), s(:lasgn, :result, s(:str, "green"))), s(:case, s(:lvar, :result), s(:when, s(:array, s(:str, "red")), s(:lasgn, :var, s(:lit, 1))), s(:when, s(:array, s(:str, "yellow")), s(:lasgn, :var, s(:lit, 2))), s(:when, s(:array, s(:str, "green")), s(:lasgn, :var, s(:lit, 3))), nil))) add_tests("case_nested", "Ruby" => "var1 = 1\nvar2 = 2\nresult = nil\ncase var1\nwhen 1 then\n case var2\n when 1 then\n result = 1\n when 2 then\n result = 2\n else\n result = 3\n end\nwhen 2 then\n case var2\n when 1 then\n result = 4\n when 2 then\n result = 5\n else\n result = 6\n end\nelse\n result = 7\nend\n", "ParseTree" => s(:block, s(:lasgn, :var1, s(:lit, 1)), s(:lasgn, :var2, s(:lit, 2)), s(:lasgn, :result, s(:nil)), s(:case, s(:lvar, :var1), s(:when, s(:array, s(:lit, 1)), s(:case, s(:lvar, :var2), s(:when, s(:array, s(:lit, 1)), s(:lasgn, :result, s(:lit, 1))), s(:when, s(:array, s(:lit, 2)), s(:lasgn, :result, s(:lit, 2))), s(:lasgn, :result, s(:lit, 3)))), s(:when, s(:array, s(:lit, 2)), s(:case, s(:lvar, :var2), s(:when, s(:array, s(:lit, 1)), s(:lasgn, :result, s(:lit, 4))), s(:when, s(:array, s(:lit, 2)), s(:lasgn, :result, s(:lit, 5))), s(:lasgn, :result, s(:lit, 6)))), s(:lasgn, :result, s(:lit, 7))))) add_tests("case_nested_inner_no_expr", "Ruby" => "case a\nwhen b then\n case\n when (d and e) then\n f\n else\n # do nothing\n end\nelse\n # do nothing\nend", "ParseTree" => s(:case, s(:call, nil, :a), s(:when, s(:array, s(:call, nil, :b)), s(:case, nil, s(:when, s(:array, s(:and, s(:call, nil, :d), s(:call, nil, :e))), s(:call, nil, :f)), nil)), nil)) add_tests("case_no_expr", "Ruby" => "case\nwhen (a == 1) then\n :a\nwhen (a == 2) then\n :b\nelse\n :c\nend", "ParseTree" => s(:case, nil, s(:when, s(:array, s(:call, s(:call, nil, :a), :==, s(:lit, 1))), s(:lit, :a)), s(:when, s(:array, s(:call, s(:call, nil, :a), :==, s(:lit, 2))), s(:lit, :b)), s(:lit, :c))) add_tests("case_splat", "Ruby" => "case a\nwhen :b, *c then\n d\nelse\n e\nend", "ParseTree" => s(:case, s(:call, nil, :a), s(:when, s(:array, s(:lit, :b), s(:splat, s(:call, nil, :c))), s(:call, nil, :d)), s(:call, nil, :e))) add_tests("cdecl", "Ruby" => "X = 42", "ParseTree" => s(:cdecl, :X, s(:lit, 42))) add_tests("class_plain", "Ruby" => "class X\n puts((1 + 1))\n \n def blah\n puts(\"hello\")\n end\nend", "ParseTree" => s(:class, :X, nil, s(:call, nil, :puts, s(:call, s(:lit, 1), :+, s(:lit, 1))), s(:defn, :blah, s(:args), s(:call, nil, :puts, s(:str, "hello"))))) add_tests("class_scoped", "Ruby" => "class X::Y\n c\nend", "ParseTree" => s(:class, s(:colon2, s(:const, :X), :Y), nil, s(:call, nil, :c))) add_tests("class_scoped3", "Ruby" => "class ::Y\n c\nend", "ParseTree" => s(:class, s(:colon3, :Y), nil, s(:call, nil, :c))) add_tests("class_super_array", "Ruby" => "class X < Array\nend", "ParseTree" => s(:class, :X, s(:const, :Array))) add_tests("class_super_expr", "Ruby" => "class X < expr\nend", "ParseTree" => s(:class, :X, s(:call, nil, :expr))) add_tests("class_super_object", "Ruby" => "class X < Object\nend", "ParseTree" => s(:class, :X, s(:const, :Object))) add_tests("colon2", "Ruby" => "X::Y", "ParseTree" => s(:colon2, s(:const, :X), :Y)) add_tests("colon3", "Ruby" => "::X", "ParseTree" => s(:colon3, :X)) add_tests("const", "Ruby" => "X", "ParseTree" => s(:const, :X)) add_tests("constX", "Ruby" => "X = 1", "ParseTree" => s(:cdecl, :X, s(:lit, 1))) add_tests("constY", "Ruby" => "::X = 1", "ParseTree" => s(:cdecl, s(:colon3, :X), s(:lit, 1))) add_tests("constZ", "Ruby" => "X::Y = 1", "ParseTree" => s(:cdecl, s(:colon2, s(:const, :X), :Y), s(:lit, 1))) add_tests("cvar", "Ruby" => "@@x", "ParseTree" => s(:cvar, :@@x)) add_tests("cvasgn", "Ruby" => "def x\n @@blah = 1\nend", "ParseTree" => s(:defn, :x, s(:args), s(:cvasgn, :@@blah, s(:lit, 1)))) add_tests("cvasgn_cls_method", "Ruby" => "def self.quiet_mode=(boolean)\n @@quiet_mode = boolean\nend", "ParseTree" => s(:defs, s(:self), :quiet_mode=, s(:args, :boolean), s(:cvasgn, :@@quiet_mode, s(:lvar, :boolean)))) add_tests("cvdecl", "Ruby" => "class X\n @@blah = 1\nend", "ParseTree" => s(:class, :X, nil, s(:cvdecl, :@@blah, s(:lit, 1)))) add_tests("dasgn_0", "Ruby" => "a.each { |x| b.each { |y| x = (x + 1) } if true }", "ParseTree" => s(:iter, s(:call, s(:call, nil, :a), :each), s(:args, :x), s(:if, s(:true), s(:iter, s(:call, s(:call, nil, :b), :each), s(:args, :y), s(:lasgn, :x, s(:call, s(:lvar, :x), :+, s(:lit, 1)))), nil))) add_tests("dasgn_1", "Ruby" => "a.each { |x| b.each { |y| c = (c + 1) } if true }", "ParseTree" => s(:iter, s(:call, s(:call, nil, :a), :each), s(:args, :x), s(:if, s(:true), s(:iter, s(:call, s(:call, nil, :b), :each), s(:args, :y), s(:lasgn, :c, s(:call, s(:lvar, :c), :+, s(:lit, 1)))), nil))) add_tests("dasgn_2", "Ruby" => "a.each do |x|\n if true then\n c = 0\n b.each { |y| c = (c + 1) }\n end\nend", "ParseTree" => s(:iter, s(:call, s(:call, nil, :a), :each), s(:args, :x), s(:if, s(:true), s(:block, s(:lasgn, :c, s(:lit, 0)), s(:iter, s(:call, s(:call, nil, :b), :each), s(:args, :y), s(:lasgn, :c, s(:call, s(:lvar, :c), :+, s(:lit, 1))))), nil))) add_tests("dasgn_curr", "Ruby" => "data.each do |x, y|\n a = 1\n b = a\n b = a = x\nend", "ParseTree" => s(:iter, s(:call, s(:call, nil, :data), :each), s(:args, :x, :y), s(:block, s(:lasgn, :a, s(:lit, 1)), s(:lasgn, :b, s(:lvar, :a)), s(:lasgn, :b, s(:lasgn, :a, s(:lvar, :x)))))) add_tests("dasgn_icky", "Ruby" => "a do\n v = nil\n assert_block(full_message) do\n begin\n yield\n rescue Exception => v\n break\n end\n end\nend", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args), s(:block, s(:lasgn, :v, s(:nil)), s(:iter, s(:call, nil, :assert_block, s(:call, nil, :full_message)), s(:args), s(:rescue, s(:yield), s(:resbody, s(:array, s(:const, :Exception), s(:lasgn, :v, s(:gvar, :$!))), s(:break))))))) add_tests("dasgn_mixed", "Ruby" => "t = 0\nns.each { |n| t += n }\n", "ParseTree" => s(:block, s(:lasgn, :t, s(:lit, 0)), s(:iter, s(:call, s(:call, nil, :ns), :each), s(:args, :n), s(:lasgn, :t, s(:call, s(:lvar, :t), :+, s(:lvar, :n))))), "Ruby2Ruby" => "t = 0\nns.each { |n| t = (t + n) }\n") add_tests("defined", "Ruby" => "defined? $x", "ParseTree" => s(:defined, s(:gvar, :$x))) add_tests("defn_args_block", # TODO: make all the defn_args* p their arglist "Ruby" => "def f(&block)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :"&block"), s(:nil))) add_tests("defn_args_mand", "Ruby" => "def f(mand)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand), s(:nil))) add_tests("defn_args_mand_block", "Ruby" => "def f(mand, &block)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand, :"&block"), s(:nil))) add_tests("defn_args_mand_opt", "Ruby" => "def f(mand, opt = 42)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand, s(:lasgn, :opt, s(:lit, 42))), s(:nil))) add_tests("defn_args_mand_opt_block", "Ruby" => "def f(mand, opt = 42, &block)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand, s(:lasgn, :opt, s(:lit, 42)), :"&block"), s(:nil))) add_tests("defn_args_mand_opt_splat", "Ruby" => "def f(mand, opt = 42, *rest)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand, s(:lasgn, :opt, s(:lit, 42)), :"*rest"), s(:nil))) add_tests("defn_args_mand_opt_splat_block", "Ruby" => "def f(mand, opt = 42, *rest, &block)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand, s(:lasgn, :opt, s(:lit, 42)), :"*rest", :"&block"), s(:nil))) add_tests("defn_args_mand_opt_splat_no_name", "Ruby" => "def x(a, b = 42, *)\n # do nothing\nend", "ParseTree" => s(:defn, :x, s(:args, :a, s(:lasgn, :b, s(:lit, 42)), :"*"), s(:nil))) add_tests("defn_args_mand_splat", "Ruby" => "def f(mand, *rest)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand, :"*rest"), s(:nil))) add_tests("defn_args_mand_splat_block", "Ruby" => "def f(mand, *rest, &block)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :mand, :"*rest", :"&block"), s(:nil))) add_tests("defn_args_mand_splat_no_name", "Ruby" => "def x(a, *args)\n p(a, args)\nend", "ParseTree" => s(:defn, :x, s(:args, :a, :"*args"), s(:call, nil, :p, s(:lvar, :a), s(:lvar, :args)))) add_tests("defn_args_none", "Ruby" => "def empty\n # do nothing\nend", "ParseTree" => s(:defn, :empty, s(:args), s(:nil))) add_tests("defn_args_opt", "Ruby" => "def f(opt = 42)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, s(:lasgn, :opt, s(:lit, 42))), s(:nil))) add_tests("defn_args_opt_block", "Ruby" => "def f(opt = 42, &block)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, s(:lasgn, :opt, s(:lit, 42)), :"&block"), s(:nil))) add_tests("defn_args_opt_splat", "Ruby" => "def f(opt = 42, *rest)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, s(:lasgn, :opt, s(:lit, 42)), :"*rest"), s(:nil))) add_tests("defn_args_opt_splat_block", "Ruby" => "def f(opt = 42, *rest, &block)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, s(:lasgn, :opt, s(:lit, 42)), :"*rest", :"&block"), s(:nil))) add_tests("defn_args_opt_splat_no_name", "Ruby" => "def x(b = 42, *)\n # do nothing\nend", "ParseTree" => s(:defn, :x, s(:args, s(:lasgn, :b, s(:lit, 42)), :"*"), s(:nil))) add_tests("defn_args_splat", "Ruby" => "def f(*rest)\n # do nothing\nend", "ParseTree" => s(:defn, :f, s(:args, :"*rest"), s(:nil))) add_tests("defn_args_splat_no_name", "Ruby" => "def x(*)\n # do nothing\nend", "ParseTree" => s(:defn, :x, s(:args, :"*"), s(:nil))) add_tests("defn_or", "Ruby" => "def |(o)\n # do nothing\nend", "ParseTree" => s(:defn, :|, s(:args, :o), s(:nil))) add_tests("defn_rescue", "Ruby" => "def eql?(resource)\n (self.uuid == resource.uuid)\nrescue\n false\nend", "ParseTree" => s(:defn, :eql?, s(:args, :resource), s(:rescue, s(:call, s(:call, s(:self), :uuid), :==, s(:call, s(:lvar, :resource), :uuid)), s(:resbody, s(:array), s(:false)))), "Ruby2Ruby" => "def eql?(resource)\n (self.uuid == resource.uuid) rescue false\nend") add_tests("defn_rescue_mri_verbose_flag", "Ruby" => "def eql?(resource)\n (self.uuid == resource.uuid)\nrescue\n false\nend", "ParseTree" => s(:defn, :eql?, s(:args, :resource), s(:rescue, s(:call, s(:call, s(:self), :uuid), :==, s(:call, s(:lvar, :resource), :uuid)), s(:resbody, s(:array), s(:false)))), "Ruby2Ruby" => "def eql?(resource)\n (self.uuid == resource.uuid) rescue false\nend") add_tests("defn_something_eh", "Ruby" => "def something?\n # do nothing\nend", "ParseTree" => s(:defn, :something?, s(:args), s(:nil))) add_tests("defn_splat_no_name", "Ruby" => "def x(a, *)\n p(a)\nend", "ParseTree" => s(:defn, :x, s(:args, :a, :"*"), s(:call, nil, :p, s(:lvar, :a)))) add_tests("defn_zarray", "Ruby" => "def zarray\n a = []\n return a\nend", "ParseTree" => s(:defn, :zarray, s(:args), s(:lasgn, :a, s(:array)), s(:return, s(:lvar, :a)))) add_tests("defs", "Ruby" => "def self.x(y)\n (y + 1)\nend", "ParseTree" => s(:defs, s(:self), :x, s(:args, :y), s(:call, s(:lvar, :y), :+, s(:lit, 1)))) add_tests("defs_empty", "Ruby" => "def self.empty\n # do nothing\nend", "ParseTree" => s(:defs, s(:self), :empty, s(:args))) add_tests("defs_empty_args", "Ruby" => "def self.empty(*)\n # do nothing\nend", "ParseTree" => s(:defs, s(:self), :empty, s(:args, :*))) add_tests("defs_expr_wtf", "Ruby" => "def (a.b).empty(*)\n # do nothing\nend", "ParseTree" => s(:defs, s(:call, s(:call, nil, :a), :b), :empty, s(:args, :*))) add_tests("dmethod", "Ruby" => [Examples, :dmethod_added], "ParseTree" => s(:defn, :dmethod_added, s(:args, :x), s(:call, s(:lvar, :x), :+, s(:lit, 1))), "Ruby2Ruby" => "def dmethod_added(x)\n (x + 1)\nend") add_tests("dot2", "Ruby" => "(a..b)", "ParseTree" => s(:dot2, s(:call, nil, :a), s(:call, nil, :b))) add_tests("dot3", "Ruby" => "(a...b)", "ParseTree" => s(:dot3, s(:call, nil, :a), s(:call, nil, :b))) add_tests("dregx", "Ruby" => "/x#\{(1 + 1)}y/", "ParseTree" => s(:dregx, "x", s(:evstr, s(:call, s(:lit, 1), :+, s(:lit, 1))), s(:str, "y"))) add_tests("dregx_interp", "Ruby" => "/#\{@rakefile}/", "ParseTree" => s(:dregx, '', s(:evstr, s(:ivar, :@rakefile)))) add_tests("dregx_interp_empty", "Ruby" => "/a#\{}b/", "ParseTree" => s(:dregx, 'a', s(:evstr), s(:str, "b"))) add_tests("dregx_n", "Ruby" => '/#{1}/n', "ParseTree" => s(:dregx, '', s(:evstr, s(:lit, 1)), /x/n.options)) add_tests("dregx_once", "Ruby" => "/x#\{(1 + 1)}y/o", "ParseTree" => s(:dregx_once, "x", s(:evstr, s(:call, s(:lit, 1), :+, s(:lit, 1))), s(:str, "y"))) add_tests("dregx_once_n_interp", "Ruby" => "/#\{IAC}#\{SB}/no", "ParseTree" => s(:dregx_once, '', s(:evstr, s(:const, :IAC)), s(:evstr, s(:const, :SB)), /x/n.options)) add_tests("dstr", "Ruby" => "argl = 1\n\"x#\{argl}y\"\n", "ParseTree" => s(:block, s(:lasgn, :argl, s(:lit, 1)), s(:dstr, "x", s(:evstr, s(:lvar, :argl)), s(:str, "y")))) add_tests("dstr_2", "Ruby" => "argl = 1\n\"x#\{(\"%.2f\" % 3.14159)}y\"\n", "ParseTree" => s(:block, s(:lasgn, :argl, s(:lit, 1)), s(:dstr, "x", s(:evstr, s(:call, s(:str, "%.2f"), :%, s(:lit, 3.14159))), s(:str, "y")))) add_tests("dstr_3", "Ruby" => "max = 2\nargl = 1\n\"x#\{(\"%.#\{max}f\" % 3.14159)}y\"\n", "ParseTree" => s(:block, s(:lasgn, :max, s(:lit, 2)), s(:lasgn, :argl, s(:lit, 1)), s(:dstr, "x", s(:evstr, s(:call, s(:dstr, "%.", s(:evstr, s(:lvar, :max)), s(:str, "f")), :%, s(:lit, 3.14159))), s(:str, "y")))) add_tests("dstr_concat", "Ruby" => '"#{22}aa" "cd#{44}" "55" "#{66}"', "ParseTree" => s(:dstr, "", s(:evstr, s(:lit, 22)), s(:str, "aa"), s(:str, "cd"), s(:evstr, s(:lit, 44)), s(:str, "55"), s(:evstr, s(:lit, 66))), "Ruby2Ruby" => '"#{22}aacd#{44}55#{66}"') add_tests("dstr_gross", "Ruby" => '"a #$global b #@ivar c #@@cvar d"', "ParseTree" => s(:dstr, "a ", s(:evstr, s(:gvar, :$global)), s(:str, " b "), s(:evstr, s(:ivar, :@ivar)), s(:str, " c "), s(:evstr, s(:cvar, :@@cvar)), s(:str, " d")), "Ruby2Ruby" => '"a #{$global} b #{@ivar} c #{@@cvar} d"') add_tests("dstr_heredoc_expand", "Ruby" => "< s(:dstr, " blah\n", s(:evstr, s(:call, s(:lit, 1), :+, s(:lit, 1))), s(:str, "blah\n")), "Ruby2Ruby" => "\" blah\\n#\{(1 + 1)}blah\\n\"") add_tests("dstr_heredoc_windoze_sucks", "Ruby" => "<<-EOF\r\ndef test_#\{action}_valid_feed\r\n EOF\r\n", "ParseTree" => s(:dstr, 'def test_', s(:evstr, s(:call, nil, :action)), s(:str, "_valid_feed\n")), "Ruby2Ruby" => "\"def test_#\{action}_valid_feed\\n\"") add_tests("dstr_heredoc_yet_again", "Ruby" => "<<-EOF\ns1 '#\{RUBY_PLATFORM}' s2\n#\{__FILE__}\n EOF\n", "ParseTree" => s(:dstr, "s1 '", s(:evstr, s(:const, :RUBY_PLATFORM)), s(:str, "' s2\n"), s(:str, "(string)"), s(:str, "\n")), "Ruby2Ruby" => "\"s1 '#\{RUBY_PLATFORM}' s2\\n(string)\\n\"") add_tests("dstr_nest", "Ruby" => "%Q[before [#\{nest}] after]", "ParseTree" => s(:dstr, "before [", s(:evstr, s(:call, nil, :nest)), s(:str, "] after")), "Ruby2Ruby" => "\"before [#\{nest}] after\"") add_tests("dstr_str_lit_start", "Ruby" => '"#{"blah"}#{__FILE__}:#{__LINE__}: warning: #{$!.message} (#{$!.class})"', "ParseTree" => s(:dstr, "blah(string):", s(:evstr, s(:lit, 1)), s(:str, ": warning: "), s(:evstr, s(:call, s(:gvar, :$!), :message)), s(:str, " ("), s(:evstr, s(:call, s(:gvar, :$!), :class)), s(:str, ")")), "Ruby2Ruby" => '"blah(string):#{1}: warning: #{$!.message} (#{$!.class})"') add_tests("dstr_the_revenge", "Ruby" => '"before #{from} middle #{to} (#{__FILE__}:#{__LINE__})"', "ParseTree" => s(:dstr, "before ", s(:evstr, s(:call, nil, :from)), s(:str, " middle "), s(:evstr, s(:call, nil, :to)), s(:str, " ("), s(:str, "(string)"), s(:str, ":"), s(:evstr, s(:lit, 1)), s(:str, ")")), "Ruby2Ruby" => '"before #{from} middle #{to} ((string):#{1})"') add_tests("dsym", "Ruby" => ":\"x#\{(1 + 1)}y\"", "ParseTree" => s(:dsym, "x", s(:evstr, s(:call, s(:lit, 1), :+, s(:lit, 1))), s(:str, "y"))) add_tests("dxstr", "Ruby" => "t = 5\n`touch #\{t}`\n", "ParseTree" => s(:block, s(:lasgn, :t, s(:lit, 5)), s(:dxstr, 'touch ', s(:evstr, s(:lvar, :t))))) add_tests("ensure", "Ruby" => "begin\n (1 + 1)\nrescue SyntaxError => e1\n 2\nrescue Exception => e2\n 3\nelse\n 4\nensure\n 5\nend", "ParseTree" => s(:ensure, s(:rescue, s(:call, s(:lit, 1), :+, s(:lit, 1)), s(:resbody, s(:array, s(:const, :SyntaxError), s(:lasgn, :e1, s(:gvar, :$!))), s(:lit, 2)), s(:resbody, s(:array, s(:const, :Exception), s(:lasgn, :e2, s(:gvar, :$!))), s(:lit, 3)), s(:lit, 4)), s(:lit, 5))) add_tests("false", "Ruby" => "false", "ParseTree" => s(:false)) add_tests("fbody", "Ruby" => [Examples, :an_alias], "ParseTree" => s(:defn, :an_alias, s(:args, :x), s(:call, s(:lvar, :x), :+, s(:lit, 1))), "Ruby2Ruby" => "def an_alias(x)\n (x + 1)\nend") add_tests("fcall_arglist", "Ruby" => "m(42)", "ParseTree" => s(:call, nil, :m, s(:lit, 42))) add_tests("fcall_arglist_hash", "Ruby" => "m(:a => 1, :b => 2)", "ParseTree" => s(:call, nil, :m, s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2)))) add_tests("fcall_arglist_norm_hash", "Ruby" => "m(42, :a => 1, :b => 2)", "ParseTree" => s(:call, nil, :m, s(:lit, 42), s(:hash, s(:lit, :a), s(:lit, 1), s(:lit, :b), s(:lit, 2)))) add_tests("fcall_block", "Ruby" => "a(:b) { :c }", "ParseTree" => s(:iter, s(:call, nil, :a, s(:lit, :b)), s(:args), s(:lit, :c))) add_tests("fcall_index_space", "Ruby" => "a [42]", "ParseTree" => s(:call, nil, :a, s(:array, s(:lit, 42))), "Ruby2Ruby" => "a([42])") add_tests("fcall_inside_parens", "Ruby" => "( a (b), c)", "ParseTree" => s(:call, nil, :a, s(:call, nil, :b), s(:call, nil, :c)), "Ruby2Ruby" => "a(b, c)") add_tests("fcall_keyword", "Ruby" => "42 if block_given?", "ParseTree" => s(:if, s(:call, nil, :block_given?), s(:lit, 42), nil)) add_tests("flip2", "Ruby" => "x = if ((i % 4) == 0)..((i % 3) == 0) then\n i\nelse\n nil\nend", "ParseTree" => s(:lasgn, :x, s(:if, s(:flip2, s(:call, s(:call, s(:call, nil, :i), :%, s(:lit, 4)), :==, s(:lit, 0)), s(:call, s(:call, s(:call, nil, :i), :%, s(:lit, 3)), :==, s(:lit, 0))), s(:call, nil, :i), s(:nil)))) add_tests("flip2_method", "Ruby" => "if 1..2.a?(b) then\n nil\nend", "ParseTree" => s(:if, s(:flip2, s(:lit, 1), s(:call, s(:lit, 2), :a?, s(:call, nil, :b))), s(:nil), nil)) add_tests("flip3", "Ruby" => "x = if ((i % 4) == 0)...((i % 3) == 0) then\n i\nelse\n nil\nend", "ParseTree" => s(:lasgn, :x, s(:if, s(:flip3, s(:call, s(:call, s(:call, nil, :i), :%, s(:lit, 4)), :==, s(:lit, 0)), s(:call, s(:call, s(:call, nil, :i), :%, s(:lit, 3)), :==, s(:lit, 0))), s(:call, nil, :i), s(:nil)))) add_tests("for", "Ruby" => "for o in ary do\n puts(o)\nend", "ParseTree" => s(:for, s(:call, nil, :ary), s(:lasgn, :o), s(:call, nil, :puts, s(:lvar, :o)))) add_tests("for_no_body", "Ruby" => "for i in (0..max) do\n # do nothing\nend", "ParseTree" => s(:for, s(:dot2, s(:lit, 0), s(:call, nil, :max)), s(:lasgn, :i))) add_tests("gasgn", "Ruby" => "$x = 42", "ParseTree" => s(:gasgn, :$x, s(:lit, 42))) add_tests("global", "Ruby" => "$stderr", "ParseTree" => s(:gvar, :$stderr)) add_tests("gvar", "Ruby" => "$x", "ParseTree" => s(:gvar, :$x)) add_tests("gvar_underscore", "Ruby" => "$_", "ParseTree" => s(:gvar, :$_)) add_tests("gvar_underscore_blah", "Ruby" => "$__blah", "ParseTree" => s(:gvar, :$__blah)) add_tests("hash", "Ruby" => "{ 1 => 2, 3 => 4 }", "ParseTree" => s(:hash, s(:lit, 1), s(:lit, 2), s(:lit, 3), s(:lit, 4))) add_tests("hash_rescue", "Ruby" => "{ 1 => (2 rescue 3) }", "ParseTree" => s(:hash, s(:lit, 1), s(:rescue, s(:lit, 2), s(:resbody, s(:array), s(:lit, 3))))) add_tests("iasgn", "Ruby" => "@a = 4", "ParseTree" => s(:iasgn, :@a, s(:lit, 4))) add_tests("if_block_condition", "Ruby" => "if (x = 5\n(x + 1)) then\n nil\nend", "ParseTree" => s(:if, s(:block, s(:lasgn, :x, s(:lit, 5)), s(:call, s(:lvar, :x), :+, s(:lit, 1))), s(:nil), nil)) add_tests("if_lasgn_short", "Ruby" => "if x = obj.x then\n x.do_it\nend", "ParseTree" => s(:if, s(:lasgn, :x, s(:call, s(:call, nil, :obj), :x)), s(:call, s(:lvar, :x), :do_it), nil)) add_tests("if_nested", "Ruby" => "return if false unless true", "ParseTree" => s(:if, s(:true), nil, s(:if, s(:false), s(:return), nil))) add_tests("if_post", "Ruby" => "a if b", "ParseTree" => s(:if, s(:call, nil, :b), s(:call, nil, :a), nil)) add_tests("if_pre", "Ruby" => "if b then a end", "ParseTree" => s(:if, s(:call, nil, :b), s(:call, nil, :a), nil), "Ruby2Ruby" => "a if b") add_tests("iter_call_arglist_space", "Ruby" => "a (1) {|c|d}", "ParseTree" => s(:iter, s(:call, nil, :a, s(:lit, 1)), s(:args, :c), s(:call, nil, :d)), "Ruby2Ruby" => "a(1) { |c| d }") add_tests("iter_dasgn_curr_dasgn_madness", "Ruby" => "as.each { |a|\n b += a.b(false) }", "ParseTree" => s(:iter, s(:call, s(:call, nil, :as), :each), s(:args, :a), s(:lasgn, :b, s(:call, s(:lvar, :b), :+, s(:call, s(:lvar, :a), :b, s(:false))))), "Ruby2Ruby" => "as.each { |a| b = (b + a.b(false)) }") add_tests("iter_downto", "Ruby" => "3.downto(1) { |n| puts(n.to_s) }", "ParseTree" => s(:iter, s(:call, s(:lit, 3), :downto, s(:lit, 1)), s(:args, :n), s(:call, nil, :puts, s(:call, s(:lvar, :n), :to_s)))) add_tests("iter_each_lvar", "Ruby" => "array = [1, 2, 3]\narray.each { |x| puts(x.to_s) }\n", "ParseTree" => s(:block, s(:lasgn, :array, s(:array, s(:lit, 1), s(:lit, 2), s(:lit, 3))), s(:iter, s(:call, s(:lvar, :array), :each), s(:args, :x), s(:call, nil, :puts, s(:call, s(:lvar, :x), :to_s))))) add_tests("iter_each_nested", "Ruby" => "array1 = [1, 2, 3]\narray2 = [4, 5, 6, 7]\narray1.each do |x|\n array2.each do |y|\n puts(x.to_s)\n puts(y.to_s)\n end\nend\n", "ParseTree" => s(:block, s(:lasgn, :array1, s(:array, s(:lit, 1), s(:lit, 2), s(:lit, 3))), s(:lasgn, :array2, s(:array, s(:lit, 4), s(:lit, 5), s(:lit, 6), s(:lit, 7))), s(:iter, s(:call, s(:lvar, :array1), :each), s(:args, :x), s(:iter, s(:call, s(:lvar, :array2), :each), s(:args, :y), s(:block, s(:call, nil, :puts, s(:call, s(:lvar, :x), :to_s)), s(:call, nil, :puts, s(:call, s(:lvar, :y), :to_s))))))) add_tests("iter_loop_empty", "Ruby" => "loop { }", "ParseTree" => s(:iter, s(:call, nil, :loop), s(:args))) add_tests("iter_masgn_2", "Ruby" => "a { |b, c| p(c) }", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args, :b, :c), s(:call, nil, :p, s(:lvar, :c)))) add_tests("iter_masgn_args_splat", "Ruby" => "a { |b, c, *d| p(c) }", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args, :b, :c, :"*d"), s(:call, nil, :p, s(:lvar, :c)))) add_tests("iter_masgn_args_splat_no_name", "Ruby" => "a { |b, c, *| p(c) }", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args, :b, :c, :*), s(:call, nil, :p, s(:lvar, :c)))) add_tests("iter_masgn_splat", "Ruby" => "a { |*c| p(c) }", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args, :"*c"), s(:call, nil, :p, s(:lvar, :c)))) add_tests("iter_masgn_splat_no_name", "Ruby" => "a { |*| p(c) }", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args, :*), s(:call, nil, :p, s(:call, nil, :c)))) add_tests("iter_shadowed_var", "Ruby" => "a do |x|\n b do |x|\n puts x\n end\nend", "ParseTree" => s(:iter, s(:call, nil, :a), s(:args, :x), s(:iter, s(:call, nil, :b), s(:args, :x), s(:call, nil, :puts, s(:lvar, :x)))), "Ruby2Ruby" => "a { |x| b { |x| puts(x) } }") add_tests("iter_upto", "Ruby" => "1.upto(3) { |n| puts(n.to_s) }", "ParseTree" => s(:iter, s(:call, s(:lit, 1), :upto, s(:lit, 3)), s(:args, :n), s(:call, nil, :puts, s(:call, s(:lvar, :n), :to_s)))) add_tests("iter_while", "Ruby" => "argl = 10\nwhile (argl >= 1) do\n puts(\"hello\")\n argl = (argl - 1)\nend\n", "ParseTree" => s(:block, s(:lasgn, :argl, s(:lit, 10)), s(:while, s(:call, s(:lvar, :argl), :">=", s(:lit, 1)), s(:block, s(:call, nil, :puts, s(:str, "hello")), s(:lasgn, :argl, s(:call, s(:lvar, :argl), :"-", s(:lit, 1)))), true))) add_tests("ivar", "Ruby" => [Examples, :reader], "ParseTree" => s(:defn, :reader, s(:args), s(:ivar, :@reader)), "Ruby2Ruby" => "attr_reader :reader") add_tests("lambda_args_anon_star", "Ruby" => "lambda { |*| nil }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :*), s(:nil))) add_tests("lambda_args_anon_star_block", "Ruby" => "lambda { |*, &block| block }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :*, :"&block"), s(:lvar, :block))) add_tests("lambda_args_block", "Ruby" => "lambda { |&block| block }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :"&block"), s(:lvar, :block))) add_tests("lambda_args_norm_anon_star", "Ruby" => "lambda { |a, *| a }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :a, :*), s(:lvar, :a))) add_tests("lambda_args_norm_anon_star_block", "Ruby" => "lambda { |a, *, &block| block }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :a, :*, :"&block"), s(:lvar, :block))) add_tests("lambda_args_norm_block", "Ruby" => "lambda { |a, &block| block }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :a, :"&block"), s(:lvar, :block))) add_tests("lambda_args_norm_comma", "Ruby" => "lambda { |a,| a }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :a), s(:lvar, :a)), "Ruby2Ruby" => "lambda { |a| a }") add_tests("lambda_args_norm_comma2", "Ruby" => "lambda { |a,b,| a }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :a, :b), s(:lvar, :a)), "Ruby2Ruby" => "lambda { |a, b| a }") add_tests("lambda_args_norm_star", "Ruby" => "lambda { |a, *star| star }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :a, :"*star"), s(:lvar, :star))) add_tests("lambda_args_norm_star_block", "Ruby" => "lambda { |a, *star, &block| block }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :a, :"*star", :"&block"), s(:lvar, :block))) add_tests("lambda_args_star", "Ruby" => "lambda { |*star| star }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :"*star"), s(:lvar, :star))) add_tests("lambda_args_star_block", "Ruby" => "lambda { |*star, &block| block }", "ParseTree" => s(:iter, s(:call, nil, :lambda), s(:args, :"*star", :"&block"), s(:lvar, :block))) add_tests("lasgn_array", "Ruby" => "var = [\"foo\", \"bar\"]", "ParseTree" => s(:lasgn, :var, s(:array, s(:str, "foo"), s(:str, "bar")))) add_tests("lasgn_call", "Ruby" => "c = (2 + 3)", "ParseTree" => s(:lasgn, :c, s(:call, s(:lit, 2), :+, s(:lit, 3)))) add_tests("lit_bool_false", "Ruby" => "false", "ParseTree" => s(:false)) add_tests("lit_bool_true", "Ruby" => "true", "ParseTree" => s(:true)) add_tests("lit_float", "Ruby" => "1.1", "ParseTree" => s(:lit, 1.1)) add_tests("lit_long", "Ruby" => "1", "ParseTree" => s(:lit, 1)) add_tests("lit_long_negative", "Ruby" => "-1", "ParseTree" => s(:lit, -1)) add_tests("lit_range2", "Ruby" => "(1..10)", "ParseTree" => s(:lit, 1..10)) add_tests("lit_range3", "Ruby" => "(1...10)", "ParseTree" => s(:lit, 1...10)) add_tests("lit_regexp", "Ruby" => "/x/", "ParseTree" => s(:lit, /x/)) add_tests("lit_regexp_i_wwtt", "Ruby" => 'str.split(//i)', "ParseTree" => s(:call, s(:call, nil, :str), :split, s(:lit, //i))) add_tests("lit_regexp_n", "Ruby" => "/x/n", # HACK differs on 1.9 - this is easiest "ParseTree" => s(:lit, /x/n), "Ruby2Ruby" => /x/n.inspect) add_tests("lit_regexp_once", "Ruby" => "/x/o", "ParseTree" => s(:lit, /x/), "Ruby2Ruby" => "/x/") add_tests("lit_sym", "Ruby" => ":x", "ParseTree" => s(:lit, :x)) add_tests("lit_sym_splat", "Ruby" => ":\"*args\"", "ParseTree" => s(:lit, :"*args")) add_tests("lvar_def_boundary", "Ruby" => "b = 42\ndef a\n c do\n begin\n do_stuff\n rescue RuntimeError => b\n puts(b)\n end\n end\nend\n", "ParseTree" => s(:block, s(:lasgn, :b, s(:lit, 42)), s(:defn, :a, s(:args), s(:iter, s(:call, nil, :c), s(:args), s(:rescue, s(:call, nil, :do_stuff), s(:resbody, s(:array, s(:const, :RuntimeError), s(:lasgn, :b, s(:gvar, :$!))), s(:call, nil, :puts, s(:lvar, :b)))))))) add_tests("masgn", "Ruby" => "a, b = c, d", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b)), s(:array, s(:call, nil, :c), s(:call, nil, :d)))) add_tests("masgn_argscat", "Ruby" => "a, b, *c = 1, 2, *[3, 4]", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b), s(:splat, s(:lasgn, :c))), s(:array, s(:lit, 1), s(:lit, 2), s(:splat, s(:array, s(:lit, 3), s(:lit, 4)))))) add_tests("masgn_attrasgn", "Ruby" => "a, b.c = d, e", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:attrasgn, s(:call, nil, :b), :c=)), s(:array, s(:call, nil, :d), s(:call, nil, :e)))) add_tests("masgn_attrasgn_array_rhs", "Ruby" => "a.b, a.c, _ = q", "ParseTree" => s(:masgn, s(:array, s(:attrasgn, s(:call, nil, :a), :b=), s(:attrasgn, s(:call, nil, :a), :c=), s(:lasgn, :_)), s(:to_ary, s(:call, nil, :q)))) add_tests("masgn_attrasgn_idx", "Ruby" => "a, i, j = [], 1, 2\na[i], a[j] = a[j], a[i]\n", "ParseTree" => s(:block, s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :i), s(:lasgn, :j)), s(:array, s(:array), s(:lit, 1), s(:lit, 2))), s(:masgn, s(:array, s(:attrasgn, s(:lvar, :a), :[]=, s(:lvar, :i)), s(:attrasgn, s(:lvar, :a), :[]=, s(:lvar, :j))), s(:array, s(:call, s(:lvar, :a), :[], s(:lvar, :j)), s(:call, s(:lvar, :a), :[], s(:lvar, :i)))))) add_tests("masgn_cdecl", "Ruby" => "A, B, C = 1, 2, 3", "ParseTree" => s(:masgn, s(:array, s(:cdecl, :A), s(:cdecl, :B), s(:cdecl, :C)), s(:array, s(:lit, 1), s(:lit, 2), s(:lit, 3)))) add_tests("masgn_iasgn", "Ruby" => "a, @b = c, d", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:iasgn, :"@b")), s(:array, s(:call, nil, :c), s(:call, nil, :d)))) add_tests("masgn_masgn", "Ruby" => "a, (b, c) = [1, [2, 3]]", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:masgn, s(:array, s(:lasgn, :b), s(:lasgn, :c)))), s(:to_ary, s(:array, s(:lit, 1), s(:array, s(:lit, 2), s(:lit, 3)))))) add_tests("masgn_splat_lhs", "Ruby" => "a, b, *c = d, e, f, g", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b), s(:splat, s(:lasgn, :c))), s(:array, s(:call, nil, :d), s(:call, nil, :e), s(:call, nil, :f), s(:call, nil, :g)))) add_tests("masgn_splat_no_name_to_ary", "Ruby" => "a, b, * = c", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b), s(:splat)), s(:to_ary, s(:call, nil, :c)))) add_tests("masgn_splat_no_name_trailing", "Ruby" => "a, b, = c", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b)), s(:to_ary, s(:call, nil, :c))), "Ruby2Ruby" => "a, b = c") # TODO: check this is right add_tests("masgn_splat_rhs_1", "Ruby" => "a, b = *c", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b)), s(:splat, s(:call, nil, :c)))) add_tests("masgn_splat_rhs_n", "Ruby" => "a, b = c, d, *e", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b)), s(:array, s(:call, nil, :c), s(:call, nil, :d), s(:splat, s(:call, nil, :e))))) add_tests("masgn_splat_to_ary", "Ruby" => "a, b, *c = d", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b), s(:splat, s(:lasgn, :c))), s(:to_ary, s(:call, nil, :d)))) add_tests("masgn_splat_to_ary2", "Ruby" => "a, b, *c = d.e(\"f\")", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b), s(:splat, s(:lasgn, :c))), s(:to_ary, s(:call, s(:call, nil, :d), :e, s(:str, 'f'))))) add_tests("match", "Ruby" => "1 if /x/", "ParseTree" => s(:if, s(:match, s(:lit, /x/)), s(:lit, 1), nil)) add_tests("match2", "Ruby" => "/x/ =~ \"blah\"", "ParseTree" => s(:match2, s(:lit, /x/), s(:str, "blah"))) add_tests("match3", "Ruby" => "\"blah\" =~ /x/", "ParseTree" => s(:match3, s(:lit, /x/), s(:str, "blah"))) add_tests("module", "Ruby" => "module X\n def y\n # do nothing\n end\nend", "ParseTree" => s(:module, :X, s(:defn, :y, s(:args), s(:nil)))) add_tests("module2", "Ruby" => "module X\n def y\n # do nothing\n end\n \n def z\n # do nothing\n end\nend", "ParseTree" => s(:module, :X, s(:defn, :y, s(:args), s(:nil)), s(:defn, :z, s(:args), s(:nil)))) add_tests("module_scoped", "Ruby" => "module X::Y\n c\nend", "ParseTree" => s(:module, s(:colon2, s(:const, :X), :Y), s(:call, nil, :c))) add_tests("module_scoped3", "Ruby" => "module ::Y\n c\nend", "ParseTree" => s(:module, s(:colon3, :Y), s(:call, nil, :c))) add_tests("next", "Ruby" => "loop { next if false }", "ParseTree" => s(:iter, s(:call, nil, :loop), s(:args), s(:if, s(:false), s(:next), nil))) add_tests("next_arg", "Ruby" => "loop { next 42 if false }", "ParseTree" => s(:iter, s(:call, nil, :loop), s(:args), s(:if, s(:false), s(:next, s(:lit, 42)), nil))) add_tests("nth_ref", "Ruby" => "$1", "ParseTree" => s(:nth_ref, 1)) add_tests("op_asgn1", "Ruby" => "b = []\nb[1] ||= 10\nb[2] &&= 11\nb[3] += 12\n", "ParseTree" => s(:block, s(:lasgn, :b, s(:array)), s(:op_asgn1, s(:lvar, :b), s(:arglist, s(:lit, 1)), :"||", s(:lit, 10)), s(:op_asgn1, s(:lvar, :b), s(:arglist, s(:lit, 2)), :"&&", s(:lit, 11)), s(:op_asgn1, s(:lvar, :b), s(:arglist, s(:lit, 3)), :+, s(:lit, 12)))) add_tests("op_asgn1_ivar", "Ruby" => "@b = []\n@b[1] ||= 10\n@b[2] &&= 11\n@b[3] += 12\n", "ParseTree" => s(:block, s(:iasgn, :@b, s(:array)), s(:op_asgn1, s(:ivar, :@b), s(:arglist, s(:lit, 1)), :"||", s(:lit, 10)), s(:op_asgn1, s(:ivar, :@b), s(:arglist, s(:lit, 2)), :"&&", s(:lit, 11)), s(:op_asgn1, s(:ivar, :@b), s(:arglist, s(:lit, 3)), :+, s(:lit, 12)))) add_tests("op_asgn2", "Ruby" => "s = Struct.new(:var)\nc = s.new(nil)\nc.var ||= 20\nc.var &&= 21\nc.var += 22\nc.d.e.f ||= 42\n", "ParseTree" => s(:block, s(:lasgn, :s, s(:call, s(:const, :Struct), :new, s(:lit, :var))), s(:lasgn, :c, s(:call, s(:lvar, :s), :new, s(:nil))), s(:op_asgn2, s(:lvar, :c), :var=, :"||", s(:lit, 20)), s(:op_asgn2, s(:lvar, :c), :var=, :"&&", s(:lit, 21)), s(:op_asgn2, s(:lvar, :c), :var=, :+, s(:lit, 22)), s(:op_asgn2, s(:call, s(:call, s(:lvar, :c), :d), :e), :f=, :"||", s(:lit, 42)))) add_tests("op_asgn2_self", "Ruby" => "self.Bag ||= Bag.new", "ParseTree" => s(:op_asgn2, s(:self), :"Bag=", :"||", s(:call, s(:const, :Bag), :new))) add_tests("op_asgn_and", "Ruby" => "a = 0\na &&= 2\n", "ParseTree" => s(:block, s(:lasgn, :a, s(:lit, 0)), s(:op_asgn_and, s(:lvar, :a), s(:lasgn, :a, s(:lit, 2))))) add_tests("op_asgn_and_ivar2", "Ruby" => "@fetcher &&= new(Gem.configuration[:http_proxy])", "ParseTree" => s(:op_asgn_and, s(:ivar, :@fetcher), s(:iasgn, :@fetcher, s(:call, nil, :new, s(:call, s(:call, s(:const, :Gem), :configuration), :[], s(:lit, :http_proxy)))))) add_tests("op_asgn_or", "Ruby" => "a = 0\na ||= 1\n", "ParseTree" => s(:block, s(:lasgn, :a, s(:lit, 0)), s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, s(:lit, 1))))) add_tests("op_asgn_or_block", "Ruby" => "a ||= begin\n b\n rescue\n c\n end", "ParseTree" => s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, s(:rescue, s(:call, nil, :b), s(:resbody, s(:array), s(:call, nil, :c))))), "Ruby2Ruby" => "a ||= b rescue c") add_tests("op_asgn_or_ivar", "Ruby" => "@v ||= {}", "ParseTree" => s(:op_asgn_or, s(:ivar, :@v), s(:iasgn, :@v, s(:hash)))) add_tests("op_asgn_or_ivar2", "Ruby" => "@fetcher ||= new(Gem.configuration[:http_proxy])", "ParseTree" => s(:op_asgn_or, s(:ivar, :@fetcher), s(:iasgn, :@fetcher, s(:call, nil, :new, s(:call, s(:call, s(:const, :Gem), :configuration), :[], s(:lit, :http_proxy)))))) add_tests("or", "Ruby" => "(a or b)", "ParseTree" => s(:or, s(:call, nil, :a), s(:call, nil, :b))) add_tests("or_big", "Ruby" => "((a or b) or (c and d))", "ParseTree" => s(:or, s(:or, s(:call, nil, :a), s(:call, nil, :b)), s(:and, s(:call, nil, :c), s(:call, nil, :d)))) add_tests("or_big2", "Ruby" => "((a || b) || (c && d))", "ParseTree" => s(:or, s(:or, s(:call, nil, :a), s(:call, nil, :b)), s(:and, s(:call, nil, :c), s(:call, nil, :d))), "Ruby2Ruby" => "((a or b) or (c and d))") add_tests("parse_floats_as_args", "Ruby" => "def x(a=0.0,b=0.0)\n a+b\nend", "ParseTree" => s(:defn, :x, s(:args, s(:lasgn, :a, s(:lit, 0.0)), s(:lasgn, :b, s(:lit, 0.0))), s(:call, s(:lvar, :a), :+, s(:lvar, :b))), "Ruby2Ruby" => "def x(a = 0.0, b = 0.0)\n (a + b)\nend") add_tests("postexe", "Ruby" => "END { 1 }", "ParseTree" => s(:iter, s(:postexe), s(:args), s(:lit, 1))) add_tests("proc_args_0", "Ruby" => "proc { || (x + 1) }", "ParseTree" => s(:iter, s(:call, nil, :proc), 0, s(:call, s(:call, nil, :x), :+, s(:lit, 1)))) add_tests("proc_args_1", "Ruby" => "proc { |x| (x + 1) }", "ParseTree" => s(:iter, s(:call, nil, :proc), s(:args, :x), s(:call, s(:lvar, :x), :+, s(:lit, 1)))) add_tests("proc_args_2", "Ruby" => "proc { |x, y| (x + y) }", "ParseTree" => s(:iter, s(:call, nil, :proc), s(:args, :x, :y), s(:call, s(:lvar, :x), :+, s(:lvar, :y)))) add_tests("proc_args_no", "Ruby" => "proc { (x + 1) }", "ParseTree" => s(:iter, s(:call, nil, :proc), s(:args), s(:call, s(:call, nil, :x), :+, s(:lit, 1)))) add_tests("redo", "Ruby" => "loop { redo if false }", "ParseTree" => s(:iter, s(:call, nil, :loop), s(:args), s(:if, s(:false), s(:redo), nil))) add_tests("rescue", # TODO: need a resbody w/ multiple classes and a splat "Ruby" => "blah rescue nil", "ParseTree" => s(:rescue, s(:call, nil, :blah), s(:resbody, s(:array), s(:nil)))) add_tests("rescue_block_body", "Ruby" => "begin\n a\nrescue => e\n c\n d\nend", "ParseTree" => s(:rescue, s(:call, nil, :a), s(:resbody, s(:array, s(:lasgn, :e, s(:gvar, :$!))), s(:call, nil, :c), s(:call, nil, :d)))) add_tests("rescue_block_body_3", "Ruby" => "begin\n a\nrescue A\n b\nrescue B\n c\nrescue C\n d\nend", "ParseTree" => s(:rescue, s(:call, nil, :a), s(:resbody, s(:array, s(:const, :A)), s(:call, nil, :b)), s(:resbody, s(:array, s(:const, :B)), s(:call, nil, :c)), s(:resbody, s(:array, s(:const, :C)), s(:call, nil, :d)))) add_tests("rescue_block_body_ivar", "Ruby" => "begin\n a\nrescue => @e\n c\n d\nend", "ParseTree" => s(:rescue, s(:call, nil, :a), s(:resbody, s(:array, s(:iasgn, :@e, s(:gvar, :$!))), s(:call, nil, :c), s(:call, nil, :d)))) add_tests("rescue_block_nada", "Ruby" => "begin\n blah\nrescue\n # do nothing\nend", "ParseTree" => s(:rescue, s(:call, nil, :blah), s(:resbody, s(:array), nil))) add_tests("rescue_exceptions", "Ruby" => "begin\n blah\nrescue RuntimeError => r\n # do nothing\nend", "ParseTree" => s(:rescue, s(:call, nil, :blah), s(:resbody, s(:array, s(:const, :RuntimeError), s(:lasgn, :r, s(:gvar, :$!))), nil))) add_tests("rescue_iasgn_var_empty", "Ruby" => "begin\n 1\nrescue => @e\n # do nothing\nend", "ParseTree" => s(:rescue, s(:lit, 1), s(:resbody, s(:array, s(:iasgn, :@e, s(:gvar, :$!))), nil))) add_tests("rescue_lasgn", "Ruby" => "begin\n 1\nrescue\n var = 2\nend", "ParseTree" => s(:rescue, s(:lit, 1), s(:resbody, s(:array), s(:lasgn, :var, s(:lit, 2)))), "Ruby2Ruby" => "1 rescue var = 2") add_tests("rescue_lasgn_var", "Ruby" => "begin\n 1\nrescue => e\n var = 2\nend", "ParseTree" => s(:rescue, s(:lit, 1), s(:resbody, s(:array, s(:lasgn, :e, s(:gvar, :$!))), s(:lasgn, :var, s(:lit, 2))))) add_tests("rescue_lasgn_var_empty", "Ruby" => "begin\n 1\nrescue => e\n # do nothing\nend", "ParseTree" => s(:rescue, s(:lit, 1), s(:resbody, s(:array, s(:lasgn, :e, s(:gvar, :$!))), nil))) add_tests("retry", "Ruby" => "retry", "ParseTree" => s(:retry)) add_tests("return_0", "Ruby" => "return", "ParseTree" => s(:return)) add_tests("return_1", "Ruby" => "return 1", "ParseTree" => s(:return, s(:lit, 1))) add_tests("return_1_splatted", "Ruby" => "return *1", "ParseTree" => s(:return, s(:svalue, s(:splat, s(:lit, 1))))) add_tests("return_n", "Ruby" => "return 1, 2, 3", "ParseTree" => s(:return, s(:array, s(:lit, 1), s(:lit, 2), s(:lit, 3))), "Ruby2Ruby" => "return [1, 2, 3]") add_tests("sclass", "Ruby" => "class << self\n 42\nend", "ParseTree" => s(:sclass, s(:self), s(:lit, 42))) add_tests("sclass_multiple", "Ruby" => "class << self\n x\n y\nend", "ParseTree" => s(:sclass, s(:self), s(:call, nil, :x), s(:call, nil, :y))) add_tests("sclass_trailing_class", "Ruby" => "class A\n class << self\n a\n end\n \n class B\n end\nend", "ParseTree" => s(:class, :A, nil, s(:sclass, s(:self), s(:call, nil, :a)), s(:class, :B, nil))) add_tests("splat", "Ruby" => "def x(*b)\n a(*b)\nend", "ParseTree" => s(:defn, :x, s(:args, :"*b"), s(:call, nil, :a, s(:splat, s(:lvar, :b))))) add_tests("splat_array", "Ruby" => "[*[1]]", "ParseTree" => s(:array, s(:splat, s(:array, s(:lit, 1))))) add_tests("splat_break", "Ruby" => "break *[1]", "ParseTree" => s(:break, s(:svalue, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_break_array", "Ruby" => "break [*[1]]", "ParseTree" => s(:break, s(:array, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_fcall", "Ruby" => "meth(*[1])", "ParseTree" => s(:call, nil, :meth, s(:splat, s(:array, s(:lit, 1))))) add_tests("splat_fcall_array", "Ruby" => "meth([*[1]])", "ParseTree" => s(:call, nil, :meth, s(:array, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_lasgn", "Ruby" => "x = *[1]", "ParseTree" => s(:lasgn, :x, s(:svalue, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_lasgn_array", "Ruby" => "x = [*[1]]", "ParseTree" => s(:lasgn, :x, s(:array, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_lit_1", "Ruby" => "[*1]", # UGH - damn MRI "ParseTree" => s(:array, s(:splat, s(:lit, 1)))) add_tests("splat_lit_n", "Ruby" => "[1, *2]", "ParseTree" => s(:array, s(:lit, 1), s(:splat, s(:lit, 2)))) add_tests("splat_next", "Ruby" => "next *[1]", "ParseTree" => s(:next, s(:svalue, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_next_array", "Ruby" => "next [*[1]]", "ParseTree" => s(:next, s(:array, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_return", "Ruby" => "return *[1]", "ParseTree" => s(:return, s(:svalue, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_return_array", "Ruby" => "return [*[1]]", "ParseTree" => s(:return, s(:array, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_super", "Ruby" => "super(*[1])", "ParseTree" => s(:super, s(:splat, s(:array, s(:lit, 1))))) add_tests("splat_super_array", "Ruby" => "super([*[1]])", "ParseTree" => s(:super, s(:array, s(:splat, s(:array, s(:lit, 1)))))) add_tests("splat_yield", "Ruby" => "yield(*[1])", "ParseTree" => s(:yield, s(:splat, s(:array, s(:lit, 1))))) add_tests("splat_yield_array", "Ruby" => "yield([*[1]])", "ParseTree" => s(:yield, s(:array, s(:splat, s(:array, s(:lit, 1)))))) add_tests("str", "Ruby" => '"x"', "ParseTree" => s(:str, "x")) add_tests("str_concat_newline", # FIX? make prettier? possible? "Ruby" => '"before" \\ " after"', "ParseTree" => s(:str, "before after"), "Ruby2Ruby" => '"before after"') add_tests("str_concat_space", "Ruby" => '"before" " after"', "ParseTree" => s(:str, "before after"), "Ruby2Ruby" => '"before after"') add_tests("str_heredoc", "Ruby" => "<<'EOM'\n blah\nblah\nEOM", "ParseTree" => s(:str, " blah\nblah\n"), "Ruby2Ruby" => "\" blah\\nblah\\n\"") add_tests("str_heredoc_call", "Ruby" => "<<'EOM'.strip\n blah\nblah\nEOM", "ParseTree" => s(:call, s(:str, " blah\nblah\n"), :strip), "Ruby2Ruby" => "\" blah\\nblah\\n\".strip") add_tests("str_heredoc_double", "Ruby" => "a += <<-H1 + b + <<-H2\n first\nH1\n second\nH2", "ParseTree" => s(:lasgn, :a, s(:call, s(:lvar, :a), :+, s(:call, s(:call, s(:str, " first\n"), :+, s(:call, nil, :b)), :+, s(:str, " second\n")))), "Ruby2Ruby" => "a = (a + ((\" first\\n\" + b) + \" second\\n\"))") add_tests("str_heredoc_empty", # yes... tarded "Ruby" => "<<'EOM'\nEOM", "ParseTree" => s(:str, ""), "Ruby2Ruby" => '""') add_tests("str_heredoc_indent", "Ruby" => "<<-EOM\n blah\nblah\n\n EOM", "ParseTree" => s(:str, " blah\nblah\n\n"), "Ruby2Ruby" => "\" blah\\nblah\\n\\n\"") add_tests("str_interp_file", "Ruby" => '"file = #{__FILE__}\n"', "ParseTree" => s(:str, "file = (string)\n"), "Ruby2Ruby" => '"file = (string)\\n"') add_tests("structure_extra_block_for_dvar_scoping", "Ruby" => "a.b do |c, d|\n unless e.f(c) then\n g = false\n d.h { |x, i| g = true }\n end\nend", "ParseTree" => s(:iter, s(:call, s(:call, nil, :a), :b), s(:args, :c, :d), s(:if, s(:call, s(:call, nil, :e), :f, s(:lvar, :c)), nil, s(:block, s(:lasgn, :g, s(:false)), s(:iter, s(:call, s(:lvar, :d), :h), s(:args, :x, :i), s(:lasgn, :g, s(:true))))))) add_tests("structure_remove_begin_1", "Ruby" => "a << begin\n b\n rescue\n c\n end", "ParseTree" => s(:call, s(:call, nil, :a), :<<, s(:rescue, s(:call, nil, :b), s(:resbody, s(:array), s(:call, nil, :c)))), "Ruby2Ruby" => "(a << (b rescue c))") add_tests("structure_remove_begin_2", "Ruby" => "a = if c\n begin\n b\n rescue\n nil\n end\n end\na", "ParseTree" => s(:block, s(:lasgn, :a, s(:if, s(:call, nil, :c), s(:rescue, s(:call, nil, :b), s(:resbody, s(:array), s(:nil))), nil)), s(:lvar, :a)), "Ruby2Ruby" => "a = b rescue nil if c\na\n") # OMG that's awesome add_tests("super_0", "Ruby" => "def x\n super()\nend", "ParseTree" => s(:defn, :x, s(:args), s(:super))) add_tests("super_1", "Ruby" => "def x\n super(4)\nend", "ParseTree" => s(:defn, :x, s(:args), s(:super, s(:lit, 4)))) add_tests("super_1_array", "Ruby" => "def x\n super([24, 42])\nend", "ParseTree" => s(:defn, :x, s(:args), s(:super, s(:array, s(:lit, 24), s(:lit, 42))))) add_tests("super_block_pass", "Ruby" => "super(a, &b)", "ParseTree" => s(:super, s(:call, nil, :a), s(:block_pass, s(:call, nil, :b)))) add_tests("super_block_splat", "Ruby" => "super(a, *b)", "ParseTree" => s(:super, s(:call, nil, :a), s(:splat, s(:call, nil, :b)))) add_tests("super_n", "Ruby" => "def x\n super(24, 42)\nend", "ParseTree" => s(:defn, :x, s(:args), s(:super, s(:lit, 24), s(:lit, 42)))) add_tests("svalue", "Ruby" => "a = *b", "ParseTree" => s(:lasgn, :a, s(:svalue, s(:splat, s(:call, nil, :b))))) add_tests("ternary_nil_no_space", "Ruby" => "1 ? nil: 1", "ParseTree" => s(:if, s(:lit, 1), s(:nil), s(:lit, 1)), "Ruby2Ruby" => "1 ? (nil) : (1)") add_tests("ternary_symbol_no_spaces", "Ruby" => "1?:x:1", "ParseTree" => s(:if, s(:lit, 1), s(:lit, :x), s(:lit, 1)), "Ruby2Ruby" => "1 ? (:x) : (1)") add_tests("to_ary", "Ruby" => "a, b = c", "ParseTree" => s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b)), s(:to_ary, s(:call, nil, :c)))) add_tests("true", "Ruby" => "true", "ParseTree" => s(:true)) add_tests("undef", "Ruby" => "undef :x", "ParseTree" => s(:undef, s(:lit, :x))) add_tests("undef_2", "Ruby" => "undef :x, :y", "ParseTree" => s(:block, s(:undef, s(:lit, :x)), s(:undef, s(:lit, :y))), "Ruby2Ruby" => "undef :x\nundef :y\n") add_tests("undef_3", "Ruby" => "undef :x, :y, :z", "ParseTree" => s(:block, s(:undef, s(:lit, :x)), s(:undef, s(:lit, :y)), s(:undef, s(:lit, :z))), "Ruby2Ruby" => "undef :x\nundef :y\nundef :z\n") add_tests("undef_block_1", "Ruby" => "f1\nundef :x\n", # TODO: don't like the extra return "ParseTree" => s(:block, s(:call, nil, :f1), s(:undef, s(:lit, :x)))) add_tests("undef_block_2", "Ruby" => "f1\nundef :x, :y", "ParseTree" => s(:block, s(:call, nil, :f1), s(:block, s(:undef, s(:lit, :x)), s(:undef, s(:lit, :y)))), "Ruby2Ruby" => "f1\n(undef :x\nundef :y)\n") add_tests("undef_block_3", "Ruby" => "f1\nundef :x, :y, :z", "ParseTree" => s(:block, s(:call, nil, :f1), s(:block, s(:undef, s(:lit, :x)), s(:undef, s(:lit, :y)), s(:undef, s(:lit, :z)))), "Ruby2Ruby" => "f1\n(undef :x\nundef :y\nundef :z)\n") add_tests("undef_block_3_post", "Ruby" => "undef :x, :y, :z\nf2", "ParseTree" => s(:block, s(:undef, s(:lit, :x)), s(:undef, s(:lit, :y)), s(:undef, s(:lit, :z)), s(:call, nil, :f2)), "Ruby2Ruby" => "undef :x\nundef :y\nundef :z\nf2\n") add_tests("undef_block_wtf", "Ruby" => "f1\nundef :x, :y, :z\nf2", "ParseTree" => s(:block, s(:call, nil, :f1), s(:block, s(:undef, s(:lit, :x)), s(:undef, s(:lit, :y)), s(:undef, s(:lit, :z))), s(:call, nil, :f2)), "Ruby2Ruby" => "f1\n(undef :x\nundef :y\nundef :z)\nf2\n") add_tests("unless_post", "Ruby" => "a unless b", "ParseTree" => s(:if, s(:call, nil, :b), nil, s(:call, nil, :a))) add_tests("unless_pre", "Ruby" => "unless b then a end", "ParseTree" => s(:if, s(:call, nil, :b), nil, s(:call, nil, :a)), "Ruby2Ruby" => "a unless b") add_tests("until_post", "Ruby" => "begin\n (1 + 1)\nend until false", "ParseTree" => s(:until, s(:false), s(:call, s(:lit, 1), :+, s(:lit, 1)), false)) add_tests("until_pre", "Ruby" => "until false do\n (1 + 1)\nend", "ParseTree" => s(:until, s(:false), s(:call, s(:lit, 1), :+, s(:lit, 1)), true)) add_tests("until_pre_mod", "Ruby" => "(1 + 1) until false", "ParseTree" => s(:until, s(:false), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "until false do\n (1 + 1)\nend") add_tests("valias", "Ruby" => "alias $y $x", "ParseTree" => s(:valias, :$y, :$x)) add_tests("vcall", "Ruby" => "method", "ParseTree" => s(:call, nil, :method)) add_tests("while_post", "Ruby" => "begin\n (1 + 1)\nend while false", "ParseTree" => s(:while, s(:false), s(:call, s(:lit, 1), :+, s(:lit, 1)), false)) add_tests("while_post2", "Ruby" => "begin\n (1 + 2)\n (3 + 4)\nend while false", "ParseTree" => s(:while, s(:false), s(:block, s(:call, s(:lit, 1), :+, s(:lit, 2)), s(:call, s(:lit, 3), :+, s(:lit, 4))), false)) add_tests("while_pre", "Ruby" => "while false do\n (1 + 1)\nend", "ParseTree" => s(:while, s(:false), s(:call, s(:lit, 1), :+, s(:lit, 1)), true)) add_tests("while_pre_mod", "Ruby" => "(1 + 1) while false", "ParseTree" => s(:while, s(:false), s(:call, s(:lit, 1), :+, s(:lit, 1)), true), "Ruby2Ruby" => "while false do\n (1 + 1)\nend") # FIX can be one liner add_tests("while_pre_nil", "Ruby" => "while false do\nend", "ParseTree" => s(:while, s(:false), nil, true)) add_tests("xstr", "Ruby" => "`touch 5`", "ParseTree" => s(:xstr, 'touch 5')) add_tests("yield_0", "Ruby" => "yield", "ParseTree" => s(:yield)) add_tests("yield_1", "Ruby" => "yield(42)", "ParseTree" => s(:yield, s(:lit, 42))) add_tests("yield_array_0", "Ruby" => "yield([])", "ParseTree" => s(:yield, s(:array))) add_tests("yield_array_1", "Ruby" => "yield([42])", "ParseTree" => s(:yield, s(:array, s(:lit, 42)))) add_tests("yield_array_n", "Ruby" => "yield([42, 24])", "ParseTree" => s(:yield, s(:array, s(:lit, 42), s(:lit, 24)))) add_tests("yield_n", "Ruby" => "yield(42, 24)", "ParseTree" => s(:yield, s(:lit, 42), s(:lit, 24))) add_tests("zarray", "Ruby" => "a = []", "ParseTree" => s(:lasgn, :a, s(:array))) add_tests("zsuper", "Ruby" => "def x\n super\nend", "ParseTree" => s(:defn, :x, s(:args), s(:zsuper))) # TODO: discuss and decide which lit we like # it "converts a regexp to an sexp" do # "/blah/".to_sexp.should == s(:regex, "blah", 0) # "/blah/i".to_sexp.should == s(:regex, "blah", 1) # "/blah/u".to_sexp.should == s(:regex, "blah", 64) # end end sexp_processor-4.4.1/lib/sexp.rb0000444000004100000410000001426512256477515016724 0ustar www-datawww-data$TESTING ||= false # unless defined $TESTING ## # Sexps are the basic storage mechanism of SexpProcessor. Sexps have # a +type+ (to be renamed +node_type+) which is the first element of # the Sexp. The type is used by SexpProcessor to determine whom to # dispatch the Sexp to for processing. class Sexp < Array # ZenTest FULL attr_writer :line attr_accessor :file, :comments @@array_types = [ :array, :args, ] ## # Create a new Sexp containing +args+. def initialize(*args) super(args) end ## # Creates a new Sexp from Array +a+. def self.from_array(a) ary = Array === a ? a : [a] result = self.new ary.each do |x| case x when Sexp result << x when Array result << self.from_array(x) else result << x end end result end def ==(obj) # :nodoc: obj.class == self.class and super end ## # Returns true if this Sexp's pattern matches +sexp+. def ===(sexp) return nil unless Sexp === sexp pattern = self # this is just for my brain return true if pattern == sexp sexp.each do |subset| return true if pattern === subset end return nil end ## # Returns true if this Sexp matches +pattern+. (Opposite of #===.) def =~(pattern) return pattern === self end ## # Returns true if the node_type is +array+ or +args+. # # REFACTOR: to TypedSexp - we only care when we have units. def array_type? type = self.first @@array_types.include? type end def compact # :nodoc: self.delete_if { |o| o.nil? } end ## # Recursively enumerates the sexp yielding to +block+ for every element. # TODO: test def deep_each(&block) self.each_sexp do |sexp| block[sexp] sexp.deep_each(&block) end end ## # Enumeratates the sexp yielding to +b+ when the node_type == +t+. def each_of_type(t, &b) each do | elem | if Sexp === elem then elem.each_of_type(t, &b) b.call(elem) if elem.first == t end end end ## # Recursively enumerates all sub-sexps skipping non-Sexp elements. # TODO: test def each_sexp self.each do |sexp| next unless Sexp === sexp yield sexp end end ## # Replaces all elements whose node_type is +from+ with +to+. Used # only for the most trivial of rewrites. def find_and_replace_all(from, to) each_with_index do | elem, index | if Sexp === elem then elem.find_and_replace_all(from, to) else self[index] = to if elem == from end end end ## # Replaces all Sexps matching +pattern+ with Sexp +repl+. def gsub(pattern, repl) return repl if pattern == self new = self.map do |subset| case subset when Sexp then subset.gsub(pattern, repl) else subset end end return Sexp.from_array(new) end def inspect # :nodoc: sexp_str = self.map {|x|x.inspect}.join(', ') if ENV['VERBOSE'] && line then "s(#{sexp_str}).line(#{line})" else "s(#{sexp_str})" end end def find_node name, delete = false matches = find_nodes name case matches.size when 0 then nil when 1 then match = matches.first delete match if delete match else raise NoMethodError, "multiple nodes for #{name} were found in #{inspect}" end end ## # Find every node with type +name+. def find_nodes name find_all { | sexp | Sexp === sexp and sexp.first == name } end ## # If passed a line number, sets the line and returns self. Otherwise # returns the line number. This allows you to do message cascades # and still get the sexp back. def line(n=nil) if n then @line = n self else @line ||= nil end end ## # Returns the size of the sexp, flattened. def mass @mass ||= self.structure.flatten.size end ## # Returns the node named +node+, deleting it if +delete+ is true. def method_missing meth, delete = false find_node meth, delete end def respond_to? msg, private = false # :nodoc: # why do I need this? Because ruby 2.0 is broken. That's why. super end def pretty_print(q) # :nodoc: nnd = ')' nnd << ".line(#{line})" if line && ENV['VERBOSE'] q.group(1, 's(', nnd) do q.seplist(self) {|v| q.pp v } end end ## # Returns the node type of the Sexp. def sexp_type first end ## # Returns the Sexp body, ie the values without the node type. def sexp_body self[1..-1] end alias :head :sexp_type alias :rest :sexp_body ## # If run with debug, Sexp will raise if you shift on an empty # Sexp. Helps with debugging. def shift raise "I'm empty" if self.empty? super end if ($DEBUG or $TESTING) unless (defined?(RUBY_ENGINE) and RUBY_ENGINE == "maglev") ## # Returns the bare bones structure of the sexp. # s(:a, :b, s(:c, :d), :e) => s(:a, s(:c)) def structure if Array === self.first then s(:bogus, *self).structure # TODO: remove >= 4.2.0 else result = s(self.first) self.each do |subexp| result << subexp.structure if Sexp === subexp end result end end ## # Replaces the Sexp matching +pattern+ with +repl+. def sub(pattern, repl) return repl.dup if pattern == self done = false new = self.map do |subset| if done then subset else case subset when Sexp then if pattern == subset then done = true repl.dup elsif pattern === subset then done = true subset.sub pattern, repl else subset end else subset end end end return Sexp.from_array(new) end def to_a # :nodoc: self.map { |o| Sexp === o ? o.to_a : o } end def to_s # :nodoc: inspect end end class SexpMatchSpecial < Sexp; end class SexpAny < SexpMatchSpecial def ==(o) Sexp === o end def ===(o) return Sexp === o end def inspect "ANY" end end module SexpMatchSpecials def ANY(); return SexpAny.new; end end ## # This is a very important shortcut to make using Sexps much more awesome. def s(*args) Sexp.new(*args) end sexp_processor-4.4.1/lib/unique.rb0000444000004100000410000000030412256477515017240 0ustar www-datawww-data## # Unique creates unique variable names. class Unique def self.reset # mostly for testing @@curr = 0 end def self.next @@curr += 1 "temp_#{@@curr}".intern end reset end sexp_processor-4.4.1/metadata.yml0000644000004100000410000000753312256477515017157 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: sexp_processor version: !ruby/object:Gem::Version version: 4.4.1 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: 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: |- sexp_processor branches from ParseTree bringing all the generic sexp processing tools with it. Sexp, SexpProcessor, Environment, etc... all for your language processing pleasure. email: - ryand-ruby@zenspider.com executables: [] extensions: [] extra_rdoc_files: - History.txt - Manifest.txt - README.txt files: - History.txt - Manifest.txt - README.txt - Rakefile - lib/composite_sexp_processor.rb - lib/pt_testcase.rb - lib/sexp.rb - lib/sexp_processor.rb - lib/unique.rb - test/test_composite_sexp_processor.rb - test/test_environment.rb - test/test_sexp.rb - test/test_sexp_processor.rb - .gemtest homepage: https://github.com/seattlerb/sexp_processor 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: parsetree rubygems_version: 2.1.10 signing_key: specification_version: 4 summary: sexp_processor branches from ParseTree bringing all the generic sexp processing tools with it test_files: - test/test_composite_sexp_processor.rb - test/test_environment.rb - test/test_sexp.rb - test/test_sexp_processor.rb sexp_processor-4.4.1/test/0000755000004100000410000000000012256477515015623 5ustar www-datawww-datasexp_processor-4.4.1/test/test_sexp_processor.rb0000555000004100000410000002071412256477515022272 0ustar www-datawww-data#!/usr/local/bin/ruby -w $TESTING = true require 'sexp_processor' require 'stringio' require 'minitest/autorun' require 'pp' # Fake test classes: class TestProcessor < SexpProcessor # ZenTest SKIP attr_accessor :auto_shift_type def process_acc1(exp) out = self.expected.new(:acc2, exp.thing_three, exp.thing_two, exp.thing_one) exp.clear return out end def process_acc2(exp) out = [] out << exp.thing_one end def process_specific(exp) _ = exp.shift result = s(:blah) until exp.empty? result.push process(exp.shift) end result end def process_strip(exp) result = exp.deep_clone exp.clear result end def process_nonempty(exp) s(*exp) end def process_broken(exp) result = [*exp] exp.clear result end def process_expected(exp) exp.clear return {} end def process_string(exp) return exp.shift end def rewrite_rewritable(exp) # (a b c) => (a c b) return s(exp.shift, exp.pop, exp.shift) end def process_rewritable(exp) @n ||= 0 exp.shift # name result = s(:rewritten) until exp.empty? result.push process(exp.shift) end result.push @n @n += 1 result end def rewrite_major_rewrite(exp) exp[0] = :rewritable exp end end class TestProcessorDefault < SexpProcessor # ZenTest SKIP def initialize super self.default_method = :def_method end def def_method(exp) exp.clear self.expected.new(42) end end # Real test classes: class TestSexpProcessor < Minitest::Test def setup @processor = TestProcessor.new end def test_process_specific a = [:specific, [:x, 1], [:y, 2], [:z, 3]] expected = [:blah, [:x, 1], [:y, 2], [:z, 3]] assert_equal(expected, @processor.process(a)) end def test_process_generic a = [:blah, 1, 2, 3] expected = a.deep_clone assert_equal(expected, @processor.process(a)) end def test_process_default @processor = TestProcessorDefault.new @processor.warn_on_default = false a = s(:blah, 1, 2, 3) assert_equal(@processor.expected.new(42), @processor.process(a)) end def test_process_not_sexp @processor = TestProcessor.new @processor.warn_on_default = false assert_raises SexpTypeError do @processor.process([:broken, 1, 2, 3]) end end def test_process_unsupported_wrong @processor = TestProcessor.new @processor.unsupported << :strip assert_raises UnsupportedNodeError do @processor.process([:whatever]) end end def test_unsupported_equal @processor.strict = true @processor.unsupported = [ :unsupported ] assert_raises UnsupportedNodeError do @processor.process([:unsupported, 42]) end end def test_strict @processor.strict = true assert_raises UnknownNodeError do @processor.process([:blah, 1, 2, 3]) end end def test_strict=; skip; end #Handled def test_require_empty_false @processor.require_empty = false assert_equal s(:nonempty, 1, 2, 3), @processor.process([:nonempty, 1, 2, 3]) end def test_require_empty_true assert_raises NotEmptyError do @processor.process([:nonempty, 1, 2, 3]) end end def test_require_empty=; skip; end # handled def test_process_strip @processor.auto_shift_type = true assert_equal([1, 2, 3], @processor.process(s(:strip, 1, 2, 3))) end def test_rewrite assert_equal(s(:rewritable, :b, :a), @processor.rewrite(s(:rewritable, :a, :b))) end def test_rewrite_different_type assert_equal(s(:rewritable, :b, :a), @processor.rewrite(s(:major_rewrite, :a, :b))) end def test_rewrite_deep assert_equal(s(:specific, s(:rewritable, :b, :a)), @processor.rewrite(s(:specific, s(:rewritable, :a, :b)))) end def test_rewrite_not_empty insert = s(:rewritable, 1, 2, 2) expect = s(:rewritable, 2, 1) result = @processor.rewrite(insert) assert_equal(expect, result) assert_equal(s(2), insert) # post-processing end def test_process_rewrite assert_equal(s(:rewritten, s(:y, 2), s(:x, 1), 0), @processor.process(s(:rewritable, s(:x, 1), s(:y, 2)))) end def test_process_rewrite_deep assert_equal(s(:blah, s(:rewritten, s(:b), s(:a), 0)), @processor.process(s(:specific, s(:rewritable, s(:a), s(:b))))) end def test_rewrite_depth_first inn = s(:specific, s(:rewritable, s(:a), s(:rewritable, s(:rewritable, s(:b), s(:c)), s(:d)))) out = s(:specific, s(:rewritable, s(:rewritable, s(:d), s(:rewritable, s(:c), s(:b))), s(:a))) assert_equal(out, @processor.rewrite(inn)) end def test_process_rewrite_depth_first inn = s(:specific, s(:rewritable, s(:a), s(:rewritable, s(:rewritable, s(:b), s(:c)), s(:d)))) out = s(:blah, s(:rewritten, s(:rewritten, s(:d), s(:rewritten, s(:c), s(:b), 0), 1), s(:a), 2)) assert_equal(out, @processor.process(inn)) end def test_assert_type_hit assert_nil @processor.assert_type([:blah, 1, 2, 3], :blah) end def test_assert_type_miss assert_raises SexpTypeError do @processor.assert_type([:thingy, 1, 2, 3], :blah) end end def test_generate skip "nothing to test at this time... soon." end def test_auto_shift_type @processor.auto_shift_type = false assert_equal(false, @processor.auto_shift_type) @processor.auto_shift_type = true assert_equal(true, @processor.auto_shift_type) end def test_auto_shift_type_equal; skip; end # handled def test_default_method # default functionality tested in process_default assert_nil @processor.default_method @processor.default_method = :something assert_equal :something, @processor.default_method end def test_default_method=; skip; end # handled def test_expected assert_equal Sexp, @processor.expected assert_raises SexpTypeError do @processor.process([:expected]) # should raise end @processor.process(s(:str, "string")) # shouldn't raise @processor.expected = Hash assert_equal Hash, @processor.expected assert !(Hash === s()), "Hash === s() should not be true" assert_raises SexpTypeError do @processor.process(s(:string, "string")) # should raise end @processor.process([:expected]) # shouldn't raise end def test_expected=; skip; end # handled # Not Testing: def test_debug; skip; end def test_debug=; skip; end def test_warn_on_default; skip; end def test_warn_on_default=; skip; end end class TestMethodBasedSexpProcessor < Minitest::Test attr_accessor :processor def setup self.processor = MethodBasedSexpProcessor.new end def test_in_klass assert_empty processor.class_stack processor.in_klass "xxx::yyy" do assert_equal ["xxx::yyy"], processor.class_stack end assert_empty processor.class_stack end def test_in_method assert_empty processor.method_stack processor.in_method "xxx", "file.rb", 42 do assert_equal ["xxx"], processor.method_stack end assert_empty processor.method_stack expected = {"main#xxx" => "file.rb:42"} assert_equal expected, processor.method_locations end def test_klass_name assert_equal :main, processor.klass_name processor.class_stack << "whatevs" << "flog" assert_equal "flog::whatevs", processor.klass_name end def test_klass_name_sexp processor.in_klass s(:colon2, s(:const, :X), :Y) do assert_equal "X::Y", processor.klass_name end processor.in_klass s(:colon3, :Y) do assert_equal "Y", processor.klass_name end end def test_method_name assert_equal "#none", processor.method_name processor.method_stack << "whatevs" assert_equal "#whatevs", processor.method_name end def test_method_name_cls assert_equal "#none", processor.method_name processor.method_stack << "::whatevs" assert_equal "::whatevs", processor.method_name end def test_signature assert_equal "main#none", processor.signature processor.class_stack << "X" assert_equal "X#none", processor.signature processor.method_stack << "y" assert_equal "X#y", processor.signature processor.class_stack.shift assert_equal "main#y", processor.signature end end sexp_processor-4.4.1/test/test_composite_sexp_processor.rb0000555000004100000410000000255512256477515024357 0ustar www-datawww-data#!/usr/local/bin/ruby -w $TESTING = true require 'composite_sexp_processor' require 'minitest/autorun' class FakeProcessor1 < SexpProcessor # ZenTest SKIP def initialize super self.warn_on_default = false self.default_method = :default_processor self.expected = Array end def default_processor(exp) result = [] result << exp.shift until exp.empty? do result << exp.shift.to_s + " woot" end result end end class TestCompositeSexpProcessor < Minitest::Test def setup @p = CompositeSexpProcessor.new end def test_process_default data = [1, 2, 3] result = @p.process(data.dup) assert_equal(data.dup, result) end def test_process_fake1 data = [:x, 1, 2, 3] @p << FakeProcessor1.new result = @p.process(data.dup) assert_equal [:x, "1 woot", "2 woot", "3 woot"], result end def test_process_fake1_twice data = [:x, 1, 2, 3] @p << FakeProcessor1.new @p << FakeProcessor1.new result = @p.process(data.dup) assert_equal [:x, "1 woot woot", "2 woot woot", "3 woot woot"], result end def test_processors # everything is tested by test_append skip end def test_append assert_equal([], @p.processors) assert_raises(ArgumentError) do @p << 42 end fp1 = FakeProcessor1.new @p << fp1 assert_equal([fp1], @p.processors) end end sexp_processor-4.4.1/test/test_sexp.rb0000555000004100000410000002022712256477515020172 0ustar www-datawww-data#!/usr/local/bin/ruby -w $TESTING = true require 'minitest/autorun' require 'sexp_processor' require 'stringio' require 'pp' class SexpTestCase < Minitest::Test # KEY for regex tests # :a == no change # :b == will change (but sometimes ONLY once) # :c == change to include SexpMatchSpecials def util_equals(x, y) result = x == y refute_nil result, "#{x.inspect} does not === #{y.inspect}" end def util_equals3(x, y) result = x === y refute_nil result, "#{x.inspect} does not === #{y.inspect}" end def setup @any = ANY() end end class TestSexp < SexpTestCase # ZenTest FULL class SexpFor def method 1 end end def util_pretty_print(expect, input) io = StringIO.new PP.pp(input, io) io.rewind assert_equal(expect, io.read.chomp) end def setup super @sexp_class = Object.const_get(self.class.name[4..-1]) @processor = SexpProcessor.new @sexp = @sexp_class.new(1, 2, 3) @basic_sexp = s(:lasgn, :var, s(:lit, 42)) @re = s(:lit, 42) @bad1 = s(:lit, 24) @bad1 = s(:blah, 42) end def test_class_from_array skip 'Need to write test_class_from_array' end def test_class_index skip 'Need to write test_class_index' end def test_array_type_eh assert_equal false, @sexp.array_type? @sexp.unshift :array assert_equal true, @sexp.array_type? end def test_each_of_type # TODO: huh... this tests fails if top level sexp :b is removed @sexp = s(:b, s(:a, s(:b, s(:a), :a, s(:b, :a), s(:b, s(:a))))) count = 0 @sexp.each_of_type(:a) do |exp| count += 1 end assert_equal(3, count, "must find 3 a's in #{@sexp.inspect}") end def test_equals2_array # can't use assert_equals because it uses array as receiver refute_equal(@sexp, [1, 2, 3], "Sexp must not be equal to equivalent array") # both directions just in case # HACK - this seems to be a bug in ruby as far as I'm concerned # assert_not_equal([1, 2, 3], @sexp, # "Sexp must not be equal to equivalent array") end def test_equals2_not_body sexp2 = s(1, 2, 5) refute_equal(@sexp, sexp2) end def test_equals2_sexp sexp2 = s(1, 2, 3) if @sexp.class == Sexp then skip "Not applicable to this target." else refute_equal(@sexp, sexp2) end end def test_equals3_any util_equals3 @any, s() util_equals3 @any, s(:a) util_equals3 @any, s(:a, :b, s(:c)) end def test_equals3_full_match util_equals3 s(), s() # 0 util_equals3 s(:blah), s(:blah) # 1 util_equals3 s(:a, :b), s(:a, :b) # 2 util_equals3 @basic_sexp, @basic_sexp.dup # deeper structure end def test_equals3_mismatch assert_nil s() === s(:a) assert_nil s(:a) === s() assert_nil s(:blah1) === s(:blah2) assert_nil s(:a) === s(:a, :b) assert_nil s(:a, :b) === s(:a) assert_nil s(:a1, :b) === s(:a2, :b) assert_nil s(:a, :b1) === s(:a, :b2) assert_nil @basic_sexp === @basic_sexp.dup.push(42) assert_nil @basic_sexp.dup.push(42) === @basic_sexp end def test_equals3_subset_match util_equals3 s(:a), s(s(:a), s(:b)) # left util_equals3 s(:a), s(:blah, s(:a ), s(:b)) # mid 1 util_equals3 s(:a, 1), s(:blah, s(:a, 1), s(:b)) # mid 2 util_equals3 @basic_sexp, s(:blah, @basic_sexp.dup, s(:b)) # mid deeper util_equals3 @basic_sexp, s(@basic_sexp.dup, s(:a), s(:b)) # left deeper util_equals3 s(:a), s(:blah, s(:blah, s(:a))) # left deeper end # def test_equalstilde_any # result = @basic_sexp =~ s(:lit, ANY()) # p result # assert result # end def test_equalstilde_fancy assert_nil s(:b) =~ s(:a, s(:b), :c) refute_nil s(:a, s(:b), :c) =~ s(:b) end def test_equalstilde_plain result = @basic_sexp =~ @re assert result end def test_find_and_replace_all @sexp = s(:a, s(:b, s(:a), s(:b), s(:b, s(:a)))) expected = s(:a, s(:a, s(:a), s(:a), s(:a, s(:a)))) @sexp.find_and_replace_all(:b, :a) assert_equal(expected, @sexp) end def test_gsub assert_equal s(:c), s(:b). gsub(s(:b), s(:c)) assert_equal s(:a), s(:a). gsub(s(:b), s(:c)) assert_equal s(:a, s(:c)), s(:a, s(:b)).gsub(s(:b), s(:c)) end def test_gsub_empty assert_equal s(:c), s().gsub(s(), s(:c)) end def test_gsub_multiple assert_equal(s(:a, s(:c), s(:c)), s(:a, s(:b), s(:b)). gsub(s(:b), s(:c))) assert_equal(s(:a, s(:c), s(:a, s(:c))), s(:a, s(:b), s(:a, s(:b))). gsub(s(:b), s(:c))) end def test_inspect k = @sexp_class n = k.name[0].chr.downcase assert_equal("#{n}()", k.new().inspect) assert_equal("#{n}(:a)", k.new(:a).inspect) assert_equal("#{n}(:a, :b)", k.new(:a, :b).inspect) assert_equal("#{n}(:a, #{n}(:b))", k.new(:a, k.new(:b)).inspect) end def test_mass assert_equal 1, s(:a).mass assert_equal 3, s(:a, s(:b), s(:c)).mass s = s(:iter, s(:call, nil, :a, s(:arglist, s(:lit, 1))), s(:lasgn, :c), s(:call, nil, :d, s(:arglist))) assert_equal 7, s.mass end def test_mass_auto_shift assert_equal 1, s(:a).mass assert_equal 3, s(s(:b), s(:c)).mass s = s(s(:call, nil, :a, s(:arglist, s(:lit, 1))), s(:lasgn, :c), s(:call, nil, :d, s(:arglist))) assert_equal 7, s.mass end def test_method_missing assert_nil @sexp.not_there assert_equal s(:lit, 42), @basic_sexp.lit end def test_method_missing_ambigious assert_raises NoMethodError do pirate = s(:says, s(:arrr!), s(:arrr!), s(:arrr!)) pirate.arrr! end end def test_method_missing_deep sexp = s(:blah, s(:a, s(:b, s(:c, :yay!)))) assert_equal(s(:c, :yay!), sexp.a.b.c) end def test_method_missing_delete sexp = s(:blah, s(:a, s(:b, s(:c, :yay!)))) assert_equal(s(:c, :yay!), sexp.a.b.c(true)) assert_equal(s(:blah, s(:a, s(:b))), sexp) end def test_pretty_print util_pretty_print("s()", s()) util_pretty_print("s(:a)", s(:a)) util_pretty_print("s(:a, :b)", s(:a, :b)) util_pretty_print("s(:a, s(:b))", s(:a, s(:b))) end def test_sexp_body assert_equal [2, 3], @sexp.sexp_body end def test_shift skip "https://github.com/MagLev/maglev/issues/250" if maglev? assert_equal(1, @sexp.shift) assert_equal(2, @sexp.shift) assert_equal(3, @sexp.shift) assert_raises(RuntimeError) do @sexp.shift end end def test_deep_clone @sexp = s(:a, 1, 2, s(:b, 3, 4), 5, 6) backup = @sexp.deep_clone refute_same @sexp, backup, "deep clone is broken again?" assert_equal @sexp, backup, "deep clone is broken again?" end def test_structure @sexp = s(:a, 1, 2, s(:b, 3, 4), 5, 6) backup = @sexp.deep_clone refute_same @sexp, backup, "deep clone is broken again?" assert_equal @sexp, backup, "deep clone is broken again?" expected = s(:a, s(:b)) assert_equal(expected, @sexp.structure) assert_equal(backup, @sexp) end def test_sub assert_equal s(:c), s(:b). sub(s(:b), s(:c)) assert_equal s(:a, s(:c), s(:b)), s(:a, s(:b), s(:b)). sub(s(:b), s(:c)) assert_equal s(:a, s(:c), s(:a)), s(:a, s(:b), s(:a)). sub(s(:b), s(:c)) end def test_sub_miss assert_equal s(:a), s(:a). sub(s(:b), s(:c)) assert_equal s(:a, s(:c)), s(:a, s(:c)). sub(s(:b), s(:c)) end def test_sub_empty assert_equal s(:c), s(). sub(s(), s(:c)) end def test_sub_structure assert_equal(s(:a, s(:c, s(:b))), s(:a, s(:b)). sub(s(:b), s(:c, s(:b)))) end def test_to_a assert_equal([1, 2, 3], @sexp.to_a) end def test_to_s test_inspect end end class TestSexpAny < SexpTestCase def setup super end def test_equals util_equals @any, s() util_equals @any, s(:a) util_equals @any, s(:a, :b, s(:c)) end def test_equals3 util_equals3 @any, s() util_equals3 @any, s(:a) util_equals3 @any, s(:a, :b, s(:c)) end end sexp_processor-4.4.1/test/test_environment.rb0000555000004100000410000000302712256477515021556 0ustar www-datawww-data#!/usr/local/bin/ruby -w $TESTING = true require 'minitest/autorun' require 'sexp_processor' class TestEnvironment < Minitest::Test def setup @env = SexpProcessor::Environment.new end def test_all @env.scope do @env[:x] = 42 @env.scope do @env[:y] = 3 @env[:x] = Math::PI expected = { :x => Math::PI, :y => 3 } assert_equal expected, @env.all end expected = { :x => Math::PI } assert_equal expected, @env.all end end def test_depth assert_equal 1, @env.depth @env.scope do assert_equal 2, @env.depth end assert_equal 1, @env.depth end def test_index test_index_equals end def test_index_unknown assert_nil @env[:unknown] end def test_index_out_of_scope @env.scope do @env[:var] = 42 assert_equal 42, @env[:var] end assert_nil @env[:var] end def test_index_equals @env[:var] = 42 assert_equal 42, @env[:var] end def test_lookup_scope @env[:var] = 42 assert_equal 42, @env[:var] @env.scope do assert_equal 42, @env[:var] end end def test_scope @env[:var] = 42 assert_equal 42, @env[:var] @env.scope do @env[:var] = Math::PI assert_equal Math::PI, @env[:var] end assert_equal Math::PI, @env[:var] end def test_current_shadow @env[:var] = 42 assert_equal 42, @env[:var] @env.scope do @env.current[:var] = 23 assert_equal 23, @env[:var] end assert_equal 42, @env[:var] end end sexp_processor-4.4.1/checksums.yaml.gz.sig0000444000004100000410000000040012256477515020705 0ustar www-datawww-data/%?j;W.^P-rɌKgIfDw&_3p+*UUqH:Y6RZf_󉼧հhי S{7pm"<.KRLQDO$|Ąыp_Hkl>Ҿsp%]dJ7{z=k7#peK`*H.]80R~gxE)uF; "㉎kg9rdVmksexp_processor-4.4.1/metadata.gz.sig0000444000004100000410000000040012256477515017537 0ustar www-datawww-data=Fc?0`𳖗m!p̊SpIq 0e%{= {X'`Կ88x)߅;G9 \N\tpa j0ZSEמV}QϕO qn#w98Ug`iVkqjӬŕ Sor|ZdERpkW-)l\ @c6i#Y$Mp! |Qo҉߱&e9vVe??B(=fD1 lsexp_processor-4.4.1/checksums.yaml.gz0000444000004100000410000000041412256477515020131 0ustar www-datawww-data߯Re=R@F"ϲ =,`e)ynU`uo˖LF`űÿ\q ,Uqj"܅ Q*Hԕ!Iwڙdróц ҵAf'"6u*A`9RW3 {c#I݌gmȽwy8Eu)P<&k>0IZtw@(yvQ@)/?3/)