RubyVM::AST を便利に使いたいので gem を作った
さっと作りました。 rubygems には登録してません(名前が重複してるかすら調べてないや)
経緯
Ruby 2.6.0preview2 から RubyVM::AST
モジュールが使えるようになりました。
RubyVM::AST [Experimental] Ruby 2.6 introduces RubyVM::AST module.
This module has parse method which parses a given ruby code of string and returns AST (Abstract Syntax Tree) nodes, and parse_file method which parses a given ruby code file and returns AST nodes.
RubyVM::AST::Node class is also introduced you can get location information and children nodes from Node objects. This feature is experimental. Compatibility of the structure of AST nodes are not guaranteed.
要約:
- Experimental だよ。互換性とか全然まるっきり全く担保する気がないよ
- parse, parse_file というメソッドがあって AST を返すよ
こいつは parse すると RubyVM::AST::Node
を返します。tree なので子供がいるのですが children と呼ぶと RubyVM::AST::Node | NilClass
の配列が返ります。
なんですけど、ちょっとわかりにくいんですよね。children の数は node_type によって固定なんですが覚えられないし、何番目が何かわからないし。ちなみに具体的な対応はこの辺を参照してください
なので雑に node_type 文字列を key にした Hash を返すようにしてみました。わーべんり(べんり?)
RubyVM::AST.parse("1 + 2").children # => [nil, #<RubyVM::AST::Node(NODE_OPCALL(36) 1:0, 1:5): >] require 'ast_tools/hash' RubyVM::AST.parse("1 + 2").children # => {"node_opcall"=>#<RubyVM::AST::Node(NODE_OPCALL(36) 1:0, 1:5): >}
他にももう少し RubyVM::AST
を用いて遊ぶ予定があるのでそのときに使おうと思います
追記
便利そうだけど children 上書きするのやめて別メソッド生やすか、せめてRefinementsで上書きするようにしてほしい / “RubyVM::AST を便利に使いたいので gem を作った - Smoky God Ex…” https://t.co/HFKL9ChOK6
— tagomoris (@tagomoris) June 5, 2018
ハイパーそうですねという感じなので使い方を変えました
https://github.com/hkdnet/ast_tools/pull/2
RubyVM::AST.parse("1 + 2").children # => [nil, #<RubyVM::AST::Node(NODE_OPCALL(36) 1:0, 1:5): >] AstTools::Hash.convert(RubyVM::AST.parse("1 + 2").children) # => {"node_opcall"=>#<RubyVM::AST::Node(NODE_OPCALL(36) 1:0, 1:5): >} # or refinement module Foo using AstTools::Hash def self.foo RubyVM::AST.parse("1 + 2").children # => {"node_opcall"=>#<RubyVM::AST::Node(NODE_OPCALL(36) 1:0, 1:5): >} end end