inline #6 一旦まとめ
- lisp/evalmacs.l::defun を変更
- 関数定義の lambda expression を(とりあえず symbol-plist に)保存
- # defun の定義が2つあるので注意
- どっかで function-lambda-expression を定義
- どっかで expand-inline を定義
- lisp package から inline を export しておく
- compile.l で inline という symbol を使ってて、inline を export した file を compile するのに compile.l を読み込むのでそこで衝突するが、export した状態で compile.l を読み込んでから compile しなおせばだいじょぶ。
- proclaim と declaim を変更(まだやってない
- inline 指定された関数の compiler::optimize-form property に expand-inline をセット
- lisp/compile.l::compile-form を変更
- optimize-form した後、必要なら special-form の方に投げる
以下作りかけのコード
;;; http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/fun_function-_a-expression.html (defun function-lambda-expression (fn) "Returns information about function as follows: a) function defining lambda-expression, or nil b) non-nil if function has some non-null lexical environment. c) name of function" (labels ((closure-p (def) (or (si:closure-variable def) (si:closure-function def) (si:closure-frame def)))) (if (symbolp fn) (values (get fn 'lisp::function-definition) (closure-p (symbol-function fn)) fn) (values (unless (compiled-function-p fn) (si:closure-body fn)) (closure-p fn) nil)))) ;; TODO: ;; - supplied-p-parameter for &optional/&key ;; - &aux ;; - ((:key var) default) in &key parameters (defun expand-inline (form) (let ((fn (car form)) (*vals (cdr form))) (multiple-value-bind (*vars body) (multiple-value-bind (lambda-expr closure-p) (function-lambda-expression fn) (if (or (null lambda-expr) closure-p) (return-from expand-inline) (values (cadr lambda-expr) (cddr lambda-expr)))) (let ((vars *vars) (vals *vals) var (state :required) (allowed-llks '(&optional &rest &key &aux)) (pri-binds nil) rest-var (key-binds nil)) (macrolet ((!invalid () '(error 'invalid-lambda-list :datum *vars)) (!few-args () '(error 'too-few-arguments :datum form)) (var/default () `(if (symbolp var) var (values (car var) (cdr var)))) (pop? (list &optional error) `(or (pop ,list) ,(when error `(,error))))) (while (setq var (pop vars)) (if (member var lambda-list-keywords) (let ((left (member var allowed-llks))) (unless left (!invalid)) (setf state var allowed-llks (cdr left))) (case state (:required (push `(,var ,(pop? vals !few-args)) pri-binds)) (&optional (multiple-value-bind (var default) (var/default) (push `(,var ,(or (pop vals) default)) pri-binds))) (&rest (setq rest-var (pop? vars !invalid)) (when (not (member (car vars) allowed-llks)) (!invalid))) (&key (unless rest-var (setq rest-var '#:rest)) (multiple-value-bind (var default) (var/default) (push `(,var (or (getf ,rest-var ,(keyword var)) ,default)) key-binds))) (t (error "unkown state: ~S" state))))) `(let (,@(nreverse pri-binds) ,@(when rest-var `((,rest-var (list ,@vals))))) ,@(if (and rest-var key-binds) `((let ,(nreverse key-binds) ,@body)) body)))))))