LoginSignup
1
1

More than 5 years have passed since last update.

RPPL

Posted at

RPPLとは、Read Parse Print Loopの頭字語である。(今考えた。)

次を~/.pryrcに追記する。1

$__is_pry_rubyvm_ast_mode = false

def ast!
  $__is_pry_rubyvm_ast_mode = !$__is_pry_rubyvm_ast_mode
end

Pry.config.hooks.add_hook(:before_eval, :"RPPL") do |code, _pry|
  next if code == "ast!\n"
  next unless $__is_pry_rubyvm_ast_mode

  x = code.inspect
  code.clear
  code << "RubyVM::AbstractSyntaxTree.parse(#{x})"
end

そしてpryでast!を実行する。
するとpryに打ち込んだコードがASTとなって出力されて、便利である。

$ pry
[1] pry(main)> 1 + 1
=> 2
[2] pry(main)> ast!
=> true
[3] pry(main)> 1 + 1
=> (SCOPE@1:0-1:5 tbl: [] args: nil body: (OPCALL@1:0-1:5 (LIT@1:0-1:1 1) :+ (ARRAY@1:4-1:5 (LIT@1:4-1:5 1) nil)))
[4] pry(main)> 

https://qiita.com/hanachin_/items/d744e322b4a778574ed7 を参考にしたり、アイディアを得たりしている。

簡単な解説

pryはbefore_evalフックでコードを実行する前にフックを実行できる。

    exec_hook :before_eval, code, self

    result = current_binding.eval(code, Pry.eval_path, Pry.current_line)

フックにはevalする予定の文字列が渡される。
そしてこの文字列はevalにも同じオブジェクトが渡されるため、オブジェクトを破壊的に書き換えればpryが実行するコードを変えることができる。

文字列の書き換えは、String#clearString#<<を使っている。clearで文字列を空にして、<<でパースを行うコードを書き加えている。


雑に実装しただけだしまだ試しただけなので便利なのかもよくわからないが、ひたすらASTを観察したい時には便利な気がする。
ぱっと思いつく課題を挙げれば、取得したASTに対してメソッドを呼び出したい(RubyVM::AbstractSyntaxTree::Node#childrenなど)という需要は容易に考えられるが、この実装だとその需要を満たすことはできない。
真面目に使うのであれば、その辺を改善していくと良いだろう。

より良い実装やアイディアがあったらぜひ教えてほしい。


  1. なおこのコードのライセンスはCC0とする。 https://creativecommons.jp/sciencecommons/aboutcc0/ 

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1