about summary refs log tree commit diff stats
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
parent9fc64bbc95bb4e55f28f5262d0f5c660177f0a19 (diff)
downloadmu-01b2852b653a81c4d5e197a0c52659c7e0dcaf5f.tar.gz
782 - promote literate version to canonical C++ version
-rw-r--r--cpp/000organization (renamed from cpp/literate/000organization)0
-rw-r--r--cpp/000test.cc28
-rw-r--r--cpp/001test (renamed from cpp/literate/001test)0
-rw-r--r--cpp/001trace.cc351
-rw-r--r--cpp/002main.cc378
-rw-r--r--cpp/002main.test.cc29
-rw-r--r--cpp/002trace (renamed from cpp/literate/002trace)0
-rw-r--r--cpp/002trace.tests (renamed from cpp/literate/002trace.tests)0
-rw-r--r--cpp/009includes (renamed from cpp/literate/009includes)0
-rw-r--r--cpp/010vm (renamed from cpp/literate/010vm)0
-rw-r--r--cpp/011load (renamed from cpp/literate/011load)0
-rw-r--r--cpp/012run (renamed from cpp/literate/012run)0
-rw-r--r--cpp/boot.cc66
-rwxr-xr-xcpp/build_and_test_until (renamed from cpp/literate/build_and_test_until)0
-rw-r--r--cpp/literate/makefile26
-rw-r--r--cpp/literate/tangle/001trace.test.cc164
-rw-r--r--cpp/makefile37
-rw-r--r--cpp/tangle/000test.cc (renamed from cpp/literate/tangle/000test.cc)0
-rw-r--r--cpp/tangle/001trace.cc (renamed from cpp/literate/tangle/001trace.cc)0
-rw-r--r--cpp/tangle/001trace.test.cc (renamed from cpp/001trace.test.cc)0
-rw-r--r--cpp/tangle/002main.cc (renamed from cpp/literate/tangle/002main.cc)0
-rw-r--r--cpp/tangle/030tangle.cc (renamed from cpp/literate/tangle/030tangle.cc)0
-rw-r--r--cpp/tangle/030tangle.test.cc (renamed from cpp/literate/tangle/030tangle.test.cc)0
-rw-r--r--cpp/tangle/boot.cc (renamed from cpp/literate/tangle/boot.cc)0
-rw-r--r--cpp/tangle/makefile (renamed from cpp/literate/tangle/makefile)0
-rw-r--r--cpp/vimrc.vim (renamed from cpp/literate/vimrc.vim)0
26 files changed, 19 insertions, 1060 deletions
diff --git a/cpp/literate/000organization b/cpp/000organization
index ba82dd52..ba82dd52 100644
--- a/cpp/literate/000organization
+++ b/cpp/000organization
diff --git a/cpp/000test.cc b/cpp/000test.cc
deleted file mode 100644
index 1a731804..00000000
--- a/cpp/000test.cc
+++ /dev/null
@@ -1,28 +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 TEST(name) void test_##name() { Trace_file = #name;
-
-#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/001test b/cpp/001test
index 45ec591d..45ec591d 100644
--- a/cpp/literate/001test
+++ b/cpp/001test
diff --git a/cpp/001trace.cc b/cpp/001trace.cc
deleted file mode 100644
index 0de7c687..00000000
--- a/cpp/001trace.cc
+++ /dev/null
@@ -1,351 +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.
-string Trace_file;
-static string Trace_dir = ".traces/";
-struct lease_tracer {
-  lease_tracer() { Trace_stream = new trace_stream; }
-  ~lease_tracer() {
-//?     cerr << "write to file? " << Trace_file << "$\n"; //? 1
-    if (!Trace_file.empty()) {
-//?       cerr << "writing\n"; //? 1
-      ofstream fout((Trace_dir+Trace_file).c_str());
-      fout << Trace_stream->readable_contents("");
-      fout.close();
-    }
-    delete Trace_stream, Trace_stream = NULL; Trace_file = ""; }
-};
-
-#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, "");
-//?   cout << "aa check2 " << layer << ": " << expected_lines.size() << '\n'; //? 1
-  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;
-//?     cout << "comparing " << p->second.second << '\n'; //? 1
-//?     cout << "     with " << expected_lines[curr_expected_line] << '\n'; //? 1
-    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/002main.cc b/cpp/002main.cc
deleted file mode 100644
index c6b72104..00000000
--- a/cpp/002main.cc
+++ /dev/null
@@ -1,378 +0,0 @@
-//? enum recipe_number {
-//?   // arithmetic
-//?   add = 1,
-//?   subtract,
-//?   multiply,
-//?   divide,
-//?   divide_with_remainder,
-//? 
-//?   // boolean
-//?   conjunction,  // 'and' is a keyword
-//?   disjunction,  // 'or' is a keyword
-//?   negation,  // 'not' is a keyword
-//? 
-//?   // comparison
-//?   equal,
-//?   not_equal,
-//?   less_than,
-//?   greater_than,
-//?   lesser_or_equal,
-//?   greater_or_equal,
-//? 
-//?   // control flow
-//?   jump,
-//?   jump_if,
-//?   jump_unless,
-//? 
-//?   // data management: scalars, arrays, and_records (structs)
-//?   copy,
-//?   get,
-//?   get_address,
-//?   index,
-//?   index_address,
-//?   allocate,
-//?   size,
-//?   length,
-//? 
-//?   // tagged_values require one primitive
-//?   save_type,
-//? 
-//?   // code points for characters
-//?   character_to_integer,
-//?   integer_to_character,
-//? 
-//?   // multiprocessing
-//?   fork,
-//?   fork_helper,
-//?   sleep,
-//?   assert,
-//?   assert_false,
-//? 
-//?   // cursor-based (text mode) interaction
-//?   cursor_mode,
-//?   retro_mode,
-//?   clear_host_screen,
-//?   clear_line_on_host,
-//?   cursor_on_host,
-//?   cursor_on_host_to_next_line,
-//?   cursor_up_on_host,
-//?   cursor_down_on_host,
-//?   cursor_right_on_host,
-//?   cursor_left_on_host,
-//?   print_character_to_host,
-//?   read_key_from_host,
-//? 
-//?   // debugging aides
-//?   _dump_memory,
-//?   _dump_trace,
-//?   _start_tracing,
-//?   _stop_tracing,
-//?   _dump_routine,
-//?   _dump_channel,
-//?   _quit,
-//?   _wait_for_key_from_host,
-//?   _print,
-//? 
-//?   // first-class continuations
-//?   current_continuation,
-//?   continue_from,
-//? 
-//?   // user-defined functions
-//?   next_input,
-//?   input,
-//?   prepare_reply,
-//?   reply,
-//? 
-//?   Max_primitive_recipe,
-//? };
-
-struct property {
-  vector<string> values;
-};
-
-typedef int type_number;
-
-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) {}
-};
-
-unordered_map<string, type_number> Type_number;
-unordered_map<type_number, type_info> Type;
-int Next_type_number = 1;
-
-unordered_map<int, int> Memory;
-
-struct reagent {
-  string name;
-  vector<type_number> types;
-  vector<pair<string, property> > properties;
-  reagent(string s) {
-    istringstream in(s);
-    name = slurp_until(in, ':');
-    types.push_back(Type_number[slurp_until(in, '/')]);  // todo: multiple types
-  }
-  string to_string() {
-    ostringstream out;
-    out << "{name: \"" << name << "\", type: " << types[0] << "}";  // todo: properties
-    return out.str();
-  }
-};
-
-const int idle = 0;
-
-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() :is_label(false), operation(idle) {}
-  void clear() { is_label=false; label.clear(); operation=idle; ingredients.clear(); products.clear(); }
-};
-
-struct recipe {
-  vector<instruction> step;
-};
-
-typedef int recipe_number;
-unordered_map<string, recipe_number> Recipe_number;
-unordered_map<recipe_number, recipe> Recipe;
-int Next_recipe_number = 1;
-
-void load(string filename) {
-}
-
-void run(string function_name) {
-}
-
-void setup_memory() {
-  Memory.clear();
-}
-
-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;
-}
-
-void setup_recipes() {
-  Recipe.clear();  Recipe_number.clear();
-  Recipe_number["idle"] = 0;
-  Next_recipe_number = 1;
-  Recipe_number["copy"] = Next_recipe_number++;
-//?   dbg << "AAA " << Recipe_number["copy"] << '\n'; //? 1
-}
-
-void compile(string form) {
-  istringstream in(form);
-  in >> std::noskipws;
-
-  string _recipe = next_word(in);
-//?   cout << _recipe << '\n'; //? 1
-  if (_recipe != "recipe")
-    raise << "top-level forms must be of the form 'recipe _name_ [ _instruction_ ... ]'\n";
-
-  string recipe_name = next_word(in);
-//?   cout << '^' << recipe_name << "$\n"; //? 1
-  if (recipe_name.empty())
-    raise << "empty recipe name in " << form << '\n';
-  int r = Recipe_number[recipe_name] = Next_recipe_number++;
-
-//?   string foo = next_word(in); //? 1
-//?   cout << '^' << foo << "$ (" << foo.size() << ")\n"; //? 1
-  if (next_word(in) != "[")
-    raise << "recipe body must begin with '['\n";
-
-  skip_newlines(in);
-
-  instruction curr;
-  while (next_instruction(in, &curr)) {
-    Recipe[r].step.push_back(curr);
-  }
-}
-
-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> ingredients, products; //? 1
-  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;
-//?   cout << "words: "; //? 1
-//?   for (vector<string>::iterator p = words.begin(); p != words.end(); ++p) { //? 1
-//?     cout << *p << "; "; //? 1
-//?   } //? 1
-//?   cout << '\n'; //? 1
-//?   return true; //? 1
-
-  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()) {
-//?     cout << "instruction yields products\n"; //? 1
-    for (; *p != "<-"; ++p) {
-      if (*p == ",") continue;
-//?       cout << "product: " << *p << '\n'; //? 1
-//?       products.push_back(*p); //? 1
-      curr->products.push_back(reagent(*p));
-    }
-    ++p;  // skip <-
-  }
-//?   return true; //? 1
-
-  curr->operation = Recipe_number[*p];  ++p;
-
-  for (; p != words.end(); ++p) {
-    if (*p == ",") continue;
-//?     cout << "ingredient: " << *p << '\n'; //? 1
-    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;
-//?   cout << "1: " << (int)in.peek() << '\n'; //? 1
-  skip_whitespace(in);
-//?   cout << "2: " << (int)in.peek() << '\n'; //? 1
-  slurp_word(in, out);
-//?   cout << "3: " << (int)in.peek() << '\n'; //? 1
-//?   cout << out.str() << '\n'; //? 1
-  return out.str();
-}
-
-void slurp_word(istream& in, ostream& out) {
-  char c;
-  if (in.peek() == ',') {
-    in >> c;
-    out << c;
-    return;
-  }
-  while (in >> c) {
-//?     cout << c << '\n'; //? 1
-    if (isspace(c) || c == ',') {
-//?       cout << "  space\n"; //? 1
-      in.putback(c);
-      break;
-    }
-    out << c;
-  }
-}
-
-void skip_whitespace(istream& in) {
-  while (isspace(in.peek()) && in.peek() != '\n') {
-//?     cout << "skip\n"; //? 1
-    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);
-}
-
-string slurp_until(istream& in, char delim) {
-  ostringstream out;
-  char c;
-  while (in >> c) {
-    if (c == delim) {
-      break;
-    }
-    out << c;
-  }
-  return out.str();
-}
-
-
-
-//// test harness
-
-void run_tests() {
-  for (unsigned long i=0; i < sizeof(Tests)/sizeof(Tests[0]); ++i) {
-    START_TRACING_UNTIL_END_OF_SCOPE;
-    setup();
-    CLEAR_TRACE;
-    (*Tests[i])();
-    verify();
-  }
-  cerr << '\n';
-  if (Num_failures > 0)
-    cerr << Num_failures << " failure"
-         << (Num_failures > 1 ? "s" : "")
-         << '\n';
-}
-
-void verify() {
-  if (!Passed)
-    ;
-  else
-    cerr << ".";
-}
-
-void setup() {
-  setup_memory();
-  setup_types();
-  setup_recipes();
-  Passed = true;
-}
-
-string time_string() {
-  time_t t;
-  time(&t);
-  char buffer[10];
-  if (!strftime(buffer, 10, "%H:%M:%S", localtime(&t)))
-    return "";
-  return buffer;
-}
-
-}  // end namespace mu
-
-int main(int argc, const char* argv[]) {
-  if (argc == 2 && string(argv[1]) == "test") {
-    mu::run_tests();
-    return 0;
-  }
-
-  for (int i = 1; i < argc; ++i) {
-    mu::load(argv[i]);
-  }
-  mu::run("main");
-}
-
-namespace mu {
diff --git a/cpp/002main.test.cc b/cpp/002main.test.cc
deleted file mode 100644
index 72dbe41f..00000000
--- a/cpp/002main.test.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-TEST(parse)
-  compile("recipe main [\n"
-          "  1:integer <- copy 23:literal\n"
-          "]\n");
-  CHECK_TRACE_CONTENTS("parse", "instruction: 1  ingredient: {name: \"23\", type: 0}  product: {name: \"1\", type: 1}");
-}
-
-TEST(parse_label)
-  compile("recipe main [\n"
-          "  foo:\n"
-          "]\n");
-  CHECK_TRACE_CONTENTS("parse", "label: foo");
-  CHECK_TRACE_DOESNT_CONTAIN("parse", "instruction: 1");
-}
-
-TEST(parse2)
-  compile("recipe main [\n"
-          "  1:integer, 2:integer <- copy 23:literal\n"
-          "]\n");
-  CHECK_TRACE_CONTENTS("parse", "instruction: 1  ingredient: {name: \"23\", type: 0}  product: {name: \"1\", type: 1}  product: {name: \"2\", type: 1}");
-}
-
-TEST(literal)
-  compile("recipe main [\n"
-          "  1:integer <- copy 23:literal\n"
-          "]\n");
-  run("main");
-  CHECK_EQ(Memory[1], 23);
-}
diff --git a/cpp/literate/002trace b/cpp/002trace
index 4d584cb1..4d584cb1 100644
--- a/cpp/literate/002trace
+++ b/cpp/002trace
diff --git a/cpp/literate/002trace.tests b/cpp/002trace.tests
index 00705346..00705346 100644
--- a/cpp/literate/002trace.tests
+++ b/cpp/002trace.tests
diff --git a/cpp/literate/009includes b/cpp/009includes
index 5c9a8d65..5c9a8d65 100644
--- a/cpp/literate/009includes
+++ b/cpp/009includes
diff --git a/cpp/literate/010vm b/cpp/010vm
index 3b8a7c96..3b8a7c96 100644
--- a/cpp/literate/010vm
+++ b/cpp/010vm
diff --git a/cpp/literate/011load b/cpp/011load
index f2855e5f..f2855e5f 100644
--- a/cpp/literate/011load
+++ b/cpp/011load
diff --git a/cpp/literate/012run b/cpp/012run
index f7b5469a..f7b5469a 100644
--- a/cpp/literate/012run
+++ b/cpp/012run
diff --git a/cpp/boot.cc b/cpp/boot.cc
deleted file mode 100644
index 64a0c58e..00000000
--- a/cpp/boot.cc
+++ /dev/null
@@ -1,66 +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
-namespace mu {
-
-#include "type_list"
-
-#include "function_list"
-
-// interpreter impl
-
-#include "file_list"
-
-// interpreter tests
-
-#include "test_file_list"
-
-}  // namespace mu
diff --git a/cpp/literate/build_and_test_until b/cpp/build_and_test_until
index 3661c93a..3661c93a 100755
--- a/cpp/literate/build_and_test_until
+++ b/cpp/build_and_test_until
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/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/makefile b/cpp/makefile
index 0dcdbce5..97187383 100644
--- a/cpp/makefile
+++ b/cpp/makefile
@@ -1,25 +1,26 @@
-mu: makefile type_list function_list file_list test_file_list test_list
-	g++ -O3 -Wall -Wextra -fno-strict-aliasing boot.cc -o mu
+mu: makefile tangle/tangle mu.cc
+	g++ -g -Wall -Wextra -fno-strict-aliasing mu.cc -o mu
+	-@./mu test
 
-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
+# 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
 
-function_list: boot.cc [0-9]*.cc
-	@# assumes function decl has space before '{'
-	@grep -h "^[^ #].*) {" [0-9]*.cc |perl -pwe 's/ {.*/;/' > function_list
-	@grep -h "^[[:space:]]*TEST(" [0-9]*.cc |perl -pwe 's/^\s*TEST\((.*)\)$$/void test_$$1();/' >> function_list
+tangle/tangle:
+	cd tangle && make
 
-file_list: boot.cc [0-9]*.cc
-	@ls [0-9]*.cc |grep -v "\.test\.cc$$" |perl -pwe 's/.*/#include "$$&"/' > file_list
+# auto-generated files; by convention they end in '_list'.
+.PHONY: autogenerated_lists
+autogenerated_lists: mu.cc function_list test_list
 
-test_file_list: [0-9]*.test.cc
-	@ls [0-9]*.test.cc |perl -pwe 's/.*/#include "$$&"/' > test_file_list
+function_list: mu.cc
+	@grep -h "^[^ #].*) {" mu.cc |perl -pwe 's/ {.*/;/' > function_list
 
-test_list: [0-9]*.cc
-	@grep -h "^[[:space:]]*void test_" [0-9]*.cc |perl -pwe 's/^\s*void (.*)\(\) {$$/$$1,/' > test_list
-	@grep -h "^[[:space:]]*TEST(" [0-9]*.cc |perl -pwe 's/^\s*TEST\((.*)\)$$/test_$$1,/' >> test_list
+test_list: mu.cc
+	@grep -h "^[[:space:]]*void test_" mu.cc |perl -pwe 's/^\s*void (.*)\(\) {.*/$$1,/' > test_list
 
 clean:
-	rm -rf mu* *_list
+	cd tangle && make clean
+	rm -rf mu.cc mu *_list
diff --git a/cpp/literate/tangle/000test.cc b/cpp/tangle/000test.cc
index 2754b254..2754b254 100644
--- a/cpp/literate/tangle/000test.cc
+++ b/cpp/tangle/000test.cc
diff --git a/cpp/literate/tangle/001trace.cc b/cpp/tangle/001trace.cc
index a99951e0..a99951e0 100644
--- a/cpp/literate/tangle/001trace.cc
+++ b/cpp/tangle/001trace.cc
diff --git a/cpp/001trace.test.cc b/cpp/tangle/001trace.test.cc
index e0db457c..e0db457c 100644
--- a/cpp/001trace.test.cc
+++ b/cpp/tangle/001trace.test.cc
diff --git a/cpp/literate/tangle/002main.cc b/cpp/tangle/002main.cc
index 851811c8..851811c8 100644
--- a/cpp/literate/tangle/002main.cc
+++ b/cpp/tangle/002main.cc
diff --git a/cpp/literate/tangle/030tangle.cc b/cpp/tangle/030tangle.cc
index 2dda8667..2dda8667 100644
--- a/cpp/literate/tangle/030tangle.cc
+++ b/cpp/tangle/030tangle.cc
diff --git a/cpp/literate/tangle/030tangle.test.cc b/cpp/tangle/030tangle.test.cc
index 36ce2d1f..36ce2d1f 100644
--- a/cpp/literate/tangle/030tangle.test.cc
+++ b/cpp/tangle/030tangle.test.cc
diff --git a/cpp/literate/tangle/boot.cc b/cpp/tangle/boot.cc
index 89f943a8..89f943a8 100644
--- a/cpp/literate/tangle/boot.cc
+++ b/cpp/tangle/boot.cc
diff --git a/cpp/literate/tangle/makefile b/cpp/tangle/makefile
index 3d938c09..3d938c09 100644
--- a/cpp/literate/tangle/makefile
+++ b/cpp/tangle/makefile
diff --git a/cpp/literate/vimrc.vim b/cpp/vimrc.vim
index 65fd4575..65fd4575 100644
--- a/cpp/literate/vimrc.vim
+++ b/cpp/vimrc.vim