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-variablesList of variables known to be dynamically bound.
cconv-liftwhenTry 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)

Defined faces (0)