mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	instruction. for example, at the following script def m() p:xyzzy 1 2 end compiler ignores `1' because there is no effect. However, `trace(line)' instruction remains in bytecode. This modification removes such redundant trace(line) instruction. * test/ruby/test_iseq.rb: add a test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39539 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			120 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
require 'test/unit'
 | 
						|
require_relative 'envutil'
 | 
						|
 | 
						|
class TestISeq < Test::Unit::TestCase
 | 
						|
  ISeq = RubyVM::InstructionSequence
 | 
						|
 | 
						|
  def test_no_linenum
 | 
						|
    bug5894 = '[ruby-dev:45130]'
 | 
						|
    assert_normal_exit('p RubyVM::InstructionSequence.compile("1", "mac", "", 0).to_a', bug5894)
 | 
						|
  end
 | 
						|
 | 
						|
  def lines src
 | 
						|
    body = RubyVM::InstructionSequence.new(src).to_a[13]
 | 
						|
    lines = body.find_all{|e| e.kind_of? Fixnum}
 | 
						|
  end
 | 
						|
 | 
						|
  def test_to_a_lines
 | 
						|
    src = <<-EOS
 | 
						|
    p __LINE__ # 1
 | 
						|
    p __LINE__ # 2
 | 
						|
               # 3
 | 
						|
    p __LINE__ # 4
 | 
						|
    EOS
 | 
						|
    assert_equal [1, 2, 4], lines(src)
 | 
						|
 | 
						|
    src = <<-EOS
 | 
						|
               # 1
 | 
						|
    p __LINE__ # 2
 | 
						|
               # 3
 | 
						|
    p __LINE__ # 4
 | 
						|
               # 5
 | 
						|
    EOS
 | 
						|
    assert_equal [2, 4], lines(src)
 | 
						|
 | 
						|
    src = <<-EOS
 | 
						|
    1 # should be optimized out
 | 
						|
    2 # should be optimized out
 | 
						|
    p __LINE__ # 3
 | 
						|
    p __LINE__ # 4
 | 
						|
    5 # should be optimized out
 | 
						|
    6 # should be optimized out
 | 
						|
    p __LINE__ # 7
 | 
						|
    8 # should be optimized out
 | 
						|
    9
 | 
						|
    EOS
 | 
						|
    assert_equal [3, 4, 7, 9], lines(src)
 | 
						|
  end
 | 
						|
 | 
						|
  def test_unsupport_type
 | 
						|
    ary = RubyVM::InstructionSequence.compile("p").to_a
 | 
						|
    ary[9] = :foobar
 | 
						|
    e = assert_raise(TypeError) {RubyVM::InstructionSequence.load(ary)}
 | 
						|
    assert_match(/:foobar/, e.message)
 | 
						|
  end if defined?(RubyVM::InstructionSequence.load)
 | 
						|
 | 
						|
  def test_disasm_encoding
 | 
						|
    src = "\u{3042} = 1; \u{3042}"
 | 
						|
    enc, Encoding.default_internal = Encoding.default_internal, src.encoding
 | 
						|
    assert_equal(src.encoding, RubyVM::InstructionSequence.compile(src).disasm.encoding)
 | 
						|
    src.encode!(Encoding::Shift_JIS)
 | 
						|
    assert_equal(true, RubyVM::InstructionSequence.compile(src).disasm.ascii_only?)
 | 
						|
  ensure
 | 
						|
    Encoding.default_internal = enc
 | 
						|
  end
 | 
						|
 | 
						|
  LINE_BEFORE_METHOD = __LINE__
 | 
						|
  def method_test_line_trace
 | 
						|
 | 
						|
    a = 1
 | 
						|
 | 
						|
    b = 2
 | 
						|
 | 
						|
  end
 | 
						|
 | 
						|
  def test_line_trace
 | 
						|
    iseq = ISeq.compile \
 | 
						|
  %q{ a = 1
 | 
						|
      b = 2
 | 
						|
      c = 3
 | 
						|
      # d = 4
 | 
						|
      e = 5
 | 
						|
      # f = 6
 | 
						|
      g = 7
 | 
						|
 | 
						|
    }
 | 
						|
    assert_equal([1, 2, 3, 5, 7], iseq.line_trace_all)
 | 
						|
    iseq.line_trace_specify(1, true) # line 2
 | 
						|
    iseq.line_trace_specify(3, true) # line 5
 | 
						|
 | 
						|
    result = []
 | 
						|
    TracePoint.new(:specified_line){|tp|
 | 
						|
      result << tp.lineno
 | 
						|
    }.enable{
 | 
						|
      iseq.eval
 | 
						|
    }
 | 
						|
    assert_equal([2, 5], result)
 | 
						|
 | 
						|
    iseq = ISeq.of(self.class.instance_method(:method_test_line_trace))
 | 
						|
    assert_equal([LINE_BEFORE_METHOD + 3, LINE_BEFORE_METHOD + 5], iseq.line_trace_all)
 | 
						|
  end if false # TODO: now, it is only for C APIs.
 | 
						|
 | 
						|
  LINE_OF_HERE = __LINE__
 | 
						|
  def test_location
 | 
						|
    iseq = ISeq.of(method(:test_location))
 | 
						|
 | 
						|
    assert_equal(__FILE__, iseq.path)
 | 
						|
    assert(/#{__FILE__}/ =~ iseq.absolute_path)
 | 
						|
    assert_equal("test_location", iseq.label)
 | 
						|
    assert_equal("test_location", iseq.base_label)
 | 
						|
    assert_equal(LINE_OF_HERE+1, iseq.first_lineno)
 | 
						|
 | 
						|
    line = __LINE__
 | 
						|
    iseq = ISeq.of(Proc.new{})
 | 
						|
    assert_equal(__FILE__, iseq.path)
 | 
						|
    assert(/#{__FILE__}/ =~ iseq.absolute_path)
 | 
						|
    assert_equal("test_location", iseq.base_label)
 | 
						|
    assert_equal("block in test_location", iseq.label)
 | 
						|
    assert_equal(line+1, iseq.first_lineno)
 | 
						|
  end
 | 
						|
end
 |