File: compiler.html

package info (click to toggle)
sbcl 1%3A0.8.16-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 15,028 kB
  • ctags: 14,790
  • sloc: lisp: 194,656; ansic: 16,544; asm: 2,060; sh: 1,674; makefile: 199
file content (225 lines) | stat: -rw-r--r-- 16,852 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>Chapter2.The Compiler</title><meta name="generator" content="DocBook XSL Stylesheets V1.62.4" /><link rel="home" href="index.html" title="SBCL User Manual" /><link rel="up" href="index.html" title="SBCL User Manual" /><link rel="previous" href="implementation.html" title="Overview Of SBCL, How It Works And Where It Came From" /><link rel="next" href="compiler-types.html" title="The Compiler's Handling of Types" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter2.The Compiler</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="implementation.html">Prev</a></td><th width="60%" align="center"></th><td width="20%" align="right"><a accesskey="n" href="compiler-types.html">Next</a></td></tr></table><hr /></div><div class="chapter" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a id="compiler"></a>Chapter2.The Compiler</h2></div></div><div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="compiler.html#error-messages">Error Messages</a></span></dt><dd><dl><dt><span class="sect2"><a href="compiler.html#id2897853">The Parts of the Error Message</a></span></dt><dt><span class="sect2"><a href="compiler.html#id2906982">The Original and Actual Source</a></span></dt><dt><span class="sect2"><a href="compiler.html#id2957752">The Processing Path</a></span></dt><dt><span class="sect2"><a href="compiler.html#id2957842">Error Severity</a></span></dt><dt><span class="sect2"><a href="compiler.html#id2957898">Errors During Macroexpansion</a></span></dt><dt><span class="sect2"><a href="compiler.html#id2831850">Read Errors</a></span></dt></dl></dd><dt><span class="sect1"><a href="compiler-types.html">The Compiler's Handling of Types</a></span></dt><dd><dl><dt><span class="sect2"><a href="compiler-types.html#compiler-impl-limitations">Implementation Limitations</a></span></dt><dt><span class="sect2"><a href="compiler-types.html#id2831996">Type Errors at Compile Time</a></span></dt><dt><span class="sect2"><a href="compiler-types.html#precisetypechecking">Precise Type Checking</a></span></dt><dt><span class="sect2"><a href="compiler-types.html#weakened-type-checking">Weakened Type Checking</a></span></dt><dt><span class="sect2"><a href="compiler-types.html#id2839069">Getting Existing Programs to Run</a></span></dt></dl></dd><dt><span class="sect1"><a href="compiler-policy.html">Compiler Policy</a></span></dt><dt><span class="sect1"><a href="open-coding.html">Open Coding and Inline Expansion</a></span></dt></dl></div><p>This chapter will discuss most compiler issues other than
efficiency, including compiler error messages, the <span class="application">SBCL</span> compiler's
unusual approach to type safety in the presence of type declarations,
the effects of various compiler optimization policies, and the way
that inlining and open coding may cause optimized code to differ from
a naive translation. Efficiency issues are sufficiently varied and
separate that they have <a href="efficiency.html" title="Chapter3.Efficiency">their own
chapter</a>.</p><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="error-messages"></a>Error Messages</h2></div></div><div></div></div><p>The compiler supplies a large amount of source location
information in error messages. The error messages contain a lot of
detail in a terse format, so they may be confusing at first. Error
messages will be illustrated using this example program:
</p><pre class="programlisting">(defmacro zoq (x)
`(roq (ploq (+ ,x 3))))

(defun foo (y)
(declare (symbol y))
(zoq y))</pre><p>
The main problem with this program is that it is trying to add
<tt class="literal">3</tt> to a symbol. Note also that the functions
<tt class="function">roq</tt> and <tt class="function">ploq</tt> aren't defined anywhere.
</p><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2897853"></a>The Parts of the Error Message</h3></div></div><div></div></div><p>When processing this program, the compiler will produce this
warning: 

</p><pre class="screen">file: /tmp/foo.lisp

in: DEFUN FOO
(ZOQ Y)
--&gt; ROQ PLOQ + 
==&gt;
Y
caught WARNING:
Result is a SYMBOL, not a NUMBER.</pre><p>
In this example we see each of the six possible parts of a compiler error
message:
</p><div class="orderedlist"><ol type="1"><li><p><tt class="computeroutput">File: /tmp/foo.lisp</tt>
  This is the name of the file that the compiler read the relevant
  code from.  The file name is displayed because it may not be
  immediately obvious when there is an error during compilation of a
  large system, especially when
  <tt class="function">with-compilation-unit</tt> is used to delay
  undefined warnings.</p></li><li><p><tt class="computeroutput">in: DEFUN FOO</tt> This is the
  definition top level form responsible for the error. It is
  obtained by taking the first two elements of the enclosing form
  whose first element is a symbol beginning with &#8220;<span class="quote"><tt class="literal">def</tt></span>&#8221;.
  If there is no such enclosing &#8220;<span class="quote"><tt class="literal">def</tt></span>&#8221; form, then the 
  outermost form is used.  If there are multiple <tt class="literal">def</tt>
  forms, then they are all printed from the outside in, separated by
  <tt class="literal">=&gt;</tt>'s.  In this example, the problem was in the
  <tt class="function">defun</tt> for <tt class="function">foo</tt>.</p></li><li><p><tt class="computeroutput">(ZOQ Y)</tt> This is the
  <span class="emphasis"><em>original source</em></span> form responsible for the error.
  Original source means that the form directly appeared in the
  original input to the compiler, i.e. in the lambda passed to
  <tt class="function">compile</tt> or in the top level form read from the
  source file. In this example, the expansion of the <tt class="function">zoq</tt>
  macro was responsible for the error.</p></li><li><p><tt class="computeroutput">--&gt; ROQ PLOQ +</tt> This is the
  <span class="emphasis"><em>processing path</em></span> that the compiler used to produce
  the errorful code.  The processing path is a representation of
  the evaluated forms enclosing the actual source that the
  compiler encountered when processing the original source.
  The path is the first element of each form, or the form itself
  if the form is not a list.  These forms result from the
  expansion of macros or source-to-source transformation done
  by the compiler.  In this example, the enclosing evaluated forms
  are the calls to <tt class="function">roq</tt>, <tt class="function">ploq</tt> and
  <tt class="function">+</tt>.  These calls resulted from the expansion of
  the <tt class="function">zoq</tt> macro.</p></li><li><p><tt class="computeroutput">==&gt; Y</tt> This is the
  <span class="emphasis"><em>actual source</em></span> responsible for the error. If
  the actual source appears in the explanation, then
  we print the next enclosing evaluated form, instead of
  printing the actual source twice.  (This is the form
  that would otherwise have been the last form of the processing
  path.) In this example, the problem is with the evaluation of
  the reference to the variable <tt class="varname">y</tt>.</p></li><li><p>
  <tt class="computeroutput">caught WARNING: Result is a SYMBOL, not a NUMBER.</tt>
  This is the <span class="emphasis"><em>explanation</em></span> of the problem. In this
  example, the problem is that <tt class="varname">y</tt> evaluates to a symbol,
  but is in a context where a number is required (the argument
  to <tt class="function">+</tt>).</p></li></ol></div><p>

Note that each part of the error message is distinctively marked:

</p><div class="itemizedlist"><ul type="disc"><li><p> <tt class="computeroutput">file:</tt> and <tt class="computeroutput">in:</tt>
  mark the file and definition, respectively.</p></li><li><p> The original source is an indented form with no
  prefix.</p></li><li><p> Each line of the processing path is prefixed with
  <tt class="computeroutput">--&gt;</tt></p></li><li><p> The actual source form is indented like the original
  source, but is marked by a preceding <tt class="computeroutput">==&gt;</tt> line.
  </p></li><li><p> The explanation is prefixed with the error
  severity, which can be <tt class="computeroutput">caught ERROR:</tt>,
  <tt class="computeroutput">caught WARNING:</tt>,
  <tt class="computeroutput">caught STYLE-WARNING:</tt>, or
  <tt class="computeroutput">note:</tt>. </p></li></ul></div><p>
</p><p>Each part of the error message is more specific than the preceding
one.  If consecutive error messages are for nearby locations, then the
front part of the error messages would be the same.  In this case, the
compiler omits as much of the second message as in common with the
first.  For example:
</p><pre class="screen">file: /tmp/foo.lisp

in: DEFUN FOO
(ZOQ Y)
--&gt; ROQ
==&gt;
(PLOQ (+ Y 3))
caught STYLE-WARNING:
undefined function: PLOQ

==&gt;
(ROQ (PLOQ (+ Y 3)))
caught STYLE-WARNING:
undefined function: ROQ</pre><p>
In this example, the file, definition and original source are
identical for the two messages, so the compiler omits them in the
second message.  If consecutive messages are entirely identical, then
the compiler prints only the first message, followed by:
<tt class="computeroutput">[Last message occurs <i class="replaceable"><tt>repeats</tt></i> times]</tt>
where <i class="replaceable"><tt>repeats</tt></i> is the number of times the message
was given.</p><p>If the source was not from a file, then no file line is printed.
If the actual source is the same as the original source, then the
processing path and actual source will be omitted. If no forms
intervene between the original source and the actual source, then the
processing path will also be omitted.</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2906982"></a>The Original and Actual Source</h3></div></div><div></div></div><p>The <span class="emphasis"><em>original source</em></span> displayed will almost always be
a list. If the actual source for an error message is a symbol, the
original source will be the immediately enclosing evaluated list form.
So even if the offending symbol does appear in the original source,
the compiler will print the enclosing list and then print the symbol
as the actual source (as though the symbol were introduced by a
macro.)</p><p>When the <span class="emphasis"><em>actual source</em></span> is displayed
(and is not a symbol), it will always
be code that resulted from the expansion of a macro or a source-to-source
compiler optimization.  This is code that did not appear in the original
source program; it was introduced by the compiler.</p><p>Keep in mind that when the compiler displays a source form
in an error message, it always displays the most specific (innermost)
responsible form.  For example, compiling this function
</p><pre class="programlisting">(defun bar (x)
(let (a)
(declare (fixnum a))
(setq a (foo x))
a))</pre><p>
gives this error message
</p><pre class="screen">in: DEFUN BAR
(LET (A) (DECLARE (FIXNUM A)) (SETQ A (FOO X)) A)
caught WARNING: The binding of A is not a FIXNUM:
NIL</pre><p>
This error message is not saying &#8220;<span class="quote">there is a problem somewhere in
this <tt class="function">let</tt></span>&#8221; &#8212; it is saying that there is a
problem with the <tt class="function">let</tt> itself. In this example, the problem
is that <tt class="varname">a</tt>'s <tt class="literal">nil</tt> initial value is not a
<tt class="type">fixnum</tt>.</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2957752"></a>The Processing Path</h3></div></div><div></div></div><p>The processing path is mainly useful for debugging macros, so if
you don't write macros, you can probably ignore it. Consider this
example:

</p><pre class="programlisting">(defun foo (n)
(dotimes (i n *undefined*)))
</pre><p>

Compiling results in this error message:

</p><pre class="screen">in: DEFUN FOO
(DOTIMES (I N *UNDEFINED*))
--&gt; DO BLOCK LET TAGBODY RETURN-FROM
==&gt;
(PROGN *UNDEFINED*)
caught STYLE-WARNING:
undefined variable: *UNDEFINED*</pre><p>

Note that <tt class="function">do</tt> appears in the processing path. This is because
<tt class="function">dotimes</tt> expands into:

</p><pre class="programlisting">(do ((i 0 (1+ i)) (#:g1 n))
((&gt;= i #:g1) *undefined*)
(declare (type unsigned-byte i)))</pre><p>

The rest of the processing path results from the expansion
of <tt class="function">do</tt>:

</p><pre class="programlisting">
  (block nil
  (let ((i 0) (#:g1 n))
  (declare (type unsigned-byte i))
  (tagbody (go #:g3)
  #:g2    (psetq i (1+ i))
  #:g3    (unless (&gt;= i #:g1) (go #:g2))
  (return-from nil (progn *undefined*)))))
</pre><p>

In this example, the compiler descended into the <tt class="function">block</tt>,
<tt class="function">let</tt>, <tt class="function">tagbody</tt> and <tt class="function">return-from</tt> to
reach the <tt class="function">progn</tt> printed as the actual source. This is a
place where the &#8220;<span class="quote">actual source appears in explanation</span>&#8221; rule
was applied. The innermost actual source form was the symbol
<tt class="varname">*undefined*</tt> itself, but that also appeared in the
explanation, so the compiler backed out one level.</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2957842"></a>Error Severity</h3></div></div><div></div></div><p>There are four levels of compiler error severity:
<i class="wordasword">error</i>, <i class="wordasword">warning</i>, <i class="wordasword">style
warning</i>, and <i class="wordasword">note</i>. The first three levels correspond
to condition classes which are defined in the <span class="acronym">ANSI</span> standard for
Common Lisp and which have special significance to the
<tt class="function">compile</tt> and <tt class="function">compile-file</tt> functions. These
levels of compiler error severity occur when the compiler handles
conditions of these classes. The fourth level of compiler error
severity, <i class="wordasword">note</i>, is used for problems which are too mild
for the standard condition classes, typically hints about how
efficiency might be improved.</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2957898"></a>Errors During Macroexpansion</h3></div></div><div></div></div><p>The compiler handles errors that happen during macroexpansion,
turning them into compiler errors. If you want to debug the error (to
debug a macro), you can set <tt class="varname">*break-on-signals*</tt> to
<tt class="literal">error</tt>. For example, this definition:

</p><pre class="programlisting">(defun foo (e l)
(do ((current l (cdr current))
((atom current) nil))
(when (eq (car current) e) (return current))))</pre><p>

gives this error:

</p><pre class="screen">in: DEFUN FOO
(DO ((CURRENT L #) (# NIL)) (WHEN (EQ # E) (RETURN CURRENT)) )
caught ERROR: 
(in macroexpansion of (DO # #))
(hint: For more precise location, try *BREAK-ON-SIGNALS*.)
DO step variable is not a symbol: (ATOM CURRENT)</pre><p>
</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="id2831850"></a>Read Errors</h3></div></div><div></div></div><p><span class="application">SBCL</span>'s compiler (unlike <span class="application">CMU CL</span>'s) does not attempt to recover
from read errors when reading a source file, but instead just reports
the offending character position and gives up on the entire source
file.</p></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="implementation.html">Prev</a></td><td width="20%" align="center"><a accesskey="u" href="index.html">Up</a></td><td width="40%" align="right"><a accesskey="n" href="compiler-types.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Overview Of SBCL, How It Works And Where It Came From</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">The Compiler's Handling of Types</td></tr></table></div></body></html>