about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--cpp/000organization173
-rw-r--r--cpp/002trace167
-rw-r--r--cpp/009includes4
-rw-r--r--cpp/010vm10
-rw-r--r--cpp/011load2
-rw-r--r--cpp/012run32
-rw-r--r--cpp/017record6
-rw-r--r--cpp/018address8
-rw-r--r--cpp/019array11
-rw-r--r--cpp/020call3
-rw-r--r--cpp/021call_ingredient4
-rw-r--r--cpp/022call_reply2
-rw-r--r--cpp/makefile2
13 files changed, 223 insertions, 201 deletions
diff --git a/cpp/000organization b/cpp/000organization
index ab1cee79..6c513809 100644
--- a/cpp/000organization
+++ b/cpp/000organization
@@ -1,86 +1,89 @@
-// 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.
+//: 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".
+//: A simple tool will 'tangle' these files according to the directives, though
+//: it'll drop these comments starting with a '//:' prefix that only make sense
+//: in the context of layers.
+//:
+//: 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
@@ -102,5 +105,5 @@ void setup() {
   // End Setup
 }
 
-// Without directives or with the :(code) directive, lines get added at the
-// end.
+//: Without directives or with the :(code) directive, lines get added at the
+//: end.
diff --git a/cpp/002trace b/cpp/002trace
index b4d0cfca..dd07beed 100644
--- a/cpp/002trace
+++ b/cpp/002trace
@@ -1,87 +1,86 @@
-// 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)
+//: 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
+//: We try 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
diff --git a/cpp/009includes b/cpp/009includes
index 5c9a8d65..c9f96288 100644
--- a/cpp/009includes
+++ b/cpp/009includes
@@ -1,5 +1,5 @@
-// Some common includes needed all over the place.
-// More tightly-targeted includes show up in other files.
+//: Some common includes needed all over the place.
+//: More tightly-targeted includes show up in other files.
 
 :(before "End Includes")
 #include<assert.h>
diff --git a/cpp/010vm b/cpp/010vm
index 57f0be1f..53496fde 100644
--- a/cpp/010vm
+++ b/cpp/010vm
@@ -56,7 +56,7 @@ unordered_map<int, int> Memory;
   Memory.clear();
 
 :(after "Types")
-// Types encode how the numbers stored in different parts of memory are
+// Mu 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.
@@ -74,14 +74,14 @@ void setup_types() {
   Type.clear();  Type_number.clear();
   Type_number["literal"] = 0;
   Next_type_number = 1;
-  // Mu Types.
+  // Mu Types Initialization.
   int integer = Type_number["integer"] = Next_type_number++;
   Type[integer].size = 1;
   int address = Type_number["address"] = Next_type_number++;
   Type[address].size = 1;
   int boolean = Type_number["boolean"] = Next_type_number++;
   Type[boolean].size = 1;
-  // End Mu Types.
+  // End Mu Types Initialization.
 }
 :(before "End Setup")
   setup_types();
@@ -127,8 +127,10 @@ void setup_recipes() {
 
 
 
+//: Helpers
+
 :(code)
-// Helpers
+// indent members to avoid generating prototypes for them
   instruction::instruction() :is_label(false), operation(IDLE) {}
   void instruction::clear() { is_label=false; label.clear(); operation=IDLE; ingredients.clear(); products.clear(); }
 
diff --git a/cpp/011load b/cpp/011load
index 707f9e59..0891a247 100644
--- a/cpp/011load
+++ b/cpp/011load
@@ -1,4 +1,4 @@
-// It's often convenient to express recipes in a textual fashion.
+//: It's often convenient to express recipes in a textual fashion.
 :(scenarios add_recipes)
 :(scenario first_recipe)
 recipe main [
diff --git a/cpp/012run b/cpp/012run
index 42b5d477..3d1395a9 100644
--- a/cpp/012run
+++ b/cpp/012run
@@ -19,7 +19,7 @@ recipe main [
 
 :(before "End Types")
 // Book-keeping while running a recipe.
-// Later layers will change this.
+//: Later layers will change this.
 struct routine {
   recipe_number running_recipe;
   size_t running_at;
@@ -27,11 +27,6 @@ struct routine {
 };
 
 :(code)
-void run(string form) {
-  vector<recipe_number> recipes_added = add_recipes(form);
-  run(recipes_added.front());
-}
-
 void run(recipe_number r) {
   run(routine(r));
 }
@@ -59,9 +54,9 @@ void run(routine rr) {
   }
 }
 
-// Some helpers.
-// We'll need to override these later as we change the definition of routine.
-// Important that they return referrences into the routine.
+//: Some helpers.
+//: We'll need to override these later as we change the definition of routine.
+//: Important that they return referrences into the routine.
 inline size_t& running_at(routine& rr) {
   return rr.running_at;
 }
@@ -92,6 +87,25 @@ if (argc > 1) {
   dump_memory();
 }
 
+//: helper for tests
+
+:(before "End Globals")
+vector<recipe_number> recipes_added_by_test;
+
+:(code)
+void run(string form) {
+  vector<recipe_number> tmp = add_recipes(form);
+  recipes_added_by_test.insert(recipes_added_by_test.end(), tmp.begin(), tmp.end());
+  run(recipes_added_by_test.front());
+}
+
+:(before "End Setup")
+for (size_t i = 0; i < recipes_added_by_test.size(); ++i) {
+  Recipe_number.erase(Recipe[recipes_added_by_test[i]].name);
+  Recipe.erase(recipes_added_by_test[i]);
+}
+recipes_added_by_test.clear();
+
 :(code)
 vector<int> read_memory(reagent x) {
 //?   cout << "read_memory: " << x.to_string() << '\n'; //? 1
diff --git a/cpp/017record b/cpp/017record
index d64fdcb6..f42531be 100644
--- a/cpp/017record
+++ b/cpp/017record
@@ -1,5 +1,5 @@
-// Support for records.
-:(before "End Mu Types")
+//: Support for records.
+:(before "End Mu Types Initialization")
 // We'll use this record as a running example, with two integer fields
 int point = Type_number["point"] = Next_type_number++;
 Type[point].size = 2;
@@ -73,7 +73,7 @@ recipe main [
 +run: product 0 is 35
 +mem: storing in location 15
 
-:(before "End Mu Types")
+:(before "End Mu Types Initialization")
 // A more complex record, containing another record.
 int point_integer = Type_number["point-integer"] = Next_type_number++;
 Type[point_integer].size = 2;
diff --git a/cpp/018address b/cpp/018address
index bdf10685..cd4f180e 100644
--- a/cpp/018address
+++ b/cpp/018address
@@ -1,5 +1,6 @@
+//: Instructions can read from addresses pointing at other locations using the
+//: 'deref' property.
 :(scenario "copy_indirect")
-# Instructions can read from addresses pointing at other locations using the 'deref' property.
 recipe main [
   1:address:integer <- copy 2:literal
   2:integer <- copy 34:literal
@@ -29,8 +30,9 @@ vector<int> read_memory(reagent x) {
   return result;
 }
 
+//: similarly, write to addresses pointing at other locations using the
+//: 'deref' property
 :(scenario "store_indirect")
-# similarly, write to addresses pointing at other locations using the 'deref' property
 recipe main [
   1:address:integer <- copy 2:literal
   1:address:integer/deref <- copy 34:literal
@@ -95,8 +97,8 @@ reagent deref(reagent x) {
   return result;
 }
 
+//: 'get' can read from record address
 :(scenario "get_indirect")
-# 'get' can read from record address
 recipe main [
   1:integer <- copy 2:literal
   2:integer <- copy 34:literal
diff --git a/cpp/019array b/cpp/019array
index 3d797161..8a9af8c4 100644
--- a/cpp/019array
+++ b/cpp/019array
@@ -1,13 +1,14 @@
-// Support for arrays.
-:(before "End Mu Types")
-// We'll use this array as a running example:
+//: Support for arrays.
+:(before "End Mu Types Initialization")
+//: We'll use this array as a running example:
 int integer_array = Type_number["integer-array"] = Next_type_number++;
 Type[integer_array].is_array = true;
 Type[integer_array].element.push_back(integer);
 
+//: Arrays can be copied around with a single instruction just like integers,
+//: no matter how large they are.
+
 :(scenario copy_array)
-# Arrays can be copied around with a single instruction just like integers,
-# no matter how large they are.
 recipe main [
   1:integer <- copy 3:literal
   2:integer <- copy 14:literal
diff --git a/cpp/020call b/cpp/020call
index f926a100..8efee27c 100644
--- a/cpp/020call
+++ b/cpp/020call
@@ -1,4 +1,4 @@
-// So far the recipes we define can't run each other. Let's change that.
+//: So far the recipes we define can't run each other. Let's change that.
 :(scenario "calling_recipe")
 recipe main [
   f
@@ -27,6 +27,7 @@ struct routine {
     calls.push(call(r));
   }
 };
+//: now update routine's helpers
 :(replace{} "inline size_t& running_at(routine& rr)")
 inline size_t& running_at(routine& rr) {
   return rr.calls.top().pc;
diff --git a/cpp/021call_ingredient b/cpp/021call_ingredient
index f42f0b48..9cc30470 100644
--- a/cpp/021call_ingredient
+++ b/cpp/021call_ingredient
@@ -1,5 +1,5 @@
-// Calls can take ingredients just like primitives. To access a recipe's
-// ingredients, use 'next_ingredient'.
+//: Calls can take ingredients just like primitives. To access a recipe's
+//: ingredients, use 'next_ingredient'.
 :(scenario "next_ingredient")
 recipe main [
   f 2:literal
diff --git a/cpp/022call_reply b/cpp/022call_reply
index 0d0149cb..3deb5464 100644
--- a/cpp/022call_reply
+++ b/cpp/022call_reply
@@ -1,4 +1,4 @@
-// Calls can also generate results, using 'reply'.
+//: Calls can also generate results, using 'reply'.
 :(scenario "reply")
 recipe main [
   3:integer, 4:integer <- f 2:literal
diff --git a/cpp/makefile b/cpp/makefile
index 554c6c45..4fbe6759 100644
--- a/cpp/makefile
+++ b/cpp/makefile
@@ -5,7 +5,7 @@ mu: makefile tangle/tangle mu.cc
 # 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
+	./tangle/tangle --until 999 |grep -v "^\s*//:" > mu.cc
 	@make autogenerated_lists >/dev/null
 
 tangle/tangle: