1
0
Fork 0
cl-sites/ecl.common-lisp.dev/static/manual/The-interpreter.html

383 lines
16 KiB
HTML
Raw Normal View History

2024-12-24 19:15:49 +01:00
<!DOCTYPE html>
<html>
<!-- Created by GNU Texinfo 7.0.3, https://www.gnu.org/software/texinfo/ -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>The interpreter (ECL Manual)</title>
<meta name="description" content="The interpreter (ECL Manual)">
<meta name="keywords" content="The interpreter (ECL Manual)">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content="makeinfo">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="index.html" rel="start" title="Top">
<link href="Indexes.html" rel="index" title="Indexes">
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
<link href="Developer_0027s-guide.html" rel="up" title="Developer's guide">
<link href="The-compiler.html" rel="next" title="The compiler">
<link href="Environment-implementation.html" rel="prev" title="Environment implementation">
<style type="text/css">
<!--
/* colors */
div.example {margin-left: 3.2em}
span.r {font-family: initial; font-weight: normal; font-style: normal}
@media (prefers-color-scheme: dark) {
/* dark theme */
html { color: seashell;
background: #1A1A1A; }
body { background: #1A1A1A; }
th { border-bottom: 2px solid lightgray; }
h1, h2, h3, h4, h5 { background-image: linear-gradient(to left, #202020, #3A3A3A); }
code, var, code a { color: darkorange;
background: #2A2A2A; }
a { color: seashell; }
pre { background: #2A2A2A;
color: seashell;
/* mark longer code block with stripe on the left */
border-left: 5px solid darkorange;
padding-left: 10px; }
pre.screen { background: #2A2A2A;
border: 1px solid lightgray; }
pre.programlisting { background: #2A2A2A;
border-left: 1px solid lightgray;
border-top: 1px solid lightgray; }
/* we need a light background in order for the images to be readable */
img { background: white }
}
@media (prefers-color-scheme: light) {
/* light theme */
html { background: white }
body { background: white }
th { border-bottom: 2px solid gray; }
h1, h2, h3, h4, h5 { background: lightgray; }
code, var, code a { color: darkred;
background: whitesmoke; }
a { color: #000; }
pre { background: whitesmoke;
color: black;
/* mark longer code block with stripe on the left */
border-left: 5px solid darkred;
padding-left: 10px; }
pre.screen { background: #EEE;
border: 1px solid black; }
pre.programlisting { background: #EEEEEE;
border-left: 1px solid black;
border-top: 1px solid black; }
}
body {
margin: 1em 125px 0 10%;
line-height: 1.5em;
padding: 0 2em 1em 2em;
font: 13px Verdana,Arial, sans-serif
}
ul, dd, dl, dt { margin-top: 0; margin-bottom: 0; }
p, code, td, dl, dt {
line-height: 1.5em;
}
table {
font: inherit;
border-collapse: collapse;
}
th, td {
vertical-align: top;
}
h1, h2, h3 { padding-left: 15px; }
h4, h5 { padding-left: 5px; }
code, pre {
font-size: 1em;
font-family: monospace;
}
var {
font-size: 1em;
}
/* links inside code appear the same as the code itself */
code a {
font-weight: normal;
text-decoration: none;
}
/* but get an underline when hovering */
code a:hover {
text-decoration: underline;
}
/* ordinary links appear in bold */
a { font-weight: bold; }
pre.verbatim {
margin: 0 0 0 0;
}
pre {
overflow: auto;
}
pre.screen {
font-weight: bold;
padding: 0.5em;
}
pre.programlisting {
padding: 0.5em;
}
div p { padding: 0 2em }
li p { padding: 0; margin: 0 }
hr { display: none; }
div.funcsynopsis p {
text-indent: -2em;
}
div.variablelist {
padding: 0 2em;
}
.type, .funcsynopsis, .symbol {
font-family: monospace;
}
.type, .symbol, .replaceable {
white-space: nowrap;
}
-->
</style>
</head>
<body lang="en">
<div class="section-level-extent" id="The-interpreter">
<div class="nav-panel">
<p>
Next: <a href="The-compiler.html" accesskey="n" rel="next">The compiler</a>, Previous: <a href="Environment-implementation.html" accesskey="p" rel="prev">Environment implementation</a>, Up: <a href="Developer_0027s-guide.html" accesskey="u" rel="up">Developer&rsquo;s guide</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
</div>
<h3 class="section" id="The-interpreter-1">4.6 The interpreter</h3>
<ul class="mini-toc">
<li><a href="The-interpreter.html#ECL-stacks" accesskey="1">ECL stacks</a></li>
<li><a href="The-interpreter.html#Procedure-Call-Conventions" accesskey="2">Procedure Call Conventions</a></li>
<li><a href="The-interpreter.html#The-lexical-environment" accesskey="3">The lexical environment</a></li>
<li><a href="The-interpreter.html#The-interpreter-stack" accesskey="4">The interpreter stack</a></li>
</ul>
<hr>
<div class="subsection-level-extent" id="ECL-stacks">
<div class="nav-panel">
<p>
Next: <a href="The-interpreter.html#Procedure-Call-Conventions" accesskey="n" rel="next">Procedure Call Conventions</a>, Up: <a href="The-interpreter.html#The-interpreter" accesskey="u" rel="up">The interpreter</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
</div>
<h4 class="subsection" id="ECL-stacks-1">4.6.1 ECL stacks</h4>
<p>ECL uses the following stacks:
</p><table class="multitable">
<tbody><tr><td width="30%">Frame Stack</td><td width="70%">consisting of catch, block, tagbody frames</td></tr>
<tr><td width="30%">Bind Stack</td><td width="70%">for shallow binding of dynamic variables</td></tr>
<tr><td width="30%">Interpreter Stack</td><td width="70%">acts as a Forth data stack, keeping intermediate arguments to interpreted functions, plus a history of called functions.</td></tr>
<tr><td width="30%">C Control Stack</td><td width="70%">used for arguments/values passing, typed lexical variables, temporary values, and function invocation.</td></tr>
</tbody>
</table>
<hr>
</div>
<div class="subsection-level-extent" id="Procedure-Call-Conventions">
<div class="nav-panel">
<p>
Next: <a href="The-interpreter.html#The-lexical-environment" accesskey="n" rel="next">The lexical environment</a>, Previous: <a href="The-interpreter.html#ECL-stacks" accesskey="p" rel="prev">ECL stacks</a>, Up: <a href="The-interpreter.html#The-interpreter" accesskey="u" rel="up">The interpreter</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
</div>
<h4 class="subsection" id="Procedure-Call-Conventions-1">4.6.2 Procedure Call Conventions</h4>
<p>ECL employs standard C calling conventions to achieve efficiency and
interoperability with other languages. Each Lisp function is
implemented as a C function which takes as many arguments as the Lisp
original. If the function takes optional or keyword arguments, the
corresponding C function takes one additional integer argument which
holds the number of actual arguments. The function sets <code class="code">nvalues</code>
in the thread local environment to the number of Lisp values produced,
it returns the first one and the remaining ones are kept in a global
(per thread) array (<code class="code">values</code>).
</p>
<p>To show the argument/value passing mechanism, here we list the actual
code for the Common-Lisp function last.
</p>
<div class="example">
<pre class="verbatim">cl_object
cl_last(cl_narg narg, cl_object l, ...)
{
const cl_env_ptr the_env = ecl_process_env();
cl_object k;
va_list ARGS;
va_start(ARGS, l);
if (ecl_unlikely(narg &lt; 1|| narg &gt; 2)) FEwrong_num_arguments(/* ... */);
if (narg &gt; 1) {
k = va_arg(ARGS,cl_object);
} else {
k = ecl_make_fixnum(1);
}
cl_object __value0 = ecl_last(l, ecl_to_size(k));
the_env-&gt;nvalues = 1;
the_env-&gt;values[0] = __value0;
va_end(ARGS);
return __value0;
}
</pre></div>
<p>ECL adopts the convention that the name of a function that implements
a Common-Lisp function begins with a short package name (<code class="code">cl</code> for
<code class="code">COMMON-LISP</code>, <code class="code">si</code> for <code class="code">SYSTEM</code>, etc), followed by
<code class="code">L</code>, and followed by the name of the Common-Lisp
function. (Strictly speaking, &lsquo;<code class="code">-</code>&rsquo; and &lsquo;<code class="code">*</code>&rsquo; in the
Common-Lisp function name are replaced by &lsquo;<code class="code">_</code>&rsquo; and &lsquo;<code class="code">A</code>&rsquo;,
respectively, to obey the syntax of C.)
</p>
<p>The code for the function <code class="code">last</code> first checks that the right
number of arguments are supplied to <code class="code">cl_last</code>. That is, it checks
that <code class="code">narg</code> is 1 or 2, and otherwise, it causes an error.
Following that, the optional variable <code class="code">k</code> is initialized and the
return value <code class="code">__value0</code> is computed. The number assigned to
<code class="code">nvalues</code> set by the function (1 in this case) represents the
number of values of the function. The return value of the function is
copied in the <code class="code">values</code> array as well as returned directly.
</p>
<p>In general, if one is to play with the C kernel of ECL there is no
need to know about all these conventions. There is a preprocessor
(see <a class="pxref" href="Defun-preprocessor.html">Defun preprocessor</a>) that takes care of the details, by using a
lisp representation of the statements that output values, and of the
function definitions. For instance, the actual source code for
<code class="code">cl_last</code> in <samp class="file">src/c/list.d</samp> is
</p>
<div class="example">
<pre class="verbatim">@(defun last (l &amp;optional (k ecl_make_fixnum(1)))
@
@(return ecl_last(l, ecl_to_size(k)));
@)
</pre></div>
<hr>
</div>
<div class="subsection-level-extent" id="The-lexical-environment">
<div class="nav-panel">
<p>
Next: <a href="The-interpreter.html#The-interpreter-stack" accesskey="n" rel="next">The interpreter stack</a>, Previous: <a href="The-interpreter.html#Procedure-Call-Conventions" accesskey="p" rel="prev">Procedure Call Conventions</a>, Up: <a href="The-interpreter.html#The-interpreter" accesskey="u" rel="up">The interpreter</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
</div>
<h4 class="subsection" id="The-lexical-environment-1">4.6.3 The lexical environment</h4>
<p>The ECL interpreter uses a list containing local functions and macros,
variables, tags and blocks to represent the lexical environment. When
a function closure is created, the current lexical environment is
saved in the closure along with the lambda expression. Later, when the
closure is invoked, this list is used to recover the lexical
environment.
</p>
<p>Note that this list is different from what the Common Lisp standard
calls a lexical environment, which is the content of a
<code class="code">&amp;environment</code> parameter to <code class="code">defmacro</code>. For the differences
between this two environments see the comments in
<samp class="file">src/c/compiler.d</samp> and <samp class="file">src/c/interpreter.d</samp>.
</p>
<hr>
</div>
<div class="subsection-level-extent" id="The-interpreter-stack">
<div class="nav-panel">
<p>
Previous: <a href="The-interpreter.html#The-lexical-environment" accesskey="p" rel="prev">The lexical environment</a>, Up: <a href="The-interpreter.html#The-interpreter" accesskey="u" rel="up">The interpreter</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
</div>
<h4 class="subsection" id="The-interpreter-stack-1">4.6.4 The interpreter stack</h4>
<p>The bytecodes interpreter uses a stack of its own to save and restore
values from intermediate calculations. This Forth-like data stack is
also used in other parts of the C kernel for various purposes, such as
saving compiled code, keeping arguments to <code class="code">format</code>, etc.
</p>
<p>However, one of the most important roles of the Interpreter Stack is
to keep a log of the functions which are called during the execution
of bytecodes. For each function invoked, the interpreter keeps three
lisp objects on the stack:
</p>
<pre class="verbatim"> +----------+------------------------------------------------+
| function | lexical environment | index to previous record |
+----------+---------------------+--------------------------+
</pre>
<p>The first item is the object which is funcalled. It can be a bytecodes
object, a compiled function or a generic function. In the last two
cases the lexical environment is just <code class="code">nil</code>. In the first case,
the second item on the stack is the lexical environment on which the
code is executed. Each of these records are popped out of the stack
after function invocation.
</p>
<p>Let us see how these invocation records are used for debugging.
</p>
<div class="example">
<pre class="verbatim">&gt; (defun fact (x) ;;; Wrong definition of the
(if (= x 0) ;;; factorial function.
one ;;; one should be 1.
(* x (fact (1- x)))))
FACT
&gt; (fact 3) ;;; Tries 3!
Error: The variable ONE is unbound.
Error signalled by IF.
Broken at IF.
&gt;&gt; :b ;;; Backtrace.
Backtrace: eval &gt; fact &gt; if &gt; fact &gt; if &gt; fact &gt; if &gt; fact &gt; IF
;;; Currently at the last IF.
&gt;&gt; :h ;;; Help.
Break commands:
:q(uit) Return to some previous break level.
:pop Pop to previous break level.
:c(ontinue) Continue execution.
:b(acktrace) Print backtrace.
:f(unction) Show current function.
:p(revious) Go to previous function.
:n(ext) Go to next function.
:g(o) Go to next function.
:fs Search forward for function.
:bs Search backward for function.
:v(ariables) Show local variables, functions, blocks, and tags.
:l(ocal) Return the nth local value on the stack.
:hide Hide function.
:unhide Unhide function.
:hp Hide package.
:unhp Unhide package.
:unhide-all Unhide all variables and packages.
:bds Show binding stack.
:m(essage) Show error message.
:hs Help stack.
Top level commands:
:cf Compile file.
:exit or ^D Exit Lisp.
:ld Load file.
:step Single step form.
:tr(ace) Trace function.
:untr(ace) Untrace function.
Help commands:
:apropos Apropos.
:doc(ument) Document.
:h(elp) or ? Help. Type &quot;:help help&quot; for more information.
&gt;&gt; :p ;;; Move to the last call of FACT.
Broken at IF.
&gt;&gt; :b
Backtrace: eval &gt; fact &gt; if &gt; fact &gt; if &gt; fact &gt; if &gt; FACT &gt; if
;;; Now at the last FACT.
&gt;&gt; :v ;;; The environment at the last call
Local variables: ;;; to FACT is recovered.
X: 0 ;;; X is the only bound variable.
Block names: FACT. ;;; The block FACT is established.
&gt;&gt; x
0 ;;; The value of x is 0.
&gt;&gt;(return-from fact 1) ;;; Return from the last call of
6 ;;; FACT with the value of 0.
;;; The execution is resumed and
&gt; ;;; the value 6 is returned.
;;; Again at the top-level loop.
</pre></div>
</div>
</div>
<hr>
<div class="nav-panel">
<p>
Next: <a href="The-compiler.html" accesskey="n" rel="next">The compiler</a>, Previous: <a href="Environment-implementation.html" accesskey="p" rel="prev">Environment implementation</a>, Up: <a href="Developer_0027s-guide.html" accesskey="u" rel="up">Developer&rsquo;s guide</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Indexes.html" title="Index" rel="index">Index</a>]</p>
</div>
</body>
</html>