SyntaxError の仕様が Rubinis と MRI とで違う

Rubinis と MRI とでは、SyntaxError クラスの仕様が結構違う。

  • MRI では SyntaxError#message にファイル名と行番号が含まれるが、Rubinius では含まれない。
  • Rubinius には SyntaxError#file と SyntaxError#line が定義されており、これでファイル名と行番号を取得する。これらは MRI には存在しない。


確認してみる。

$ cat foo.rb
if else              # syntax error を起こすコード
$ cat main.rb
begin
  require 'foo'      # syntax error が発生
rescue SyntaxError => ex
  p ex.message
  p ex.file if ex.respond_to? :file
  p ex.line if ex.respond_to? :line
end
### MRI では message にファイル名と行番号が含まれる
$ ruby main.rb
"./foo.rb:1: syntax error, unexpected kELSE"
### Rubinius では message とファイル名と行番号が分離されている
$ rubinius main.rb
"syntax error, unexpected kELSE"
"./foo.rb"
1


これはどう考えても、メッセージとファイル名と行番号が分離している Rubinius のほうが「あるべき姿」だろう。PHP5 でも Exception のメッセージとファイル名と行番号は分離しているから、MRI の Exception は PHP5 以下といえる。残念!

ただし、Rubinius では SyntaxError#file と SyntaxError#line は定義されていても Exception#file と Exception#line が定義されているわけではない。#file と #line が定義されているのはあくまで SyntaxError だけみたい。でもこれは Exception に定義してほしいところだ。PHP5 ではそうなっているから、個人的には Rubinius の Exception は PHP5 以下。残念!ウソ、勘違いでした。

さて、MRIRuby とで仕様が違った場合、どうやって spec ファイルを記述すればいいのだろうか。これについては、次のエントリに書く。