<html><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968"><title>4.3. Implementation of Compiled Closures</title><link rel="stylesheet" type="text/css" href="ecl.css"><meta name="generator" content="DocBook XSL Stylesheets V1.76.1"><link rel="home" href="index.html" title="The ECL manual"><link rel="up" href="ch27.html" title="Chapter 4. The compiler"><link rel="prev" href="ch27s02.html" title="4.2. The compiler mimics human C programmer"><link rel="next" href="ch27s04.html" title="4.4. Use of Declarations to Improve Efficiency"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4.3. Implementation of Compiled Closures</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch27s02.html">Prev</a> </td><th width="60%" align="center">Chapter 4. The compiler</th><td width="20%" align="right"> <a accesskey="n" href="ch27s04.html">Next</a></td></tr></table><hr></div><div class="section" title="4.3. Implementation of Compiled Closures"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="Internals-Implementation-of-Compiled-Closures"></a>4.3. Implementation of Compiled Closures</h2></div></div></div><p>The <span class="application">ECL</span> compiler takes two passes before it invokes the C compiler. The major role of the first pass is to detect function closures and to detect, for each function closure, those lexical objects (i.e., lexical variable, local function definitions, tags, and block-names) to be enclosed within the closure. This check must be done before the C code generation in the second pass, because lexical objects to be enclosed in function closures are treated in a different way from those not enclosed.</p><p>Ordinarily, lexical variables in a compiled function <span class="emphasis"><em>f</em></span> are allocated on the C stack. However, if a lexical variable is to be enclosed in function closures, it is allocated on a list, called the “environment list”, which is local to <span class="emphasis"><em>f</em></span>. In addition, a local variable is created which points to the lexical variable's location (within the environment list), so that the variable may be accessed through an indirection rather than by list traversal.</p><p>The environment list is a pushdown list: It is empty when <span class="emphasis"><em>f</em></span> is called. An element is pushed on the environment list when a variable to be enclosed in closures is bound, and is popped when the binding is no more in effect. That is, at any moment during execution of <span class="emphasis"><em>f</em></span>, the environment list contains those lexical variables whose binding is still in effect and which should be enclosed in closures. When a compiled closure is created during execution of <span class="emphasis"><em>f</em></span>, the compiled code for the closure is coupled with the environment list at that moment to form the compiled closure.</p><p>Later, when the compiled closure is invoked, a pointer is set up to each lexical variable in the environment list, so that each object may be referenced through a memory indirection.</p><p>Let us see an example. Suppose the following function has been compiled.</p><pre class="programlisting"> (defun foo (x) (let ((a #'(lambda () (incf x))) (y x)) (values a #'(lambda () (incf x y))))) </pre><p><code class="literal">foo</code> returns two compiled closures. The first closure increments <em class="replaceable"><code>x</code></em> by one, whereas the second closure increments <em class="replaceable"><code>x</code></em> by the initial value of <em class="replaceable"><code>x</code></em>. Both closures return the incremented value of <em class="replaceable"><code>x</code></em>.</p><pre class="screen"> >(multiple-value-setq (f g) (foo 10)) #<compiled-closure nil> >(funcall f) 11 >(funcall g) 21 > </pre><p>After this, the two compiled closures look like:</p><pre class="screen"> second closure y: x: |-------|------| |-------|------| |------|------| | ** | --|----->| 10 | --|------>| 21 | nil | |-------|------| |-------|------| |------|------| ^ first closure | |-------|------| | | * | --|----------| |-------|------| * : address of the compiled code for #'(lambda () (incf x)) ** : address of the compiled code for #'(lambda () (incf x y)) </pre></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch27s02.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ch27.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch27s04.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4.2. The compiler mimics human C programmer </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 4.4. Use of Declarations to Improve Efficiency</td></tr></table></div></body></html>