こんにちは kk8511 です。
最近ふとRuboCopに興味が出たのでCopの実装方法を調べていました。
Ast を眺めただけで力尽きましたが備忘録として記載します。
AST
RuboCop では Abstract Syntax Tree (AST) が利用されるので、まずruby-parseコマンドでサクッと AST を確認してみました。
値
値には型がつく。
% ruby-parse -e '1' (int 1) % ruby-parse -e '"hello"' (str "hello") % ruby-parse -e '[1,2,3]' (array (int 1) (int 2) (int 3))
メソッドチェーン
メソッドチェーンは send のネストになっている。
% ruby-parse -e '(-1.2).floor.abs'
(send
(send
(begin
(float -1.2)) :floor) :abs)
ブロック
ブロックはメソッドの send を囲む形になっている。
% ruby-parse -e '3.times { puts "Hello" }'
(block
(send
(int 3) :times)
(args)
(send nil :puts
(str "Hello")))
% ruby-parse -e '3.times {|i| puts "Hello #{i}" }'
(block
(send
(int 3) :times)
(args
(procarg0
(arg :i)))
(send nil :puts
(dstr
(str "Hello ")
(begin
(lvar :i)))))
おわりに
今まで Ruby を含め、どの言語でも AST を意識したことはなかったため興味深かったです。
RuboCop を触るつもりが Ast を眺めただけで満足してしまったので、ひとまずここまでとなります。
(そもそも、既存のCopが色々とあるので、自前で実装する日は来るだろうか......)