📄 ch18_02.htm
字号:
<html><head><title>Compiling Your Code (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Compiling Your Code"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch18_01.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="ch18_01.htm">Chapter 18: Compiling</a></td><td align="right" valign="top" width="172"><a href="ch18_03.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h2 class="sect1">18.2. Compiling Your Code</h2><p><a name="INDEX-3243"></a>Perl is always in one of two modes of operation: either it is compilingyour program, or it is executing it--never both at the same time.Throughout this book, we refer to certain events as happening at compiletime, or we say that "the Perl compiler does this and that". At otherpoints, we mention that something else occurs at run time, or that "thePerl interpreter does this and that". Although you can get by withthinking of both the compiler and interpreter as simply "Perl",understanding which of these two roles Perl is playing at any givenpoint is essential to understanding why many things happen as they do.The <em class="emphasis">perl</em> executable implements both roles: first the compiler, then the interpreter. (Other roles are possible, too;<em class="emphasis">perl</em> is also an optimizer and a code generator.Occasionally, it's even a trickster--but all in good fun.)</p><p><a name="INDEX-3244"></a><a name="INDEX-3245"></a>It's also important to understand the distinction between compile phase andcompile time, and between run phase and run time. A typical Perl programgets one compile phase, and then one run phase. A "phase" is a large-scaleconcept. But compile time and run time are small-scale concepts. Agiven compile phase does mostly compile-time stuff, but it also does somerun-time stuff via <tt class="literal">BEGIN</tt> blocks. A given run phase does mostlyrun-time stuff, but it can do compile-time stuff through operators like<tt class="literal">eval</tt><em class="replaceable">STRING</em>.</p><p>In the typical course of events, the Perl compiler reads through yourentire program source before execution starts. This is when Perlparses the declarations, statements, and expressions to make surethey're syntactically legal.<a href="#FOOTNOTE-3">[3]</a> If it finds asyntax error, the compiler attempts to recover from the error so itcan report any other errors later in the source. Sometimes thisworks, and sometimes it doesn't; syntax errors have a noisy tendencyto trigger a cascade of false alarms. Perl bails out in frustrationafter about 10 errors.</p><blockquote class="footnote"><a name="FOOTNOTE-3"></a><p>[3] No, there's no formalsyntax diagram like a BNF, but you're welcome to peruse the<em class="emphasis">perly.y</em> file in the Perl source tree, whichcontains the <em class="emphasis">yacc</em>(1) grammar Perl uses. Werecommend that you stay out of the lexer, which has been known toinduce eating disorders in lab rats.</p></blockquote><p><a name="INDEX-3246"></a><a name="INDEX-3247"></a><a name="INDEX-3248"></a><a name="INDEX-3249"></a><a name="INDEX-3250"></a>In addition to the interpreter that processes the<tt class="literal">BEGIN</tt> blocks, the compiler processes your programwith the connivance of three notional agents. The<em class="emphasis">lexer</em> scans for each minimal unit of meaning inyour program. These are sometimes called "lexemes", but you'll moreoften hear them referred to as <em class="emphasis">tokens</em> in textsabout programming languages. The lexer is sometimes called a tokeneror a scanner, and what it does is sometimes called lexing ortokenizing. The <em class="emphasis">parser</em> then tries to make senseout of groups of these tokens by assembling them into largerconstructs, such as expressions and statements, based on the grammarof the Perl language. The <em class="emphasis">optimizer</em> rearrangesand reduces these larger groupings into more efficient sequences. Itpicks its optimizations carefully, not wasting time on marginaloptimizations, because the Perl compiler has to be blazing fast whenused as a load-and-go compiler.</p><p>This doesn't happen in independent stages, but all at once with a lotof cross talk between the agents. The lexer occasionally needs hintsfrom the parser to know which of several possible token types it'slooking at. (Oddly, lexical scope is one of the things the lexicalanalyzer <em class="emphasis">doesn't</em> understand, because that's theother meaning of "lexical".) The optimizer also needs to keep trackof what the parser is doing, because some optimizations can't happenuntil the parse has reached a certain point, like finishing anexpression, statement, block, or subroutine.</p><p>You may think it odd that the Perl compiler does all these things atonce instead of one after another, but it's really just the samemessy process you go through to understand natural language on the fly,while you're listening to it or reading it. You don't wait till theend of a chapter to figure out what the first sentence meant. Youcould think of the following correspondences:</p><a name="perl3-tab-compnatlang"></a><table border="1"><tr><th>Computer Language</th><th>Natural Language</th></tr><tr><td>Character</td><td>Letter</td></tr><tr><td>Token</td><td>Morpheme</td></tr><tr><td>Term</td><td>Word</td></tr><tr><td>Expression</td><td>Phrase</td></tr><tr><td>Statement</td><td>Sentence</td></tr><tr><td>Block</td><td>Paragraph</td></tr><tr><td>File</td><td>Chapter</td></tr><tr><td>Program</td><td>Story</td></tr></table><p><a name="INDEX-3251"></a><a name="INDEX-3252"></a>Assuming the parse goes well, the compiler deems your input a validstory, er, program. If you use the <tt class="userinput"><b>-c</b></tt> switch when running yourprogram, it prints out a "syntax OK" message and exits. Otherwise, thecompiler passes the fruits of its efforts on to other agents. These"fruits" come in the form of a <em class="emphasis">parse tree</em>. Each fruit on thetree--or <em class="emphasis">node</em>, as it's called--represents one of Perl's internal<em class="emphasis">opcodes</em>, and the branches on the tree represent that tree'shistorical growth pattern. Eventually, the nodes will be strungtogether linearly, one after another, to indicate the execution orderin which the run-time system will visit those nodes.</p><p>Each opcode is the smallest unit of executable instruction that Perlcan think about. You might see an expression like <tt class="literal">$a = -($b + $c)</tt>as one statement, but Perl thinks of it as six separate opcodes. Laidout in a simplified format, the parse tree for that expression wouldlook like <a href="ch18_02.htm#perl3-opcode-order">Figure 18-2</a>. The numbers represent thevisitation order that the Perl run-time system will eventually follow.</p><a name="perl3-opcode-order"></a><div class="figure"></div><h4 class="objtitle">Figure 18.2. Opcode visitation order of $a = -($b + $c)</h4><p>Perl isn't a one-pass compiler as some might imagine. (One-passcompilers are great at making things easy for the computer and hard forthe programmer.) It's really a multipass, optimizing compilerconsisting of at least three different logical passes that are interleaved in practice. Passes 1 and 2 run alternately as the compiler repeatedly scurries up and down the parse tree during its construction; pass 3 happens whenever a subroutine or file is completely parsed. Here are those passes:</p><dl><dt><b>Pass 1: Bottom-Up Parsing</b></dt><dd>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -