#:g1: com.informatimago.common-lisp.lisp-sexpの紹介

Posted 2014-12-01 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の336日目です。

com.informatimago.common-lisp.lisp-sexpとはなにか

 com.informatimago.common-lisp.lisp-sexpは、Pascal Bourguignon氏作のCommon Lispの構文を操作するユーティリティです。

パッケージ情報

パッケージ名com.informatimago.common-lisp.lisp-sexp
Quicklisp

インストール方法

(ql:quickload :com.informatimago.common-lisp.lisp-sexp)

試してみる

 定義構文のマクロは構文要素に分解するのが面倒だったりするのですが、com.informatimago.common-lisp.lisp-sexpを利用すれば、lambda-listや定義ボディ部の宣言やドキュメンテーション文字列を簡単に扱えます。
主な関数は、parse-bodyと、parse-lambda-listです。

parse-body

 parse-bodyは、ボディ部の式を取ってドキュメンテーション文字列、宣言、残り本体、の3つの値を返します。

(defparameter *form*
  '(defun foo (n)
    "foo(n): return: n + 42"
    (declare (fixnum n))
    (+ 42 n)))

(parse-body :lambda (cdddr *form*)) ;=> ("foo(n): return: n + 42") ; ((DECLARE (FIXNUM N))) ; ((+ 42 N))

ボディのタイプとしては、:lambda、:locally、:prognがあります。

parse-lambda-list

 parse-lambda-listの方は、:ordinary :boa :specialized :modify-macro :generic :macro :type :destructuring :setf :method-combinationのタイプをサポート

(defmacro defun-form (name (&rest args) &body body)
  (let ((args (parse-lambda-list args :macro)))
    (multiple-value-bind (doc dcls body) (parse-body :lambda body)
      `'(:name ,name
         :lambda-list ,(make-lambda-list args)
         :doc ,@doc
         :decls ,@dcls
         :body ,@body))))

(defun-form foo (n o p &environment env) "foo" (declare (ignore n)) (declare (ignore o)) (declare (ignore p)) :foo :bar :baz) ;=> (:NAME FOO :LAMBDA-LIST (&ENVIRONMENT ENV N O P) :DOC "foo" :DECLS ; (DECLARE (IGNORE P)) (DECLARE (IGNORE O)) (DECLARE (IGNORE N)) :BODY :FOO :BAR ; :BAZ)

まとめ

 今回は、com.informatimago.common-lisp.lisp-sexpを紹介してみました。lambda-listや、宣言のパーズは、割合に面倒なので、こういうユーティリティは便利です。

comments powered by Disqus