Index: doc/generic_types/evaluation/Makefile
===================================================================
--- doc/generic_types/evaluation/Makefile	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/Makefile	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -33,4 +33,9 @@
 CFAOBJS = cfa-stack.o cfa-pair.o cfa-print.o
 
+CFILES = c-bench.c bench.h $(COBJS:.o=.h) $(COBJS:.o=.c)
+CPPFILES = cpp-bench.cpp bench.hpp cpp-stack.hpp cpp-print.hpp
+CPPVFILES = cpp-vbench.cpp bench.hpp object.hpp $(CPPVOBJS:.o=.hpp) $(CPPVOBJS:.o=.cpp) cpp-vprint.hpp
+CFAFILES = cfa-bench.c bench.h cfa-stack.h cfa-print.h cfa-stack.c cfa-print.c
+
 c-bench: c-bench.c c-bench.d $(COBJS)
 	$(COMPILE.c) -o $@ $< $(COBJS) $(LDFLAGS)
@@ -61,5 +66,6 @@
 	@echo '## C ##'
 	@/usr/bin/time -f 'max_memory:\t%M kilobytes' ./c-bench
-	@printf 'source_size:\t%8d lines\n' `cat c-bench.c bench.h c-stack.{h,c} c-pair.{h,c} c-print.{h,c} | wc -l`
+	@printf 'source_size:\t%8d lines\n' `cat $(CFILES) | wc -l`
+	@printf 'redundant_type_annotations:%8d count\n' `cat $(CFILES) | fgrep '/***/' -c`
 	@printf 'binary_size:\t%8d bytes\n' `stat -c %s c-bench`
 
@@ -68,5 +74,6 @@
 	@echo '## Cforall ##'
 	@/usr/bin/time -f 'max_memory:\t %M kilobytes' ./cfa-bench
-	@printf 'source_size:\t%8d lines\n' `cat cfa-bench.c bench.h cfa-stack.h cfa-stack.c cfa-print.h cfa-print.c | wc -l`
+	@printf 'source_size:\t%8d lines\n' `cat $(CFAFILES) | wc -l`
+	@printf 'redundant_type_annotations:%8d count\n' `cat $(CFAFILES) | fgrep '/***/' -c`
 	@printf 'binary_size:\t%8d bytes\n' `stat -c %s cfa-bench`
 
@@ -75,5 +82,6 @@
 	@echo '## C++ ##'
 	@/usr/bin/time -f 'max_memory:\t %M kilobytes' ./cpp-bench
-	@printf 'source_size:\t%8d lines\n' `cat cpp-bench.cpp bench.hpp cpp-stack.hpp cpp-print.hpp | wc -l`
+	@printf 'source_size:\t%8d lines\n' `cat $(CPPFILES) | wc -l`
+	@printf 'redundant_type_annotations:%8d count\n' `cat $(CPPFILES) | fgrep '/***/' -c`
 	@printf 'binary_size:\t%8d bytes\n' `stat -c %s cpp-bench`
 
@@ -82,5 +90,6 @@
 	@echo '## C++ virtual ##'
 	@/usr/bin/time -f 'max_memory:\t%M kilobytes' ./cpp-vbench
-	@printf 'source_size:\t%8d lines\n' `cat cpp-vbench.cpp bench.hpp object.hpp cpp-vstack.{hpp,cpp} cpp-vprint.hpp | wc -l`
+	@printf 'source_size:\t%8d lines\n' `cat $(CPPVFILES) | wc -l`
+	@printf 'redundant_type_annotations:%8d count\n' `cat $(CPPVFILES) | fgrep '/***/' -c`
 	@printf 'binary_size:\t%8d bytes\n' `stat -c %s cpp-vbench`
 
Index: doc/generic_types/evaluation/bench.h
===================================================================
--- doc/generic_types/evaluation/bench.h	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/bench.h	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -20,3 +20,5 @@
 }
 
-#define REPEAT_TIMED(name, code) TIMED( name, for (int _i = 0; _i < N; ++_i) { code } )
+#define REPEAT_N_TIMED(name, n, code) TIMED( name, for (int _i = 0; _i < n; ++_i) { code } )
+
+#define REPEAT_TIMED(name, code) REPEAT_N_TIMED(name, N, code)
Index: doc/generic_types/evaluation/bench.hpp
===================================================================
--- doc/generic_types/evaluation/bench.hpp	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/bench.hpp	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -21,3 +21,5 @@
 }
 
-#define REPEAT_TIMED(name, code) TIMED( name, for (int _i = 0; _i < N; ++_i) { code } )
+#define REPEAT_N_TIMED(name, n, code) TIMED( name, for (int _i = 0; _i < n; ++_i) { code } )
+
+#define REPEAT_TIMED(name, code) REPEAT_N_TIMED(name, N, code)
Index: doc/generic_types/evaluation/c-bench.c
===================================================================
--- doc/generic_types/evaluation/c-bench.c	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/c-bench.c	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -7,5 +7,5 @@
 
 _Bool* new_bool( _Bool b ) {
-	_Bool* q = malloc(sizeof(_Bool));
+	_Bool* q = malloc(sizeof(_Bool)); /***/
 	*q = b;
 	return q;
@@ -13,5 +13,5 @@
 
 char* new_char( char c ) {
-	char* q = malloc(sizeof(char));
+	char* q = malloc(sizeof(char)); /***/
 	*q = c;
 	return q;
@@ -19,28 +19,29 @@
 
 int* new_int( int i ) {
-	int* q = malloc(sizeof(int));
+	int* q = malloc(sizeof(int)); /***/
 	*q = i;
 	return q;
 }
 
-void* copy_bool( const void* p ) { return new_bool( *(const _Bool*)p ); }
+void* copy_bool( const void* p ) { return new_bool( *(const _Bool*)p ); } /***/
 
-void* copy_char( const void* p ) { return new_char( *(const char*)p ); }
+void* copy_char( const void* p ) { return new_char( *(const char*)p ); } /***/
 
-void* copy_int( const void* p ) { return new_int( *(const int*)p ); }
+void* copy_int( const void* p ) { return new_int( *(const int*)p ); } /***/
 
-void* copy_pair_bool_char( const void* p ) { return copy_pair( p, copy_bool, copy_char ); }
+void* copy_pair_bool_char( const void* p ) { return copy_pair( p, copy_bool, copy_char ); } /***/
 
-void free_pair_bool_char( void* p ) { free_pair( p, free, free ); }
+void free_pair_bool_char( void* p ) { free_pair( p, free, free ); } /***/
 
 int cmp_bool( const void* a, const void* b ) {
-	return *(const _Bool*)a == *(const _Bool*)b ? 0 : *(const _Bool*)a < *(const _Bool*)b ? -1 : 1;
+	return *(const _Bool*)a == *(const _Bool*)b ? 0 : *(const _Bool*)a < *(const _Bool*)b ? -1 : 1; /***/
 }
 
 int cmp_char( const void* a, const void* b ) {
-	return *(const char*)a == *(const char*)b ? 0 : *(const char*)a < *(const char*)b ? -1 : 1;
+	return *(const char*)a == *(const char*)b ? 0 : *(const char*)a < *(const char*)b ? -1 : 1; /***/
 }
 
 int main(int argc, char** argv) {
+	FILE* out = fopen("c-out.txt", "w");
 	srand(20171025);
 
@@ -52,16 +53,21 @@
 	struct stack t;
 	TIMED( "copy_int",
-		copy_stack(&t, &s, copy_int);
+		copy_stack(&t, &s, copy_int); /***/
 	)
 
 	TIMED( "clear_int",
-		clear_stack(&s, free);
+		clear_stack(&s, free); /***/
 	)
 
 	int max = 0;
 	REPEAT_TIMED( "pop_int", 
-		int* x = pop_stack(&t);
+		int* x = pop_stack(&t); /***/
 		if ( *x > max ) { max = *x; }
 		free(x);
+	)
+	print( out, "d", max, "\n" ); /***/
+
+	REPEAT_N_TIMED( "print_int", N/2, 
+		print( out, "dsds", rand(), ":", rand(), "\n" ); /***/
 	)
 
@@ -73,35 +79,32 @@
 	struct stack t2;
 	TIMED( "copy_bool_char", 
-		copy_stack(&t2, &s2, copy_pair_bool_char);
+		copy_stack(&t2, &s2, copy_pair_bool_char); /***/
 	)
 
 	TIMED( "clear_bool_char", 
-		clear_stack(&s2, free_pair_bool_char);
+		clear_stack(&s2, free_pair_bool_char); /***/
 	)
 
 	struct pair* max2 = new_pair( new_bool(0), new_char('\0') );
 	REPEAT_TIMED( "pop_bool_char", 
-		struct pair* x = pop_stack(&t2);
-		if ( cmp_pair( x, max2, cmp_bool, cmp_char ) > 0 ) {
-			free_pair_bool_char( max2 );
+		struct pair* x = pop_stack(&t2); /***/
+		if ( cmp_pair( x, max2, cmp_bool, cmp_char ) > 0 ) { /***/
+			free_pair_bool_char( max2 ); /***/
 			max2 = x;
 		} else {
-			free_pair_bool_char( x );
+			free_pair_bool_char( x ); /***/
 		}
 	)
-	free_pair_bool_char( max2 );
+	print( out, "pbc", *max2, "\n" ); /***/
+	free_pair_bool_char( max2 ); /***/
 
-	FILE* out = fopen("c-out.txt", "w");
-	REPEAT_TIMED( "print_int",
-		print( out, "dsds", rand(), ":", rand(), "\n" );
+	REPEAT_N_TIMED( "print_pair", N/2, 
+		struct pair p1 = ((struct pair){ new_bool(rand() & 0x1), new_char(rand() & 0x7F) }); /***/
+		struct pair p2 = ((struct pair){ new_bool(rand() & 0x1), new_char(rand() & 0x7F) }); /***/
+		print( out, "pbcspbcs", p1, ":", p2, "\n" ); /***/
+		free(p1.first); free(p1.second); /***/
+		free(p2.first); free(p2.second); /***/
 	)
-
-	REPEAT_TIMED( "print_pair", 
-		struct pair p1 = ((struct pair){ new_bool(rand() & 0x1), new_char(rand() & 0x7F) });
-		struct pair p2 = ((struct pair){ new_bool(rand() & 0x1), new_char(rand() & 0x7F) });
-		print( out, "pbcspbcs", p1, ":", p2, "\n" );
-		free(p1.first); free(p1.second);
-		free(p2.first); free(p2.second);
-	)
+	
 	fclose(out);
 }
Index: doc/generic_types/evaluation/c-pair.c
===================================================================
--- doc/generic_types/evaluation/c-pair.c	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/c-pair.c	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -3,6 +3,6 @@
 
 struct pair* new_pair(void* first, void* second) {
-	struct pair* p = malloc(sizeof(struct pair));
-	*p = (struct pair){ first, second };
+	struct pair* p = malloc(sizeof(struct pair)); /***/
+	*p = (struct pair){ first, second }; /***/
 	return p;
 }
Index: doc/generic_types/evaluation/c-print.c
===================================================================
--- doc/generic_types/evaluation/c-print.c	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/c-print.c	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -17,8 +17,8 @@
 void print_fmt(FILE* out, char fmt, void* p) {
 	switch( fmt ) {
-	case 's': print_string(out, (const char*)p); break;
-	case 'b': print_bool(out, *(_Bool*)p); break;
-	case 'c': print_char(out, *(char*)p); break;
-	case 'd': print_int(out, *(int*)p); break;
+	case 's': print_string(out, (const char*)p); break; /***/
+	case 'b': print_bool(out, *(_Bool*)p); break; /***/
+	case 'c': print_char(out, *(char*)p); break; /***/
+	case 'd': print_int(out, *(int*)p); break; /***/
 	}
 }
@@ -29,14 +29,14 @@
 	for (const char* it = fmt; *it; ++it) {
 		switch( *it ) {
-		case 's': print_string(out, va_arg(args, const char*)); break;
-		case 'b': print_bool(out, va_arg(args, int)); break;
-		case 'c': print_char(out, va_arg(args, int)); break;
-		case 'd': print_int(out, va_arg(args, int)); break;
+		case 's': print_string(out, va_arg(args, const char*)); break; /***/
+		case 'b': print_bool(out, va_arg(args, int)); break; /***/
+		case 'c': print_char(out, va_arg(args, int)); break; /***/
+		case 'd': print_int(out, va_arg(args, int)); break; /***/
 		case 'p': {
-			const struct pair x = va_arg(args, const struct pair);
+			const struct pair x = va_arg(args, const struct pair); /***/
 			fprintf(out, "[");
-			print_fmt(out, *++it, x.first);
+			print_fmt(out, *++it, x.first); /***/
 			fprintf(out, ", ");
-			print_fmt(out, *++it, x.second);
+			print_fmt(out, *++it, x.second); /***/
 			fprintf(out, "]");
 			break;
Index: doc/generic_types/evaluation/c-stack.c
===================================================================
--- doc/generic_types/evaluation/c-stack.c	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/c-stack.c	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -8,5 +8,5 @@
 
 struct stack new_stack() {
-	return (struct stack){ NULL };
+	return (struct stack){ NULL }; /***/
 }
 
@@ -15,6 +15,6 @@
 	struct stack_node* next = t->head;
 	while ( next ) {
-		*crnt = malloc(sizeof(struct stack_node));
-		**crnt = (struct stack_node){ copy(next->value) };
+		*crnt = malloc(sizeof(struct stack_node)); /***/
+		**crnt = (struct stack_node){ copy(next->value) }; /***/
 		crnt = &(*crnt)->next;
 		next = next->next;
@@ -39,6 +39,6 @@
 
 void push_stack(struct stack* s, void* value) {
-	struct stack_node* n = malloc(sizeof(struct stack_node));
-	*n = (struct stack_node){ value, s->head };
+	struct stack_node* n = malloc(sizeof(struct stack_node)); /***/
+	*n = (struct stack_node){ value, s->head }; /***/
 	s->head = n;
 }
Index: doc/generic_types/evaluation/cfa-bench.c
===================================================================
--- doc/generic_types/evaluation/cfa-bench.c	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/cfa-bench.c	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -8,4 +8,5 @@
 
 int main(int argc, char** argv) {
+	FILE* out = fopen("cfa-out.txt", "w");
 	srand(20171025);
 
@@ -28,4 +29,9 @@
 		max = max( max, pop( &t ) );
 	)
+	print( out, max, "\n" );
+
+	REPEAT_N_TIMED( "print_int", N/2, 
+		print( out, rand(), ":", rand(), "\n" );
+	)
 
 	stack(pair(_Bool, char)) s2;
@@ -47,11 +53,7 @@
 		max2 = max( max2, pop( &t2 ) );
 	)
+	print( out, max2, "\n" );
 
-	FILE* out = fopen("cfa-out.txt", "w");
-	REPEAT_TIMED( "print_int",
-		print( out, rand(), ":", rand(), "\n" );
-	)
-
-	REPEAT_TIMED( "print_pair",
+	REPEAT_N_TIMED( "print_pair", N/2, 
 		print( out, (pair(_Bool, char)){ rand() & 0x1, rand() & 0x7F }, ":",
 				(pair(_Bool, char)){ rand() & 0x1, rand() & 0x7F }, "\n" );
Index: doc/generic_types/evaluation/cfa-stack.c
===================================================================
--- doc/generic_types/evaluation/cfa-stack.c	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/cfa-stack.c	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -15,5 +15,5 @@
 	stack_node(T)* next = t->head;
 	while ( next ) {
-		*crnt = ((stack_node(T)*)malloc()){ next->value };
+		*crnt = ((stack_node(T)*)malloc()){ next->value }; /***/
 		stack_node(T)* acrnt = *crnt;
 		crnt = &acrnt->next;
@@ -27,5 +27,5 @@
 	stack_node(T)* next = t.head;
 	while ( next ) {
-		*crnt = ((stack_node(T)*)malloc()){ next->value };
+		*crnt = ((stack_node(T)*)malloc()){ next->value }; /***/
 		stack_node(T)* acrnt = *crnt;
 		crnt = &acrnt->next;
@@ -51,5 +51,5 @@
 
 forall(otype T) void push(stack(T)* s, T value) {
-	s->head = ((stack_node(T)*)malloc()){ value, s->head };
+	s->head = ((stack_node(T)*)malloc()){ value, s->head }; /***/
 }
 
Index: doc/generic_types/evaluation/cpp-bench.cpp
===================================================================
--- doc/generic_types/evaluation/cpp-bench.cpp	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/cpp-bench.cpp	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -8,4 +8,5 @@
 
 int main(int argc, char** argv) {
+	std::ofstream out{"cpp-out.txt"};
 	srand(20171025);
 
@@ -28,4 +29,9 @@
 		max = std::max( max, t.pop() );
 	)
+	print( out, max, "\n" );
+
+	REPEAT_N_TIMED( "print_int", N/2, 
+		print( out, rand(), ":", rand(), "\n" );
+	)
 
 	stack<std::pair<bool, char>> s2;
@@ -47,11 +53,7 @@
 		max2 = std::max( max2, t2.pop() );
 	)
+	print( out, max2, "\n" );
 
-	std::ofstream out{"cpp-out.txt"};
-	REPEAT_TIMED( "print_int",
-		print( out, rand(), ":", rand(), "\n" );
-	)
-
-	REPEAT_TIMED( "print_pair",
+	REPEAT_N_TIMED( "print_pair", N/2, 
 		print( out, std::pair<bool, char>{ rand() & 0x1, rand() & 0x7F }, ":",
 				std::pair<bool, char>{ rand() & 0x1, rand() & 0x7F }, "\n" );
Index: doc/generic_types/evaluation/cpp-stack.hpp
===================================================================
--- doc/generic_types/evaluation/cpp-stack.hpp	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/cpp-stack.hpp	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -18,5 +18,5 @@
 		node* next = o.head;
 		while ( next ) {
-			*crnt = new node{ next->value };
+			*crnt = new node{ next->value }; /***/
 			crnt = &(*crnt)->next;
 			next = next->next;
@@ -63,5 +63,5 @@
 
 	void push(T&& value) {
-		head = new node{ std::move(value), head };
+		head = new node{ std::move(value), head };  /***/
 	}
 
Index: doc/generic_types/evaluation/cpp-vbench.cpp
===================================================================
--- doc/generic_types/evaluation/cpp-vbench.cpp	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/cpp-vbench.cpp	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -8,4 +8,5 @@
 
 int main(int argc, char** argv) {
+	std::ofstream out{"cpp-vout.txt"};
 	srand(20171025);
 
@@ -26,5 +27,10 @@
 	integer max;
 	REPEAT_TIMED( "pop_int",
-		max = std::max( max, t.pop()->as<integer>() );
+		max = std::max( max, t.pop()->as<integer>() ); /***/
+	)
+	print( out, max, c_string{"\n"} );
+
+	REPEAT_N_TIMED( "print_int", N/2, 
+		print( out, integer{rand()}, c_string{":"}, integer{rand()}, c_string{"\n"} );
 	)
 
@@ -47,14 +53,10 @@
 		std::make_unique<character>('\0') );
 	REPEAT_TIMED( "pop_bool_char",
-		std::unique_ptr<pair> x = as_ptr<pair>( t2.pop() );
+		std::unique_ptr<pair> x = as_ptr<pair>( t2.pop() ); /***/
 		if ( *x > *max2 ) { max2 = std::move(x); }
 	)
+	print( out, *max2, c_string{"\n"} );
 
-	std::ofstream out{"cpp-vout.txt"};
-	REPEAT_TIMED( "print_int",
-		print( out, integer{rand()}, c_string{":"}, integer{rand()}, c_string{"\n"} );
-	)
-
-	REPEAT_TIMED( "print_pair", 
+	REPEAT_N_TIMED( "print_pair", N/2, 
 		print( out, pair{ std::make_unique<boolean>( rand() & 0x1 ), 
 			std::make_unique<character>( rand() & 0x7F ) }, c_string{":"}, 
Index: doc/generic_types/evaluation/cpp-vstack.cpp
===================================================================
--- doc/generic_types/evaluation/cpp-vstack.cpp	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/cpp-vstack.cpp	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -55,5 +55,5 @@
 
 void stack::push(std::unique_ptr<object>&& value) {
-	head = new node{ std::move(value), head };
+	head = new node{ std::move(value), head }; /***/
 }
 
Index: doc/generic_types/evaluation/object.hpp
===================================================================
--- doc/generic_types/evaluation/object.hpp	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/object.hpp	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -96,5 +96,5 @@
 	}
 
-	object& operator= (const object& that) override { return *this = that.as<boolean>(); }
+	object& operator= (const object& that) override { return *this = that.as<boolean>(); } /***/
 
 	~boolean() override = default;
@@ -102,5 +102,5 @@
 	int cmp(const boolean& that) const { return x == that.x ? 0 : x == false ? -1 : 1; }
 
-	int cmp(const ordered& that) const override { return cmp( that.as<boolean>() ); }
+	int cmp(const ordered& that) const override { return cmp( that.as<boolean>() ); } /***/
 
 	void print(std::ostream& out) const override { out << (x ? "true" : "false"); }
@@ -124,5 +124,5 @@
 	}
 
-	object& operator= (const object& that) override { return *this = that.as<character>(); }
+	object& operator= (const object& that) override { return *this = that.as<character>(); } /***/
 
 	~character() override = default;
@@ -130,5 +130,5 @@
 	int cmp(const character& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; }
 
-	int cmp(const ordered& that) const override { return cmp( that.as<character>() ); }
+	int cmp(const ordered& that) const override { return cmp( that.as<character>() ); } /***/
 
 	void print(std::ostream& out) const override {
@@ -155,5 +155,5 @@
 	}
 
-	object& operator= (const object& that) override { return *this = that.as<integer>(); }
+	object& operator= (const object& that) override { return *this = that.as<integer>(); } /***/
 
 	~integer() override = default;
@@ -161,5 +161,5 @@
 	int cmp(const integer& that) const { return x == that.x ? 0 : x < that.x ? -1 : 1; }
 
-	int cmp(const ordered& that) const override { return cmp( that.as<integer>() ); }
+	int cmp(const ordered& that) const override { return cmp( that.as<integer>() ); } /***/
 
 	void print(std::ostream& out) const override { out << x; }
@@ -183,5 +183,5 @@
 	}
 
-	object& operator= (const object& that) override { return *this = that.as<c_string>(); }
+	object& operator= (const object& that) override { return *this = that.as<c_string>(); } /***/
 
 	~c_string() override = default;
@@ -212,12 +212,12 @@
 	}
 
-	object& operator= (const object& that) override { return *this = that.as<pair>(); }
+	object& operator= (const object& that) override { return *this = that.as<pair>(); } /***/
 
 	~pair() override = default;
 
 	int cmp(const pair& that) const {
-		int c = x->as<ordered>().cmp( that.x->as<ordered>() );
+		int c = x->as<ordered>().cmp( that.x->as<ordered>() ); /***/
 		if ( c != 0 ) return c;
-		return y->as<ordered>().cmp( that.y->as<ordered>() );
+		return y->as<ordered>().cmp( that.y->as<ordered>() ); /***/
 	}
 
@@ -226,7 +226,7 @@
 	void print(std::ostream& out) const override {
 		out << "[";
-		x->as<printable>().print(out);
+		x->as<printable>().print(out); /***/
 		out << ", ";
-		y->as<printable>().print(out);
+		y->as<printable>().print(out); /***/
 		out << "]";
 	}
Index: doc/generic_types/evaluation/timing.csv
===================================================================
--- doc/generic_types/evaluation/timing.csv	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/timing.csv	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -1,11 +1,12 @@
-"400 million repetitions","C","\\CFA{}","\\CC{}","\\CC{obj}","units"
-"push\nint",3379,2616,1928,3527,"ms"
-"copy\nint",3036,2268,1564,3182,"ms"
-"clear\nint",1389,834,751,1502,"ms"
-"pop\nint",1421,2728,738,5245,"ms"
-"push\npair",4598,3708,1776,7302,"ms"
-"copy\npair",6367,1920,1009,6982,"ms"
-"clear\npair",2906,875,732,3387,"ms"
-"pop\npair",3136,8283,861,21669,"ms"
-"print\nint",17373,17157,9779,10051,"ms"
-"print\npair",24862,27693,20599,42533,"ms"
+"400 million repetitions","C","\\CFA{}","\\CC{}","\\CC{obj}"
+"push\nint",3358,2616,1929,3559
+"copy\nint",2966,2268,1534,3097
+"clear\nint",1343,834,708,1487
+"pop\nint",1385,2728,711,5122
+"print\nint",6609,17157,5006,5023
+"push\npair",4930,3708,1795,7136
+"copy\npair",6203,1920,996,7043
+"clear\npair",2811,875,712,3393
+"pop\npair",3054,8283,883,21262
+"print\npair",12364,27693,10448,21468
+
Index: doc/generic_types/evaluation/timing.gp
===================================================================
--- doc/generic_types/evaluation/timing.gp	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/evaluation/timing.gp	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -12,5 +12,5 @@
 set boxwidth 0.8
 
-set ylabel "seconds"
+set ylabel "milliseconds"
 set key top left reverse Left
 
Index: doc/generic_types/generic_types.tex
===================================================================
--- doc/generic_types/generic_types.tex	(revision bbe856cb49de5a25ada3357ed15ae1d431bbc03b)
+++ doc/generic_types/generic_types.tex	(revision 15045368f019113e5a59e80528d1efd5bcbd9ba9)
@@ -969,7 +969,7 @@
 The \CCV variant illustrates an alternative object-oriented idiom where all objects inherit from a base @object@ class, mimicking a Java-like interface;
 hence runtime checks are necessary to safely down-cast objects.
-The most notable difference among the implementations is in optimizations: \CFA and \CC inline the stack and pair elements into corresponding list and pair nodes, while the C and \CCV lack generic-type capability {\color{red}(AWKWARD) to store generic objects via pointers to separately-allocated objects}.
-For the print benchmark, idiomatic printing is used: the C and \CFA variants used @cstdio.h@, while the \CC and \CCV variants used @iostream@.
-Preliminary tests show the difference has little runtime effect.
+The most notable difference among the implementations is in memory layout of generic types: \CFA and \CC inline the stack and pair elements into corresponding list and pair nodes, while C and \CCV lack such a capability and store generic objects via pointers to separately-allocated objects instead.
+For the print benchmark, idiomatic printing is used: the C and \CFA variants use @stdio.h@, while the \CC and \CCV variants use @iostream@.
+Preliminary tests show this difference has little runtime effect.
 Finally, the C @rand@ function is used generate random numbers.
 
@@ -1014,14 +1014,15 @@
 \newcommand{\CT}[1]{\multicolumn{1}{c}{#1}}
 \begin{tabular}{r|rrrr}
-							& \CT{C}	& \CT{\CFA}	& \CT{\CC}	&	\CT{\CCV}	\\ \hline
-maximum memory usage (MB)	& 10001		& 2501		& 2503		&	11253		\\
-source code size (lines)	& 301		& 224		& 188		&	437			\\
-binary size (KB)			& 18		& 234		& 18		&	42			\\
+									& \CT{C}	& \CT{\CFA}	& \CT{\CC}	&	\CT{\CCV}	\\ \hline
+maximum memory usage (MB)			& 10001		& 2501		& 2503		&	11253		\\
+source code size (lines)			& 301		& 224		& 188		&	437			\\
+redundant type annotations (lines)	& 46		& 3			& 2			&	15			\\
+binary size (KB)					& 18		& 234		& 18		&	42			\\
 \end{tabular}
 \end{table}
 
 Figure~\ref{fig:eval} and Table~\ref{tab:eval} show the benchmark results.
-Each data point is the time for 40M function call, repeated times where appropriate.
-The five functions are $N$ stack pushes of randomly generated elements, deep copy of an $N$ element stack, clearing all nodes of an $N$ element stack, $N/2$ variadic @print@ calls each containing two constant strings and two stack elements \TODO{right now $N$ fresh elements: FIX}, and $N$ stack pops, keeping a running record of the maximum element to ensure that the object copies are not optimized out.
+Each data point is the time for $N = 40M$ function calls or loop iterations, as appropriate.
+The five functions are $N$ stack pushes of randomly generated elements, deep copy of an $N$ element stack, clearing all nodes of an $N$ element stack, $N$ stack pops (keeping a running record of the maximum element to ensure that the object copies are not optimized out), and $N/2$ variadic @print@ calls each containing two constant strings and two stack elements.
 These five functions are run first for a stack of integers, and second for a stack of generic pairs of a boolean and a @char@.
 \TODO{} The data shown is the median of 5 consecutive runs of each program, with an initial warm-up run omitted.
@@ -1032,11 +1033,11 @@
 
 \CC performs best because it uses header-only inlined libraries (i.e., no separate compilation).
-\CFA and \CC have the advantage of a pre-written generic @pair@ type to reduce line count, while C and \CCV require it to written by the programmer. {\color{red} Why?}
-The definition of @object@ and wrapper classes for @bool@, @char@, @int@, and @const char *@ are included in the line count for \CCV, which somewhat inflates its line count, as an actual object-oriented language would include these in the standard library and with their omission the \CCV line count is similar to C;
-we justify the given line count by the fact that many object-oriented languages do not allow implementing new interfaces on library types without subclassing or boilerplate-filled wrapper types, which may be similarly verbose.
+\CFA and \CC have the advantage of a pre-written generic @pair@ type to reduce line count, while C and \CCV require it to written by the programmer, as C does not have a generic collections library in its standard distribution and \CCV does not use the \CC standard template library by construction.
+The definition of @object@ and wrapper classes for @bool@, @char@, @int@, and @const char *@ are included in the line count for \CCV, which somewhat inflates its line count, as an actual object-oriented language would include these in the standard library; with their omission the \CCV line count is similar to C.
+We justify the given line count by noting that many object-oriented languages do not allow implementing new interfaces on library types without subclassing or boilerplate-filled wrapper types, which may be similarly verbose.
+
 Raw line-count, however, is a fairly rough measure of code complexity;
 another important factor is how much type information the programmer must manually specify, especially where that information is not checked by the compiler.
-Such un-checked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointers arguments and format codes, or \CCV, with its extensive use of un-type-checked downcasts (\eg @object@ to @integer@ when popping a stack, or @object@ to @printable@ when printing the elements of a @pair@) \TODO{Actually calculate this; I want to put a distinctive comment in the source code and grep for it}.
-
+Such un-checked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointers arguments and format codes, or \CCV, with its extensive use of un-type-checked downcasts (\eg @object@ to @integer@ when popping a stack, or @object@ to @printable@ when printing the elements of a @pair@). To quantify this, the ``redundant type annotations'' line in Table~\ref{tab:eval} counts the number of lines on which the type of a known variable is re-specified, either as a format specifier, explicit downcast, type-specific function, or by name in a @sizeof@, struct literal, or @new@ expression. The \CC benchmark uses two redundant type annotations to create a new stack nodes, while the C and \CCV benchmarks have several such annotations spread throughout their code. The three instances in which the \CFA benchmark still uses redundant type specifiers are to cast the result of a polymorphic @malloc@ call (the @sizeof@ argument is inferred by the compiler). These uses are similar to the @new@ expressions in \CC, though ongoing work on the \CFA compiler's type resolver should shortly render even these type casts superfluous.
 
 \section{Related Work}
@@ -1127,5 +1128,4 @@
 \appendix
 
-
 \section{BenchMarks}
 \label{sec:BenchMarks}
