Index: doc/generic_types/evaluation/Makefile
===================================================================
--- doc/generic_types/evaluation/Makefile	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/Makefile	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -1,8 +1,11 @@
 CFA = my-cfa
 DEPFLAGS = -MMD -MP
+OPT = -O2
+CFLAGS = $(OPT)
+CXXFLAGS = $(OPT)
 
 .PHONY: all clean distclean bench
 
-all: c-bench cpp-bench cfa-bench c2-bench cpp2-bench cfa2-bench
+all: c-bench cpp-bench cfa-bench
 
 # rewrite object generation to auto-determine deps
@@ -13,50 +16,26 @@
 c-%.o : c-%.c
 c-%.o : c-%.c c-%.d
-	$(COMPILE.c) -O0 $(OUTPUT_OPTION) -c $<
+	$(COMPILE.c) $(OUTPUT_OPTION) -c $<
 
 cpp-%.o : cpp-%.cpp
 cpp-%.o : cpp-%.cpp cpp-%.d
-	$(COMPILE.cpp) -O0 $(OUTPUT_OPTION) -c $<
+	$(COMPILE.cpp) $(OUTPUT_OPTION) -c $<
 
 cfa-%.o : cfa-%.c
 cfa-%.o : cfa-%.c cfa-%.d
-	$(COMPILE.cfa) -O0 $(OUTPUT_OPTION) -c $<
-
-c2-%.o : c-%.c
-c2-%.o : c-%.c c-%.d
-	$(COMPILE.c) -O2 $(OUTPUT_OPTION) -c $<
-
-cpp2-%.o : cpp-%.cpp
-cpp2-%.o : cpp-%.cpp cpp-%.d
-	$(COMPILE.cpp) -O2 $(OUTPUT_OPTION) -c $<
-
-cfa2-%.o : cfa-%.c
-cfa2-%.o : cfa-%.c cfa-%.d
-	$(COMPILE.cfa) -O2 $(OUTPUT_OPTION) -c $<
+	$(COMPILE.cfa) $(OUTPUT_OPTION) -c $<
 
 COBJS = c-stack.o
 CPPOBJS = 
 CFAOBJS = cfa-stack.o
-C2OBJS = $(patsubst c-%,c2-%, $(COBJS))
-CPP2OBJS = $(patsubst cpp-%,cpp2-%, $(CPPOBJS))
-CFA2OBJS = $(patsubst cfa-%,cfa2-%, $(CFAOBJS))
 
 c-bench: c-bench.c c-bench.d $(COBJS)
-	$(COMPILE.c) -O0 -o $@ $< $(COBJS) $(LDFLAGS)
+	$(COMPILE.c) -o $@ $< $(COBJS) $(LDFLAGS)
 
 cpp-bench: cpp-bench.cpp cpp-bench.d $(CPPOBJS)
-	$(COMPILE.cpp) -O0 -o $@ $< $(CPPOBJS) $(LDFLAGS)
+	$(COMPILE.cpp) -o $@ $< $(CPPOBJS) $(LDFLAGS)
 
 cfa-bench: cfa-bench.c cfa-bench.d $(CFAOBJS)
-	$(COMPILE.cfa) -O0 -o $@ $< $(CFAOBJS) $(LDFLAGS)
-
-c2-bench: c-bench.c c-bench.d $(C2OBJS)
-	$(COMPILE.c) -O2 -o $@ $< $(C2OBJS) $(LDFLAGS)
-
-cpp2-bench: cpp-bench.cpp cpp-bench.d $(CPP2OBJS)
-	$(COMPILE.cpp) -O2 -o $@ $< $(CPP2OBJS) $(LDFLAGS)
-
-cfa2-bench: cfa-bench.c cfa-bench.d $(CFA2OBJS)
-	$(COMPILE.cfa) -O2 -o $@ $< $(CFA2OBJS) $(LDFLAGS)
+	$(COMPILE.cfa) -o $@ $< $(CFAOBJS) $(LDFLAGS)
 
 clean:
@@ -64,7 +43,4 @@
 	-rm $(CPPOBJS) cpp-bench
 	-rm $(CFAOBJS) cfa-bench
-	-rm $(C2OBJS) c2-bench
-	-rm $(CPP2OBJS) cpp2-bench
-	-rm $(CFA2OBJS) cfa2-bench
 
 distclean: clean
@@ -73,5 +49,5 @@
 	-rm $(CFAOBJS:.o=.d) cfa-bench.d
 
-bench: c-bench cpp-bench cfa-bench c2-bench cpp2-bench cfa2-bench
+bench: c-bench cpp-bench cfa-bench
 	@echo '## C ##'
 	@./c-bench
@@ -80,10 +56,4 @@
 	@echo '## Cforall ##'
 	@./cfa-bench
-	@echo '## C -O2 ##'
-	@./c2-bench
-	@echo '## C++ -O2 ##'
-	@./cpp2-bench
-	@echo '## Cforall -O2 ##'
-	@./cfa2-bench
 
 # so make doesn't fail without dependency files
Index: doc/generic_types/evaluation/bench.h
===================================================================
--- doc/generic_types/evaluation/bench.h	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/bench.h	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -2,5 +2,7 @@
 #include <time.h>
 
-#define N 200000000
+ // #define N 50000000
+ #define N 5
+
 
 long ms_between(clock_t start, clock_t end) {
Index: doc/generic_types/evaluation/c-bench.c
===================================================================
--- doc/generic_types/evaluation/c-bench.c	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/c-bench.c	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -2,4 +2,10 @@
 #include "bench.h"
 #include "c-stack.h"
+
+void* copy_int( void* p ) {
+	int* q = malloc(sizeof(int));
+	*q = *(int*)p;
+	return q;
+}
 
 int main(int argc, char** argv) {
@@ -7,5 +13,4 @@
 
 	struct stack s = new_stack();
-
 	REPEAT_TIMED( "push_int",
 		int* x = malloc(sizeof(int));
@@ -14,4 +19,18 @@
 	)
 
-	clear_stack(&s);
+	struct stack t;
+	TIMED( "copy_int",
+		copy_stack(&t, &s, copy_int);
+	)
+
+	TIMED( "clear_int",
+		clear_stack(&s);
+	)
+
+	int sum;
+	REPEAT_TIMED( "pop_int", 
+		int* x = pop_stack(&t);
+		sum += *x;
+		free(x);
+	)
 }
Index: doc/generic_types/evaluation/c-stack.c
===================================================================
--- doc/generic_types/evaluation/c-stack.c	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/c-stack.c	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -9,4 +9,16 @@
 struct stack new_stack() {
 	return (struct stack){ NULL };
+}
+
+void copy_stack(struct stack* s, struct stack* t, void* (*copy)(void*)) {
+	struct stack_node** crnt = &s->head;
+	struct stack_node* next = t->head;
+	while ( next ) {
+		*crnt = malloc(sizeof(struct stack_node));
+		**crnt = (struct stack_node){ copy(next->value) };
+		crnt = &(*crnt)->next;
+		next = next->next;
+	}
+	*crnt = 0;
 }
 
Index: doc/generic_types/evaluation/c-stack.h
===================================================================
--- doc/generic_types/evaluation/c-stack.h	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/c-stack.h	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -7,4 +7,6 @@
 struct stack new_stack();
 
+void copy_stack(struct stack* dst, struct stack* src, void* (*copy)(void*));
+
 void clear_stack(struct stack* s);
 
Index: doc/generic_types/evaluation/cfa-bench.c
===================================================================
--- doc/generic_types/evaluation/cfa-bench.c	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/cfa-bench.c	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -7,7 +7,20 @@
 
 	stack(int) s;
-
 	REPEAT_TIMED( "push_int",
 		push( &s, rand() );
 	)
+
+	stack(int) t;
+	TIMED( "copy_int", 
+		t = s;
+	)
+
+	TIMED( "clear_int", 
+		clear( &s );
+	)
+
+	int sum;
+	REPEAT_TIMED( "pop_int", 
+		sum += pop( &t );
+	)
 }
Index: doc/generic_types/evaluation/cfa-stack.c
===================================================================
--- doc/generic_types/evaluation/cfa-stack.c	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/cfa-stack.c	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -8,14 +8,28 @@
 
 forall(otype T) void ?{}(stack(T)* s) {
-	?{}( &s->head, 0 );
+	(&s->head){ 0 };
+}
+
+forall(otype T) void ?{}(stack(T)* s, stack(T) t) {
+	stack_node(T)** crnt = &s->head;
+	stack_node(T)* next = t.head;
+	while ( next ) {
+		*crnt = ((stack_node(T)*)malloc()){ next->value };
+		stack_node(T)* acrnt = *crnt;
+		crnt = &acrnt->next;
+		next = next->next;
+	}
+	*crnt = 0;
+}
+
+forall(otype T) stack(T) ?=?(stack(T)* s, stack(T) t) {
+	if ( s->head == t.head ) return *s;
+	clear(s);
+	s{ t };
+	return *s;
 }
 
 forall(otype T) void ^?{}(stack(T)* s) {
-	stack_node(T)* next = s->head;
-	while ( next ) {
-		stack_node(T)* crnt = next;
-		next = crnt->next;
-		delete(crnt);
-	}
+	clear(s);
 }
 
@@ -35,2 +49,11 @@
 	return x;
 }
+
+forall(otype T) void clear(stack(T)* s) {
+	stack_node(T)* next = s->head;
+	while ( next ) {
+		stack_node(T)* crnt = next;
+		next = crnt->next;
+		delete(crnt);
+	}
+}
Index: doc/generic_types/evaluation/cfa-stack.h
===================================================================
--- doc/generic_types/evaluation/cfa-stack.h	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/cfa-stack.h	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -7,4 +7,8 @@
 forall(otype T) void ?{}(stack(T)* s);
 
+forall(otype T) void ?{}(stack(T)* s, stack(T) t);
+
+forall(otype T) stack(T) ?=?(stack(T)* s, stack(T) t);
+
 forall(otype T) void ^?{}(stack(T)* s);
 
@@ -14,2 +18,4 @@
 
 forall(otype T) T pop(stack(T)* s);
+
+forall(otype T) void clear(stack(T)* s);
Index: doc/generic_types/evaluation/cpp-bench.cpp
===================================================================
--- doc/generic_types/evaluation/cpp-bench.cpp	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/cpp-bench.cpp	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -7,7 +7,20 @@
 
 	stack<int> s;
-
 	REPEAT_TIMED( "push_int",
 		s.push( rand() );
 	)
+
+	stack<int> t;
+	TIMED( "copy_int", 
+		t = s;
+	)
+
+	TIMED( "clear_int", 
+		s.clear();
+	)
+
+	int sum;
+	REPEAT_TIMED( "pop_int",
+		sum += t.pop();
+	)
 }
Index: doc/generic_types/evaluation/cpp-stack.h
===================================================================
--- doc/generic_types/evaluation/cpp-stack.h	(revision 4cfcf416b483f3a5b5908144db49912d0e627898)
+++ doc/generic_types/evaluation/cpp-stack.h	(revision 122aecd1d7210e548fcc07170850004dd4eb2e64)
@@ -6,4 +6,5 @@
 		node* next;
 
+		node( T& v ) : value(v), next(nullptr) {}
 		node( T&& v, node* n ) : value(std::move(v)), next(n) {}
 	};
@@ -11,8 +12,17 @@
 	node* head;
 
+	void copy(const stack<T>& o) {
+		node** crnt = &head;
+		node* next = o.head;
+		while ( next ) {
+			*crnt = new node{ next->value };
+			crnt = &(*crnt)->next;
+			next = next->next;
+		}
+		*crnt = nullptr;
+	}
+
 public:
-	stack() : head(nullptr) {}
-
-	~stack() {
+	void clear() {
 		node* next = head;
 		while ( next ) {
@@ -21,4 +31,26 @@
 			delete crnt;
 		}
+	}
+
+	stack() : head(nullptr) {}
+
+	stack(const stack<T>& o) { copy(o); }
+
+	stack(stack<T>&& o) : head(o.head) { o.head = nullptr; }
+
+	~stack() { clear(); }
+
+	stack& operator= (const stack<T>& o) {
+		if ( this == &o ) return *this;
+		clear();
+		copy(o);
+		return *this;if ( this == &o ) return *this;
+	}
+
+	stack& operator= (stack<T>&& o) {
+		if ( this == &o ) return *this;
+		head = o.head;
+		o.head = nullptr;
+		return *this;
 	}
 
