diff options
Diffstat (limited to 'lisp/emacs-lisp/oclosure.el')
| -rw-r--r-- | lisp/emacs-lisp/oclosure.el | 96 |
1 files changed, 39 insertions, 57 deletions
diff --git a/lisp/emacs-lisp/oclosure.el b/lisp/emacs-lisp/oclosure.el index 4da8e61aaa7..165d7c4b6e8 100644 --- a/lisp/emacs-lisp/oclosure.el +++ b/lisp/emacs-lisp/oclosure.el | |||
| @@ -146,7 +146,7 @@ | |||
| 146 | (setf (cl--find-class 'oclosure) | 146 | (setf (cl--find-class 'oclosure) |
| 147 | (oclosure--class-make 'oclosure | 147 | (oclosure--class-make 'oclosure |
| 148 | "The root parent of all OClosure types" | 148 | "The root parent of all OClosure types" |
| 149 | nil (list (cl--find-class 'function)) | 149 | nil (list (cl--find-class 'closure)) |
| 150 | '(oclosure))) | 150 | '(oclosure))) |
| 151 | (defun oclosure--p (oclosure) | 151 | (defun oclosure--p (oclosure) |
| 152 | (not (not (oclosure-type oclosure)))) | 152 | (not (not (oclosure-type oclosure)))) |
| @@ -431,75 +431,57 @@ ARGS and BODY are the same as for `lambda'." | |||
| 431 | 431 | ||
| 432 | (defun oclosure--fix-type (_ignore oclosure) | 432 | (defun oclosure--fix-type (_ignore oclosure) |
| 433 | "Helper function to implement `oclosure-lambda' via a macro. | 433 | "Helper function to implement `oclosure-lambda' via a macro. |
| 434 | This has 2 uses: | 434 | This is used as a marker which cconv uses to check that |
| 435 | - For interpreted code, this converts the representation of type information | 435 | immutable fields are indeed not mutated." |
| 436 | by moving it from the docstring to the environment. | 436 | (cl-assert (closurep oclosure)) |
| 437 | - For compiled code, this is used as a marker which cconv uses to check that | 437 | ;; This should happen only for interpreted closures since `cconv.el' |
| 438 | immutable fields are indeed not mutated." | 438 | ;; should have optimized away the call to this function. |
| 439 | (if (byte-code-function-p oclosure) | 439 | oclosure) |
| 440 | ;; Actually, this should never happen since `cconv.el' should have | ||
| 441 | ;; optimized away the call to this function. | ||
| 442 | oclosure | ||
| 443 | ;; For byte-coded functions, we store the type as a symbol in the docstring | ||
| 444 | ;; slot. For interpreted functions, there's no specific docstring slot | ||
| 445 | ;; so `Ffunction' turns the symbol into a string. | ||
| 446 | ;; We thus have convert it back into a symbol (via `intern') and then | ||
| 447 | ;; stuff it into the environment part of the closure with a special | ||
| 448 | ;; marker so we can distinguish this entry from actual variables. | ||
| 449 | (cl-assert (eq 'closure (car-safe oclosure))) | ||
| 450 | (let ((typename (nth 3 oclosure))) ;; The "docstring". | ||
| 451 | (cl-assert (stringp typename)) | ||
| 452 | (push (cons :type (intern typename)) | ||
| 453 | (cadr oclosure)) | ||
| 454 | oclosure))) | ||
| 455 | 440 | ||
| 456 | (defun oclosure--copy (oclosure mutlist &rest args) | 441 | (defun oclosure--copy (oclosure mutlist &rest args) |
| 442 | (cl-assert (closurep oclosure)) | ||
| 457 | (if (byte-code-function-p oclosure) | 443 | (if (byte-code-function-p oclosure) |
| 458 | (apply #'make-closure oclosure | 444 | (apply #'make-closure oclosure |
| 459 | (if (null mutlist) | 445 | (if (null mutlist) |
| 460 | args | 446 | args |
| 461 | (mapcar (lambda (arg) (if (pop mutlist) (list arg) arg)) args))) | 447 | (mapcar (lambda (arg) (if (pop mutlist) (list arg) arg)) args))) |
| 462 | (cl-assert (eq 'closure (car-safe oclosure)) | 448 | (cl-assert (consp (aref oclosure 1))) |
| 463 | nil "oclosure not closure: %S" oclosure) | 449 | (cl-assert (null (aref oclosure 3))) |
| 464 | (cl-assert (eq :type (caar (cadr oclosure)))) | 450 | (cl-assert (symbolp (aref oclosure 4))) |
| 465 | (let ((env (cadr oclosure))) | 451 | (let ((env (aref oclosure 2))) |
| 466 | `(closure | 452 | (make-interpreted-closure |
| 467 | (,(car env) | 453 | (aref oclosure 0) |
| 468 | ,@(named-let loop ((env (cdr env)) (args args)) | 454 | (aref oclosure 1) |
| 469 | (when args | 455 | (named-let loop ((env env) (args args)) |
| 470 | (cons (cons (caar env) (car args)) | 456 | (if (null args) env |
| 471 | (loop (cdr env) (cdr args))))) | 457 | (cons (cons (caar env) (car args)) |
| 472 | ,@(nthcdr (1+ (length args)) env)) | 458 | (loop (cdr env) (cdr args))))) |
| 473 | ,@(nthcdr 2 oclosure))))) | 459 | (aref oclosure 4) |
| 460 | (if (> (length oclosure) 5) | ||
| 461 | `(interactive ,(aref oclosure 5))))))) | ||
| 474 | 462 | ||
| 475 | (defun oclosure--get (oclosure index mutable) | 463 | (defun oclosure--get (oclosure index mutable) |
| 476 | (if (byte-code-function-p oclosure) | 464 | (cl-assert (closurep oclosure)) |
| 477 | (let* ((csts (aref oclosure 2)) | 465 | (let* ((csts (aref oclosure 2))) |
| 478 | (v (aref csts index))) | 466 | (if (vectorp csts) |
| 479 | (if mutable (car v) v)) | 467 | (let ((v (aref csts index))) |
| 480 | (cl-assert (eq 'closure (car-safe oclosure))) | 468 | (if mutable (car v) v)) |
| 481 | (cl-assert (eq :type (caar (cadr oclosure)))) | 469 | (cdr (nth index csts))))) |
| 482 | (cdr (nth (1+ index) (cadr oclosure))))) | ||
| 483 | 470 | ||
| 484 | (defun oclosure--set (v oclosure index) | 471 | (defun oclosure--set (v oclosure index) |
| 485 | (if (byte-code-function-p oclosure) | 472 | (cl-assert (closurep oclosure)) |
| 486 | (let* ((csts (aref oclosure 2)) | 473 | (let ((csts (aref oclosure 2))) |
| 487 | (cell (aref csts index))) | 474 | (if (vectorp csts) |
| 488 | (setcar cell v)) | 475 | (let ((cell (aref csts index))) |
| 489 | (cl-assert (eq 'closure (car-safe oclosure))) | 476 | (setcar cell v)) |
| 490 | (cl-assert (eq :type (caar (cadr oclosure)))) | 477 | (setcdr (nth index csts) v)))) |
| 491 | (setcdr (nth (1+ index) (cadr oclosure)) v))) | ||
| 492 | 478 | ||
| 493 | (defun oclosure-type (oclosure) | 479 | (defun oclosure-type (oclosure) |
| 494 | "Return the type of OCLOSURE, or nil if the arg is not a OClosure." | 480 | "Return the type of OCLOSURE, or nil if the arg is not an OClosure." |
| 495 | (if (byte-code-function-p oclosure) | 481 | (and (closurep oclosure) |
| 496 | (let ((type (and (> (length oclosure) 4) (aref oclosure 4)))) | 482 | (> (length oclosure) 4) |
| 497 | (if (symbolp type) type)) | 483 | (let ((type (aref oclosure 4))) |
| 498 | (and (eq 'closure (car-safe oclosure)) | 484 | (if (symbolp type) type)))) |
| 499 | (let* ((env (car-safe (cdr oclosure))) | ||
| 500 | (first-var (car-safe env))) | ||
| 501 | (and (eq :type (car-safe first-var)) | ||
| 502 | (cdr first-var)))))) | ||
| 503 | 485 | ||
| 504 | (defconst oclosure--accessor-prototype | 486 | (defconst oclosure--accessor-prototype |
| 505 | ;; Use `oclosure--lambda' to circumvent a bootstrapping problem: | 487 | ;; Use `oclosure--lambda' to circumvent a bootstrapping problem: |