comparison lisp/bytecomp.el @ 5574:d4f334808463

Support inlining labels, bytecomp.el. lisp/ChangeLog addition: 2011-10-02 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el (byte-compile-initial-macro-environment): Add #'declare to this, so it doesn't need to rely on #'cl-compiling file to determine when we're byte-compiling. Update #'labels to support declaring labels inline, as Common Lisp requires. * bytecomp.el (byte-compile-function-form): Don't error if FUNCTION is quoting a non-lambda, non-symbol, just return it. * cl-extra.el (cl-macroexpand-all): If a label name has been quoted, expand to the label placeholder quoted with 'function. This allows the byte compiler to distinguish between uses of the placeholder as data and uses in contexts where it should be inlined. * cl-macs.el: * cl-macs.el (cl-do-proclaim): When proclaming something as inline, if it is bound as a label, don't modify the symbol's plist; instead, treat the first element of its placeholder constant vector as a place to store compile information. * cl-macs.el (declare): Leave processing declarations while compiling to the implementation of #'declare in byte-compile-initial-macro-environment. tests/ChangeLog addition: 2011-10-02 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-tests.el: * automated/lisp-tests.el (+): Test #'labels and inlining.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 02 Oct 2011 15:32:16 +0100
parents f0f1fd0d8486
children 89cb6a66a61f
comparison
equal deleted inserted replaced
5573:f0f1fd0d8486 5574:d4f334808463
492 (byte-compile-warn 492 (byte-compile-warn
493 "%s is not of type %s" form type))) 493 "%s is not of type %s" form type)))
494 (if byte-compile-delete-errors 494 (if byte-compile-delete-errors
495 form 495 form
496 (funcall (cdr (symbol-function 'the)) type form)))) 496 (funcall (cdr (symbol-function 'the)) type form))))
497 (declare
498 . ,#'(lambda (&rest specs)
499 (while specs
500 (if (listp cl-declare-stack) (push (car specs) cl-declare-stack))
501 (cl-do-proclaim (pop specs) nil))))
497 (load-time-value 502 (load-time-value
498 . ,#'(lambda (form &optional read-only) 503 . ,#'(lambda (form &optional read-only)
499 (let* ((gensym (gensym)) 504 (let* ((gensym (gensym))
500 (byte-compile-bound-variables 505 (byte-compile-bound-variables
501 (acons gensym byte-compile-global-bit 506 (acons gensym byte-compile-global-bit
515 definition name))))) 520 definition name)))))
516 bindings)) 521 bindings))
517 (placeholders 522 (placeholders
518 (mapcar #'(lambda (lambda) 523 (mapcar #'(lambda (lambda)
519 (make-byte-code (second lambda) "\xc0\x87" 524 (make-byte-code (second lambda) "\xc0\x87"
520 [42] 1)) 525 ;; This list is used for
526 ;; the byte-optimize
527 ;; property, if the
528 ;; function is to be
529 ;; inlined. See
530 ;; cl-do-proclaim.
531 (vector nil) 1))
521 lambdas)) 532 lambdas))
522 (byte-compile-macro-environment 533 (byte-compile-macro-environment
523 (pairlis names (mapcar 534 (pairlis names (mapcar
524 #'(lambda (placeholder) 535 #'(lambda (placeholder)
525 `(lambda (&rest cl-labels-args) 536 `(lambda (&rest cl-labels-args)
537 ;; Be careful not to quote
538 ;; PLACEHOLDER, otherwise
539 ;; byte-optimize-funcall inlines
540 ;; it.
526 (list* 'funcall ,placeholder 541 (list* 'funcall ,placeholder
527 cl-labels-args))) 542 cl-labels-args)))
528 placeholders) 543 placeholders)
529 byte-compile-macro-environment)) 544 byte-compile-macro-environment))
530 (gensym (gensym))) 545 (gensym (gensym)))
531 (put gensym 'byte-compile-label-alist 546 (labels
532 (pairlis placeholders 547 ((byte-compile-transform-labels (form names lambdas
533 (mapcar 'second (mapcar 'cl-macroexpand-all 548 placeholders)
534 lambdas)))) 549 (let* ((inline
535 (put gensym 'byte-compile 550 (mapcan
536 #'(lambda (form) 551 #'(lambda (name placeholder lambda)
537 (let* ((byte-compile-label-alist 552 (and
538 (get (car form) 'byte-compile-label-alist))) 553 (eq
539 (dolist (acons byte-compile-label-alist) 554 (getf (aref
540 (setf (cdr acons) 555 (compiled-function-constants
541 (byte-compile-lambda (cdr acons)))) 556 placeholder) 0)
542 (byte-compile-body-do-effect 557 'byte-optimizer)
543 (sublis byte-compile-label-alist (cdr form) 558 'byte-compile-inline-expand)
544 :test #'eq)) 559 `(((function ,placeholder)
545 (dolist (acons byte-compile-label-alist) 560 ,(byte-compile-lambda lambda)
546 (nsubst (cdr acons) (car acons) 561 (function ,lambda)))))
547 byte-compile-label-alist :test #'eq 562 names placeholders lambdas))
548 :descend-structures t))))) 563 (compiled
549 (cl-macroexpand-all (cons gensym body) 564 (mapcar #'byte-compile-lambda
550 byte-compile-macro-environment)))) 565 (if (not inline)
566 lambdas
567 ;; See further down for the
568 ;; rationale of the sublis calls.
569 (sublis (pairlis
570 (mapcar #'cadar inline)
571 (mapcar #'third inline))
572 (sublis
573 (pairlis
574 (mapcar #'car inline)
575 (mapcar #'second inline))
576 lambdas :test #'equal)
577 :test #'eq))))
578 elt)
579 (mapc #'(lambda (placeholder function)
580 (nsubst function placeholder compiled
581 :test #'eq
582 :descend-structures t))
583 placeholders compiled)
584 (when inline
585 (dolist (triad inline)
586 (nsubst (setq elt (elt compiled
587 (position (cadar triad)
588 placeholders)))
589 (second triad) compiled :test #'eq
590 :descend-structures t)
591 (setf (second triad) elt))
592 ;; For inlined labels: first, replace uses of
593 ;; the placeholder in places where it's not an
594 ;; evident, explicit funcall (that is, where
595 ;; it is not to be inlined) with the compiled
596 ;; function:
597 (setq form (sublis
598 (pairlis (mapcar #'car inline)
599 (mapcar #'second inline))
600 form :test #'equal)
601 ;; Now replace uses of the placeholder
602 ;; where it is an evident funcall with the
603 ;; lambda, quoted as a function, to allow
604 ;; byte-optimize-funcall to do its
605 ;; thing. Note that the lambdas still have
606 ;; the placeholders, so there's no risk
607 ;; of recursive inlining.
608 form (sublis (pairlis
609 (mapcar #'cadar inline)
610 (mapcar #'third inline))
611 form :test #'eq)))
612 (sublis (pairlis placeholders compiled) form
613 :test #'eq))))
614 (put gensym 'byte-compile
615 #'(lambda (form)
616 (let* ((names (cadr (cl-pop2 form)))
617 (lambdas (mapcar #'cadr (cdr (pop form))))
618 (placeholders (cadr (pop form))))
619 (byte-compile-body-do-effect
620 (byte-compile-transform-labels form names
621 lambdas
622 placeholders)))))
623 (put gensym 'byte-hunk-handler
624 #'(lambda (form)
625 (let* ((names (cadr (cl-pop2 form)))
626 (lambdas (mapcar #'cadr (cdr (pop form))))
627 (placeholders (cadr (pop form))))
628 (byte-compile-file-form
629 (cons 'progn
630 (byte-compile-transform-labels
631 form names lambdas placeholders))))))
632 (cl-macroexpand-all `(,gensym ',names (list ,@lambdas)
633 ',placeholders ,@body)
634 byte-compile-macro-environment)))))
551 (flet . 635 (flet .
552 ,#'(lambda (bindings &rest body) 636 ,#'(lambda (bindings &rest body)
553 (let* ((names (mapcar 'car bindings)) 637 (let* ((names (mapcar 'car bindings))
554 (lambdas (mapcar 638 (lambdas (mapcar
555 (function* 639 (function*
3697 3781
3698 (defun byte-compile-function-form (form) 3782 (defun byte-compile-function-form (form)
3699 (if (cddr form) 3783 (if (cddr form)
3700 (byte-compile-normal-call 3784 (byte-compile-normal-call
3701 `(signal 'wrong-number-of-arguments '(function ,(length (cdr form))))) 3785 `(signal 'wrong-number-of-arguments '(function ,(length (cdr form)))))
3702 (byte-compile-constant 3786 (byte-compile-constant (if (eq 'lambda (car-safe (nth 1 form)))
3703 (cond ((symbolp (nth 1 form)) 3787 (byte-compile-lambda (nth 1 form))
3704 (nth 1 form)) 3788 (nth 1 form)))))
3705 ((byte-compile-lambda (nth 1 form)))))))
3706 3789
3707 (defun byte-compile-insert (form) 3790 (defun byte-compile-insert (form)
3708 (cond ((null (cdr form)) 3791 (cond ((null (cdr form))
3709 (byte-compile-constant nil)) 3792 (byte-compile-constant nil))
3710 ((<= (length form) 256) 3793 ((<= (length form) 256)