diff options
| author | Stefan Monnier | 2011-02-21 18:40:54 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2011-02-21 18:40:54 -0500 |
| commit | cb9336bd977d3345b86234c36d45228f7fb27eec (patch) | |
| tree | b4b88a95c633e7d732b31f12a5cfc3f61d579e07 | |
| parent | f619ad4ca2ce943d53589469c010e451afab97dd (diff) | |
| download | emacs-cb9336bd977d3345b86234c36d45228f7fb27eec.tar.gz emacs-cb9336bd977d3345b86234c36d45228f7fb27eec.zip | |
* lisp/emacs-lisp/cconv.el (cconv-closure-convert-rec): Let the byte
compiler choose the representation of closures.
(cconv--env-var): Remove.
* lisp/emacs-lisp/bytecomp.el (byte-compile--env-var): New var.
(byte-compile-make-closure, byte-compile-get-closed-var):
New functions.
* lisp/cedet/semantic/wisent/comp.el (wisent-byte-compile-grammar):
Macroexpand before passing to byte-compile-form.
| -rw-r--r-- | lisp/ChangeLog | 9 | ||||
| -rw-r--r-- | lisp/cedet/ChangeLog | 5 | ||||
| -rw-r--r-- | lisp/cedet/semantic/wisent/comp.el | 16 | ||||
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 18 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cconv.el | 57 |
5 files changed, 61 insertions, 44 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4e2e87ab60f..f7a62bc8385 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,14 @@ | |||
| 1 | 2011-02-21 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2011-02-21 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | * emacs-lisp/cconv.el (cconv-closure-convert-rec): Let the byte | ||
| 4 | compiler choose the representation of closures. | ||
| 5 | (cconv--env-var): Remove. | ||
| 6 | * emacs-lisp/bytecomp.el (byte-compile--env-var): New var. | ||
| 7 | (byte-compile-make-closure, byte-compile-get-closed-var): | ||
| 8 | New functions. | ||
| 9 | |||
| 10 | 2011-02-21 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 11 | |||
| 3 | * subr.el (with-output-to-temp-buffer): New macro. | 12 | * subr.el (with-output-to-temp-buffer): New macro. |
| 4 | 13 | ||
| 5 | * simple.el (count-words-region): Don't use interactive-p. | 14 | * simple.el (count-words-region): Don't use interactive-p. |
diff --git a/lisp/cedet/ChangeLog b/lisp/cedet/ChangeLog index b6d5cff6b51..fa3f633d1ac 100644 --- a/lisp/cedet/ChangeLog +++ b/lisp/cedet/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2011-02-21 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * semantic/wisent/comp.el (wisent-byte-compile-grammar): | ||
| 4 | Macroexpand before passing to byte-compile-form. | ||
| 5 | |||
| 1 | 2011-01-13 Stefan Monnier <monnier@iro.umontreal.ca> | 6 | 2011-01-13 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 7 | ||
| 3 | * srecode/srt-mode.el (srecode-template-mode): Use define-derived-mode. | 8 | * srecode/srt-mode.el (srecode-template-mode): Use define-derived-mode. |
diff --git a/lisp/cedet/semantic/wisent/comp.el b/lisp/cedet/semantic/wisent/comp.el index c3243c12923..6b473f9ad81 100644 --- a/lisp/cedet/semantic/wisent/comp.el +++ b/lisp/cedet/semantic/wisent/comp.el | |||
| @@ -3452,15 +3452,13 @@ where: | |||
| 3452 | (if (wisent-automaton-p grammar) | 3452 | (if (wisent-automaton-p grammar) |
| 3453 | grammar ;; Grammar already compiled just return it | 3453 | grammar ;; Grammar already compiled just return it |
| 3454 | (wisent-with-context compile-grammar | 3454 | (wisent-with-context compile-grammar |
| 3455 | (let* ((gc-cons-threshold 1000000) | 3455 | (let* ((gc-cons-threshold 1000000)) |
| 3456 | automaton) | ||
| 3457 | (garbage-collect) | 3456 | (garbage-collect) |
| 3458 | (setq wisent-new-log-flag t) | 3457 | (setq wisent-new-log-flag t) |
| 3459 | ;; Parse input grammar | 3458 | ;; Parse input grammar |
| 3460 | (wisent-parse-grammar grammar start-list) | 3459 | (wisent-parse-grammar grammar start-list) |
| 3461 | ;; Generate the LALR(1) automaton | 3460 | ;; Generate the LALR(1) automaton |
| 3462 | (setq automaton (wisent-parser-automaton)) | 3461 | (wisent-parser-automaton))))) |
| 3463 | automaton)))) | ||
| 3464 | 3462 | ||
| 3465 | ;;;; -------------------------- | 3463 | ;;;; -------------------------- |
| 3466 | ;;;; Byte compile input grammar | 3464 | ;;;; Byte compile input grammar |
| @@ -3476,7 +3474,15 @@ Automatically called by the Emacs Lisp byte compiler as a | |||
| 3476 | ;; automaton internal data structure. Then, because the internal | 3474 | ;; automaton internal data structure. Then, because the internal |
| 3477 | ;; data structure contains an obarray, convert it to a lisp form so | 3475 | ;; data structure contains an obarray, convert it to a lisp form so |
| 3478 | ;; it can be byte-compiled. | 3476 | ;; it can be byte-compiled. |
| 3479 | (byte-compile-form (wisent-automaton-lisp-form (eval form)))) | 3477 | (byte-compile-form |
| 3478 | ;; FIXME: we macroexpand here since `byte-compile-form' expects | ||
| 3479 | ;; macroexpanded code, but that's just a workaround: for lexical-binding | ||
| 3480 | ;; the lisp form should have to pass through closure-conversion and | ||
| 3481 | ;; `wisent-byte-compile-grammar' is called much too late for that. | ||
| 3482 | ;; Why isn't this `wisent-automaton-lisp-form' performed at | ||
| 3483 | ;; macroexpansion time? --Stef | ||
| 3484 | (macroexpand-all | ||
| 3485 | (wisent-automaton-lisp-form (eval form))))) | ||
| 3480 | 3486 | ||
| 3481 | (put 'wisent-compile-grammar 'byte-compile 'wisent-byte-compile-grammar) | 3487 | (put 'wisent-compile-grammar 'byte-compile 'wisent-byte-compile-grammar) |
| 3482 | 3488 | ||
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 8892a27b29c..771306bb0e6 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -3339,6 +3339,24 @@ discarding." | |||
| 3339 | "Output byte codes to store the top-of-stack value at position STACK-POS in the stack." | 3339 | "Output byte codes to store the top-of-stack value at position STACK-POS in the stack." |
| 3340 | (byte-compile-out 'byte-stack-set (- byte-compile-depth (1+ stack-pos)))) | 3340 | (byte-compile-out 'byte-stack-set (- byte-compile-depth (1+ stack-pos)))) |
| 3341 | 3341 | ||
| 3342 | (byte-defop-compiler-1 internal-make-closure byte-compile-make-closure) | ||
| 3343 | (byte-defop-compiler-1 internal-get-closed-var byte-compile-get-closed-var) | ||
| 3344 | |||
| 3345 | (defconst byte-compile--env-var (make-symbol "env")) | ||
| 3346 | |||
| 3347 | (defun byte-compile-make-closure (form) | ||
| 3348 | ;; FIXME: don't use `curry'! | ||
| 3349 | (byte-compile-form | ||
| 3350 | (unless for-effect | ||
| 3351 | `(curry (function (lambda (,byte-compile--env-var . ,(nth 1 form)) | ||
| 3352 | . ,(nthcdr 3 form))) | ||
| 3353 | (vector . ,(nth 2 form)))) | ||
| 3354 | for-effect)) | ||
| 3355 | |||
| 3356 | (defun byte-compile-get-closed-var (form) | ||
| 3357 | (byte-compile-form (unless for-effect | ||
| 3358 | `(aref ,byte-compile--env-var ,(nth 1 form))) | ||
| 3359 | for-effect)) | ||
| 3342 | 3360 | ||
| 3343 | ;; Compile a function that accepts one or more args and is right-associative. | 3361 | ;; Compile a function that accepts one or more args and is right-associative. |
| 3344 | ;; We do it by left-associativity so that the operations | 3362 | ;; We do it by left-associativity so that the operations |
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index 66e5051c2f1..6aa4b7e0a61 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el | |||
| @@ -71,6 +71,8 @@ | |||
| 71 | ;;; Code: | 71 | ;;; Code: |
| 72 | 72 | ||
| 73 | ;;; TODO: | 73 | ;;; TODO: |
| 74 | ;; - canonize code in macro-expand so we don't have to handle (let (var) body) | ||
| 75 | ;; and other oddities. | ||
| 74 | ;; - Change new byte-code representation, so it directly gives the | 76 | ;; - Change new byte-code representation, so it directly gives the |
| 75 | ;; number of mandatory and optional arguments as well as whether or | 77 | ;; number of mandatory and optional arguments as well as whether or |
| 76 | ;; not there's a &rest arg. | 78 | ;; not there's a &rest arg. |
| @@ -229,7 +231,6 @@ Returns a form where all lambdas don't have any free variables." | |||
| 229 | res)) | 231 | res)) |
| 230 | 232 | ||
| 231 | (defconst cconv--dummy-var (make-symbol "ignored")) | 233 | (defconst cconv--dummy-var (make-symbol "ignored")) |
| 232 | (defconst cconv--env-var (make-symbol "env")) | ||
| 233 | 234 | ||
| 234 | (defun cconv--set-diff (s1 s2) | 235 | (defun cconv--set-diff (s1 s2) |
| 235 | "Return elements of set S1 that are not in set S2." | 236 | "Return elements of set S1 that are not in set S2." |
| @@ -494,32 +495,18 @@ Returns a form where all lambdas don't have any free variables." | |||
| 494 | (envector nil)) | 495 | (envector nil)) |
| 495 | (when fv | 496 | (when fv |
| 496 | ;; Here we form our environment vector. | 497 | ;; Here we form our environment vector. |
| 497 | ;; If outer closure contains all | 498 | |
| 498 | ;; free variables of this function(and nothing else) | 499 | (dolist (elm fv) |
| 499 | ;; then we use the same environment vector as for outer closure, | 500 | (push |
| 500 | ;; i.e. we leave the environment vector unchanged, | 501 | (cconv-closure-convert-rec |
| 501 | ;; otherwise we build a new environment vector. | 502 | ;; Remove `elm' from `emvrs' for this call because in case |
| 502 | (if (eq (length envs) (length fv)) | 503 | ;; `elm' is a variable that's wrapped in a cons-cell, we |
| 503 | (let ((fv-temp fv)) | 504 | ;; want to put the cons-cell itself in the closure, rather |
| 504 | (while (and fv-temp leave) | 505 | ;; than just a copy of its current content. |
| 505 | (when (not (memq (car fv-temp) fvrs-new)) (setq leave nil)) | 506 | elm (remq elm emvrs) fvrs envs lmenvs) |
| 506 | (setq fv-temp (cdr fv-temp)))) | 507 | envector)) ; Process vars for closure vector. |
| 507 | (setq leave nil)) | 508 | (setq envector (reverse envector)) |
| 508 | 509 | (setq envs fv) | |
| 509 | (if (not leave) | ||
| 510 | (progn | ||
| 511 | (dolist (elm fv) | ||
| 512 | (push | ||
| 513 | (cconv-closure-convert-rec | ||
| 514 | ;; Remove `elm' from `emvrs' for this call because in case | ||
| 515 | ;; `elm' is a variable that's wrapped in a cons-cell, we | ||
| 516 | ;; want to put the cons-cell itself in the closure, rather | ||
| 517 | ;; than just a copy of its current content. | ||
| 518 | elm (remq elm emvrs) fvrs envs lmenvs) | ||
| 519 | envector)) ; Process vars for closure vector. | ||
| 520 | (setq envector (reverse envector)) | ||
| 521 | (setq envs fv)) | ||
| 522 | (setq envector `(,cconv--env-var))) ; Leave unchanged. | ||
| 523 | (setq fvrs-new fv)) ; Update substitution list. | 510 | (setq fvrs-new fv)) ; Update substitution list. |
| 524 | 511 | ||
| 525 | (setq emvrs (cconv--set-diff emvrs vars)) | 512 | (setq emvrs (cconv--set-diff emvrs vars)) |
| @@ -546,15 +533,9 @@ Returns a form where all lambdas don't have any free variables." | |||
| 546 | ((null envector) | 533 | ((null envector) |
| 547 | `(function (lambda ,vars . ,body-forms-new))) | 534 | `(function (lambda ,vars . ,body-forms-new))) |
| 548 | ; 1 free variable - do not build vector | 535 | ; 1 free variable - do not build vector |
| 549 | ((null (cdr envector)) | ||
| 550 | `(curry | ||
| 551 | (function (lambda (,cconv--env-var . ,vars) . ,body-forms-new)) | ||
| 552 | ,(car envector))) | ||
| 553 | ; >=2 free variables - build vector | ||
| 554 | (t | 536 | (t |
| 555 | `(curry | 537 | `(internal-make-closure |
| 556 | (function (lambda (,cconv--env-var . ,vars) . ,body-forms-new)) | 538 | ,vars ,envector . ,body-forms-new))))) |
| 557 | (vector . ,envector)))))) | ||
| 558 | 539 | ||
| 559 | (`(function . ,_) form) ; Same as quote. | 540 | (`(function . ,_) form) ; Same as quote. |
| 560 | 541 | ||
| @@ -714,10 +695,8 @@ Returns a form where all lambdas don't have any free variables." | |||
| 714 | (let ((free (memq form fvrs))) | 695 | (let ((free (memq form fvrs))) |
| 715 | (if free ;form is a free variable | 696 | (if free ;form is a free variable |
| 716 | (let* ((numero (- (length fvrs) (length free))) | 697 | (let* ((numero (- (length fvrs) (length free))) |
| 717 | (var (if (null (cdr envs)) | 698 | ;; Replace form => (aref env #) |
| 718 | cconv--env-var | 699 | (var `(internal-get-closed-var ,numero))) |
| 719 | ;; Replace form => (aref env #) | ||
| 720 | `(aref ,cconv--env-var ,numero)))) | ||
| 721 | (if (memq form emvrs) ; form => (car (aref env #)) if mutable | 700 | (if (memq form emvrs) ; form => (car (aref env #)) if mutable |
| 722 | `(car ,var) | 701 | `(car ,var) |
| 723 | var)) | 702 | var)) |