*macroexpand-hook*でスタイルチェックの真似事 — #:g1

Posted 2011-04-09 13:36:00 GMT

CMUのAIリポジトリを眺めていてlint for clというものを発見しました。
面白そうなのでソースを眺めてみるに、どうやらLISPマシンには、コンパイラにstyle-checkerというものが含まれており、style-checkerにはユーザーが定義できるフックが用意されているため、これを使ってチェックさせています。
ということで、SBCLなどにもそういう層が存在してないだろうかと調べてみましたが、スタイルチェックに関しては、どうやら統一的なレイヤーのようなものはないようで、個別で警告を出しているようです。
それでは悔しいので、どうにか再現できないかと考えてみたのですが、マクロ限定となるものの *macroexpand-hook* にstyle-checkerを登録すれば似たようなことができるのではないか、と思いちょっと試してみました

(defun style-checker (expander form env)
  (awhen (get (car form) :style-checker)
    (funcall it))
  (funcall expander form env))

;; LOOPの場合 (setf (get 'cl:loop :style-checker) (lambda () (format *error-output* "~&~A: ~A~%~50:@<~A~>~%" 'loop "\"I consider Loop one of the worst flaws in CL.\"" "— Paul Graham")))

のようなものを作り、
(setq *macroexpand-hook* 'style-checker)
すると、
(defun foo ()
  (loop :for i :from 0 :to 100 :collect i))
;=> FOO
;-> LOOP: "I consider Loop one of the worst flaws in CL."
;                     — Paul Graham
という感じに文句が出ます。ちなみに警告は、*error-output*に出るので通常の結果とは混ざりません。

もっとナイスでポータブルな方法があったら是非教えて下さい!

comments powered by Disqus