aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/emacs-lisp/oclosure.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/oclosure.el')
-rw-r--r--lisp/emacs-lisp/oclosure.el96
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.
434This has 2 uses: 434This is used as a marker which cconv uses to check that
435- For interpreted code, this converts the representation of type information 435immutable 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: