summaryrefslogtreecommitdiff
path: root/miniany/doc/Writing a C Compiler, Part 2.html
blob: 835b5d546db2ebd334815929b00ac4d684ae6d44 (plain)
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
<!DOCTYPE html>
<!-- saved from url=(0058)https://norasandler.com/2017/12/05/Write-a-Compiler-2.html -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>Writing a C Compiler, Part 2</title>
  <meta name="description" content="This is the second post in a series. Read part 1 here.">

  <link rel="stylesheet" href="./Writing a C Compiler, Part 2_files/main.css">
  <link rel="canonical" href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html">
  <link rel="alternate" type="application/rss+xml" title="Nora Sandler" href="https://norasandler.com/feed.xml">
  
</head>


  <body>

    <header class="site-header" role="banner">

  <div class="wrapper">
    
    
    <a class="site-title" href="https://norasandler.com/">Nora Sandler</a>
  
    
      <nav class="site-nav">
        <input type="checkbox" id="nav-trigger" class="nav-trigger">
        <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewBox="0 0 18 15" width="18px" height="15px">
              <path fill="#424242" d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z"></path>
              <path fill="#424242" d="M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z"></path>
              <path fill="#424242" d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z"></path>
            </svg>
          </span>
        </label>

        <div class="trigger">
          
            
            
              
            
          
            
            
              
              <a class="page-link" href="https://norasandler.com/about/">About</a>
              
            
          
            
            
              
              <a class="page-link" href="https://norasandler.com/archive/">Archive</a>
              
            
          
            
            
          
            
            
              
            
          
            
            
              
            
          
            
            
              
            
          
          <a class="page-link" href="https://github.com/nlsandler">Github</a>
          <a href="https://norasandler.com/feed.xml"><img id="rss" height="20" width="20" src="./Writing a C Compiler, Part 2_files/rss.png"></a>

        </div>
      </nav>
    
  </div>
</header>


    <main class="page-content" aria-label="Content">
      <div class="wrapper">
        <article class="post h-entry" itemscope="" itemtype="http://schema.org/BlogPosting">

  <header class="post-header">
    <h1 class="post-title p-name" itemprop="name headline">Writing a C Compiler, Part 2</h1>
    <p class="post-meta">
      <time class="dt-published" datetime="2017-12-05T21:30:00+00:00" itemprop="datePublished">Dec 5, 2017
      </time></p>
  </header>

  <div class="post-content e-content" itemprop="articleBody">
    <p><em>This is the second post in a series. Read part 1 <a href="https://norasandler.com/2017/11/29/Write-a-Compiler.html">here</a>.</em></p>

<p>In the last post, we learned to compile programs that return integers. This week we’ll do math to those integers. Same as last week, you can find the accompanying tests <a href="https://github.com/nlsandler/write_a_c_compiler">here</a>.</p>

<h1 id="week-2-unary-operators">Week 2: Unary Operators</h1>

<p>This week, we’re adding three unary operators<sup id="anchor1"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn1">1</a></sup> (i.e. operators that only take one value):</p>

<p><strong>Negation (<code class="language-plaintext highlighter-rouge">-</code>)</strong></p>

<p>-5 = 0 - 5. In other words, it’s a regular negative number.</p>

<p><strong>Bitwise complement (<code class="language-plaintext highlighter-rouge">~</code>)</strong></p>

<p>This flips every bit in a number<sup id="anchor2"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn2">2</a></sup>. For example:</p>
<ul>
  <li>4 is written as 100 in binary.</li>
  <li>The bitwise complement of 100 is 011.</li>
  <li>011 in decimal is 3.</li>
  <li>So ~4 = 3.</li>
</ul>

<p><strong>Logical negation (<code class="language-plaintext highlighter-rouge">!</code>)</strong></p>

<p>The boolean “not” operator. This treats 0 as “false” and everything else as “true”.</p>

<ul>
  <li>!0 = 1</li>
  <li>!(anything else) = 0</li>
</ul>

<p>Last week we created a compiler with three stages: a lexer, a parser, and a code generator. Now we’ll update each stage to handle these new operators.</p>

<h2 id="lexing">Lexing</h2>

<p>We just need to add each of these operators to our list of tokens. Here’s the list of tokens: tokens from last week are at the top, and new tokens are bolded at the bottom.</p>

<ul>
  <li>Open brace <code class="language-plaintext highlighter-rouge">{</code></li>
  <li>Close brace <code class="language-plaintext highlighter-rouge">}</code></li>
  <li>Open parenthesis <code class="language-plaintext highlighter-rouge">\(</code></li>
  <li>Close parenthesis <code class="language-plaintext highlighter-rouge">\)</code></li>
  <li>Semicolon <code class="language-plaintext highlighter-rouge">;</code></li>
  <li>Int keyword <code class="language-plaintext highlighter-rouge">int</code></li>
  <li>Return keyword <code class="language-plaintext highlighter-rouge">return</code></li>
  <li>Identifier <code class="language-plaintext highlighter-rouge">[a-zA-Z]\w*</code></li>
  <li>Integer literal <code class="language-plaintext highlighter-rouge">[0-9]+</code></li>
  <li><strong>Negation <code class="language-plaintext highlighter-rouge">-</code></strong></li>
  <li><strong>Bitwise complement <code class="language-plaintext highlighter-rouge">~</code></strong></li>
  <li><strong>Logical negation <code class="language-plaintext highlighter-rouge">!</code></strong></li>
</ul>

<p>We can process these new tokens exactly the same way as the other single-character tokens, like braces and parentheses.</p>

<h4 id="-task">☑ Task:</h4>
<p>Update the <em>lex</em> function to handle the new tokens. It should work for all stage 1 and 2 examples in the test suite, including the invalid ones.</p>

<h2 id="parsing">Parsing</h2>

<p>Last week we defined several AST nodes, including expressions. We only defined one type of expression: constants. This week, we’ll add another type of expression, unary operations. The latest set of definitions is below. Only the definition of <code class="language-plaintext highlighter-rouge">exp</code> has changed.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>program = Program(function_declaration)
function_declaration = Function(string, statement) //string is the function name
statement = Return(exp)
exp = UnOp(operator, exp) | Constant(int)
</code></pre></div></div>

<p>Now, an expression can take one of two forms - it can be either a constant, or a unary operation. A unary operation consists of the operator (e.g. <code class="language-plaintext highlighter-rouge">~</code>), and the operand, which is itself an expression. For example, here’s how we could construct the expression <code class="language-plaintext highlighter-rouge">~3</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>c = Const(3)
exp = UnOp(COMPLEMENT, c)
</code></pre></div></div>

<p>Our definition of expressions is recursive - expressions can contain other expressions!</p>

<p>This is an expression: <code class="language-plaintext highlighter-rouge">!3</code></p>

<p>So is this: <code class="language-plaintext highlighter-rouge">!~-4</code></p>

<p>So is this: <code class="language-plaintext highlighter-rouge">!!!!!!!-~~-!3</code></p>

<p>We need to update our formal grammar too:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;program&gt; ::= &lt;function&gt;
&lt;function&gt; ::= "int" &lt;id&gt; "(" ")" "{" &lt;statement&gt; "}"
&lt;statement&gt; ::= "return" &lt;exp&gt; ";"
&lt;exp&gt; ::= &lt;unary_op&gt; &lt;exp&gt; | &lt;int&gt;
&lt;unary_op&gt; ::= "!" | "~" | "-"
</code></pre></div></div>

<p>Because the definition of an expression is recursive, the function to parse an expression should also be recursive.
Here’s the pseudocode for parsing an expression:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def parse_expression(tokens):
    tok = tokens.next()
    if tok.type == "INT":
        //parse this the same way as before, return a Const node
    else:
        op = get_operator(tok) //convert token to unary_op AST element - fail if token isn't "!", "~" or "-"
        inner_exp  = parse_expression(tokens) //HOORAY, RECURSION - this will pop more tokens off the stack
        return UnOp(op, inner_exp)
</code></pre></div></div>

<h4 id="-task-1">☑ Task:</h4>
<p>Update your expression-parsing function to handle unary operations. It should successfully parse all valid stage 1 and 2 examples in the test suite, and fail on all invalid stage 1 and 2 examples.</p>

<h2 id="code-generation">Code Generation</h2>

<p>Negation and bitwise complement are super easy; each of them can be accomplished with a single assembly instruction.</p>

<p><code class="language-plaintext highlighter-rouge">neg</code> negates the value of its operand<sup id="anchor3"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn3">3</a></sup>. Here’s an example:</p>

<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="nf">movl</span>    <span class="kc">$</span><span class="mi">3</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>    <span class="c1">;EAX register contains 3</span>
    <span class="nf">neg</span>     <span class="o">%</span><span class="nb">eax</span>        <span class="c1">;now EAX register contains -3</span>
</code></pre></div></div>

<p>Of course, we need to calculate a value before we can negate it, so we need to recursively generate code for the inner expression, then emit the <code class="language-plaintext highlighter-rouge">neg</code> instruction.</p>

<p><code class="language-plaintext highlighter-rouge">not</code> replaces a value with its bitwise complement. We can use it exactly the same way as <code class="language-plaintext highlighter-rouge">neg</code>.</p>

<p>Logical negation is a little more complicated. Remember, <code class="language-plaintext highlighter-rouge">return !exp</code> is equivalent to:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Unlike the other operations, which were straightforward bit manipulation, this requires some conditional logic. We can implement it using <code class="language-plaintext highlighter-rouge">cmpl</code><sup id="anchor4"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn4">4</a></sup>, which compares two values, and <code class="language-plaintext highlighter-rouge">sete</code> (“set if equal”). <code class="language-plaintext highlighter-rouge">sete</code> sets its operand to 1 if the result of the last comparison was equal, and 0 otherwise.</p>

<p>Comparision and conditonal instructions like <code class="language-plaintext highlighter-rouge">cmpl</code> and <code class="language-plaintext highlighter-rouge">sete</code> are a little weird; <code class="language-plaintext highlighter-rouge">cmpl</code> doesn’t explicitly store the result of the comparison, and <code class="language-plaintext highlighter-rouge">sete</code> doesn’t explicitly refer to that result, or to the values being compared. Both of these instructions - and all comparison and conditional instructions - implicitly refer to the <a href="https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture#EFLAGS_Register">FLAGS register</a><sup id="anchor5"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn5">5</a></sup>. As the name suggests, the contents of this register are interpreted as an array of one-bit flags, rather than a single integer. These flags are automatically set after every arithmetic operation. The only flag we care about right now is the zero flag (ZF), which is set on if the result of an operation is 0, and set off otherwise.</p>

<p><code class="language-plaintext highlighter-rouge">cmpl a, b</code> computes (b - a) and sets FLAGS accordingly. If two values are equal, their difference is 0, so ZF will be set on if and only if the operands to <code class="language-plaintext highlighter-rouge">cmpl</code> are equal. The <code class="language-plaintext highlighter-rouge">sete</code> instruction uses ZF to test for equality; it sets its operand to 1 if ZF is on, and 0 if ZF is off. In fact, <code class="language-plaintext highlighter-rouge">setz</code> (“set if zero”) is another mnemonic for the same instruction.</p>

<p>The last gotcha here is that <code class="language-plaintext highlighter-rouge">sete</code> can only set a <em>byte</em>, not an entire four-byte integer. We’ll have it set the AL register, which is just the least-significant byte of EAX. We just need to zero out EAX first<sup id="anchor6"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn6">6</a></sup>; since the result of <code class="language-plaintext highlighter-rouge">!</code> is always 0 or 1, we dont want to leave any stray higher bits set.</p>

<p>So that was a long explanation, but you can actually implement <code class="language-plaintext highlighter-rouge">!</code> in just three lines of assembly:</p>

<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="err">&lt;</span><span class="nf">CODE</span> <span class="nv">FOR</span> <span class="nv">exp</span> <span class="nv">GOES</span> <span class="nv">HERE</span><span class="o">&gt;</span>
    <span class="nf">cmpl</span>   <span class="kc">$</span><span class="mi">0</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>    <span class="c1">;set ZF on if exp == 0, set it off otherwise</span>
    <span class="nf">movl</span>   <span class="kc">$</span><span class="mi">0</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span>    <span class="c1">;zero out EAX (doesn't change FLAGS)</span>
    <span class="nf">sete</span>   <span class="o">%</span><span class="nb">al</span>         <span class="c1">;set AL register (the lower byte of EAX) to 1 iff ZF is on</span>
</code></pre></div></div>

<p>To convince ourselves that this is correct, let’s work through this with the expression <code class="language-plaintext highlighter-rouge">!5</code>:</p>

<ol>
  <li>First we move 5 into the EAX register.</li>
  <li>We compare 0 to 5. 5 != 0, so the ZF flag is set to 0.</li>
  <li>The EAX register is zeroed out, so we can set it in the next step.</li>
  <li>We conditionaly set AL; because ZF is 0, we set AL to 0. AL refers to the lower bytes of EAX; the upper bytes were also zeroed in step 3, so now EAX contains 0.</li>
</ol>

<h4 id="-task-2">☑ Task:</h4>
<p>Update your code-generation pass to emit correct code for <code class="language-plaintext highlighter-rouge">!</code>, <code class="language-plaintext highlighter-rouge">~</code> and <code class="language-plaintext highlighter-rouge">-</code> operations. It should generate correct assembly for all valid stage 1 and stage 2 examples.</p>

<h2 id="up-next">Up Next</h2>

<p><a href="https://norasandler.com/2017/12/15/Write-a-Compiler-3.html">Next week</a> we’ll find out whether 2+2 really does equal 4, by adding some binary operations: addition, subtraction, and more. See you then!</p>

<h2 id="update-10112023">Update 10/11/2023</h2>

<ul>
  <li>Clarified the definition of “word” in footnote 4, and updated several posts in the series to avoid the term “word”. I previously used “word” to mean a 32-bit integer. Thanks to Denton Spivey for pointing out the confusing terminology.</li>
</ul>

<p><em>If you have any questions, corrections, or other feedback, you can <a href="mailto:nora@norasandler.com">email me</a> or <a href="https://github.com/nlsandler/write_a_c_compiler/issues">open an issue</a>.</em></p>

<div class="footnote">
  <p><sup id="fn1">1</sup>
These are defined on page 89 of the <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf">C11 standard</a>.<a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor1">↩</a></p>
</div>

<div class="footnote">
  <p><sup id="fn2">2</sup>
As <a href="https://news.ycombinator.com/item?id=15864537">remcob correctly pointed out</a> on Hacker News, the bitwise complement of a number really depends on how many bits you’re using to represent it. The example above is correct if we assume all integers are 3 bits. But if an integer is 8 bits, then 4 is 00000100, so ~4 is 11111011, or 251. To make things even MORE complicated, 11111011 is only 251 if you’re dealing with an unsigned integer - if it’s signed, then 11111011 is actually the two’s complement representation of -5.<a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor2">↩</a></p>
</div>

<div class="footnote">
  <p><sup id="fn3">3</sup>
To be really pedantic, <code class="language-plaintext highlighter-rouge">neg</code> calculates the <a href="https://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html">two’s complement</a> of its operand.<a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor3">↩</a></p>
</div>

<div class="footnote">
  <p><sup id="fn4">4</sup>
Some documentation mentions <code class="language-plaintext highlighter-rouge">mov</code> and <code class="language-plaintext highlighter-rouge">cmp</code> instead of <code class="language-plaintext highlighter-rouge">movl</code> and <code class="language-plaintext highlighter-rouge">cmpl</code>; later you’ll see that “l” suffix on a lot of other instructions too. The “l” stands for “longword”, and indicates that the operand is 32 bits. (More assembly suffixes <a href="https://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax#Operation_Suffixes">here</a>.) When we describe a processor as 32- or 64-bit, we’re talking about its <a href="https://en.wikipedia.org/wiki/Word_(computer_architecture)">word size</a>, the main integer operand size it’s designed to work with. But a lot of discussions of assembly code call 16-bit values “words,” 32-bit values “longwords” or “doublewords,” and 64-bit values “quadwords,” regardless of the processor’s word size. This terminology is a relic of the era of 16-bit processors.
<a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor4">↩</a></p>
</div>

<div class="footnote">
  <p><sup id="fn5">5</sup>
Actually, it’s FLAGS on 16-bit machines, EFLAGS on 32-bit machines, and RFLAGS on 64-bit machines, so your computer almost definitely doesn’t have a FLAGS register. But the flags we care about are all in the lower 16 bits so it doesn’t really matter. <a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor5">↩</a></p>
</div>

<div class="footnote">
  <p><sup id="fn6">6</sup>
<code class="language-plaintext highlighter-rouge">mov $0, %eax</code> is the most obvious way to zero out a register, but it isn’t the quickest. <code class="language-plaintext highlighter-rouge">xor %eax, %eax</code> is better, for reasons you can read about <a href="https://stackoverflow.com/questions/33666617/what-is-the-best-way-to-set-a-register-to-zero-in-x86-assembly-xor-mov-or-and/33668295#33668295">here</a>. There’s a whole slew of ways to zero a register; in your compiler you can use whichever one you want. <a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor6">↩</a></p>
</div>

  </div><a class="u-url" href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html" hidden=""></a>
</article>

      </div>
    </main>

    <footer class="site-footer">

  <div class="wrapper">
      <div class="footer-col-wrapper">
        <div class="footer-col footer-col-1">
            <div class="rc-scout" data-scout-rendered="true"><p class="rc-scout__text"><i class="rc-scout__logo"></i> Want to become a better programmer? <a class="rc-scout__link" href="https://www.recurse.com/scout/click?t=8f520efbc4be09fb83a71920f53a07b7">Join the Recurse Center!</a></p></div><script async="" defer="" src="./Writing a C Compiler, Part 2_files/loader.js"></script>
        </div>
      </div>
    <div class="footer-col-wrapper">
      <div class="footer-col footer-col-1">
        © 2023 Nora Sandler.
      </div>
    </div>
  </div>

</footer>


  


<script async="" src="./Writing a C Compiler, Part 2_files/scout-176be16681a03cbddd686f3cc96694d3aab338ea5cb65452f83d989309810528.js"></script><style class="rc-scout__style" type="text/css">.rc-scout {
  display: block;
  padding: 0;
  border: 0;
  margin: 0;
}
.rc-scout__text {
  display: block;
  padding: 0;
  border: 0;
  margin: 0;
  height: 100%;
  font-size: 100%;
}
.rc-scout__logo {
  display: inline-block;
  padding: 0;
  border: 0;
  margin: 0;
  width: 0.85em;
  height: 0.85em;
  background: no-repeat center url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2012%2015%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2212%22%20height%3D%2210%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%221%22%20y%3D%221%22%20width%3D%2210%22%20height%3D%228%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%222%22%20width%3D%228%22%20height%3D%226%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%223%22%20y%3D%225%22%20width%3D%222%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%225%22%20width%3D%222%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%229%22%20width%3D%224%22%20height%3D%223%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%221%22%20y%3D%2211%22%20width%3D%2210%22%20height%3D%224%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%220%22%20y%3D%2212%22%20width%3D%2212%22%20height%3D%223%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%223%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%225%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%227%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%228%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%229%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3C%2Fsvg%3E');
}
.rc-scout__link:link, .rc-scout__link:visited {
  color: #3dc06c;
  text-decoration: underline;
}
.rc-scout__link:hover, .rc-scout__link:active {
  color: #4e8b1d;
}
</style></body></html>