383 lines
16 KiB
HTML
383 lines
16 KiB
HTML
|
<!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’s guide</a> [<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> [<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> [<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 < 1|| narg > 2)) FEwrong_num_arguments(/* ... */);
|
||
|
if (narg > 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->nvalues = 1;
|
||
|
the_env->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, ‘<code class="code">-</code>’ and ‘<code class="code">*</code>’ in the
|
||
|
Common-Lisp function name are replaced by ‘<code class="code">_</code>’ and ‘<code class="code">A</code>’,
|
||
|
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 &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> [<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">&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> [<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">> (defun fact (x) ;;; Wrong definition of the
|
||
|
(if (= x 0) ;;; factorial function.
|
||
|
one ;;; one should be 1.
|
||
|
(* x (fact (1- x)))))
|
||
|
FACT
|
||
|
|
||
|
> (fact 3) ;;; Tries 3!
|
||
|
Error: The variable ONE is unbound.
|
||
|
Error signalled by IF.
|
||
|
Broken at IF.
|
||
|
>> :b ;;; Backtrace.
|
||
|
Backtrace: eval > fact > if > fact > if > fact > if > fact > IF
|
||
|
;;; Currently at the last IF.
|
||
|
>> :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 ":help help" for more information.
|
||
|
|
||
|
>> :p ;;; Move to the last call of FACT.
|
||
|
Broken at IF.
|
||
|
|
||
|
>> :b
|
||
|
Backtrace: eval > fact > if > fact > if > fact > if > FACT > if
|
||
|
;;; Now at the last FACT.
|
||
|
>> :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.
|
||
|
|
||
|
>> x
|
||
|
0 ;;; The value of x is 0.
|
||
|
|
||
|
>>(return-from fact 1) ;;; Return from the last call of
|
||
|
6 ;;; FACT with the value of 0.
|
||
|
;;; The execution is resumed and
|
||
|
> ;;; 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’s guide</a> [<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>
|