Sophie

Sophie

distrib > Fedora > 14 > x86_64 > by-pkgid > e3d62627d1d1aab7ab1be2dd7f65a872 > files > 313

ecl-10.4.1-1.fc14.x86_64.rpm

<html><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968"><title>4.3.&#160;Implementation of Compiled Closures</title><link rel="stylesheet" href="ecl.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"><link rel="home" href="index.html" title="The ECL manual"><link rel="up" href="ch27.html" title="Chapter&#160;4.&#160;The compiler"><link rel="prev" href="ch27s02.html" title="4.2.&#160;The compiler mimics human C programmer"><link rel="next" href="ch27s04.html" title="4.4.&#160;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.&#160;Implementation of Compiled Closures</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch27s02.html">Prev</a>&#160;</td><th width="60%" align="center">Chapter&#160;4.&#160;The compiler</th><td width="20%" align="right">&#160;<a accesskey="n" href="ch27s04.html">Next</a></td></tr></table><hr></div><div class="section" title="4.3.&#160;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.&#160;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 &#8220;environment list&#8221;, 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">
   &gt;(multiple-value-setq (f g) (foo 10))
   #&lt;compiled-closure nil&gt;

   &gt;(funcall f)
   11

   &gt;(funcall g)
   21

   &gt;
  </pre><p>After this, the two compiled closures look like:</p><pre class="screen">
  second closure       y:                     x:
  |-------|------|      |-------|------|       |------|------| 
  |  **   |    --|-----&gt;|  10   |    --|------&gt;|  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>&#160;</td><td width="20%" align="center"><a accesskey="u" href="ch27.html">Up</a></td><td width="40%" align="right">&#160;<a accesskey="n" href="ch27s04.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4.2.&#160;The compiler mimics human C programmer&#160;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&#160;4.4.&#160;Use of Declarations to Improve Efficiency</td></tr></table></div></body></html>