about summary refs log tree commit diff stats
path: root/html/003trace.cc.html
blob: 991df32e791f5ff0030ea1a8bd51bd8280bc9047 (plain) (blame)
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
MIT/X Consortium License

(C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the 
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software. 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
DEALINGS IN THE SOFTWARE.
a id='n241' href='#n241'>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 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 003trace.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 12pt; font-size: 1em; }
.Constant { color: #00a0a0; }
.Comment { color: #9090ff; }
.Delimiter { color: #800080; }
.cSpecial { color: #008000; }
.Identifier { color: #c0a020; }
.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
.PreProc { color: #800080; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: The goal of this skeleton is to make programs more easy to understand and</span>
<span class="Comment">//: more malleable, easy to rewrite in radical ways without accidentally</span>
<span class="Comment">//: breaking some corner case. Tests further both goals. They help</span>
<span class="Comment">//: understandability by letting one make small changes and get feedback. What</span>
<span class="Comment">//: if I wrote this line like so? What if I removed this function call, is it</span>
<span class="Comment">//: really necessary? Just try it, see if the tests pass. Want to explore</span>
<span class="Comment">//: rewriting this bit in this way? Tests put many refactorings on a firmer</span>
<span class="Comment">//: footing.</span>
<span class="Comment">//:</span>
<span class="Comment">//: But the usual way we write tests seems incomplete. Refactorings tend to</span>
<span class="Comment">//: work in the small, but don't help with changes to function boundaries. If</span>
<span class="Comment">//: you want to extract a new function you have to manually test-drive it to</span>
<span class="Comment">//: create tests for it. If you want to inline a function its tests are no</span>
<span class="Comment">//: longer valid. In both cases you end up having to reorganize code as well as</span>
<span class="Comment">//: tests, an error-prone activity.</span>
<span class="Comment">//:</span>
<span class="Comment">//: This file tries to fix this problem by supporting domain-driven testing</span>
<span class="Comment">//: We try to focus on the domain of inputs the program should work on. All</span>
<span class="Comment">//: tests invoke the program in a single way: by calling run() with different</span>
<span class="Comment">//: inputs. The program operates on the input and logs _facts_ it deduces to a</span>
<span class="Comment">//: trace:</span>
<span class="Comment">//:   trace(&quot;label&quot;) &lt;&lt; &quot;fact 1: &quot; &lt;&lt; val;</span>
<span class="Comment">//:</span>
<span class="Comment">//: The tests check for facts:</span>
<span class="Comment">//:   :(scenario foo)</span>
<span class="Comment">//:   34  # call run() with this input</span>
<span class="Comment">//:   +label: fact 1: 34  # trace should have logged this at the end</span>
<span class="Comment">//:   -label: fact 1: 35  # trace should never contain such a line</span>
<span class="Comment">//:</span>
<span class="Comment">//: Since we never call anything but the run() function directly, we never have</span>
<span class="Comment">//: to rewrite the tests when we reorganize the internals of the program. We</span>
<span class="Comment">//: just have to make sure our rewrite deduces the same facts about the domain,</span>
<span class="Comment">//: and that's something we're going to have to do anyway.</span>
<span class="Comment">//:</span>
<span class="Comment">//: To avoid the combinatorial explosion of integration tests, we organize the</span>
<span class="Comment">//: program into different layers, and each fact is logged to the trace with a</span>
<span class="Comment">//: specific label. Individual tests can focus on specific labels. In essence,</span>
<span class="Comment">//: validating the facts logged with a specific label is identical to calling</span>
<span class="Comment">//: some internal subsystem.</span>
<span class="Comment">//:</span>
<span class="Comment">//: Traces interact salubriously with layers. Thanks to our ordering</span>
<span class="Comment">//: directives, each layer can contain its own tests. They may rely on other</span>
<span class="Comment">//: layers, but when a test fails its usually due to breakage in the same</span>
<span class="Comment">//: layer. When multiple tests fail, it's usually useful to debug the very</span>
<span class="Comment">//: first test to fail. This is in contrast with the traditional approach,</span>
<span class="Comment">//: where changes can cause breakages in faraway subsystems, and picking the</span>
<span class="Comment">//: right test to debug can be an important skill to pick up.</span>
<span class="Comment">//:</span>
<span class="Comment">//: To build robust tests, trace facts about your domain rather than details of</span>
<span class="Comment">//: how you computed them.</span>
<span class="Comment">//:</span>
<span class="Comment">//: More details: <a href="http://akkartik.name/blog/tracing-tests">http://akkartik.name/blog/tracing-tests</a></span>
<span class="Comment">//:</span>
<span class="Comment">//: ---</span>
<span class="Comment">//:</span>
<span class="Comment">//: Between layers and domain-driven testing, programming starts to look like a</span>
<span class="Comment">//: fundamentally different activity. Instead of a) superficial, b) local rules</span>
<span class="Comment">//: on c) code [like <a href="http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet],">http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet],</a></span>
<span class="Comment">//: we allow programmers to engage with the a) deep, b) global structure of the</span>
<span class="Comment">//: c) domain. If you can systematically track discontinuities in the domain</span>
<span class="Comment">//: you don't care if the code used gotos as long as it passed the tests. If</span>
<span class="Comment">//: tests become more robust to run it becomes easier to try out radically</span>
<span class="Comment">//: different implementations for the same program. If code is super-easy to</span>
<span class="Comment">//: rewrite, it becomes less important what indentation style it uses, or that</span>
<span class="Comment">//: the objects are appropriately encapsulated, or that the functions are</span>
<span class="Comment">//: referentially transparent.</span>
<span class="Comment">//:</span>
<span class="Comment">//: Instead of plumbing, programming becomes building and gradually refining a</span>
<span class="Comment">//: map of the environment the program must operate under. Whether a program is</span>
<span class="Comment">//: 'correct' at a given point in time is a red herring; what matters is</span>
<span class="Comment">//: avoiding regression by monotonically nailing down the more 'eventful' parts</span>
<span class="Comment">//: of the terrain. It helps readers new and old and rewards curiosity to</span>
<span class="Comment">//: organize large programs in self-similar hiearchies of example scenarios</span>
<span class="Comment">//: colocated with the code that makes them work.</span>
<span class="Comment">//:</span>
<span class="Comment">//:   &quot;Programming properly should be regarded as an activity by which</span>
<span class="Comment">//:   programmers form a mental model, rather than as production of a program.&quot;</span>
<span class="Comment">//:   -- Peter Naur (<a href="http://alistair.cockburn.us/ASD+book+extract%3A+%22Naur,+Ehn,+Musashi%22)">http://alistair.cockburn.us/ASD+book+extract%3A+%22Naur,+Ehn,+Musashi%22)</a></span>

<span class="Delimiter">:(before &quot;End Types&quot;)</span>
<span class="Normal">struct</span> trace_line <span class="Delimiter">{</span>
  <span class="Normal">int</span> depth<span class="Delimiter">;</span>  <span class="Comment">// optional field just to help browse traces later</span>
  string label<span class="Delimiter">;</span>
  string contents<span class="Delimiter">;</span>
  trace_line<span class="Delimiter">(</span>string l<span class="Delimiter">,</span> string c<span class="Delimiter">)</span> :depth<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> label<span class="Delimiter">(</span>l<span class="Delimiter">),</span> contents<span class="Delimiter">(</span>c<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
  trace_line<span class="Delimiter">(</span><span class="Normal">int</span> d<span class="Delimiter">,</span> string l<span class="Delimiter">,</span> string c<span class="Delimiter">)</span> :depth<span class="Delimiter">(</span>d<span class="Delimiter">),</span> label<span class="Delimiter">(</span>l<span class="Delimiter">),</span> contents<span class="Delimiter">(</span>c<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
<span class="Delimiter">};</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
<span class="Normal">bool</span> Hide_errors = <span class="Constant">false</span><span class="Delimiter">;</span>
<span class="Normal">bool</span> Dump_trace = <span class="Constant">false</span><span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End Setup&quot;)</span>
Hide_errors = <span class="Constant">false</span><span class="Delimiter">;</span>
Dump_trace = <span class="Constant">false</span><span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End Types&quot;)</span>
<span class="Comment">// Pre-define some global constants that trace_stream needs to know about.</span>
<span class="Comment">// Since they're in the Types section, they'll be included in any cleaved</span>
<span class="Comment">// compilation units. So no extern linkage.</span>
<span class="Normal">const</span> <span class="Normal">int</span> Max_depth = <span class="Constant">9999</span><span class="Delimiter">;</span>
<span class="Normal">const</span> <span class="Normal">int</span> Error_depth = <span class="Constant">0</span><span class="Delimiter">;</span>  <span class="Comment">// definitely always print errors</span>
<span class="Normal">const</span> <span class="Normal">int</span> App_depth = <span class="Constant">2</span><span class="Delimiter">;</span>  <span class="Comment">// temporarily where all mu code will trace to</span>

<span class="Normal">struct</span> trace_stream <span class="Delimiter">{</span>
  vector&lt;trace_line&gt; past_lines<span class="Delimiter">;</span>
  <span class="Comment">// accumulator for current line</span>
  ostringstream* curr_stream<span class="Delimiter">;</span>
  string curr_label<span class="Delimiter">;</span>
  <span class="Normal">int</span> curr_depth<span class="Delimiter">;</span>
  <span class="Normal">int</span> callstack_depth<span class="Delimiter">;</span>
  <span class="Normal">int</span> collect_depth<span class="Delimiter">;</span>
  ofstream null_stream<span class="Delimiter">;</span>  <span class="Comment">// never opens a file, so writes silently fail</span>
  trace_stream<span class="Delimiter">()</span> :curr_stream<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> curr_depth<span class="Delimiter">(</span>Max_depth<span class="Delimiter">),</span> callstack_depth<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> collect_depth<span class="Delimiter">(</span>Max_depth<span class="Delimiter">)</span> <span class="Delimiter">{}</span>
  ~trace_stream<span class="Delimiter">()</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>curr_stream<span class="Delimiter">)</span> <span class="Normal">delete</span> curr_stream<span class="Delimiter">;</span> <span class="Delimiter">}</span>

  ostream&amp; stream<span class="Delimiter">(</span>string label<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Identifier">return</span> stream<span class="Delimiter">(</span>Max_depth<span class="Delimiter">,</span> label<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>

  ostream&amp; stream<span class="Delimiter">(</span><span class="Normal">int</span> depth<span class="Delimiter">,</span> string label<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>depth &gt; collect_depth<span class="Delimiter">)</span> <span class="Identifier">return</span> null_stream<span class="Delimiter">;</span>
    curr_stream = <span class="Normal">new</span> ostringstream<span class="Delimiter">;</span>
    curr_label = label<span class="Delimiter">;</span>
    curr_depth = depth<span class="Delimiter">;</span>
    <span class="Identifier">return</span> *curr_stream<span class="Delimiter">;</span>
  <span class="Delimiter">}</span>

  <span class="Comment">// be sure to call this before messing with curr_stream or curr_label</span>
  <span class="Normal">void</span> newline<span class="Delimiter">();</span>
  <span class="Comment">// useful for debugging</span>
  string readable_contents<span class="Delimiter">(</span>string label<span class="Delimiter">);</span>  <span class="Comment">// empty label = show everything</span>
<span class="Delimiter">};</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">void</span> trace_stream::newline<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!curr_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  string curr_contents = curr_stream<span class="Delimiter">-&gt;</span>str<span class="Delimiter">();</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!curr_contents<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
    past_lines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>trace_line<span class="Delimiter">(</span>curr_depth<span class="Delimiter">,</span> trim<span class="Delimiter">(</span>curr_label<span class="Delimiter">),</span> curr_contents<span class="Delimiter">));</span>  <span class="Comment">// preserve indent in contents</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>Dump_trace || <span class="Delimiter">(</span>!Hide_errors &amp;&amp; curr_label == <span class="Constant">&quot;error&quot;</span><span class="Delimiter">))</span>
      cerr &lt;&lt; curr_label &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; curr_contents &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Normal">delete</span> curr_stream<span class="Delimiter">;</span>
  curr_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span>
  curr_label<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
  curr_depth = Max_depth<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

string trace_stream::readable_contents<span class="Delimiter">(</span>string label<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  ostringstream output<span class="Delimiter">;</span>
  label = trim<span class="Delimiter">(</span>label<span class="Delimiter">);</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span>vector&lt;trace_line&gt;::iterator p = past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span>  p != past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span>  ++p<span class="Delimiter">)</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>label<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || label == p<span class="Delimiter">-&gt;</span>label<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      output &lt;&lt; std::setw<span class="Delimiter">(</span><span class="Constant">4</span><span class="Delimiter">)</span> &lt;&lt; p<span class="Delimiter">-&gt;</span>depth &lt;&lt; <span class="Constant">' '</span> &lt;&lt; p<span class="Delimiter">-&gt;</span>label &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; p<span class="Delimiter">-&gt;</span>contents &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Identifier">return</span> output<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
trace_stream* Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span>
<span class="Normal">int</span> Trace_errors = <span class="Constant">0</span><span class="Delimiter">;</span>  <span class="Comment">// used only when Trace_stream is NULL</span>

<span class="Delimiter">:(before &quot;End Includes&quot;)</span>
<span class="PreProc">#define CLEAR_TRACE  </span><span class="Normal">delete</span><span class="PreProc"> Trace_stream</span><span class="Delimiter">,</span><span class="PreProc"> Trace_stream = </span><span class="Normal">new</span><span class="PreProc"> trace_stream</span><span class="Delimiter">;</span>

<span class="Comment">// Top-level helper. IMPORTANT: can't nest</span>
<span class="PreProc">#define trace(</span><span class="Delimiter">...</span><span class="PreProc">)  !Trace_stream ? cerr </span><span class="Comment">/*</span><span class="Comment">print nothing</span><span class="Comment">*/</span><span class="PreProc"> : Trace_stream</span><span class="Delimiter">-&gt;</span><span class="PreProc">stream(__VA_ARGS__)</span>

<span class="Comment">// Just for debugging; 'git log' should never show any calls to 'dbg'.</span>
<span class="PreProc">#define dbg trace(</span><span class="Constant">0</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">&quot;a&quot;</span><span class="PreProc">)</span>
<span class="PreProc">#define DUMP(label)  </span><span class="Normal">if</span><span class="PreProc"> (Trace_stream) cerr &lt;&lt; Trace_stream</span><span class="Delimiter">-&gt;</span><span class="PreProc">readable_contents(label)</span><span class="Delimiter">;</span>

<span class="Comment">// Errors are a special layer.</span>
<span class="PreProc">#define raise  (!Trace_stream ? (tb_shutdown()</span><span class="Delimiter">,</span><span class="PreProc">++Trace_errors</span><span class="Delimiter">,</span><span class="PreProc">cerr) </span><span class="Comment">/*</span><span class="Comment">do print</span><span class="Comment">*/</span><span class="PreProc"> : Trace_stream</span><span class="Delimiter">-&gt;</span><span class="PreProc">stream(Error_depth</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">&quot;error&quot;</span><span class="PreProc">))</span>

<span class="Comment">// Inside tests, fail any tests that displayed (unexpected) errors.</span>
<span class="Comment">// Expected errors in tests should always be hidden and silently checked for.</span>
<span class="Delimiter">:(before &quot;End Test Teardown&quot;)</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>Passed &amp;&amp; !Hide_errors &amp;&amp; trace_count<span class="Delimiter">(</span><span class="Constant">&quot;error&quot;</span><span class="Delimiter">)</span> &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
  Passed = <span class="Constant">false</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Types&quot;)</span>
<span class="Normal">struct</span> end <span class="Delimiter">{};</span>
<span class="Delimiter">:(code)</span>
ostream&amp; <span class="Normal">operator</span>&lt;&lt;<span class="Delimiter">(</span>ostream&amp; os<span class="Delimiter">,</span> unused end<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> Trace_stream<span class="Delimiter">-&gt;</span>newline<span class="Delimiter">();</span>
  <span class="Identifier">return</span> os<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
<span class="Normal">bool</span> Save_trace = <span class="Constant">false</span><span class="Delimiter">;</span>

<span class="Comment">// Trace_stream is a resource, lease_tracer uses RAII to manage it.</span>
<span class="Delimiter">:(before &quot;End Types&quot;)</span>
<span class="Normal">struct</span> lease_tracer <span class="Delimiter">{</span>
  lease_tracer<span class="Delimiter">();</span>
  ~lease_tracer<span class="Delimiter">();</span>
<span class="Delimiter">};</span>
<span class="Delimiter">:(code)</span>
lease_tracer::lease_tracer<span class="Delimiter">()</span> <span class="Delimiter">{</span> Trace_stream = <span class="Normal">new</span> trace_stream<span class="Delimiter">;</span> <span class="Delimiter">}</span>
lease_tracer::~lease_tracer<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>  <span class="Comment">// in case tests close Trace_stream</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>Save_trace<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    ofstream fout<span class="Delimiter">(</span><span class="Constant">&quot;last_trace&quot;</span><span class="Delimiter">);</span>
    fout &lt;&lt; Trace_stream<span class="Delimiter">-&gt;</span>readable_contents<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span>
    fout<span class="Delimiter">.</span>close<span class="Delimiter">();</span>
  <span class="Delimiter">}</span>
  <span class="Normal">delete</span> Trace_stream<span class="Delimiter">,</span> Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(before &quot;End Includes&quot;)</span>
<span class="PreProc">#define START_TRACING_UNTIL_END_OF_SCOPE  lease_tracer leased_tracer</span><span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End Test Setup&quot;)</span>
START_TRACING_UNTIL_END_OF_SCOPE

<span class="Delimiter">:(before &quot;End Includes&quot;)</span>
<span class="PreProc">#define CHECK_TRACE_CONTENTS(</span><span class="Delimiter">...</span><span class="PreProc">)  check_trace_contents(__FUNCTION__</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">__FILE__</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">__LINE__</span><span class="Delimiter">,</span><span class="PreProc"> __VA_ARGS__)</span>

<span class="PreProc">#define CHECK_TRACE_CONTAINS_ERROR()  CHECK(trace_count(</span><span class="Constant">&quot;error&quot;</span><span class="PreProc">) &gt; </span><span class="Constant">0</span><span class="PreProc">)</span>
<span class="PreProc">#define CHECK_TRACE_DOESNT_CONTAIN_ERROR() \</span>
<span class="PreProc">  </span><span class="Normal">if</span><span class="PreProc"> (Passed &amp;&amp; trace_count(</span><span class="Constant">&quot;error&quot;</span><span class="PreProc">) &gt; </span><span class="Constant">0</span><span class="PreProc">) </span><span class="Delimiter">{</span><span class="PreProc"> \</span>
<span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span><span class="PreProc"> &lt;&lt; __FUNCTION__ &lt;&lt; </span><span class="Constant">&quot;(&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__FILE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;:&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__LINE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;): unexpected errors</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
<span class="PreProc">    DUMP(</span><span class="Constant">&quot;error&quot;</span><span class="PreProc">)</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
<span class="PreProc">    Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
<span class="PreProc">    </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
<span class="PreProc">  </span><span class="Delimiter">}</span>

<span class="PreProc">#define CHECK_TRACE_COUNT(label</span><span class="Delimiter">,</span><span class="PreProc"> count) \</span>
<span class="PreProc">  </span><span class="Normal">if</span><span class="PreProc"> (Passed &amp;&amp; trace_count(label) != (count)) </span><span class="Delimiter">{</span><span class="PreProc"> \</span>
<span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span><span class="PreProc"> &lt;&lt; __FUNCTION__ &lt;&lt; </span><span class="Constant">&quot;(&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__FILE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;:&quot;</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">__LINE__</span><span class="PreProc"> &lt;&lt; </span><span class="Constant">&quot;): trace_count of &quot;</span><span class="PreProc"> &lt;&lt; label &lt;&lt; </span><span class="Constant">&quot; should be &quot;</span><span class="PreProc"> &lt;&lt; count &lt;&lt; </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
<span class="PreProc">    cerr &lt;&lt; </span><span class="Constant">&quot;  got &quot;</span><span class="PreProc"> &lt;&lt; trace_count(label) &lt;&lt; </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc">  </span><span class="Comment">/*</span><span class="Comment"> multiple eval </span><span class="Comment">*/</span><span class="PreProc"> \</span>
<span class="PreProc">    DUMP(label)</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
<span class="PreProc">    Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span>
<span class="PreProc">    </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc">  </span><span class="Comment">/*</span><span class="Comment"> Currently we stop at the very first failure. </span><span class="Comment">*/</span><span class="PreProc"> \</span>
<span class="PreProc">  </span><span class="Delimiter">}</span>

<span class="PreProc">#define CHECK_TRACE_DOESNT_CONTAIN(</span><span class="Delimiter">...</span><span class="PreProc">)  CHECK(trace_doesnt_contain(__VA_ARGS__))</span>

<span class="Delimiter">:(code)</span>
<span class="Normal">bool</span> check_trace_contents<span class="Delimiter">(</span>string FUNCTION<span class="Delimiter">,</span> string <span class="Normal">FILE</span><span class="Delimiter">,</span> <span class="Normal">int</span> LINE<span class="Delimiter">,</span> string expected<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!Passed<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
  vector&lt;string&gt; expected_lines = split<span class="Delimiter">(</span>expected<span class="Delimiter">,</span> <span class="Constant">&quot;^D&quot;</span><span class="Delimiter">);</span>
  <span class="Normal">int</span> curr_expected_line = <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Normal">while</span> <span class="Delimiter">(</span>curr_expected_line &lt; SIZE<span class="Delimiter">(</span>expected_lines<span class="Delimiter">)</span> &amp;&amp; expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">).</span>empty<span class="Delimiter">())</span>
    ++curr_expected_line<span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>curr_expected_line == SIZE<span class="Delimiter">(</span>expected_lines<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
  string label<span class="Delimiter">,</span> contents<span class="Delimiter">;</span>
  split_label_contents<span class="Delimiter">(</span>expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">),</span> &amp;label<span class="Delimiter">,</span> &amp;contents<span class="Delimiter">);</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span>vector&lt;trace_line&gt;::iterator p = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span>  p != Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span>  ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>label != p<span class="Delimiter">-&gt;</span>label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>contents != trim<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
    ++curr_expected_line<span class="Delimiter">;</span>
    <span class="Normal">while</span> <span class="Delimiter">(</span>curr_expected_line &lt; SIZE<span class="Delimiter">(</span>expected_lines<span class="Delimiter">)</span> &amp;&amp; expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">).</span>empty<span class="Delimiter">())</span>
      ++curr_expected_line<span class="Delimiter">;</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>curr_expected_line == SIZE<span class="Delimiter">(</span>expected_lines<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
    split_label_contents<span class="Delimiter">(</span>expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">),</span> &amp;label<span class="Delimiter">,</span> &amp;contents<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>

  <span class="Normal">if</span> <span class="Delimiter">(</span>line_exists_anywhere<span class="Delimiter">(</span>label<span class="Delimiter">,</span> contents<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    cerr &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; FUNCTION &lt;&lt; <span class="Constant">&quot;(&quot;</span> &lt;&lt; <span class="Normal">FILE</span> &lt;&lt; <span class="Constant">&quot;:&quot;</span> &lt;&lt; LINE &lt;&lt; <span class="Constant">&quot;): line [&quot;</span> &lt;&lt; label &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; contents &lt;&lt; <span class="Constant">&quot;] out of order in trace:</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
    DUMP<span class="Delimiter">(</span><span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  <span class="Normal">else</span> <span class="Delimiter">{</span>
    cerr &lt;&lt; <span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">F - &quot;</span> &lt;&lt; FUNCTION &lt;&lt; <span class="Constant">&quot;(&quot;</span> &lt;&lt; <span class="Normal">FILE</span> &lt;&lt; <span class="Constant">&quot;:&quot;</span> &lt;&lt; LINE &lt;&lt; <span class="Constant">&quot;): missing [&quot;</span> &lt;&lt; contents &lt;&lt; <span class="Constant">&quot;] in trace:</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
    DUMP<span class="Delimiter">(</span>label<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  Passed = <span class="Constant">false</span><span class="Delimiter">;</span>
  <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Normal">void</span> split_label_contents<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; s<span class="Delimiter">,</span> string* label<span class="Delimiter">,</span> string* contents<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">static</span> <span class="Normal">const</span> string delim<span class="Delimiter">(</span><span class="Constant">&quot;: &quot;</span><span class="Delimiter">);</span>
  <span class="Normal">size_t</span> pos = s<span class="Delimiter">.</span>find<span class="Delimiter">(</span>delim<span class="Delimiter">);</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>pos == string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    *label = <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span>
    *contents = trim<span class="Delimiter">(</span>s<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  <span class="Normal">else</span> <span class="Delimiter">{</span>
    *label = trim<span class="Delimiter">(</span>s<span class="Delimiter">.</span>substr<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> pos<span class="Delimiter">));</span>
    *contents = trim<span class="Delimiter">(</span>s<span class="Delimiter">.</span>substr<span class="Delimiter">(</span>pos+SIZE<span class="Delimiter">(</span>delim<span class="Delimiter">)));</span>
  <span class="Delimiter">}</span>
<span class="Delimiter">}</span>

<span class="Normal">bool</span> line_exists_anywhere<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; label<span class="Delimiter">,</span> <span class="Normal">const</span> string&amp; contents<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span>vector&lt;trace_line&gt;::iterator p = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span>  p != Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span>  ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>label != p<span class="Delimiter">-&gt;</span>label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>contents == trim<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Normal">int</span> trace_count<span class="Delimiter">(</span>string label<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Identifier">return</span> trace_count<span class="Delimiter">(</span>label<span class="Delimiter">,</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Normal">int</span> trace_count<span class="Delimiter">(</span>string label<span class="Delimiter">,</span> string line<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Normal">long</span> result = <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span>vector&lt;trace_line&gt;::iterator p = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span>  p != Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span>  ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>label == p<span class="Delimiter">-&gt;</span>label<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      <span class="Normal">if</span> <span class="Delimiter">(</span>line == <span class="Constant">&quot;&quot;</span> || trim<span class="Delimiter">(</span>line<span class="Delimiter">)</span> == trim<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">))</span>
        ++result<span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Normal">int</span> trace_count_prefix<span class="Delimiter">(</span>string label<span class="Delimiter">,</span> string prefix<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Normal">long</span> result = <span class="Constant">0</span><span class="Delimiter">;</span>
  <span class="Normal">for</span> <span class="Delimiter">(</span>vector&lt;trace_line&gt;::iterator p = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span>  p != Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span>  ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>label == p<span class="Delimiter">-&gt;</span>label<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      <span class="Normal">if</span> <span class="Delimiter">(</span>starts_with<span class="Delimiter">(</span>trim<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">),</span> trim<span class="Delimiter">(</span>prefix<span class="Delimiter">)))</span>
        ++result<span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Normal">bool</span> trace_doesnt_contain<span class="Delimiter">(</span>string label<span class="Delimiter">,</span> string line<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Identifier">return</span> trace_count<span class="Delimiter">(</span>label<span class="Delimiter">,</span> line<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="Normal">bool</span> trace_doesnt_contain<span class="Delimiter">(</span>string expected<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  vector&lt;string&gt; tmp = split_first<span class="Delimiter">(</span>expected<span class="Delimiter">,</span> <span class="Constant">&quot;: &quot;</span><span class="Delimiter">);</span>
  <span class="Identifier">return</span> trace_doesnt_contain<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">));</span>
<span class="Delimiter">}</span>

vector&lt;string&gt; split<span class="Delimiter">(</span>string s<span class="Delimiter">,</span> string delim<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  vector&lt;string&gt; result<span class="Delimiter">;</span>
  <span class="Normal">size_t</span> begin=<span class="Constant">0</span><span class="Delimiter">,</span> end=s<span class="Delimiter">.</span>find<span class="Delimiter">(</span>delim<span class="Delimiter">);</span>
  <span class="Normal">while</span> <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
    <span class="Normal">if</span> <span class="Delimiter">(</span>end == string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span>
      result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>string<span class="Delimiter">(</span>s<span class="Delimiter">,</span> begin<span class="Delimiter">,</span> string::npos<span class="Delimiter">));</span>
      <span class="Identifier">break</span><span class="Delimiter">;</span>
    <span class="Delimiter">}</span>
    result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>string<span class="Delimiter">(</span>s<span class="Delimiter">,</span> begin<span class="Delimiter">,</span> end-begin<span class="Delimiter">));</span>
    begin = end+SIZE<span class="Delimiter">(</span>delim<span class="Delimiter">);</span>
    end = s<span class="Delimiter">.</span>find<span class="Delimiter">(</span>delim<span class="Delimiter">,</span> begin<span class="Delimiter">);</span>
  <span class="Delimiter">}</span>
  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

vector&lt;string&gt; split_first<span class="Delimiter">(</span>string s<span class="Delimiter">,</span> string delim<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  vector&lt;string&gt; result<span class="Delimiter">;</span>
  <span class="Normal">size_t</span> end=s<span class="Delimiter">.</span>find<span class="Delimiter">(</span>delim<span class="Delimiter">);</span>
  result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>string<span class="Delimiter">(</span>s<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">,</span> end<span class="Delimiter">));</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>end != string::npos<span class="Delimiter">)</span>
    result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>string<span class="Delimiter">(</span>s<span class="Delimiter">,</span> end+SIZE<span class="Delimiter">(</span>delim<span class="Delimiter">),</span> string::npos<span class="Delimiter">));</span>
  <span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>

string trim<span class="Delimiter">(</span><span class="Normal">const</span> string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  string::const_iterator first = s<span class="Delimiter">.</span>begin<span class="Delimiter">();</span>
  <span class="Normal">while</span> <span class="Delimiter">(</span>first != s<span class="Delimiter">.</span>end<span class="Delimiter">()</span> &amp;&amp; isspace<span class="Delimiter">(</span>*first<span class="Delimiter">))</span>
    ++first<span class="Delimiter">;</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>first == s<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">&quot;&quot;</span><span class="Delimiter">;</span>

  string::const_iterator last = --s<span class="Delimiter">.</span>end<span class="Delimiter">();</span>
  <span class="Normal">while</span> <span class="Delimiter">(</span>last != s<span class="Delimiter">.</span>begin<span class="Delimiter">()</span> &amp;&amp; isspace<span class="Delimiter">(</span>*last<span class="Delimiter">))</span>
    --last<span class="Delimiter">;</span>
  ++last<span class="Delimiter">;</span>
  <span class="Identifier">return</span> string<span class="Delimiter">(</span>first<span class="Delimiter">,</span> last<span class="Delimiter">);</span>
<span class="Delimiter">}</span>

<span class="Delimiter">:(before &quot;End Includes&quot;)</span>
<span class="PreProc">#include </span><span class="Constant">&lt;vector&gt;</span>
<span class="Normal">using</span> std::vector<span class="Delimiter">;</span>
<span class="PreProc">#include </span><span class="Constant">&lt;list&gt;</span>
<span class="Normal">using</span> std::list<span class="Delimiter">;</span>
<span class="PreProc">#include </span><span class="Constant">&lt;map&gt;</span>
<span class="Normal">using</span> std::map<span class="Delimiter">;</span>
<span class="PreProc">#include </span><span class="Constant">&lt;set&gt;</span>
<span class="Normal">using</span> std::set<span class="Delimiter">;</span>
<span class="PreProc">#include </span><span class="Constant">&lt;algorithm&gt;</span>

<span class="PreProc">#include </span><span class="Constant">&lt;sstream&gt;</span>
<span class="Normal">using</span> std::istringstream<span class="Delimiter">;</span>
<span class="Normal">using</span> std::ostringstream<span class="Delimiter">;</span>

<span class="PreProc">#include </span><span class="Constant">&lt;fstream&gt;</span>
<span class="Normal">using</span> std::ifstream<span class="Delimiter">;</span>
<span class="Normal">using</span> std::ofstream<span class="Delimiter">;</span>

<span class="PreProc">#include </span><span class="Constant">&quot;termbox/termbox.h&quot;</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
<span class="Comment">//: In future layers we'll use the depth field as follows:</span>
<span class="Comment">//:</span>
<span class="Comment">//: Errors will be depth 0.</span>
<span class="Comment">//: Mu 'applications' will be able to use depths 1-100 as they like.</span>
<span class="Comment">//: Primitive statements will occupy 101-9989</span>
<span class="Normal">extern</span> <span class="Normal">const</span> <span class="Normal">int</span> Initial_callstack_depth = <span class="Constant">101</span><span class="Delimiter">;</span>
<span class="Normal">extern</span> <span class="Normal">const</span> <span class="Normal">int</span> Max_callstack_depth = <span class="Constant">9989</span><span class="Delimiter">;</span>
<span class="Comment">//: Finally, details of primitive mu statements will occupy depth 9990-9999 (more on that later as well)</span>
<span class="Comment">//:</span>
<span class="Comment">//: This framework should help us hide some details at each level, mixing</span>
<span class="Comment">//: static ideas like layers with the dynamic notion of call-stack depth.</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->