about summary refs log tree commit diff stats
path: root/cpp/literate
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-02-18 14:48:19 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-02-18 14:48:19 -0800
commit01b2852b653a81c4d5e197a0c52659c7e0dcaf5f (patch)
tree9c9864846c27191afd73b4c1a44810ac0fdd1091 /cpp/literate
parent9fc64bbc95bb4e55f28f5262d0f5c660177f0a19 (diff)
downloadmu-01b2852b653a81c4d5e197a0c52659c7e0dcaf5f.tar.gz
782 - promote literate version to canonical C++ version
Diffstat (limited to 'cpp/literate')
-rw-r--r--cpp/literate/000organization111
-rw-r--r--cpp/literate/001test79
-rw-r--r--cpp/literate/002trace478
-rw-r--r--cpp/literate/002trace.tests164
-rw-r--r--cpp/literate/009includes48
-rw-r--r--cpp/literate/010vm145
-rw-r--r--cpp/literate/011load150
-rw-r--r--cpp/literate/012run41
-rwxr-xr-xcpp/literate/build_and_test_until7
-rw-r--r--cpp/literate/makefile26
-rw-r--r--cpp/literate/tangle/000test.cc26
-rw-r--r--cpp/literate/tangle/001trace.cc338
-rw-r--r--cpp/literate/tangle/001trace.test.cc164
-rw-r--r--cpp/literate/tangle/002main.cc61
-rw-r--r--cpp/literate/tangle/030tangle.cc355
-rw-r--r--cpp/literate/tangle/030tangle.test.cc251
-rw-r--r--cpp/literate/tangle/boot.cc63
-rw-r--r--cpp/literate/tangle/makefile23
-rw-r--r--cpp/literate/vimrc.vim18
19 files changed, 0 insertions, 2548 deletions
diff --git a/cpp/literate/000organization b/cpp/literate/000organization
deleted file mode 100644
index ba82dd52..00000000
--- a/cpp/literate/000organization
+++ /dev/null
@@ -1,111 +0,0 @@
-// You guessed right: the '000' prefix means you should start reading here.
-//
-// This project is setup to load all files with a numeric prefix. Just create
-// a new file and start hacking.
-//
-// The first few files (00*) are independent of what this program does, an
-// experimental skeleton that will hopefully make it both easier for others to
-// understand and more malleable, easier to rewrite and remould into radically
-// different shapes without breaking in subtle corner cases. The premise is
-// that understandability and rewrite-friendliness are related in a virtuous
-// cycle. Doing one well makes it easier to do the other.
-//
-// Lower down, this file contains a legal, bare-bones C++ program. It doesn't
-// do anything yet; subsequent files will add behaviors by inserting lines
-// into it with directives like:
-//   :(after "more events")
-// This will insert the following lines after a line in the program containing
-// the words "more events".
-//
-// Directives free up the programmer to order code for others to read rather
-// than as forced by the computer or compiler. Each individual feature can be
-// organized in a self-contained 'layer' that adds code to many different data
-// structures and functions all over the program. The right decomposition into
-// layers will let each layer make sense in isolation.
-//
-//   "If I look at any small part of it, I can see what is going on -- I don't
-//   need to refer to other parts to understand what something is doing.
-//
-//   If I look at any large part in overview, I can see what is going on -- I
-//   don't need to know all the details to get it.
-//
-//   Every level of detail is as locally coherent and as well thought-out as
-//   any other level."
-//
-//       -- Richard Gabriel, "The Quality Without A Name"
-//          (http://dreamsongs.com/Files/PatternsOfSoftware.pdf, page 42)
-//
-// Directives are powerful; they permit inserting or modifying any point in
-// the program. Using them tastefully requires mapping out specific lines as
-// waypoints for future layers to hook into. Often such waypoints will be in
-// comments, capitalized to hint that other layers rely on their presence.
-//
-// A single waypoint might have many different code fragments hooking into
-// it from all over the codebase. Use 'before' directives to insert
-// code at a location in order, top to bottom, and 'after' directives to
-// insert code in reverse order. By convention waypoints intended for insertion
-// before begin with 'End'. Notice below how the layers line up above the "End
-// Foo" waypoint.
-//
-//   File 001          File 002                File 003
-//   ============      ===================     ===================
-//   // Foo
-//   ------------
-//              <----  :(before "End Foo")
-//                     ....
-//                     ...
-//   ------------
-//              <----------------------------  :(before "End Foo")
-//                                             ....
-//                                             ...
-//   // End Foo
-//   ============
-//
-// Here's part of a layer in color: http://i.imgur.com/0eONnyX.png. Directives
-// are shaded dark. Notice the references to waypoints lower down in this
-// file.
-//
-// Layers do more than just shuffle code around. Past the initial skeleton of
-// this program (currently 00*-02*), it ought to be possible to stop loading
-// after any file/layer, build and run the program, and pass all tests for
-// loaded features. (Relevant is http://youtube.com/watch?v=c8N72t7aScY, a
-// scene from "2001: A Space Odyssey".)
-//
-// This 'subsetting guarantee' ensures that this directory contains a
-// cleaned-up narrative of the evolution of this codebase. Organizing
-// autobiographically allows a newcomer to rapidly orient himself, reading the
-// first few files to understand a simple gestalt of a program's core purpose
-// and features, and later gradually working his way through other features as
-// the need arises. Each step should be as simple as possible (but no simpler).
-//
-// Programmers shouldn't need to understand everything about a program to hack
-// on it. But they shouldn't be prevented from a thorough understanding of
-// each aspect either. The goal of layers is to reward curiosity.
-
-// Includes
-// End Includes
-
-// Types
-// End Types
-
-// prototypes are auto-generated; define your functions in any order
-#include "function_list"  // by convention, files ending with '_list' are auto-generated
-
-// Globals
-// End Globals
-
-int main(int argc, char* argv[]) {
-  if (argc > 1) {
-    // Commandline Options
-  }
-
-  setup();
-  return 0;  // End Main
-}
-
-void setup() {
-  // End Setup
-}
-
-// Without directives or with the :(code) directive, lines get added at the
-// end.
diff --git a/cpp/literate/001test b/cpp/literate/001test
deleted file mode 100644
index 45ec591d..00000000
--- a/cpp/literate/001test
+++ /dev/null
@@ -1,79 +0,0 @@
-// A simple test harness. To create new tests define functions starting with
-// 'test_'. To run all tests so defined, run:
-//   $ wart test
-//
-// So far it seems tasteful for layers to never ever reach back to modify
-// previously-defined tests. Every test is a contract once written, and should
-// pass as-is if it is included, regardless of how much later layers change
-// the program. Avoid writing 'temporary' tests that only work with some
-// subsets of the program.
-
-:(before "End Types")
-typedef void (*test_fn)(void);
-
-:(before "End Globals")
-const test_fn Tests[] = {
-  #include "test_list"  // auto-generated; see makefile
-};
-
-bool Passed = true;
-
-long Num_failures = 0;
-
-#define CHECK(X) \
-  if (!(X)) { \
-    ++Num_failures; \
-    cerr << "\nF " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): " << #X << '\n'; \
-    Passed = false; \
-    return; \
-  }
-
-#define CHECK_EQ(X, Y) \
-  if ((X) != (Y)) { \
-    ++Num_failures; \
-    cerr << "\nF " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): " << #X << " == " << #Y << '\n'; \
-    cerr << "  got " << (X) << '\n';  /* BEWARE: multiple eval */ \
-    Passed = false; \
-    return; \
-  }
-
-:(after "Commandline Options")
-  if (is_equal(argv[1], "test")) {
-    run_tests();
-    return 0;
-  }
-
-:(code)
-void run_tests() {
-  time_t t; time(&t);
-  cerr << "C tests: " << ctime(&t);
-  for (unsigned long i=0; i < sizeof(Tests)/sizeof(Tests[0]); ++i) {
-    setup();
-    // End Test Setup
-    (*Tests[i])();
-    if (Passed) cerr << ".";
-    // Test Teardown
-    // End Test Teardown
-  }
-
-  cerr << '\n';
-  if (Num_failures > 0)
-    cerr << Num_failures << " failure"
-         << (Num_failures > 1 ? "s" : "")
-         << '\n';
-}
-
-bool is_equal(char* s, const char* lit) {
-  return strncmp(s, lit, strlen(lit)) == 0;
-}
-
-:(before "End Includes")
-#include<iostream>
-using std::istream;
-using std::ostream;
-using std::iostream;
-using std::cin;
-using std::cout;
-using std::cerr;
-
-#include<cstring>
diff --git a/cpp/literate/002trace b/cpp/literate/002trace
deleted file mode 100644
index 4d584cb1..00000000
--- a/cpp/literate/002trace
+++ /dev/null
@@ -1,478 +0,0 @@
-// The goal of this skeleton is to make programs more easy to understand and
-// more malleable, easy to rewrite in radical ways without accidentally
-// breaking some corner case. Tests further both goals. They help
-// understandability by letting one make small changes and get feedback. What
-// if I wrote this line like so? What if I removed this function call, is it
-// really necessary? Just try it, see if the tests pass. Want to explore
-// rewriting this bit in this way? Tests put many refactorings on a firmer
-// footing.
-//
-// But the usual way we write tests seems incomplete. Refactorings tend to
-// work in the small, but don't help with changes to function boundaries. If
-// you want to extract a new function you have to manually test-drive it to
-// create tests for it. If you want to inline a function its tests are no
-// longer valid. In both cases you end up having to reorganize code as well as
-// tests, an error-prone activity.
-//
-// This file tries to fix this problem by supporting domain-driven testing
-// rather than coverage-driven testing. The goal isn't to test all possible
-// paths in the code any longer, but to focus on the domain of inputs the
-// program should work on. All tests invoke the program in a single way: by
-// calling run() with different inputs. The program operates on the input and
-// logs _facts_ it deduces to a trace:
-//   trace("label") << "fact 1: " << val;
-//
-// The tests check for facts:
-//   :(scenario foo)
-//   34  # call run() with this input
-//   +label: fact 1: 34  # trace should have logged this at the end
-//   -label: fact 1: 35  # trace should never contain such a line
-//
-// Since we never call anything but the run() function directly, we never have
-// to rewrite the tests when we reorganize the internals of the program. We
-// just have to make sure our rewrite deduces the same facts about the domain,
-// and that's something we're going to have to do anyway.
-//
-// To avoid the combinatorial explosion of integration tests, we organize the
-// program into different layers, and each fact is logged to the trace with a
-// specific label. Individual tests can focus on specific labels. In essence,
-// validating the facts logged with a specific label is identical to calling
-// some internal subsystem.
-//
-// Traces interact salubriously with layers. Thanks to our ordering
-// directives, each layer can contain its own tests. They may rely on other
-// layers, but when a test fails its usually due to breakage in the same
-// layer. When multiple tests fail, it's usually useful to debug the very
-// first test to fail. This is in contrast with the traditional approach,
-// where changes can cause breakages in faraway subsystems, and picking the
-// right test to debug can be an important skill to pick up.
-//
-// A final wrinkle is for recursive functions; it's often useful to segment
-// calls of different depth in the trace:
-//   +eval/1: => 34  # the topmost call to eval should have logged this line
-// (look at new_trace_frame below)
-//
-// To build robust tests, trace facts about your domain rather than details of
-// how you computed them.
-//
-// More details: http://akkartik.name/blog/tracing-tests
-//
-// ---
-//
-// Between layers and domain-driven testing, programming starts to look like a
-// fundamentally different activity. Instead of a) superficial, b) local rules
-// on c) code [like http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet],
-// we allow programmers to engage with the a) deep, b) global structure of the
-// c) domain. If you can systematically track discontinuities in the domain
-// you don't care if the code used gotos as long as it passed the tests. If
-// tests become more robust to run it becomes easier to try out radically
-// different implementations for the same program. If code is super-easy to
-// rewrite, it becomes less important what indentation style it uses, or that
-// the objects are appropriately encapsulated, or that the functions are
-// referentially transparent.
-//
-// Instead of plumbing, programming becomes building and gradually refining a
-// map of the environment the program must operate under. Whether a program is
-// 'correct' at a given point in time is a red herring; what matters is
-// avoiding regression by monotonically nailing down the more 'eventful' parts
-// of the terrain. It helps readers new and old and rewards curiosity to
-// organize large programs in self-similar hiearchies of example scenarios
-// colocated with the code that makes them work.
-//
-//   "Programming properly should be regarded as an activity by which
-//   programmers form a mental model, rather than as production of a program."
-//   -- Peter Naur (http://alistair.cockburn.us/ASD+book+extract%3A+%22Naur,+Ehn,+Musashi%22)
-
-:(before "int main")
-// End Tracing  // hack to ensure most code in this layer comes before anything else
-
-:(before "End Tracing")
-bool Hide_warnings = false;
-:(before "End Setup")
-Hide_warnings = false;
-
-:(before "End Tracing")
-struct trace_stream {
-  vector<pair<string, pair<int, string> > > past_lines;  // [(layer label, frame, line)]
-  unordered_map<string, int> frame;
-  // accumulator for current line
-  ostringstream* curr_stream;
-  string curr_layer;
-  string dump_layer;
-  trace_stream() :curr_stream(NULL) {}
-  ~trace_stream() { if (curr_stream) delete curr_stream; }
-
-  ostringstream& stream(string layer) {
-    newline();
-    curr_stream = new ostringstream;
-    curr_layer = layer;
-    return *curr_stream;
-  }
-
-  // be sure to call this before messing with curr_stream or curr_layer or frame
-  void newline() {
-    if (!curr_stream) return;
-    past_lines.push_back(pair<string, pair<int, string> >(curr_layer, pair<int, string>(frame[curr_layer], curr_stream->str())));
-    if (curr_layer == dump_layer || curr_layer == "dump" ||
-        (!Hide_warnings && curr_layer == "warn"))
-      cerr << frame[curr_layer] << ": " << with_newline(curr_stream->str());
-    delete curr_stream;
-    curr_stream = NULL;
-  }
-
-  // Useful for debugging.
-  string readable_contents(string layer) {  // missing layer = everything, frame, hierarchical layers
-    newline();
-    ostringstream output;
-    string real_layer, frame;
-    parse_layer_and_frame(layer, &real_layer, &frame);
-    for (vector<pair<string, pair<int, string> > >::iterator p = past_lines.begin(); p != past_lines.end(); ++p)
-      if (layer.empty() || prefix_match(real_layer, p->first))
-        output << p->first << "/" << p->second.first << ": " << with_newline(p->second.second);
-    return output.str();
-  }
-
-  // Useful for a newcomer to visualize the program at work.
-  void dump_browseable_contents(string layer) {
-    ofstream dump("dump");
-    dump << "<div class='frame' frame_index='1'>start</div>\n";
-    for (vector<pair<string, pair<int, string> > >::iterator p = past_lines.begin(); p != past_lines.end(); ++p) {
-      if (p->first != layer) continue;
-      dump << "<div class='frame";
-      if (p->second.first > 1) dump << " hidden";
-      dump << "' frame_index='" << p->second.first << "'>";
-      dump << p->second.second;
-      dump << "</div>\n";
-    }
-    dump.close();
-  }
-
-  string with_newline(string s) {
-    if (s[s.size()-1] != '\n') return s+'\n';
-    return s;
-  }
-};
-
-
-
-trace_stream* Trace_stream = NULL;
-
-// Top-level helper. IMPORTANT: can't nest.
-#define trace(layer)  !Trace_stream ? cerr /*print nothing*/ : Trace_stream->stream(layer)
-// Warnings should go straight to cerr by default since calls to trace() have
-// some unfriendly constraints (they delay printing, they can't nest)
-#define raise  ((!Trace_stream || !Hide_warnings) ? cerr /*do print*/ : Trace_stream->stream("warn")) << __FILE__ << ":" << __LINE__ << " "
-
-// A separate helper for debugging. We should only trace domain-specific
-// facts. For everything else use log.
-#define xlog if (false) log
-// To turn on logging replace 'xlog' with 'log'.
-#define log cerr
-
-:(before "End Types")
-// raise << die exits after printing -- unless Hide_warnings is set.
-struct die {};
-:(before "End Tracing")
-ostream& operator<<(ostream& os, unused die) {
-  if (Hide_warnings) return os;
-  os << "dying";
-  if (Trace_stream) Trace_stream->newline();
-  exit(1);
-}
-
-#define CLEAR_TRACE  delete Trace_stream, Trace_stream = new trace_stream;
-
-#define DUMP(layer)  cerr << Trace_stream->readable_contents(layer)
-
-// Trace_stream is a resource, lease_tracer uses RAII to manage it.
-struct lease_tracer {
-  lease_tracer() { Trace_stream = new trace_stream; }
-  ~lease_tracer() { delete Trace_stream, Trace_stream = NULL; }
-};
-
-#define START_TRACING_UNTIL_END_OF_SCOPE  lease_tracer leased_tracer;
-:(before "End Test Setup")
-  START_TRACING_UNTIL_END_OF_SCOPE
-
-:(before "End Tracing")
-void trace_all(const string& label, const list<string>& in) {
-  for (list<string>::const_iterator p = in.begin(); p != in.end(); ++p)
-    trace(label) << *p;
-}
-
-bool check_trace_contents(string FUNCTION, string FILE, int LINE, string expected) {  // missing layer == anywhere, frame, hierarchical layers
-  vector<string> expected_lines = split(expected, "");
-  size_t curr_expected_line = 0;
-  while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-    ++curr_expected_line;
-  if (curr_expected_line == expected_lines.size()) return true;
-  Trace_stream->newline();
-  ostringstream output;
-  string layer, frame, contents;
-  parse_layer_frame_contents(expected_lines[curr_expected_line], &layer, &frame, &contents);
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (!layer.empty() && !prefix_match(layer, p->first))
-      continue;
-
-    if (!frame.empty() && strtol(frame.c_str(), NULL, 0) != p->second.first)
-      continue;
-
-    if (contents != p->second.second)
-      continue;
-
-    ++curr_expected_line;
-    while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-      ++curr_expected_line;
-    if (curr_expected_line == expected_lines.size()) return true;
-    parse_layer_frame_contents(expected_lines[curr_expected_line], &layer, &frame, &contents);
-  }
-
-  ++Num_failures;
-  cerr << "\nF " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << contents << "] in trace:\n";
-  DUMP(layer);
-  Passed = false;
-  return false;
-}
-
-void parse_layer_frame_contents(const string& orig, string* layer, string* frame, string* contents) {
-  string layer_and_frame;
-  parse_contents(orig, ": ", &layer_and_frame, contents);
-  parse_layer_and_frame(layer_and_frame, layer, frame);
-}
-
-void parse_contents(const string& s, const string& delim, string* prefix, string* contents) {
-  string::size_type pos = s.find(delim);
-  if (pos == NOT_FOUND) {
-    *prefix = "";
-    *contents = s;
-  }
-  else {
-    *prefix = s.substr(0, pos);
-    *contents = s.substr(pos+delim.size());
-  }
-}
-
-void parse_layer_and_frame(const string& orig, string* layer, string* frame) {
-  size_t last_slash = orig.rfind('/');
-  if (last_slash == NOT_FOUND
-      || orig.find_last_not_of("0123456789") != last_slash) {
-    *layer = orig;
-    *frame = "";
-  }
-  else {
-    *layer = orig.substr(0, last_slash);
-    *frame = orig.substr(last_slash+1);
-  }
-}
-
-
-
-bool check_trace_contents(string FUNCTION, string FILE, int LINE, string layer, string expected) {  // empty layer == everything, multiple layers, hierarchical layers
-  vector<string> expected_lines = split(expected, "");
-  size_t curr_expected_line = 0;
-  while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-    ++curr_expected_line;
-  if (curr_expected_line == expected_lines.size()) return true;
-  Trace_stream->newline();
-  ostringstream output;
-  vector<string> layers = split(layer, ",");
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (!layer.empty() && !any_prefix_match(layers, p->first))
-      continue;
-    if (p->second.second != expected_lines[curr_expected_line])
-      continue;
-    ++curr_expected_line;
-    while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-      ++curr_expected_line;
-    if (curr_expected_line == expected_lines.size()) return true;
-  }
-
-  ++Num_failures;
-  cerr << "\nF " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << expected_lines[curr_expected_line] << "] in trace:\n";
-  DUMP(layer);
-  Passed = false;
-  return false;
-}
-
-#define CHECK_TRACE_CONTENTS(...)  check_trace_contents(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
-
-int trace_count(string layer) {
-  return trace_count(layer, "");
-}
-
-int trace_count(string layer, string line) {
-  Trace_stream->newline();
-  long result = 0;
-  vector<string> layers = split(layer, ",");
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (any_prefix_match(layers, p->first))
-      if (line == "" || p->second.second == line)
-        ++result;
-  }
-  return result;
-}
-
-int trace_count(string layer, int frame, string line) {
-  Trace_stream->newline();
-  long result = 0;
-  vector<string> layers = split(layer, ",");
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (any_prefix_match(layers, p->first) && p->second.first == frame)
-      if (line == "" || p->second.second == line)
-        ++result;
-  }
-  return result;
-}
-
-#define CHECK_TRACE_WARNS()  CHECK(trace_count("warn") > 0)
-#define CHECK_TRACE_DOESNT_WARN() \
-  if (trace_count("warn") > 0) { \
-    ++Num_failures; \
-    cerr << "\nF " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): unexpected warnings\n"; \
-    DUMP("warn"); \
-    Passed = false; \
-    return; \
-  }
-
-bool trace_doesnt_contain(string layer, string line) {
-  return trace_count(layer, line) == 0;
-}
-
-bool trace_doesnt_contain(string expected) {
-  vector<string> tmp = split(expected, ": ");
-  return trace_doesnt_contain(tmp[0], tmp[1]);
-}
-
-bool trace_doesnt_contain(string layer, int frame, string line) {
-  return trace_count(layer, frame, line) == 0;
-}
-
-#define CHECK_TRACE_DOESNT_CONTAIN(...)  CHECK(trace_doesnt_contain(__VA_ARGS__))
-
-
-
-// manage layer counts in Trace_stream using RAII
-struct lease_trace_frame {
-  string layer;
-  lease_trace_frame(string l) :layer(l) {
-    if (!Trace_stream) return;
-    Trace_stream->newline();
-    ++Trace_stream->frame[layer];
-  }
-  ~lease_trace_frame() {
-    if (!Trace_stream) return;
-    Trace_stream->newline();
-    --Trace_stream->frame[layer];
-  }
-};
-#define new_trace_frame(layer)  lease_trace_frame leased_frame(layer);
-
-bool check_trace_contents(string FUNCTION, string FILE, int LINE, string layer, int frame, string expected) {  // multiple layers, hierarchical layers
-  vector<string> expected_lines = split(expected, "");  // hack: doesn't handle newlines in embedded in lines
-  size_t curr_expected_line = 0;
-  while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-    ++curr_expected_line;
-  if (curr_expected_line == expected_lines.size()) return true;
-  Trace_stream->newline();
-  ostringstream output;
-  vector<string> layers = split(layer, ",");
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (!layer.empty() && !any_prefix_match(layers, p->first))
-      continue;
-    if (p->second.first != frame)
-      continue;
-    if (p->second.second != expected_lines[curr_expected_line])
-      continue;
-    ++curr_expected_line;
-    while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-      ++curr_expected_line;
-    if (curr_expected_line == expected_lines.size()) return true;
-  }
-
-  ++Num_failures;
-  cerr << "\nF " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << expected_lines[curr_expected_line] << "] in trace/" << frame << ":\n";
-  DUMP(layer);
-  Passed = false;
-  return false;
-}
-
-#define CHECK_TRACE_TOP(layer, expected)  CHECK_TRACE_CONTENTS(layer, 1, expected)
-
-
-
-vector<string> split(string s, string delim) {
-  vector<string> result;
-  string::size_type begin=0, end=s.find(delim);
-  while (true) {
-    if (end == NOT_FOUND) {
-      result.push_back(string(s, begin, NOT_FOUND));
-      break;
-    }
-    result.push_back(string(s, begin, end-begin));
-    begin = end+delim.size();
-    end = s.find(delim, begin);
-  }
-  return result;
-}
-
-bool any_prefix_match(const vector<string>& pats, const string& needle) {
-  if (pats.empty()) return false;
-  if (*pats[0].rbegin() != '/')
-    // prefix match not requested
-    return find(pats.begin(), pats.end(), needle) != pats.end();
-  // first pat ends in a '/'; assume all pats do.
-  for (vector<string>::const_iterator p = pats.begin(); p != pats.end(); ++p)
-    if (headmatch(needle, *p)) return true;
-  return false;
-}
-
-bool prefix_match(const string& pat, const string& needle) {
-  if (*pat.rbegin() != '/')
-    // prefix match not requested
-    return pat == needle;
-  return headmatch(needle, pat);
-}
-
-bool headmatch(const string& s, const string& pat) {
-  if (pat.size() > s.size()) return false;
-  return std::mismatch(pat.begin(), pat.end(), s.begin()).first == pat.end();
-}
-
-:(before "End Includes")
-#include<cstdlib>
-
-#include<string>
-using std::string;
-#define NOT_FOUND string::npos
-
-#include<vector>
-using std::vector;
-#include<list>
-using std::list;
-#include<utility>
-using std::pair;
-
-#include<tr1/unordered_map>
-using std::tr1::unordered_map;
-#include<tr1/unordered_set>
-using std::tr1::unordered_set;
-#include<algorithm>
-
-#include<iostream>
-using std::istream;
-using std::ostream;
-using std::iostream;
-using std::cin;
-using std::cout;
-using std::cerr;
-
-#include<sstream>
-using std::stringstream;
-using std::istringstream;
-using std::ostringstream;
-
-#include<fstream>
-using std::ifstream;
-using std::ofstream;
-
-#define unused  __attribute__((unused))
diff --git a/cpp/literate/002trace.tests b/cpp/literate/002trace.tests
deleted file mode 100644
index 00705346..00000000
--- a/cpp/literate/002trace.tests
+++ /dev/null
@@ -1,164 +0,0 @@
-void test_trace_check_compares() {
-  CHECK_TRACE_CONTENTS("test layer", "");
-  trace("test layer") << "foo";
-  CHECK_TRACE_CONTENTS("test layer", "foo");
-}
-
-void test_trace_check_filters_layers() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  CHECK_TRACE_CONTENTS("test layer 1", "foo");
-}
-
-void test_trace_check_ignores_other_lines() {
-  trace("test layer 1") << "foo";
-  trace("test layer 1") << "bar";
-  CHECK_TRACE_CONTENTS("test layer 1", "foo");
-}
-
-void test_trace_check_always_finds_empty_lines() {
-  CHECK_TRACE_CONTENTS("test layer 1", "");
-}
-
-void test_trace_check_treats_empty_layers_as_wildcards() {
-  trace("test layer 1") << "foo";
-  CHECK_TRACE_CONTENTS("", "foo");
-}
-
-void test_trace_check_multiple_lines_at_once() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  CHECK_TRACE_CONTENTS("", "foobar");
-}
-
-void test_trace_check_always_finds_empty_lines2() {
-  CHECK_TRACE_CONTENTS("test layer 1", "");
-}
-
-void test_trace_orders_across_layers() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("", "foobarqux");
-}
-
-void test_trace_orders_across_layers2() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("foobarqux");
-}
-
-void test_trace_checks_ordering_spanning_multiple_layers() {
-  trace("layer1") << "foo";
-  trace("layer2") << "bar";
-  trace("layer1") << "qux";
-  CHECK_TRACE_CONTENTS("layer1: foolayer2: barlayer1: qux");
-}
-
-void test_trace_segments_within_layers() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  new_trace_frame("test layer 1");
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("test layer 1", "fooqux");
-  CHECK_TRACE_CONTENTS("test layer 1", 0, "foo");
-  CHECK_TRACE_DOESNT_CONTAIN("test layer 1", 1, "foo");
-}
-
-void test_trace_checks_ordering_across_layers_and_frames() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  new_trace_frame("test layer 1");
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("test layer 1/0: footest layer 2: bartest layer 1: qux");
-  CHECK_TRACE_CONTENTS("test layer 1: footest layer 2: bartest layer 1/1: qux");
-}
-
-void trace_test_fn(int n) {
-  if (n == 0) return;
-  new_trace_frame("foo");
-  trace("foo") << "before: " << n;
-  trace_test_fn(n-1);
-  trace("foo") << "after: " << n;
-}
-
-void test_trace_keeps_level_together() {
-  CHECK_TRACE_CONTENTS("foo", "");
-  trace_test_fn(4);
-  CHECK_TRACE_CONTENTS("foo", 2, "before: 3after: 3");
-}
-
-void test_trace_supports_multiple_layers() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("test layer 1,test layer 2", "foobarqux");
-}
-
-void test_trace_supports_hierarchical_layers() {
-  trace("test layer/a") << "foo";
-  trace("different layer/c") << "foo 2";
-  trace("test layer/b") << "bar";
-  CHECK_TRACE_CONTENTS("test layer/", "foobar");
-}
-
-void test_trace_supports_count() {
-  trace("test layer 1") << "foo";
-  trace("test layer 1") << "foo";
-  CHECK_EQ(trace_count("test layer 1", "foo"), 2);
-}
-
-void test_trace_supports_count2() {
-  trace("test layer 1") << "foo";
-  trace("test layer 1") << "bar";
-  CHECK_EQ(trace_count("test layer 1"), 2);
-}
-
-// pending: DUMP tests
-// pending: readable_contents() adds newline if necessary.
-// pending: raise also prints to stderr.
-// pending: raise doesn't print to stderr if Hide_warnings is set.
-// pending: raise doesn't have to be saved if Hide_warnings is set, just printed.
-// pending: raise prints to stderr if Trace_stream is NULL.
-// pending: raise prints to stderr if Trace_stream is NULL even if Hide_warnings is set.
-// pending: raise << ... die() doesn't die if Hide_warnings is set.
-
-
-
-// can't check trace because trace methods call 'split'
-
-void test_split_returns_at_least_one_elem() {
-  vector<string> result = split("", ",");
-  CHECK_EQ(result.size(), 1);
-  CHECK_EQ(result[0], "");
-}
-
-void test_split_returns_entire_input_when_no_delim() {
-  vector<string> result = split("abc", ",");
-  CHECK_EQ(result.size(), 1);
-  CHECK_EQ(result[0], "abc");
-}
-
-void test_split_works() {
-  vector<string> result = split("abc,def", ",");
-  CHECK_EQ(result.size(), 2);
-  CHECK_EQ(result[0], "abc");
-  CHECK_EQ(result[1], "def");
-}
-
-void test_split_works2() {
-  vector<string> result = split("abc,def,ghi", ",");
-  CHECK_EQ(result.size(), 3);
-  CHECK_EQ(result[0], "abc");
-  CHECK_EQ(result[1], "def");
-  CHECK_EQ(result[2], "ghi");
-}
-
-void test_split_handles_multichar_delim() {
-  vector<string> result = split("abc,,def,,ghi", ",,");
-  CHECK_EQ(result.size(), 3);
-  CHECK_EQ(result[0], "abc");
-  CHECK_EQ(result[1], "def");
-  CHECK_EQ(result[2], "ghi");
-}
diff --git a/cpp/literate/009includes b/cpp/literate/009includes
deleted file mode 100644
index 5c9a8d65..00000000
--- a/cpp/literate/009includes
+++ /dev/null
@@ -1,48 +0,0 @@
-// Some common includes needed all over the place.
-// More tightly-targeted includes show up in other files.
-
-:(before "End Includes")
-#include<assert.h>
-#include<cstdio>
-#include<cstring>
-#include<cstdlib>
-#include<errno.h>
-#include<time.h>
-#include<math.h>
-#include<vector>
-using std::vector;
-#include<list>
-using std::list;
-#include<stack>
-using std::stack;
-#include<utility>
-using std::pair;
-
-#include<tr1/unordered_map>
-using std::tr1::unordered_map;
-#include<tr1/unordered_set>
-using std::tr1::unordered_set;
-#include<algorithm>
-
-#include<string>
-using std::string;
-#define NOT_FOUND string::npos  // macro doesn't complain about redef
-
-#include<iostream>
-using std::istream;
-using std::ostream;
-using std::iostream;
-using std::cin;
-using std::cout;
-using std::cerr;
-
-#include<sstream>
-using std::stringstream;
-using std::istringstream;
-using std::ostringstream;
-
-#include<fstream>
-using std::ifstream;
-using std::ofstream;
-
-#define unused  __attribute__((unused))
diff --git a/cpp/literate/010vm b/cpp/literate/010vm
deleted file mode 100644
index 3b8a7c96..00000000
--- a/cpp/literate/010vm
+++ /dev/null
@@ -1,145 +0,0 @@
-// A program is a book of 'recipes' (functions)
-
-:(after "Types")
-typedef int recipe_number;
-:(before "End Globals")
-unordered_map<string, recipe_number> Recipe_number;
-unordered_map<recipe_number, recipe> Recipe;
-int Next_recipe_number = 1;
-
-:(before "End Types")
-// Recipes are lists of instructions. To run a recipe, the computer runs its
-// instructions.
-struct recipe {
-  vector<instruction> steps;
-};
-
-:(before "struct recipe")
-// Each instruction is either of the form:
-//   product1, product2, product3, ... <- operation ingredient1, ingredient2, ingredient3, ...
-// or just a single 'label' followed by a colon
-//   label:
-// Labels don't do anything, they're just waypoints.
-struct instruction {
-  bool is_label;
-  string label;  // only if is_label
-  recipe_number operation;  // only if !is_label
-  vector<reagent> ingredients;  // only if !is_label
-  vector<reagent> products;  // only if !is_label
-  instruction();
-  void clear();
-};
-
-:(before "struct instruction")
-// Ingredients and products are a single species -- a reagent. Reagents refer
-// either to numbers or to locations in memory along with 'type' tags telling
-// us how to interpret them. They also can contain arbitrary other lists of
-// properties besides types, but we're getting ahead of ourselves.
-struct reagent {
-  string name;
-  vector<type_number> types;
-  vector<pair<string, property> > properties;
-  reagent(string s);
-  string to_string();
-};
-
-:(before "struct reagent")
-struct property {
-  vector<string> values;
-};
-
-:(before "End Globals")
-// Locations refer to a common 'memory'. Each location can store a number.
-unordered_map<int, int> Memory;
-:(before "End Setup")
-  Memory.clear();
-
-:(after "Types")
-// Types encode how the numbers stored in different parts of memory are
-// interpreted. A location tagged as a 'character' type will interpret the
-// number 97 as the letter 'a', while a different location of type 'integer'
-// would not.
-//
-// Unlike most computers today, mu stores types in a single big table, shared
-// by all the mu programs on the computer. This is useful in providing a
-// seamless experience to help understand arbitrary mu programs.
-typedef int type_number;
-:(before "End Globals")
-unordered_map<string, type_number> Type_number;
-unordered_map<type_number, type_info> Type;
-int Next_type_number = 1;
-:(code)
-void setup_types() {
-  Type.clear();  Type_number.clear();
-  Type_number["literal"] = 0;
-  Next_type_number = 1;
-  int integer = Type_number["integer"] = Next_type_number++;
-  Type[integer].size = 1;
-}
-:(before "End Setup")
-  setup_types();
-
-:(before "End Types")
-// You can construct arbitrary new types. Types are either 'records', containing
-// 'fields' of other types, 'array's of a single type repeated over and over,
-// or 'addresses' pointing at a location elsewhere in memory.
-struct type_info {
-  int size;
-  bool is_address;
-  bool is_record;
-  bool is_array;
-  vector<type_number> target;  // only if is_address
-  vector<vector<type_number> > elements;  // only if is_record or is_array
-  type_info() :size(0) {}
-};
-
-:(code)
-// It's all very well to construct recipes out of other recipes, but we need
-// to know how to do *something* out of the box. For the following
-// recipes there are only codes, no entries in the book, because mu just knows
-// what to do for them.
-void setup_recipes() {
-  Recipe.clear();  Recipe_number.clear();
-  Recipe_number["idle"] = 0;
-  Next_recipe_number = 1;
-  Recipe_number["copy"] = Next_recipe_number++;
-}
-:(before "End Types")
-const int idle = 0;  // always the first entry in the recipe book
-:(before "End Setup")
-  setup_recipes();
-
-
-
-:(code)
-// Helpers
-  instruction::instruction() :is_label(false), operation(idle) {}
-  void instruction::clear() { is_label=false; label.clear(); operation=idle; ingredients.clear(); products.clear(); }
-
-  // Reagents have the form <name>:<type>:<type>:.../<property>/<property>/...
-  reagent::reagent(string s) {
-    istringstream in(s);
-    name = slurp_until(in, ':');
-    types.push_back(Type_number[slurp_until(in, '/')]);  // todo: multiple types
-  }
-  string reagent::to_string() {
-    ostringstream out;
-    out << "{name: \"" << name << "\", type: " << types[0] << "}";  // todo: properties
-    return out.str();
-  }
-
-string slurp_until(istream& in, char delim) {
-  ostringstream out;
-  char c;
-  while (in >> c) {
-    if (c == delim) {
-      break;
-    }
-    out << c;
-  }
-  return out.str();
-}
-
-
-
-:(before "End Setup")
diff --git a/cpp/literate/011load b/cpp/literate/011load
deleted file mode 100644
index f2855e5f..00000000
--- a/cpp/literate/011load
+++ /dev/null
@@ -1,150 +0,0 @@
-// It's often convenient to express recipes in a textual fashion.
-:(scenarios add_recipe)
-:(scenario first_recipe)
-recipe main [
-  1:integer <- copy 23:literal
-]
-+parse: instruction: 1
-+parse:   ingredient: {name: "23", type: 0}
-+parse:   product: {name: "1", type: 1}
-
-:(code)
-int add_recipe(string form) {
-  istringstream in(form);
-  in >> std::noskipws;
-
-  string _recipe = next_word(in);
-  if (_recipe != "recipe")
-    raise << "top-level forms must be of the form 'recipe _name_ [ _instruction_ ... ]'\n";
-
-  string recipe_name = next_word(in);
-  if (recipe_name.empty())
-    raise << "empty recipe name in " << form << '\n';
-  int r = Recipe_number[recipe_name] = Next_recipe_number++;
-
-  if (next_word(in) != "[")
-    raise << "recipe body must begin with '['\n";
-
-  skip_newlines(in);
-
-  instruction curr;
-  while (next_instruction(in, &curr)) {
-    Recipe[r].steps.push_back(curr);
-  }
-  return r;
-}
-
-bool next_instruction(istream& in, instruction* curr) {
-  curr->clear();
-  if (in.eof()) return false;
-  skip_whitespace(in);  if (in.eof()) return false;
-  skip_newlines(in);  if (in.eof()) return false;
-
-  vector<string> words;
-  while (in.peek() != '\n') {
-    skip_whitespace(in);  if (in.eof()) return false;
-    string word = next_word(in);  if (in.eof()) return false;
-    words.push_back(word);
-    skip_whitespace(in);  if (in.eof()) return false;
-  }
-  skip_newlines(in);  if (in.eof()) return false;
-
-  if (words.size() == 1 && *(words[0].end()-1) == ':') {
-    curr->is_label = true;
-    words[0].erase(words[0].end()-1);
-    curr->label = words[0];
-    trace("parse") << "label: " << curr->label;
-    return !in.eof();
-  }
-
-  vector<string>::iterator p = words.begin();
-  if (find(words.begin(), words.end(), "<-") != words.end()) {
-    for (; *p != "<-"; ++p) {
-      if (*p == ",") continue;
-      curr->products.push_back(reagent(*p));
-    }
-    ++p;  // skip <-
-  }
-
-  curr->operation = Recipe_number[*p];  ++p;
-
-  for (; p != words.end(); ++p) {
-    if (*p == ",") continue;
-    curr->ingredients.push_back(reagent(*p));
-  }
-
-  trace("parse") << "instruction: " << curr->operation;
-  for (vector<reagent>::iterator p = curr->ingredients.begin(); p != curr->ingredients.end(); ++p) {
-    trace("parse") << "  ingredient: " << p->to_string();
-  }
-  for (vector<reagent>::iterator p = curr->products.begin(); p != curr->products.end(); ++p) {
-    trace("parse") << "  product: " << p->to_string();
-  }
-  return !in.eof();
-}
-
-string next_word(istream& in) {
-  ostringstream out;
-  skip_whitespace(in);
-  slurp_word(in, out);
-  return out.str();
-}
-
-void slurp_word(istream& in, ostream& out) {
-  char c;
-  if (in.peek() == ',') {
-    in >> c;
-    out << c;
-    return;
-  }
-  while (in >> c) {
-    if (isspace(c) || c == ',') {
-      in.putback(c);
-      break;
-    }
-    out << c;
-  }
-}
-
-void skip_whitespace(istream& in) {
-  while (isspace(in.peek()) && in.peek() != '\n') {
-    in.get();
-  }
-}
-
-void skip_newlines(istream& in) {
-  while (in.peek() == '\n')
-    in.get();
-}
-
-void skip_comma(istream& in) {
-  skip_whitespace(in);
-  if (in.peek() == ',') in.get();
-  skip_whitespace(in);
-}
-
-:(scenario parse_label)
-recipe main [
-  foo:
-]
-+parse: label: foo
--parse: instruction: 1
-
-:(scenario parse_multiple_products)
-recipe main [
-  1:integer, 2:integer <- copy 23:literal
-]
-+parse: instruction: 1
-+parse:   ingredient: {name: "23", type: 0}
-+parse:   product: {name: "1", type: 1}
-+parse:   product: {name: "2", type: 1}
-
-:(scenario parse_multiple_ingredients)
-recipe main [
-  1:integer, 2:integer <- copy 23:literal, 4:integer
-]
-+parse: instruction: 1
-+parse:   ingredient: {name: "23", type: 0}
-+parse:   ingredient: {name: "4", type: 1}
-+parse:   product: {name: "1", type: 1}
-+parse:   product: {name: "2", type: 1}
diff --git a/cpp/literate/012run b/cpp/literate/012run
deleted file mode 100644
index f7b5469a..00000000
--- a/cpp/literate/012run
+++ /dev/null
@@ -1,41 +0,0 @@
-:(scenarios run)
-:(scenario copy_literal)
-recipe main [
-  1:integer <- copy 23:literal
-]
-+run: instruction 0
-+run:   ingredient 23
-+mem:   storing in location 1
-
-:(code)
-void run(string form) {
-  run(add_recipe(form));
-}
-
-void run(recipe_number r) {
-  vector<instruction>& instructions(Recipe[r].steps);
-  int n = 0;
-  vector<instruction>::iterator p;
-  for (n = 0, p = instructions.begin(); p != instructions.end(); ++p, ++n) {
-    trace("run") << "instruction " << n;
-    switch (p->operation) {
-    case 1: {  // copy
-      int arg = to_int(p->ingredients[0].name);
-      trace("run") << "  ingredient " << arg;
-      int dest = to_int(p->products[0].name);
-      trace("mem") << "  storing in location " << dest;
-      Memory[dest] = arg;
-      break;
-    }
-    default:
-      raise << "undefined operation " << p->operation;
-    }
-  }
-}
-
-int to_int(string n) {
-  char* end = NULL;
-  int result = strtol(n.c_str(), &end, /*any base*/0);
-  assert(*end == '\0');
-  return result;
-}
diff --git a/cpp/literate/build_and_test_until b/cpp/literate/build_and_test_until
deleted file mode 100755
index 3661c93a..00000000
--- a/cpp/literate/build_and_test_until
+++ /dev/null
@@ -1,7 +0,0 @@
-set -e
-set -v
-make tangle/tangle
-./tangle/tangle --until $* > mu.cc
-make autogenerated_lists
-g++ -g -Wall -Wextra -fno-strict-aliasing mu.cc -o mu
-./mu test
diff --git a/cpp/literate/makefile b/cpp/literate/makefile
deleted file mode 100644
index 97187383..00000000
--- a/cpp/literate/makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-mu: makefile tangle/tangle mu.cc
-	g++ -g -Wall -Wextra -fno-strict-aliasing mu.cc -o mu
-	-@./mu test
-
-# To see what the program looks like after all layers have been applied, read
-# mu.cc
-mu.cc: 0*
-	./tangle/tangle --until 999 > mu.cc
-	@make autogenerated_lists >/dev/null
-
-tangle/tangle:
-	cd tangle && make
-
-# auto-generated files; by convention they end in '_list'.
-.PHONY: autogenerated_lists
-autogenerated_lists: mu.cc function_list test_list
-
-function_list: mu.cc
-	@grep -h "^[^ #].*) {" mu.cc |perl -pwe 's/ {.*/;/' > function_list
-
-test_list: mu.cc
-	@grep -h "^[[:space:]]*void test_" mu.cc |perl -pwe 's/^\s*void (.*)\(\) {.*/$$1,/' > test_list
-
-clean:
-	cd tangle && make clean
-	rm -rf mu.cc mu *_list
diff --git a/cpp/literate/tangle/000test.cc b/cpp/literate/tangle/000test.cc
deleted file mode 100644
index 2754b254..00000000
--- a/cpp/literate/tangle/000test.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-typedef void (*test_fn)(void);
-
-const test_fn Tests[] = {
-  #include "test_list"  // auto-generated; see makefile
-};
-
-bool Passed = true;
-
-long Num_failures = 0;
-
-#define CHECK(X) \
-  if (!(X)) { \
-    ++Num_failures; \
-    cerr << "\nF " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): " << #X << '\n'; \
-    Passed = false; \
-    return; \
-  }
-
-#define CHECK_EQ(X, Y) \
-  if ((X) != (Y)) { \
-    ++Num_failures; \
-    cerr << "\nF " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): " << #X << " == " << #Y << '\n'; \
-    cerr << "  got " << (X) << '\n';  /* BEWARE: multiple eval */ \
-    Passed = false; \
-    return; \
-  }
diff --git a/cpp/literate/tangle/001trace.cc b/cpp/literate/tangle/001trace.cc
deleted file mode 100644
index a99951e0..00000000
--- a/cpp/literate/tangle/001trace.cc
+++ /dev/null
@@ -1,338 +0,0 @@
-bool Hide_warnings = false;
-
-struct trace_stream {
-  vector<pair<string, pair<int, string> > > past_lines;  // [(layer label, frame, line)]
-  unordered_map<string, int> frame;
-  // accumulator for current line
-  ostringstream* curr_stream;
-  string curr_layer;
-  string dump_layer;
-  trace_stream() :curr_stream(NULL) {}
-  ~trace_stream() { if (curr_stream) delete curr_stream; }
-
-  ostringstream& stream(string layer) {
-    newline();
-    curr_stream = new ostringstream;
-    curr_layer = layer;
-    return *curr_stream;
-  }
-
-  // be sure to call this before messing with curr_stream or curr_layer or frame
-  void newline() {
-    if (!curr_stream) return;
-    past_lines.push_back(pair<string, pair<int, string> >(curr_layer, pair<int, string>(frame[curr_layer], curr_stream->str())));
-    if (curr_layer == "dump")
-      cerr << with_newline(curr_stream->str());
-    else if ((!dump_layer.empty() && prefix_match(dump_layer, curr_layer))
-        || (!Hide_warnings && curr_layer == "warn"))
-      cerr << curr_layer << "/" << frame[curr_layer] << ": " << with_newline(curr_stream->str());
-    delete curr_stream;
-    curr_stream = NULL;
-  }
-
-  string readable_contents(string layer) {  // missing layer = everything, frame, hierarchical layers
-    newline();
-    ostringstream output;
-    string real_layer, frame;
-    parse_layer_and_frame(layer, &real_layer, &frame);
-    for (vector<pair<string, pair<int, string> > >::iterator p = past_lines.begin(); p != past_lines.end(); ++p)
-      if (layer.empty() || prefix_match(real_layer, p->first))
-        output << p->first << "/" << p->second.first << ": " << with_newline(p->second.second);
-    return output.str();
-  }
-
-  void dump_browseable_contents(string layer) {
-    ofstream dump("dump");
-    dump << "<div class='frame' frame_index='1'>start</div>\n";
-    for (vector<pair<string, pair<int, string> > >::iterator p = past_lines.begin(); p != past_lines.end(); ++p) {
-      if (p->first != layer) continue;
-      dump << "<div class='frame";
-      if (p->second.first > 1) dump << " hidden";
-      dump << "' frame_index='" << p->second.first << "'>";
-      dump << p->second.second;
-      dump << "</div>\n";
-    }
-    dump.close();
-  }
-
-  string with_newline(string s) {
-    if (s[s.size()-1] != '\n') return s+'\n';
-    return s;
-  }
-};
-
-
-
-trace_stream* Trace_stream = NULL;
-
-// Top-level helper. IMPORTANT: can't nest.
-#define trace(layer)  !Trace_stream ? cerr /*print nothing*/ : Trace_stream->stream(layer)
-// Warnings should go straight to cerr by default since calls to trace() have
-// some unfriendly constraints (they delay printing, they can't nest)
-#define RAISE  ((!Trace_stream || !Hide_warnings) ? cerr /*do print*/ : Trace_stream->stream("warn")) << __FILE__ << ":" << __LINE__ << " "
-// Just debug logging without any test support.
-#define dbg cerr << __FUNCTION__ << '(' << __FILE__ << ':' << __LINE__ << ") "
-
-// RAISE << die exits after printing -- unless Hide_warnings is set.
-struct die {};
-ostream& operator<<(ostream& os, unused die) {
-  if (Hide_warnings) return os;
-  os << "dying";
-  exit(1);
-}
-
-#define CLEAR_TRACE  delete Trace_stream, Trace_stream = new trace_stream;
-
-#define DUMP(layer)  cerr << Trace_stream->readable_contents(layer)
-
-// Trace_stream is a resource, lease_tracer uses RAII to manage it.
-struct lease_tracer {
-  lease_tracer() { Trace_stream = new trace_stream; }
-  ~lease_tracer() { delete Trace_stream, Trace_stream = NULL; }
-};
-
-#define START_TRACING_UNTIL_END_OF_SCOPE  lease_tracer leased_tracer;
-
-void trace_all(const string& label, const list<string>& in) {
-  for (list<string>::const_iterator p = in.begin(); p != in.end(); ++p)
-    trace(label) << *p;
-}
-
-bool check_trace_contents(string FUNCTION, string FILE, int LINE, string expected) {  // missing layer == anywhere, frame, hierarchical layers
-  vector<string> expected_lines = split(expected, "");
-  size_t curr_expected_line = 0;
-  while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-    ++curr_expected_line;
-  if (curr_expected_line == expected_lines.size()) return true;
-  Trace_stream->newline();
-  ostringstream output;
-  string layer, frame, contents;
-  parse_layer_frame_contents(expected_lines[curr_expected_line], &layer, &frame, &contents);
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (!layer.empty() && !prefix_match(layer, p->first))
-      continue;
-
-    if (!frame.empty() && strtol(frame.c_str(), NULL, 0) != p->second.first)
-      continue;
-
-    if (contents != p->second.second)
-      continue;
-
-    ++curr_expected_line;
-    while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-      ++curr_expected_line;
-    if (curr_expected_line == expected_lines.size()) return true;
-    parse_layer_frame_contents(expected_lines[curr_expected_line], &layer, &frame, &contents);
-  }
-
-  ++Num_failures;
-  cerr << "\nF " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << contents << "] in trace:\n";
-  DUMP(layer);
-  Passed = false;
-  return false;
-}
-
-void parse_layer_frame_contents(const string& orig, string* layer, string* frame, string* contents) {
-  string layer_and_frame;
-  parse_contents(orig, ": ", &layer_and_frame, contents);
-  parse_layer_and_frame(layer_and_frame, layer, frame);
-}
-
-void parse_contents(const string& s, const string& delim, string* prefix, string* contents) {
-  string::size_type pos = s.find(delim);
-  if (pos == NOT_FOUND) {
-    *prefix = "";
-    *contents = s;
-  }
-  else {
-    *prefix = s.substr(0, pos);
-    *contents = s.substr(pos+delim.size());
-  }
-}
-
-void parse_layer_and_frame(const string& orig, string* layer, string* frame) {
-  size_t last_slash = orig.rfind('/');
-  if (last_slash == NOT_FOUND
-      || last_slash == orig.size()-1  // trailing slash indicates hierarchical layer
-      || orig.find_last_not_of("0123456789") != last_slash) {
-    *layer = orig;
-    *frame = "";
-  }
-  else {
-    *layer = orig.substr(0, last_slash);
-    *frame = orig.substr(last_slash+1);
-  }
-}
-
-
-
-bool check_trace_contents(string FUNCTION, string FILE, int LINE, string layer, string expected) {  // empty layer == everything, multiple layers, hierarchical layers
-  vector<string> expected_lines = split(expected, "");
-  size_t curr_expected_line = 0;
-  while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-    ++curr_expected_line;
-  if (curr_expected_line == expected_lines.size()) return true;
-  Trace_stream->newline();
-  ostringstream output;
-  vector<string> layers = split(layer, ",");
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (!layer.empty() && !any_prefix_match(layers, p->first))
-      continue;
-    if (p->second.second != expected_lines[curr_expected_line])
-      continue;
-    ++curr_expected_line;
-    while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-      ++curr_expected_line;
-    if (curr_expected_line == expected_lines.size()) return true;
-  }
-
-  ++Num_failures;
-  cerr << "\nF " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << expected_lines[curr_expected_line] << "] in trace:\n";
-  DUMP(layer);
-  Passed = false;
-  return false;
-}
-
-#define CHECK_TRACE_CONTENTS(...)  check_trace_contents(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
-
-int trace_count(string layer) {
-  return trace_count(layer, "");
-}
-
-int trace_count(string layer, string line) {
-  Trace_stream->newline();
-  long result = 0;
-  vector<string> layers = split(layer, ",");
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (any_prefix_match(layers, p->first))
-      if (line == "" || p->second.second == line)
-        ++result;
-  }
-  return result;
-}
-
-int trace_count(string layer, int frame, string line) {
-  Trace_stream->newline();
-  long result = 0;
-  vector<string> layers = split(layer, ",");
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (any_prefix_match(layers, p->first) && p->second.first == frame)
-      if (line == "" || p->second.second == line)
-        ++result;
-  }
-  return result;
-}
-
-#define CHECK_TRACE_WARNS()  CHECK(trace_count("warn") > 0)
-#define CHECK_TRACE_DOESNT_WARN() \
-  if (trace_count("warn") > 0) { \
-    ++Num_failures; \
-    cerr << "\nF " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): unexpected warnings\n"; \
-    DUMP("warn"); \
-    Passed = false; \
-    return; \
-  }
-
-bool trace_doesnt_contain(string layer, string line) {
-  return trace_count(layer, line) == 0;
-}
-
-bool trace_doesnt_contain(string expected) {
-  vector<string> tmp = split(expected, ": ");
-  return trace_doesnt_contain(tmp[0], tmp[1]);
-}
-
-bool trace_doesnt_contain(string layer, int frame, string line) {
-  return trace_count(layer, frame, line) == 0;
-}
-
-#define CHECK_TRACE_DOESNT_CONTAIN(...)  CHECK(trace_doesnt_contain(__VA_ARGS__))
-
-
-
-// manage layer counts in Trace_stream using RAII
-struct lease_trace_frame {
-  string layer;
-  lease_trace_frame(string l) :layer(l) {
-    if (!Trace_stream) return;
-    Trace_stream->newline();
-    ++Trace_stream->frame[layer];
-  }
-  ~lease_trace_frame() {
-    if (!Trace_stream) return;
-    Trace_stream->newline();
-    --Trace_stream->frame[layer];
-  }
-};
-#define new_trace_frame(layer)  lease_trace_frame leased_frame(layer);
-
-bool check_trace_contents(string FUNCTION, string FILE, int LINE, string layer, int frame, string expected) {  // multiple layers, hierarchical layers
-  vector<string> expected_lines = split(expected, "");  // hack: doesn't handle newlines in embedded in lines
-  size_t curr_expected_line = 0;
-  while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-    ++curr_expected_line;
-  if (curr_expected_line == expected_lines.size()) return true;
-  Trace_stream->newline();
-  ostringstream output;
-  vector<string> layers = split(layer, ",");
-  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
-    if (!layer.empty() && !any_prefix_match(layers, p->first))
-      continue;
-    if (p->second.first != frame)
-      continue;
-    if (p->second.second != expected_lines[curr_expected_line])
-      continue;
-    ++curr_expected_line;
-    while (curr_expected_line < expected_lines.size() && expected_lines[curr_expected_line].empty())
-      ++curr_expected_line;
-    if (curr_expected_line == expected_lines.size()) return true;
-  }
-
-  ++Num_failures;
-  cerr << "\nF " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << expected_lines[curr_expected_line] << "] in trace/" << frame << ":\n";
-  DUMP(layer);
-  Passed = false;
-  return false;
-}
-
-#define CHECK_TRACE_TOP(layer, expected)  CHECK_TRACE_CONTENTS(layer, 1, expected)
-
-
-
-vector<string> split(string s, string delim) {
-  vector<string> result;
-  string::size_type begin=0, end=s.find(delim);
-  while (true) {
-    if (end == NOT_FOUND) {
-      result.push_back(string(s, begin, NOT_FOUND));
-      break;
-    }
-    result.push_back(string(s, begin, end-begin));
-    begin = end+delim.size();
-    end = s.find(delim, begin);
-  }
-  return result;
-}
-
-bool any_prefix_match(const vector<string>& pats, const string& needle) {
-  if (pats.empty()) return false;
-  if (*pats[0].rbegin() != '/')
-    // prefix match not requested
-    return find(pats.begin(), pats.end(), needle) != pats.end();
-  // first pat ends in a '/'; assume all pats do.
-  for (vector<string>::const_iterator p = pats.begin(); p != pats.end(); ++p)
-    if (headmatch(needle, *p)) return true;
-  return false;
-}
-
-bool prefix_match(const string& pat, const string& needle) {
-  if (*pat.rbegin() != '/')
-    // prefix match not requested
-    return pat == needle;
-  return headmatch(needle, pat);
-}
-
-bool headmatch(const string& s, const string& pat) {
-  if (pat.size() > s.size()) return false;
-  return std::mismatch(pat.begin(), pat.end(), s.begin()).first == pat.end();
-}
diff --git a/cpp/literate/tangle/001trace.test.cc b/cpp/literate/tangle/001trace.test.cc
deleted file mode 100644
index e0db457c..00000000
--- a/cpp/literate/tangle/001trace.test.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-void test_trace_check_compares() {
-  CHECK_TRACE_CONTENTS("test layer", "");
-  trace("test layer") << "foo";
-  CHECK_TRACE_CONTENTS("test layer", "foo");
-}
-
-void test_trace_check_filters_layers() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  CHECK_TRACE_CONTENTS("test layer 1", "foo");
-}
-
-void test_trace_check_ignores_other_lines() {
-  trace("test layer 1") << "foo";
-  trace("test layer 1") << "bar";
-  CHECK_TRACE_CONTENTS("test layer 1", "foo");
-}
-
-void test_trace_check_always_finds_empty_lines() {
-  CHECK_TRACE_CONTENTS("test layer 1", "");
-}
-
-void test_trace_check_treats_empty_layers_as_wildcards() {
-  trace("test layer 1") << "foo";
-  CHECK_TRACE_CONTENTS("", "foo");
-}
-
-void test_trace_check_multiple_lines_at_once() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  CHECK_TRACE_CONTENTS("", "foobar");
-}
-
-void test_trace_check_always_finds_empty_lines2() {
-  CHECK_TRACE_CONTENTS("test layer 1", "");
-}
-
-void test_trace_orders_across_layers() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("", "foobarqux");
-}
-
-void test_trace_orders_across_layers2() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("foobarqux");
-}
-
-void test_trace_checks_ordering_spanning_multiple_layers() {
-  trace("layer1") << "foo";
-  trace("layer2") << "bar";
-  trace("layer1") << "qux";
-  CHECK_TRACE_CONTENTS("layer1: foolayer2: barlayer1: qux");
-}
-
-void test_trace_segments_within_layers() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  new_trace_frame("test layer 1");
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("test layer 1", "fooqux");
-  CHECK_TRACE_CONTENTS("test layer 1", 0, "foo");
-  CHECK_TRACE_DOESNT_CONTAIN("test layer 1", 1, "foo");
-}
-
-void test_trace_checks_ordering_across_layers_and_frames() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  new_trace_frame("test layer 1");
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("test layer 1/0: footest layer 2: bartest layer 1: qux");
-  CHECK_TRACE_CONTENTS("test layer 1: footest layer 2: bartest layer 1/1: qux");
-}
-
-void trace_test_fn(int n) {
-  if (n == 0) return;
-  new_trace_frame("foo");
-  trace("foo") << "before: " << n;
-  trace_test_fn(n-1);
-  trace("foo") << "after: " << n;
-}
-
-void test_trace_keeps_level_together() {
-  CHECK_TRACE_CONTENTS("foo", "");
-  trace_test_fn(4);
-  CHECK_TRACE_CONTENTS("foo", 2, "before: 3after: 3");
-}
-
-void test_trace_supports_multiple_layers() {
-  trace("test layer 1") << "foo";
-  trace("test layer 2") << "bar";
-  trace("test layer 1") << "qux";
-  CHECK_TRACE_CONTENTS("test layer 1,test layer 2", "foobarqux");
-}
-
-void test_trace_supports_hierarchical_layers() {
-  trace("test layer/a") << "foo";
-  trace("different layer/c") << "foo 2";
-  trace("test layer/b") << "bar";
-  CHECK_TRACE_CONTENTS("test layer/", "foobar");
-}
-
-void test_trace_supports_count() {
-  trace("test layer 1") << "foo";
-  trace("test layer 1") << "foo";
-  CHECK_EQ(trace_count("test layer 1", "foo"), 2);
-}
-
-void test_trace_supports_count2() {
-  trace("test layer 1") << "foo";
-  trace("test layer 1") << "bar";
-  CHECK_EQ(trace_count("test layer 1"), 2);
-}
-
-// pending: DUMP tests
-// pending: readable_contents() adds newline if necessary.
-// pending: RAISE also prints to stderr.
-// pending: RAISE doesn't print to stderr if Hide_warnings is set.
-// pending: RAISE doesn't have to be saved if Hide_warnings is set, just printed.
-// pending: RAISE prints to stderr if Trace_stream is NULL.
-// pending: RAISE prints to stderr if Trace_stream is NULL even if Hide_warnings is set.
-// pending: RAISE << ... die() doesn't die if Hide_warnings is set.
-
-
-
-// can't check trace because trace methods call 'split'
-
-void test_split_returns_at_least_one_elem() {
-  vector<string> result = split("", ",");
-  CHECK_EQ(result.size(), 1);
-  CHECK_EQ(result[0], "");
-}
-
-void test_split_returns_entire_input_when_no_delim() {
-  vector<string> result = split("abc", ",");
-  CHECK_EQ(result.size(), 1);
-  CHECK_EQ(result[0], "abc");
-}
-
-void test_split_works() {
-  vector<string> result = split("abc,def", ",");
-  CHECK_EQ(result.size(), 2);
-  CHECK_EQ(result[0], "abc");
-  CHECK_EQ(result[1], "def");
-}
-
-void test_split_works2() {
-  vector<string> result = split("abc,def,ghi", ",");
-  CHECK_EQ(result.size(), 3);
-  CHECK_EQ(result[0], "abc");
-  CHECK_EQ(result[1], "def");
-  CHECK_EQ(result[2], "ghi");
-}
-
-void test_split_handles_multichar_delim() {
-  vector<string> result = split("abc,,def,,ghi", ",,");
-  CHECK_EQ(result.size(), 3);
-  CHECK_EQ(result[0], "abc");
-  CHECK_EQ(result[1], "def");
-  CHECK_EQ(result[2], "ghi");
-}
diff --git a/cpp/literate/tangle/002main.cc b/cpp/literate/tangle/002main.cc
deleted file mode 100644
index 851811c8..00000000
--- a/cpp/literate/tangle/002main.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-string Last_file = "";
-int main(int argc, const char* argv[]) {
-  Last_file = flag_value("--until", argc, argv);
-  if (flag("test", argc, argv))
-    return run_tests();
-  return tangle_files_in_cwd();
-}
-
-bool eof(istream& in) {
-  in.peek();
-  return in.eof();
-}
-
-bool flag(const string& flag, int argc, const char* argv[]) {
-  for (int i = 1; i < argc; ++i)
-    if (string(argv[i]) == flag)
-      return true;
-  return false;
-}
-
-string flag_value(const string& flag, int argc, const char* argv[]) {
-  for (int i = 1; i < argc-1; ++i)
-    if (string(argv[i]) == flag)
-      return argv[i+1];
-  return "";
-}
-
-
-
-//// test harness
-
-int run_tests() {
-  time_t t; time(&t);
-  cerr << "C tests: " << ctime(&t);
-  for (unsigned long i=0; i < sizeof(Tests)/sizeof(Tests[0]); ++i) {
-    START_TRACING_UNTIL_END_OF_SCOPE;
-    setup();
-    (*Tests[i])();
-    verify();
-  }
-
-  cerr << '\n';
-  if (Num_failures > 0)
-    cerr << Num_failures << " failure"
-         << (Num_failures > 1 ? "s" : "")
-         << '\n';
-  return Num_failures;
-}
-
-void verify() {
-  Hide_warnings = false;
-  if (!Passed)
-    ;
-  else
-    cerr << ".";
-}
-
-void setup() {
-  Hide_warnings = false;
-  Passed = true;
-}
diff --git a/cpp/literate/tangle/030tangle.cc b/cpp/literate/tangle/030tangle.cc
deleted file mode 100644
index 2dda8667..00000000
--- a/cpp/literate/tangle/030tangle.cc
+++ /dev/null
@@ -1,355 +0,0 @@
-#include<sys/param.h>
-
-int tangle_files_in_cwd() {
-  list<string> result;
-  vector<char*> files = sorted_files(".", /*no extension*/ "");
-  for (vector<char*>::iterator p = files.begin(); p != files.end(); ++p) {
-    if ((*p)[0] < '0' || (*p)[0] > '9') continue;
-    if (!Last_file.empty() && *p > Last_file) break;
-    ifstream in(*p);
-    tangle(in, result);
-  }
-  for (list<string>::iterator p = result.begin(); p != result.end(); ++p)
-    cout << *p << '\n';
-  return 0;
-}
-
-void tangle(istream& in, list<string>& out) {
-  string curr_line;
-  while (!in.eof()) {
-    getline(in, curr_line);
-    if (starts_with(curr_line, ":("))
-      process_next_hunk(in, trim(curr_line), out);
-    else
-      out.push_back(curr_line);
-  }
-  trace_all("tangle", out);
-}
-
-string Toplevel = "run";
-
-void process_next_hunk(istream& in, const string& directive, list<string>& out) {
-  list<string> hunk;
-  string curr_line;
-  while (!in.eof()) {
-    std::streampos old = in.tellg();
-    getline(in, curr_line);
-    if (starts_with(curr_line, ":(")) {
-      in.seekg(old);
-      break;
-    }
-    else {
-      hunk.push_back(curr_line);
-    }
-  }
-
-  istringstream directive_stream(directive.substr(2));  // length of ":("
-  string cmd = next_tangle_token(directive_stream);
-
-  if (cmd == "code") {
-    out.insert(out.end(), hunk.begin(), hunk.end());
-    return;
-  }
-
-  if (cmd == "scenarios") {
-    Toplevel = next_tangle_token(directive_stream);
-    return;
-  }
-
-  if (cmd == "scenario") {
-    list<string> result;
-    string name = next_tangle_token(directive_stream);
-    emit_test(name, hunk, result);
-    out.insert(out.end(), result.begin(), result.end());
-    return;
-  }
-
-  if (cmd == "before" || cmd == "after" || cmd == "replace" || cmd == "replace{}" || cmd == "delete" || cmd == "delete{}") {
-    string pat = next_tangle_token(directive_stream);
-    if (pat == "") {
-      RAISE << "No target for " << cmd << " directive.\n" << die();
-      return;
-    }
-    list<string>::iterator target = find_substr(out, pat);
-    if (target == out.end()) {
-      RAISE << "Couldn't find target " << pat << '\n' << die();
-      return;
-    }
-
-    indent_all(hunk, target);
-
-    if (cmd == "before") {
-      out.splice(target, hunk);
-    }
-    else if (cmd == "after") {
-      ++target;
-      out.splice(target, hunk);
-    }
-    else if (cmd == "replace" || cmd == "delete") {
-      out.splice(target, hunk);
-      out.erase(target);
-    }
-    else if (cmd == "replace{}" || cmd == "delete{}") {
-      if (find_trim(hunk, ":OLD_CONTENTS") == hunk.end()) {
-        out.splice(target, hunk);
-        out.erase(target, balancing_curly(target));
-      }
-      else {
-        list<string>::iterator next = balancing_curly(target);
-        list<string> old_version;
-        old_version.splice(old_version.begin(), out, target, next);
-        old_version.pop_back();  old_version.pop_front();  // contents only please, not surrounding curlies
-
-        list<string>::iterator new_pos = find_trim(hunk, ":OLD_CONTENTS");
-        indent_all(old_version, new_pos);
-        hunk.splice(new_pos, old_version);
-        hunk.erase(new_pos);
-        out.splice(next, hunk);
-      }
-    }
-    return;
-  }
-
-  RAISE << "unknown directive " << cmd << '\n';
-}
-
-// indent all lines in l like indentation at exemplar
-void indent_all(list<string>& l, list<string>::iterator exemplar) {
-  string curr_indent = indent(*exemplar);
-  for (list<string>::iterator p = l.begin(); p != l.end(); ++p)
-    if (!p->empty())
-      p->insert(p->begin(), curr_indent.begin(), curr_indent.end());
-}
-
-string next_tangle_token(istream& in) {
-  in >> std::noskipws;
-  ostringstream out;
-  skip_whitespace(in);
-  if (in.peek() == '"')
-    slurp_tangle_string(in, out);
-  else
-    slurp_word(in, out);
-  return out.str();
-}
-
-void slurp_tangle_string(istream& in, ostream& out) {
-  in.get();
-  char c;
-  while (in >> c) {
-    if (c == '\\')  // only works for double-quotes
-      continue;
-    if (c == '"')
-      break;
-    out << c;
-  }
-}
-
-void slurp_word(istream& in, ostream& out) {
-  char c;
-  while (in >> c) {
-    if (isspace(c) || c == ')') {
-      in.putback(c);
-      break;
-    }
-    out << c;
-  }
-}
-
-void skip_whitespace(istream& in) {
-  while (isspace(in.peek()))
-    in.get();
-}
-
-list<string>::iterator balancing_curly(list<string>::iterator orig) {
-  list<string>::iterator curr = orig;
-  long open_curlies = 0;
-  do {
-    for (string::iterator p = curr->begin(); p != curr->end(); ++p) {
-      if (*p == '{') ++open_curlies;
-      if (*p == '}') --open_curlies;
-    }
-    ++curr;
-    // no guard so far against unbalanced curly
-  } while (open_curlies != 0);
-  return curr;
-}
-
-// A scenario is one or more sessions separated by calls to CLEAR_TRACE ('===')
-//  A session is one or more lines of input
-//  followed by a return value ('=>')
-//  followed by one or more lines expected in trace in order ('+')
-//  followed by one or more lines trace shouldn't include ('-')
-// Remember to update is_input below if you add to this format.
-void emit_test(const string& name, list<string>& lines, list<string>& result) {
-  result.push_back("void test_"+name+"() {");
-  while (any_non_input_line(lines)) {
-    if (!any_line_starts_with(lines, "=>"))
-      emit_session(lines, result);  // simpler version; no need to check result
-    else
-      emit_result_checking_session(lines, result);
-    if (!lines.empty() && lines.front()[0] == '+')
-      result.push_back("  CHECK_TRACE_CONTENTS(\""+expected_in_trace(lines)+"\");");
-    while (!lines.empty() && lines.front()[0] == '-') {
-      result.push_back("  CHECK_TRACE_DOESNT_CONTAIN(\""+expected_not_in_trace(lines.front())+"\");");
-      lines.pop_front();
-    }
-    if (!lines.empty() && lines.front() == "===") {
-      result.push_back("  CLEAR_TRACE;");
-      lines.pop_front();
-    }
-  }
-  result.push_back("}");
-
-  while (!lines.empty() &&
-         (trim(lines.front()).empty() || starts_with(lines.front(), "//")))
-    lines.pop_front();
-  if (!lines.empty()) {
-    cerr << lines.size() << " unprocessed lines in scenario.\n";
-    exit(1);
-  }
-}
-
-void emit_session(list<string>& lines, list<string>& result) {
-  result.push_back("  "+Toplevel+"(\""+input_lines(lines)+"\");");
-}
-
-void emit_result_checking_session(list<string>& lines, list<string>& result) {
-  result.push_back("{");
-  result.push_back("  ostringstream os;");
-  result.push_back("  TEMP(tmp, "+Toplevel+"(\""+input_lines(lines)+"\"));");
-  result.push_back("  os << tmp;");
-  if (!lines.empty() && starts_with(lines.front(), "=>")) {
-    size_t pos = lines.front().find("=>")+2;  // length of '=>'
-    result.push_back("  CHECK_EQ(os.str(), \""+trim(string(lines.front(), pos))+"\");");
-    lines.pop_front();
-  }
-  result.push_back("}");
-}
-
-bool is_input(const string& line) {
-  return line != "===" && line[0] != '+' && line[0] != '-' && !starts_with(line, "=>");
-}
-
-string input_lines(list<string>& hunk) {
-  string result;
-  while (!hunk.empty() && is_input(hunk.front())) {
-    result += hunk.front()+"";  // temporary delimiter; replace with escaped newline after escaping other backslashes
-    hunk.pop_front();
-  }
-  return escape(result);
-}
-
-string expected_in_trace(list<string>& hunk) {
-  string result;
-  while (!hunk.empty() && hunk.front()[0] == '+') {
-    hunk.front().erase(0, 1);
-    result += hunk.front()+"";
-    hunk.pop_front();
-  }
-  return escape(result);
-}
-
-string expected_not_in_trace(const string& line) {
-  return escape(line.substr(1));
-}
-
-list<string>::iterator find_substr(list<string>& in, const string& pat) {
-  for (list<string>::iterator p = in.begin(); p != in.end(); ++p)
-    if (p->find(pat) != NOT_FOUND)
-      return p;
-  return in.end();
-}
-
-list<string>::iterator find_trim(list<string>& in, const string& pat) {
-  for (list<string>::iterator p = in.begin(); p != in.end(); ++p)
-    if (trim(*p) == pat)
-      return p;
-  return in.end();
-}
-
-string escape(string s) {
-  s = replace_all(s, "\\", "\\\\");
-  s = replace_all(s, "\"", "\\\"");
-  s = replace_all(s, "", "\\n");
-  return s;
-}
-
-string replace_all(string s, const string& a, const string& b) {
-  for (size_t pos = s.find(a); pos != NOT_FOUND; pos = s.find(a, pos+b.size()))
-    s = s.replace(pos, a.size(), b);
-  return s;
-}
-
-bool any_line_starts_with(const list<string>& lines, const string& pat) {
-  for (list<string>::const_iterator p = lines.begin(); p != lines.end(); ++p)
-    if (starts_with(*p, pat)) return true;
-  return false;
-}
-
-bool any_non_input_line(const list<string>& lines) {
-  for (list<string>::const_iterator p = lines.begin(); p != lines.end(); ++p)
-    if (!is_input(*p)) return true;
-  return false;
-}
-
-#include <locale>
-using std::isspace;  // unicode-aware
-
-// does s start with pat, after skipping whitespace?
-// pat can't start with whitespace
-bool starts_with(const string& s, const string& pat) {
-  for (size_t pos = 0; pos < s.size(); ++pos)
-    if (!isspace(s[pos]))
-      return s.compare(pos, pat.size(), pat) == 0;
-  return false;
-}
-
-string indent(const string& s) {
-  for (size_t pos = 0; pos < s.size(); ++pos)
-    if (!isspace(s[pos]))
-      return s.substr(0, pos);
-  return "";
-}
-
-string strip_indent(const string& s, size_t n) {
-  if (s.empty()) return "";
-  string::const_iterator curr = s.begin();
-  while (curr != s.end() && n > 0 && isspace(*curr)) {
-    ++curr;
-    --n;
-  }
-  return string(curr, s.end());
-}
-
-string trim(const string& s) {
-  string::const_iterator first = s.begin();
-  while (first != s.end() && isspace(*first))
-    ++first;
-  if (first == s.end()) return "";
-
-  string::const_iterator last = --s.end();
-  while (last != s.begin() && isspace(*last))
-    --last;
-  ++last;
-  return string(first, last);
-}
-
-#include<dirent.h>
-
-vector<char*> sorted_files(const char* dirname, const char* ext) {
-  vector<char*> result;
-  dirent** files;
-  int num_files = scandir(dirname, &files, NULL, alphasort);
-  for (int i = 0; i < num_files; ++i) {
-    unsigned long n = strlen(files[i]->d_name), extn = strlen(ext);
-    if (n < extn) continue;
-    if (strncmp(&files[i]->d_name[n-extn], ext, extn)) continue;
-    if (!isdigit(files[i]->d_name[0])) continue;
-    char* s = new char[n+1];
-    strncpy(s, files[i]->d_name, n+1);
-    result.push_back(s);
-    free(files[i]);
-  }
-  free(files);
-  return result;
-}
diff --git a/cpp/literate/tangle/030tangle.test.cc b/cpp/literate/tangle/030tangle.test.cc
deleted file mode 100644
index 36ce2d1f..00000000
--- a/cpp/literate/tangle/030tangle.test.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-void test_tangle() {
-  istringstream in("a\nb\nc\n:(before b)\nd\n");
-  list<string> dummy;
-  tangle(in, dummy);
-  CHECK_TRACE_CONTENTS("tangle", "adbc");
-}
-
-void test_tangle2() {
-  istringstream in("a\nb\nc\n:(after b)\nd\n");
-  list<string> dummy;
-  tangle(in, dummy);
-  CHECK_TRACE_CONTENTS("tangle", "abdc");
-}
-
-void test_tangle_at_end() {
-  istringstream in("a\nb\nc\n:(after c)\nd\n");
-  list<string> dummy;
-  tangle(in, dummy);
-  CHECK_TRACE_CONTENTS("tangle", "abcd");
-}
-
-void test_tangle_indents_hunks_correctly() {
-  istringstream in("a\n  b\nc\n:(after b)\nd\n");
-  list<string> dummy;
-  tangle(in, dummy);
-  CHECK_TRACE_CONTENTS("tangle", "a  b  dc");
-}
-
-void test_tangle_warns_on_missing_target() {
-  Hide_warnings = true;
-  istringstream in(":(before)\nabc def\n");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_TRACE_WARNS();
-}
-
-void test_tangle_warns_on_unknown_target() {
-  Hide_warnings = true;
-  istringstream in(":(before \"foo\")\nabc def\n");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_TRACE_WARNS();
-}
-
-void test_tangle_delete_range_of_lines() {
-  istringstream in("a\nb {\nc\n}\n:(delete{} \"b\")\n");
-  list<string> dummy;
-  tangle(in, dummy);
-  CHECK_TRACE_CONTENTS("tangle", "a");
-  CHECK_TRACE_DOESNT_CONTAIN("tangle", "b");
-  CHECK_TRACE_DOESNT_CONTAIN("tangle", "c");
-}
-
-void test_tangle_replace() {
-  istringstream in("a\nb\nc\n:(replace b)\nd\n");
-  list<string> dummy;
-  tangle(in, dummy);
-  CHECK_TRACE_CONTENTS("tangle", "adc");
-  CHECK_TRACE_DOESNT_CONTAIN("tangle", "b");
-}
-
-void test_tangle_replace_range_of_lines() {
-  istringstream in("a\nb {\nc\n}\n:(replace{} \"b\")\nd\ne\n");
-  list<string> dummy;
-  tangle(in, dummy);
-  CHECK_TRACE_CONTENTS("tangle", "ade");
-  CHECK_TRACE_DOESNT_CONTAIN("tangle", "b {");
-  CHECK_TRACE_DOESNT_CONTAIN("tangle", "c");
-}
-
-void test_tangle_replace_tracks_old_lines() {
-  istringstream in("a\nb {\nc\n}\n:(replace{} \"b\")\nd\n:OLD_CONTENTS\ne\n");
-  list<string> dummy;
-  tangle(in, dummy);
-  CHECK_TRACE_CONTENTS("tangle", "adce");
-  CHECK_TRACE_DOESNT_CONTAIN("tangle", "b {");
-}
-
-// todo: include line numbers in tangle errors
-
-
-
-void test_tangle_supports_scenarios() {
-  istringstream in(":(scenario does_bar)\nabc def\n+layer1: pqr\n+layer2: xyz");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  run(\"abc def\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_CONTENTS(\"layer1: pqrlayer2: xyz\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-void test_tangle_supports_configurable_toplevel() {
-  istringstream in(":(scenarios foo)\n:(scenario does_bar)\nabc def\n+layer1: pqr");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  foo(\"abc def\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_CONTENTS(\"layer1: pqr\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-
-  istringstream cleanup(":(scenarios run)\n");
-  tangle(cleanup, lines);
-}
-
-void test_tangle_supports_strings_in_scenarios() {
-  istringstream in(":(scenario does_bar)\nabc \"def\"\n+layer1: pqr\n+layer2: \"xyz\"");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  run(\"abc \\\"def\\\"\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_CONTENTS(\"layer1: pqrlayer2: \\\"xyz\\\"\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-void test_tangle_supports_strings_in_scenarios2() {
-  istringstream in(":(scenario does_bar)\nabc \"\"\n+layer1: pqr\n+layer2: \"\"");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  run(\"abc \\\"\\\"\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_CONTENTS(\"layer1: pqrlayer2: \\\"\\\"\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-void test_tangle_supports_multiline_input_in_scenarios() {
-  istringstream in(":(scenario does_bar)\nabc def\n  efg\n+layer1: pqr\n+layer2: \"\"");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  run(\"abc def\\n  efg\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_CONTENTS(\"layer1: pqrlayer2: \\\"\\\"\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-void test_tangle_supports_reset_in_scenarios() {
-  istringstream in(":(scenario does_bar)\nabc def\n===\nefg\n+layer1: pqr\n+layer2: \"\"");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  run(\"abc def\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CLEAR_TRACE;");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  run(\"efg\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_CONTENTS(\"layer1: pqrlayer2: \\\"\\\"\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-void test_tangle_can_check_for_absence_at_end_of_scenarios() {
-  istringstream in(":(scenario does_bar)\nabc def\n  efg\n+layer1: pqr\n-layer1: xyz");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  run(\"abc def\\n  efg\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_CONTENTS(\"layer1: pqr\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_DOESNT_CONTAIN(\"layer1: xyz\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-void test_tangle_can_check_for_absence_at_end_of_scenarios2() {
-  istringstream in(":(scenario does_bar)\nabc def\n  efg\n-layer1: pqr\n-layer1: xyz");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  run(\"abc def\\n  efg\\n\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_DOESNT_CONTAIN(\"layer1: pqr\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_DOESNT_CONTAIN(\"layer1: xyz\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-void test_tangle_can_check_return_values_of_scenarios() {
-  istringstream in(":(scenario does_bar)\nabc def\n=> pqr");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "{");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  ostringstream os;");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  TEMP(tmp, run(\"abc def\\n\"));");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  os << tmp;");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_EQ(os.str(), \"pqr\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-void test_tangle_can_check_return_values_of_multiple_scenarios() {
-  istringstream in(":(scenario does_bar)\nabc\n=> pqr\n+layer1: pqr\ndef\n=> xyz\n");
-  list<string> lines;
-  tangle(in, lines);
-  CHECK_EQ(lines.front(), "void test_does_bar() {");  lines.pop_front();
-  CHECK_EQ(lines.front(), "{");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  ostringstream os;");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  TEMP(tmp, run(\"abc\\n\"));");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  os << tmp;");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_EQ(os.str(), \"pqr\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_TRACE_CONTENTS(\"layer1: pqr\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "{");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  ostringstream os;");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  TEMP(tmp, run(\"def\\n\"));");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  os << tmp;");  lines.pop_front();
-  CHECK_EQ(lines.front(), "  CHECK_EQ(os.str(), \"xyz\");");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK_EQ(lines.front(), "}");  lines.pop_front();
-  CHECK(lines.empty());
-}
-
-
-
-void test_trim() {
-  CHECK_EQ(trim(""), "");
-  CHECK_EQ(trim(" "), "");
-  CHECK_EQ(trim("  "), "");
-  CHECK_EQ(trim("a"), "a");
-  CHECK_EQ(trim(" a"), "a");
-  CHECK_EQ(trim("  a"), "a");
-  CHECK_EQ(trim("  ab"), "ab");
-  CHECK_EQ(trim("a "), "a");
-  CHECK_EQ(trim("a  "), "a");
-  CHECK_EQ(trim("ab  "), "ab");
-  CHECK_EQ(trim(" a "), "a");
-  CHECK_EQ(trim("  a  "), "a");
-  CHECK_EQ(trim("  ab  "), "ab");
-}
-
-void test_strip_indent() {
-  CHECK_EQ(strip_indent("", 0), "");
-  CHECK_EQ(strip_indent("", 1), "");
-  CHECK_EQ(strip_indent("", 3), "");
-  CHECK_EQ(strip_indent(" ", 0), " ");
-  CHECK_EQ(strip_indent(" a", 0), " a");
-  CHECK_EQ(strip_indent(" ", 1), "");
-  CHECK_EQ(strip_indent(" a", 1), "a");
-  CHECK_EQ(strip_indent(" ", 2), "");
-  CHECK_EQ(strip_indent(" a", 2), "a");
-  CHECK_EQ(strip_indent("  ", 0), "  ");
-  CHECK_EQ(strip_indent("  a", 0), "  a");
-  CHECK_EQ(strip_indent("  ", 1), " ");
-  CHECK_EQ(strip_indent("  a", 1), " a");
-  CHECK_EQ(strip_indent("  ", 2), "");
-  CHECK_EQ(strip_indent("  a", 2), "a");
-  CHECK_EQ(strip_indent("  ", 3), "");
-  CHECK_EQ(strip_indent("  a", 3), "a");
-}
diff --git a/cpp/literate/tangle/boot.cc b/cpp/literate/tangle/boot.cc
deleted file mode 100644
index 89f943a8..00000000
--- a/cpp/literate/tangle/boot.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// C++ style:
-//  no pointers except cell*
-//  use long as the default integer type; it's always large enough to hold pointers
-
-#define unused __attribute__((unused))
-
-#include<cstdio>
-#include<cstring>
-#include<cstdlib>
-#include<errno.h>
-#include<time.h>
-#include<math.h>
-#include<vector>
-using std::vector;
-#include<list>
-using std::list;
-#include<stack>
-using std::stack;
-#include<utility>
-using std::pair;
-
-#include<tr1/unordered_map>
-using std::tr1::unordered_map;
-#include<tr1/unordered_set>
-using std::tr1::unordered_set;
-#include<algorithm>
-
-#include<string>
-using std::string;
-const size_t NOT_FOUND = string::npos;
-
-#include<iostream>
-using std::istream;
-using std::ostream;
-using std::iostream;
-using std::cin;
-using std::cout;
-using std::cerr;
-
-#include<sstream>
-using std::stringstream;
-using std::istringstream;
-using std::ostringstream;
-
-#include<fstream>
-using std::ifstream;
-using std::ofstream;
-
-
-
-// interpreter decls
-
-#include "type_list"
-
-#include "function_list"
-
-// interpreter impl
-
-#include "file_list"
-
-// interpreter tests
-
-#include "test_file_list"
diff --git a/cpp/literate/tangle/makefile b/cpp/literate/tangle/makefile
deleted file mode 100644
index 3d938c09..00000000
--- a/cpp/literate/tangle/makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-tangle: makefile type_list function_list file_list test_file_list test_list
-	g++ -O3 -Wall -Wextra -fno-strict-aliasing boot.cc -o tangle
-
-type_list: boot.cc [0-9]*.cc
-	@# assumes struct decl has space before '{'
-	@grep -h "^struct .* {" [0-9]*.cc |perl -pwe 's/(struct *[^ ]*).*/$$1;/' > type_list
-	@grep -h typedef [0-9]*.cc >> type_list
-
-function_list: boot.cc [0-9]*.cc
-	@# assumes function decl has space before '{'
-	@grep -h "^[^ #].*) {" [0-9]*.cc |perl -pwe 's/ {.*/;/' > function_list
-
-file_list: boot.cc [0-9]*.cc
-	@ls [0-9]*.cc |grep -v "\.test\.cc$$" |perl -pwe 's/.*/#include "$$&"/' > file_list
-
-test_file_list: [0-9]*.test.cc
-	@ls [0-9]*.test.cc |perl -pwe 's/.*/#include "$$&"/' > test_file_list
-
-test_list: [0-9]*.cc
-	@grep -h "^[[:space:]]*void test_" [0-9]*.cc |perl -pwe 's/^\s*void (.*)\(\) {$$/$$1,/' > test_list
-
-clean:
-	rm -rf tangle *_list
diff --git a/cpp/literate/vimrc.vim b/cpp/literate/vimrc.vim
deleted file mode 100644
index 65fd4575..00000000
--- a/cpp/literate/vimrc.vim
+++ /dev/null
@@ -1,18 +0,0 @@
-" Highlighting wart's literate directives in C++ sources.
-function! HighlightTangledFile()
-  if &ft == ""
-    set ft=cpp
-  endif
-  syntax region wartTangle start=+:(+ skip=+".*"+ end=+)+
-  highlight link wartTangle Delimiter
-  syntax region wartTrace start="^+" end="$"
-  highlight wartTrace ctermfg=darkgreen
-  syntax region wartTraceAbsent start="^-" end="$"
-  highlight wartTraceAbsent ctermfg=darkred
-  syntax region wartTraceResult start="^=>" end="$"
-  highlight wartTraceResult ctermfg=darkgreen cterm=bold
-  syntax region wartComment start="# " end="$"
-  highlight link wartComment Comment
-endfunction
-call HighlightTangledFile()
-autocmd BufReadPost,BufNewFile 0* call HighlightTangledFile()