File: cconv.el.html
This takes a piece of Elisp code, and eliminates all free variables from
lambda expressions. The user entry point is cconv-closure-convert.
All macros should be expanded beforehand.
Here is a brief explanation how this code works.
Firstly, we analyze the tree by calling cconv-analyze-form.
This function finds all mutated variables, all functions that are suitable
for lambda lifting and all variables captured by closure. It passes the tree
once, returning a list of three lists.
Then we calculate the intersection of the first and third lists returned by
cconv-analyze-form to find all mutated variables that are captured by
closure.
Armed with this data, we call cconv-convert, that rewrites the
tree recursively, lifting lambdas where possible, building closures where it
is needed and eliminating mutable variables used in closure.
We do following replacements :
(lambda (v1 ...) ... fv1 fv2 ...) => (lambda (v1 ... fv1 fv2 ) ... fv1 fv2 .)
if the function is suitable for lambda lifting (if all calls are known)
(lambda (v0 ...) ... fv0 .. fv1 ...) =>
(internal-make-closure (v0 ...) (fv0 ...) <doc>
... (internal-get-closed-var 0) ... (internal-get-closed-var 1) ...)
If the function has no free variables, we don't do anything.
If a variable is mutated (updated by setq), and it is used in a closure
we wrap its definition with list: (list val) and we also replace
var => (car-safe var) wherever this variable is used, and also
(setq var value) => (setcar var value) where it is updated.
If defun argument is closure mutable, we letbind it and wrap it's
definition with list.
(defun foo (... mutable-arg ...) ...) =>
(defun foo (... m-arg ...) (let ((m-arg (list m-arg))) ...))
Defined variables (2)
cconv--dynbound-variables | List of variables known to be dynamically bound. |
cconv-liftwhen | Try to do lambda lifting if the number of arguments + free variables |
Defined functions (21)
cconv--analyze-function | (ARGS BODY ENV PARENTFORM) |
cconv--analyze-use | (VARDATA FORM VARKIND) |
cconv--convert-funcbody | (FUNARGS FUNCBODY ENV PARENTFORM) |
cconv--convert-function | (ARGS BODY ENV PARENTFORM &optional DOCSTRING) |
cconv--lifted-arg | (VAR ENV) |
cconv--map-diff | (M1 M2) |
cconv--map-diff-elem | (M X) |
cconv--map-diff-set | (M S) |
cconv--not-lexical-var-p | (VAR DYNBOUNDS) |
cconv--remap-llv | (NEW-ENV VAR CLOSEDSYM) |
cconv--set-diff | (S1 S2) |
cconv--set-diff-map | (S M) |
cconv--var-classification | (BINDER FORM) |
cconv--var-classification--inliner | (INLINE--FORM BINDER FORM) |
cconv--warn-unused-msg | (VAR VARKIND) |
cconv-analyse-form | (FORM ENV) |
cconv-analyze-form | (FORM ENV) |
cconv-closure-convert | (FORM &optional DYNBOUND-VARS) |
cconv-convert | (FORM ENV EXTEND) |
cconv-fv | (FORM LEXVARS DYNVARS) |
cconv-make-interpreted-closure | (FUN ENV) |