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

Posted 2014-11-29 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の334日目です。

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

 com.informatimago.common-lisp.lisp-textは、Pascal Bourguignon氏作のCommon Lispのソースコードを操作するためのライブラリです。

パッケージ情報

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

インストール方法

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

試してみる

 主な関数は、source-readで、ファイルから読み込んだ定義をソースオブジェクトとして返します。
定義や、コメント、オブジェクト等はそれぞれ別のクラスになって格納されるので、編集操作が簡単に可能です。

 試しにあるシステムから最長のdefunを抜き出すという関数を作ってみます。

(defpackage :source-text-demo
  (:use :cl)
  (:import-from :com.informatimago.common-lisp.lisp-text.source-text
                :source-read
                :source-object-text))

(cl:in-package :source-text-demo)

(defun system-sources (system) (loop :for file :in (mapcar #'asdf:component-pathname (asdf:component-children (asdf:find-system system))) :append (with-open-file (in file) (loop :for item := (source-read in nil in) :until (eq item in) :collect item))))

(defun find-the-longest-defun-form (src) (flet ((count-lines (text) (count #\Newline text))) (let* ((items (copy-list src)) (text (source-object-text (first (sort (remove-if-not (lambda (x) (and (source-object-text x) (*:scan "^\\(defun" (source-object-text x)))) items) #'> :key (lambda (x) (count-lines (source-object-text x)))))))) (format T "~&;;;~%;;; ~D line~:*~P~%;;;~%~A" (count-lines text) text))))

実行

(find-the-longest-defun-form (system-sources :contextl))
;>>  ;;;
;>>  ;;; 34 lines
;>>  ;;;
;>>  (defun ensure-layered-function
;>>         (name
;>>          &rest initargs
;>>          &key (lambda-list () lambda-list-p)
;>>          (argument-precedence-order (required-args lambda-list))
;>>          (documentation nil)
;>>          (generic-function-class 'layered-function)
;>>          &allow-other-keys)
;>>    (unless lambda-list-p
;>>      (error "The layered function ~S must be initialized with a lambda list." name))
;>>    (let ((gf (let ((layer-arg (gensym "LAYER-ARG-")))
;>>                (apply #'ensure-generic-function
;>>                       (lf-definer-name name)
;>>  		     :generic-function-class
;>>                       generic-function-class
;>>                       :argument-precedence-order
;>>                       `(,@argument-precedence-order ,layer-arg)
;>>                       :lambda-list
;>>                       `(,layer-arg ,@lambda-list)
;>>                       (loop for (key value) on initargs by #'cddr
;>>                             unless (eq key :documentation)
;>>                             nconc (list key value))))))
;>>      (setf (fdefinition name)
;>>            (let ((lambda `(lambda (&rest rest)
;>>                             (declare (optimize (speed 3) (debug 0) (safety 0)
;>>                                                (compilation-speed 0)))
;>>                             (apply (the function ,gf)
;>>                                    (layer-context-prototype *active-context*)
;>>                                    rest))))
;>>              #-ecl (compile nil lambda)
;>>              #+ecl (coerce lambda 'function)))
;>>      (when documentation
;>>        (setf (documentation name 'function) documentation))
;>>      (bind-lf-names name)
;>>      gf))
;=>  NIL

まとめ

 今回は、com.informatimago.common-lisp.lisp-textを紹介してみました。コメントを削除したり、定義間の行間を変更したりも簡単にできますし、応用次第では結構色々できそうです。

comments powered by Disqus