2016-12-22 7 views
4

は(彼らは同じですが、結果は異なります)次のシナリオの比較:ruby​​とjrubyでbegin-next-endの動作が異なるのはなぜですか?

まず、私はルビーでそれをやるのJRuby上(cruby)

~> irb 
irb(main):001:0> begin 
irb(main):002:1* begin 
irb(main):003:2* puts 1 
irb(main):004:2> next 
irb(main):005:2> end 
irb(main):006:1> puts 2 
irb(main):007:1> end 
SyntaxError: (irb):4: Can't escape from eval with next 

今同じこと:

~> jirb 
irb(main):001:0> begin 
irb(main):002:1* begin 
irb(main):003:2* puts 1 
irb(main):004:2> next 
irb(main):005:2> end 
irb(main):006:1> puts 2 
irb(main):007:1> end 
1 
=> nil 

これはcrubyのようにjrubyで失敗しないのはなぜですか?これは厄介なバグですか?

+3

もう1つの可能性は、IRbの実装アーチファクトである可能性があります。IRbの実装はハックで脆弱で(寛大である)、その動作はスクリプトと同じコード実行の動作に必ずしも対応していないことはよく知られています。よりよく知られている非互換性の中には、トップレベルのメソッドがプライベートであるにもかかわらず公開され、ローカル変数に関するいくつかの奇妙なものがあるということもあります。しかし、制御フローについてもいくつかの相違点があることは疑問ではありません。特に、あなたのエラーメッセージには 'eval'と記載されています。これはあなたも使用しません。 –

+2

...あなたのコードではなくIRb自体の実装の中でエラーが発生しているようです。 –

+0

あなたのご意見ありがとうございます! Ruby: 'Invalid next(SyntaxError)'とjruby: 'LocalJumpError:unexpected next' – Kalsan

答えて

1

私はこれをBug #13064として提出しました。

私はYARVのバージョンの様々なだけでなく、JRubyの、MRuby、およびRubiniusの最新バージョンでは、あなたのコードをテストした:

  • YARV 2.2.0(MacOSので出荷ビルド)

    # ruby -v -W -e 'begin; begin puts 1; next end; puts 2 end' 
    ruby 2.0.0p648 (2015-12-16 revision 53162) [universal.x86_64-darwin16] 
    -e:1: warning: statement not reached 
    -e:1: Invalid next 
    -e: compile error (SyntaxError) 
    
    # irb -f -d -w -W 
    irb(main):001:0> p RUBY_VERSION 
    "2.0.0" 
    => "2.0.0" 
    irb(main):002:0> p RUBY_ENGINE 
    "ruby" 
    => "ruby" 
    irb(main):003:0> 
    irb(main):004:0* begin 
    irb(main):005:1* begin 
    irb(main):006:2*  puts 1 
    irb(main):007:2>  next 
    irb(main):008:2> end 
    irb(main):009:1> puts 2 
    irb(main):010:1> end 
    (irb):9: warning: statement not reached 
    Exception `SyntaxError' at /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/irb/workspace.rb:86 - (irb):7: Can't escape from eval with next 
    Exception `SyntaxError' at /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/irb/workspace.rb:86 - (irb):7: Can't escape from eval with next 
    SyntaxError: (irb):7: Can't escape from eval with next 
        from (irb) 
    irb(main):011:0> 
    irb(main):012:0* exit 
    
  • YARV 2.3.1(現時点でのJRubyと互換性があると主張バージョン)

    # ruby -v -W -e 'begin; begin puts 1; next end; puts 2 end' 
    ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin16] 
    -e:1: warning: statement not reached 
    -e: -e:1: Invalid next (SyntaxError) 
    
    # irb -f -d -w -W 
    irb(main):001:0> p RUBY_VERSION 
    "2.3.1" 
    => "2.3.1" 
    irb(main):002:0> p RUBY_ENGINE 
    "ruby" 
    => "ruby" 
    irb(main):003:0> 
    irb(main):004:0* begin 
    irb(main):005:1* begin 
    irb(main):006:2*  puts 1 
    irb(main):007:2>  next 
    irb(main):008:2> end 
    irb(main):009:1> puts 2 
    irb(main):010:1> end 
    (irb):9: warning: statement not reached 
    Exception `SyntaxError' at /Users/joerg/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/workspace.rb:87 - (irb):7: Can't escape from eval with next 
    Exception `SyntaxError' at /Users/joerg/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/workspace.rb:87 - (irb):7: Can't escape from eval with next 
    Exception `SyntaxError' at /Users/joerg/.rbenv/versions/2.3.1/lib/ruby/2.3.0/irb/workspace.rb:87 - (irb):7: Can't escape from eval with next 
    SyntaxError: (irb):7: Can't escape from eval with next 
        from (irb) 
    irb(main):011:0> 
    irb(main):012:0* exit 
    
  • YARV 2.3.3

    # ruby -v -W -e 'begin; begin puts 1; next end; puts 2 end' 
    ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-darwin16] 
    -e:1: warning: statement not reached 
    -e: -e:1: Invalid next (SyntaxError) 
    
    # irb -f -d -w -W 
    irb(main):001:0> p RUBY_VERSION 
    "2.3.3" 
    => "2.3.3" 
    irb(main):002:0> p RUBY_ENGINE 
    "ruby" 
    => "ruby" 
    irb(main):003:0> 
    irb(main):004:0* begin 
    irb(main):005:1* begin 
    irb(main):006:2*  puts 1 
    irb(main):007:2>  next 
    irb(main):008:2> end 
    irb(main):009:1> puts 2 
    irb(main):010:1> end 
    (irb):9: warning: statement not reached 
    Exception `SyntaxError' at /Users/joerg/.rbenv/versions/2.3.3/lib/ruby/2.3.0/irb/workspace.rb:87 - (irb):7: Can't escape from eval with next 
    Exception `SyntaxError' at /Users/joerg/.rbenv/versions/2.3.3/lib/ruby/2.3.0/irb/workspace.rb:87 - (irb):7: Can't escape from eval with next 
    Exception `SyntaxError' at /Users/joerg/.rbenv/versions/2.3.3/lib/ruby/2.3.0/irb/workspace.rb:87 - (irb):7: Can't escape from eval with next 
    SyntaxError: (irb):7: Can't escape from eval with next 
        from (irb) 
    irb(main):011:0> 
    irb(main):012:0* exit 
    
  • YARV 2.4.0-preview3:

    # ruby -v -W -e 'begin; begin puts 1; next end; puts 2 end' 
    ruby 2.4.0preview3 (2016-11-07 trunk 56661) [x86_64-darwin16] 
    -e:1: warning: statement not reached 
    -e: -e:1: Invalid next (SyntaxError) 
    
    # irb -f -d -w -W 
    irb(main):001:0> p RUBY_VERSION 
    "2.4.0" 
    => "2.4.0" 
    irb(main):002:0> p RUBY_ENGINE 
    "ruby" 
    => "ruby" 
    irb(main):003:0> 
    irb(main):004:0* begin 
    irb(main):005:1* begin 
    irb(main):006:2*  puts 1 
    irb(main):007:2>  next 
    irb(main):008:2> end 
    irb(main):009:1> puts 2 
    irb(main):010:1> end 
    (irb):9: warning: statement not reached 
    Exception `SyntaxError' at /Users/joerg/.rbenv/versions/2.4.0-preview3/lib/ruby/2.4.0/irb/workspace.rb:87 - (irb):7: Can't escape from eval with next 
    SyntaxError: (irb):7: Can't escape from eval with next 
        from (irb) 
    irb(main):011:0> 
    irb(main):012:0* exit 
    
  • YARV 2.4.0-DEV(昨日のような現在のSVNトランク):

    # ruby -v -W -e 'begin; begin puts 1; next end; puts 2 end' 
    ruby 2.4.0dev (2016-12-22 trunk 57151) [x86_64-darwin16] 
    -e:1: warning: statement not reached 
    -e: -e:1: Invalid next (SyntaxError) 
    
    # irb -f -d -w -W 
    irb(main):001:0> p RUBY_VERSION 
    "2.4.0" 
    => "2.4.0" 
    irb(main):002:0> p RUBY_ENGINE 
    "ruby" 
    => "ruby" 
    irb(main):003:0> 
    irb(main):004:0* begin 
    irb(main):005:1* begin 
    irb(main):006:2*  puts 1 
    irb(main):007:2>  next 
    irb(main):008:2> end 
    irb(main):009:1> puts 2 
    irb(main):010:1> end 
    (irb):9: warning: statement not reached 
    Exception `SyntaxError' at /Users/joerg/.rbenv/versions/2.4.0-dev/lib/ruby/2.4.0/irb/workspace.rb:87 - (irb):7: Can't escape from eval with next 
    SyntaxError: (irb):7: Can't escape from eval with next 
        from (irb) 
    irb(main):011:0> 
    irb(main):012:0* exit 
    
  • ルビニウス3.69

    # rbx -v -W -e 'begin; begin puts 1; next end; puts 2 end' 
    rubinius 3.69 (2.3.1 a57071c6 2016-11-17 3.8.1) [x86_64-darwin15.6.0] 
    1 
           main # Rubinius::Loader at core/loader.rb:860 
           evals # Rubinius::Loader at core/loader.rb:646 
           eval # Kernel(Rubinius::Loader) at core/kernel.rb:1130 
        call_on_instance # Rubinius::BlockEnvironment at core/block_environment.rb:147 
        { } in __script__ # Object at -e:1 
          jump_error . Rubinius at core/rubinius.rb:279 
    
    invalid context for 'next' (LocalJumpError) 
    
    An exception occurred evaluating command line code 
    
    # irb 
    irb(main):001:0> p RUBY_VERSION 
    "2.3.1" 
    => "2.3.1" 
    irb(main):002:0> p RUBY_ENGINE 
    "rbx" 
    => "rbx" 
    irb(main):003:0> 
    irb(main):004:0* begin 
    irb(main):005:1* begin 
    irb(main):006:2*  puts 1 
    irb(main):007:2>  next 
    irb(main):008:2> end 
    irb(main):009:1> puts 2 
    irb(main):010:1> end 
    1 
    LocalJumpError: invalid context for 'next' 
        from core/rubinius.rb:279:in `jump_error' 
        from (irb):7 
        from core/block_environment.rb:147:in `call_on_instance' 
        from core/kernel.rb:1130:in `eval' 
        from core/kernel.rb:585:in `loop' 
        from core/proc.rb:20:in `call' 
        from core/kernel.rb:1067:in `catch' 
        from core/throw_catch.rb:8:in `register' 
        from core/kernel.rb:1066:in `catch' 
        from core/proc.rb:20:in `call' 
        from core/kernel.rb:1067:in `catch' 
        from core/throw_catch.rb:8:in `register' 
        from core/kernel.rb:1066:in `catch' 
        from core/code_loader.rb:505:in `load_script' 
        from core/code_loader.rb:590:in `load_script' 
        from core/loader.rb:679:in `script' 
        from core/loader.rb:861:in `main'irb(main):011:0> 
    irb(main):012:0* exit 
    
  • JRubyの9.1.6.0(最新版)

    # jruby -v -W -e 'begin; begin puts 1; next end; puts 2 end' 
    jruby 9.1.6.0 (2.3.1) 2016-11-09 0150a76 Java HotSpot(TM) 64-Bit Server VM 25.102-b14 on 1.8.0_102-b14 +jit [darwin-x86_64] 
    1 
    LocalJumpError: unexpected next 
        <main> at -e:1 
    
    # irb -f -d -w -W 
    irb(main):001:0> p RUBY_VERSION 
    "2.3.1" 
    => "2.3.1" 
    irb(main):002:0> p RUBY_ENGINE 
    "jruby" 
    => "jruby" 
    irb(main):003:0> 
    irb(main):004:0* begin 
    irb(main):005:1* begin 
    irb(main):006:2*  puts 1 
    irb(main):007:2>  next 
    irb(main):008:2> end 
    irb(main):009:1> puts 2 
    irb(main):010:1> end 
    1 
    => nil 
    irb(main):011:0> 
    irb(main):012:0* exit 
    
  • MRuby 1.2.0(自分自身をマッツによって書かれた最低限のISO準拠したRubyの実装)ほとんどは何

    # mruby -v -e 'begin; begin puts 1; next end; puts 2 end' 
    mruby 1.2.0 (2015-11-17) 
    00001 NODE_SCOPE: 
    00001 NODE_BEGIN: 
    00001  NODE_BEGIN: 
    00001  NODE_BEGIN: 
    00001   NODE_CALL: 
    00001   NODE_SELF 
    00001   method='puts' (383) 
    00001   args: 
    00001    NODE_INT 1 base 10 
    00001   NODE_NEXT: 
    00001  NODE_CALL: 
    00001   NODE_SELF 
    00001   method='puts' (383) 
    00001   args: 
    00001   NODE_INT 2 base 10 
    irep 0x7fe0e3c1b630 nregs=4 nlocals=1 pools=1 syms=1 reps=0 
    file: -e 
        1 000 OP_LOADSELF R1  
        1 001 OP_LOADI R2 1 
        1 002 OP_SEND R1 :puts 1 
        1 003 OP_ERR "unexpected next" 
        1 004 OP_LOADSELF R1  
        1 005 OP_LOADI R2 2 
        1 006 OP_SEND R1 :puts 1 
        1 007 OP_STOP 
    
    1 
    trace: 
        [0] -e:1 
    LocalJumpError: unexpected next 
    
    # irb -v 
    mruby 1.2.0 (2015-11-17) 
    mirb - Embeddable Interactive Ruby Shell 
    
    > p RUBY_VERSION 
    00001 NODE_SCOPE: 
    00001 NODE_BEGIN: 
    00001  NODE_CALL: 
    00001  NODE_SELF 
    00001  method='p' (384) 
    00001  args: 
    00001   NODE_CONST RUBY_VERSION 
    irep 0x7fceeac05220 nregs=4 nlocals=1 pools=0 syms=2 reps=0 
    file: (mirb) 
        1 000 OP_LOADSELF R1  
        1 001 OP_GETCONST R2 :RUBY_VERSION 
        1 002 OP_SEND R1 :p 1 
        1 003 OP_STOP 
    
    "1.9" 
    => "1.9" 
    > p RUBY_ENGINE 
    00002 NODE_SCOPE: 
    00002 NODE_BEGIN: 
    00002  NODE_CALL: 
    00002  NODE_SELF 
    00002  method='p' (384) 
    00002  args: 
    00002   NODE_CONST RUBY_ENGINE 
    irep 0x7fceeae05cf0 nregs=4 nlocals=1 pools=0 syms=2 reps=0 
    file: (mirb) 
        2 000 OP_LOADSELF R1  
        2 001 OP_GETCONST R2 :RUBY_ENGINE 
        2 002 OP_SEND R1 :p 1 
        2 003 OP_STOP 
    
    "mruby" 
    => "mruby" 
    > 
    00004 NODE_SCOPE: 
    00004 NODE_BEGIN: 
    irep 0x7fceeac06a50 nregs=2 nlocals=1 pools=0 syms=0 reps=0 
    file: (mirb) 
        4 000 OP_LOADNIL R1  
        4 001 OP_STOP 
    
    => nil 
    > begin 
    00005 NODE_NIL 
    * begin 
    00007 NODE_NIL 
    *  puts 1 
    00009 NODE_NIL 
    *  next 
    00011 NODE_NIL 
    * end 
    00013 NODE_NIL 
    * puts 2 
    00015 NODE_NIL 
    * end 
    00012 NODE_SCOPE: 
    00012 NODE_BEGIN: 
    00012  NODE_BEGIN: 
    00012  NODE_BEGIN: 
    00012   NODE_CALL: 
    00012   NODE_SELF 
    00012   method='puts' (383) 
    00012   args: 
    00012    NODE_INT 1 base 10 
    00013   NODE_NEXT: 
    00015  NODE_CALL: 
    00015   NODE_SELF 
    00015   method='puts' (383) 
    00015   args: 
    00015   NODE_INT 2 base 10 
    irep 0x7fceeae01130 nregs=4 nlocals=1 pools=1 syms=1 reps=0 
    file: (mirb) 
        12 000 OP_LOADSELF R1  
        12 001 OP_LOADI R2 1 
        12 002 OP_SEND R1 :puts 1 
        13 003 OP_ERR "unexpected next" 
        15 004 OP_LOADSELF R1  
        15 005 OP_LOADI R2 2 
        15 006 OP_SEND R1 :puts 1 
        15 007 OP_STOP 
    
    1 
    LocalJumpError: unexpected next 
    > 
    00012 NODE_SCOPE: 
    00012 NODE_BEGIN: 
    irep 0x7fceeae078f0 nregs=2 nlocals=1 pools=0 syms=0 reps=0 
    file: (mirb) 
        12 000 OP_LOADNIL R1  
        12 001 OP_STOP 
    
    => nil 
    > exit 
    

興味深いことに、MRuby、JRuby、Rubiniusは実際に行動に同意しますが、YARVとは異なります。 YARVか他のすべてが間違っています。しかし、私はどちらかと言うことはできません。

1

MRIは、Ruby 1.9の時間枠の周りで、LocalJumpErrorを発生させるのではなく、解析時にこれらの不正なジャンプケースの一部を検出し始めました。 JRuby、MRuby、Rubiniusは、ジャンプをそのままにしておき、すぐに構文エラーを出すのではなく、後で失敗する可能性が高いです。

JRubyでバグを報告する価値があるかもしれません。パーザは基本的にMRIのポートですので、同じエラーを発生させることができます。それを除けば、私たちはこの分析をコンパイル時に実行してエラーを発生させることができます。

関連する問題