Function: oclosure--lambda
oclosure--lambda is a macro defined in oclosure.el.gz.
Signature
(oclosure--lambda TYPE BINDINGS MUTABLES ARGS &rest BODY)
Documentation
Low level construction of an OClosure object.
TYPE should be a form returning an OClosure type (a symbol). BINDINGS should list all the slots expected by this type, in the proper order. MUTABLE is a list of symbols indicating which of the BINDINGS should be mutable. No checking is performed.
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/oclosure.el.gz
(defmacro oclosure--lambda (type bindings mutables args &rest body)
"Low level construction of an OClosure object.
TYPE should be a form returning an OClosure type (a symbol).
BINDINGS should list all the slots expected by this type, in the proper order.
MUTABLE is a list of symbols indicating which of the BINDINGS
should be mutable.
No checking is performed."
(declare (indent 3) (debug (sexp (&rest (sexp form)) sexp def-body)))
(cl-assert lexical-binding) ;Can't work in dynbind dialect.
;; FIXME: Fundamentally `oclosure-lambda' should be a special form.
;; We define it here as a macro which expands to something that
;; looks like "normal code" in order to avoid backward compatibility
;; issues with third party macros that do "code walks" and would
;; likely mishandle such a new special form (e.g. `generator.el').
;; But don't be fooled: this macro is tightly bound to `cconv.el'.
(pcase-let*
((`(,prebody . ,body) (macroexp-parse-body body))
(rovars (mapcar #'car bindings)))
(dolist (mutable mutables)
(setq rovars (delq mutable rovars)))
`(let ,(mapcar (lambda (bind)
(if (cdr bind) bind
;; Bind to something that doesn't look
;; like a value to avoid the "Variable
;; ‘foo’ left uninitialized" warning.
`(,(car bind) (progn nil))))
(reverse bindings))
;; FIXME: Make sure the slotbinds whose value is duplicable aren't
;; just value/variable-propagated by the optimizer (tho I think our
;; optimizer is too naive to be a problem currently).
(oclosure--fix-type
;; This `oclosure--fix-type' + `ignore' call is used by the compiler (in
;; `cconv.el') to detect and signal an error in case of
;; store-conversion (i.e. if a variable/slot is mutated).
(ignore ,@rovars)
(lambda ,args
(:documentation ,type)
,@prebody
;; Add dummy code which accesses the field's vars to make sure
;; they're captured in the closure.
(if t nil ,@rovars ,@(mapcar (lambda (m) `(setq ,m ,m)) mutables))
,@body)))))