Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/AST/Pass.hpp	(revision f8143a66ebf58b8335a0cd8bf5a0b1361a7cfd06)
@@ -238,31 +238,112 @@
 
 private:
-	const ast::Stmt * call_accept( const ast::Stmt * );
-	const ast::Expr * call_accept( const ast::Expr * );
-
-	// requests WithStmtsToAdd directly add to this statement, as if it is a compound.
-
-	const ast::Stmt * call_accept_as_compound(const ast::Stmt *);
-
+
+	// Regular nodes
 	template< typename node_t >
-	auto call_accept( const node_t * node ) -> typename std::enable_if<
+	struct result1 {
+		bool differs;
+		const node_t * value;
+
+		template< typename object_t, typename super_t, typename field_t >
+		void apply(object_t *, field_t super_t::* field);
+	};
+
+	result1<ast::Stmt> call_accept( const ast::Stmt * );
+	result1<ast::Expr> call_accept( const ast::Expr * );
+
+	template< typename node_t >
+	auto call_accept( const node_t * node )
+		-> typename std::enable_if<
 				!std::is_base_of<ast::Expr, node_t>::value &&
 				!std::is_base_of<ast::Stmt, node_t>::value
-			, decltype( node->accept(*this) )
+			, result1<
+				typename std::remove_pointer< decltype( node->accept(*this) ) >::type
+			>
 		>::type;
 
+	// requests WithStmtsToAdd directly add to this statement, as if it is a compound.
+	result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *);
+
+	template<typename it_t, template <class...> class container_t>
+		static inline void take_all_delta( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
+			if(empty(decls)) return;
+
+			std::transform(decls->begin(), decls->end(), it, [](ast::ptr<ast::Decl>&& decl) -> auto {
+					auto loc = decl->location;
+					auto stmt = new DeclStmt( loc, decl.release() );
+					return { {stmt}, -1, false };
+				});
+			decls->clear();
+			if(mutated) *mutated = true;
+		}
+
+	// Container of statements
 	template< template <class...> class container_t >
-	container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & );
-
+	struct resultNstmt {
+		struct delta {
+			ptr<Stmt> nval;
+			ssize_t old_idx;
+			bool is_old;
+
+			delta(const Stmt * s, ssize_t i, bool old) : nval{s}, old_idx{i}, is_old{old} {}
+		};
+
+		bool differs;
+		container_t< delta > values;
+
+		resultNstmt() : differs(false), values{} {}
+		resultNstmt(bool diff, container_t< delta > && vals) : differs(diff), values(vals) {}
+
+		template< typename object_t, typename super_t, typename field_t >
+		void apply(object_t *, field_t super_t::* field);
+
+		template< template <class...> class incontainer_t >
+		void take_all( incontainer_t<ast::ptr<ast::Stmt>> * stmts ) {
+			if(!stmts || stmts->empty()) return;
+
+			std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ), [](ast::ptr<ast::Stmt>& decl) -> delta {
+					return delta( decl.release(), -1, false );
+				});
+			stmts->clear();
+			differs = true;
+		}
+
+		template< template <class...> class incontainer_t >
+		void take_all( incontainer_t<ast::ptr<ast::Decl>> * decls ) {
+			if(!decls || decls->empty()) return;
+
+			std::transform(decls->begin(), decls->end(), std::back_inserter( values ), [](ast::ptr<ast::Decl>& decl) -> auto {
+					auto loc = decl->location;
+					auto stmt = new DeclStmt( loc, decl.release() );
+					return delta( stmt, -1, false );
+				});
+			decls->clear();
+			differs = true;
+		}
+	};
+
+	template< template <class...> class container_t >
+	resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & );
+
+	// Container of something
 	template< template <class...> class container_t, typename node_t >
-	container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
+	struct resultN {
+		bool differs;
+		container_t<ptr<node_t>> values;
+
+		template< typename object_t, typename super_t, typename field_t >
+		void apply(object_t *, field_t super_t::* field);
+	};
+
+	template< template <class...> class container_t, typename node_t >
+	resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container );
 
 public:
 	/// Logic to call the accept and mutate the parent if needed, delegates call to accept
-	template<typename node_t, typename parent_t, typename child_t>
-	void maybe_accept(const node_t * &, child_t parent_t::* child);
-
-	template<typename node_t, typename parent_t, typename child_t>
-	void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);
+	template<typename node_t, typename parent_t, typename field_t>
+	void maybe_accept(const node_t * &, field_t parent_t::* field);
+
+	template<typename node_t, typename parent_t, typename field_t>
+	void maybe_accept_as_compound(const node_t * &, field_t parent_t::* field);
 
 private:
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/AST/Pass.impl.hpp	(revision f8143a66ebf58b8335a0cd8bf5a0b1361a7cfd06)
@@ -79,9 +79,9 @@
 
 		template<typename it_t, template <class...> class container_t>
-		static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * decls, bool * mutated = nullptr ) {
-			if(empty(decls)) return;
-
-			std::move(decls->begin(), decls->end(), it);
-			decls->clear();
+		static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) {
+			if(empty(stmts)) return;
+
+			std::move(stmts->begin(), stmts->end(), it);
+			stmts->clear();
 			if(mutated) *mutated = true;
 		}
@@ -123,4 +123,12 @@
 			return !new_val.empty();
 		}
+	}
+
+
+	template< typename core_t >
+	template< typename node_t >
+	template< typename object_t, typename super_t, typename field_t >
+	void ast::Pass< core_t >::result1< node_t >::apply(object_t * object, field_t super_t::* field) {
+		object->*field = value;
 	}
 
@@ -131,5 +139,7 @@
 				!std::is_base_of<ast::Expr, node_t>::value &&
 				!std::is_base_of<ast::Stmt, node_t>::value
-			, decltype( node->accept(*this) )
+			, ast::Pass< core_t >::result1<
+				typename std::remove_pointer< decltype( node->accept(*this) ) >::type
+			>
 		>::type
 	{
@@ -140,9 +150,15 @@
 		static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
 
-		return node->accept( *this );
+		auto nval = node->accept( *this );
+		ast::Pass< core_t >::result1<
+			typename std::remove_pointer< decltype( node->accept(*this) ) >::type
+		> res;
+		res.differs = nval != node;
+		res.value = nval;
+		return res;
 	}
 
 	template< typename core_t >
-	const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
+	ast::Pass< core_t >::result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( expr );
@@ -153,17 +169,19 @@
 		}
 
-		return expr->accept( *this );
+		auto nval = expr->accept( *this );
+		return { nval != expr, nval };
 	}
 
 	template< typename core_t >
-	const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
+	ast::Pass< core_t >::result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( stmt );
 
-		return stmt->accept( *this );
+		const ast::Stmt * nval = stmt->accept( *this );
+		return { nval != stmt, nval };
 	}
 
 	template< typename core_t >
-	const ast::Stmt * ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
+	ast::Pass< core_t >::result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( stmt );
@@ -190,5 +208,5 @@
 		// If the pass doesn't want to add anything then we are done
 		if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
-			return nstmt;
+			return { nstmt != stmt, nstmt };
 		}
 
@@ -212,10 +230,33 @@
 		__pass::take_all( std::back_inserter( compound->kids ), stmts_after );
 
-		return compound;
+		return {true, compound};
 	}
 
 	template< typename core_t >
 	template< template <class...> class container_t >
-	container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
+	template< typename object_t, typename super_t, typename field_t >
+	void ast::Pass< core_t >::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
+		auto & container = object->*field;
+		__pedantic_pass_assert( container.size() <= values.size() );
+
+		auto cit = enumerate(container).begin();
+
+		container_t<ptr<Stmt>> nvals;
+		for(delta & d : values) {
+			if( d.is_old ) {
+				__pedantic_pass_assert( cit.idx <= d.old_idx );
+				std::advance( cit, d.old_idx - cit.idx );
+				nvals.push_back( std::move( (*cit).val) );
+			} else {
+				nvals.push_back( std::move(d.nval) );
+			}
+		}
+
+		object->*field = std::move(nvals);
+	}
+
+	template< typename core_t >
+	template< template <class...> class container_t >
+	ast::Pass< core_t >::resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
 		__pedantic_pass_assert( __visit_children() );
 		if( statements.empty() ) return {};
@@ -244,12 +285,13 @@
 		pass_visitor_stats.avg->push(pass_visitor_stats.depth);
 
-		bool mutated = false;
-		container_t< ptr<Stmt> > new_kids;
-		for( const Stmt * stmt : statements ) {
+		resultNstmt<container_t> new_kids;
+		for( auto value : enumerate( statements ) ) {
 			try {
+				size_t i = value.idx;
+				const Stmt * stmt = value.val;
 				__pedantic_pass_assert( stmt );
 				const ast::Stmt * new_stmt = stmt->accept( *this );
 				assert( new_stmt );
-				if(new_stmt != stmt ) mutated = true;
+				if(new_stmt != stmt ) { new_kids.differs = true; }
 
 				// Make sure that it is either adding statements or declartions but not both
@@ -261,13 +303,17 @@
 
 				// Take all the statements which should have gone after, N/A for first iteration
-				__pass::take_all( std::back_inserter( new_kids ), decls_before, &mutated );
-				__pass::take_all( std::back_inserter( new_kids ), stmts_before, &mutated );
+				new_kids.take_all( decls_before );
+				new_kids.take_all( stmts_before );
 
 				// Now add the statement if there is one
-				new_kids.emplace_back( new_stmt );
+				if(new_stmt != stmt) {
+					new_kids.values.emplace_back( new_stmt, i, false );
+				} else {
+					new_kids.values.emplace_back( nullptr, i, true );
+				}
 
 				// Take all the declarations that go before
-				__pass::take_all( std::back_inserter( new_kids ), decls_after, &mutated );
-				__pass::take_all( std::back_inserter( new_kids ), stmts_after, &mutated );
+				new_kids.take_all( decls_after );
+				new_kids.take_all( stmts_after );
 			}
 			catch ( SemanticErrorException &e ) {
@@ -278,10 +324,27 @@
 		if ( !errors.isEmpty() ) { throw errors; }
 
-		return mutated ? new_kids : container_t< ptr<Stmt> >();
+		return new_kids;
 	}
 
 	template< typename core_t >
 	template< template <class...> class container_t, typename node_t >
-	container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
+	template< typename object_t, typename super_t, typename field_t >
+	void ast::Pass< core_t >::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
+		auto & container = object->*field;
+		__pedantic_pass_assert( container.size() == values.size() );
+
+		for(size_t i = 0; i < container.size(); i++) {
+			// Take all the elements that are different in 'values'
+			// and swap them into 'container'
+			if( values[i] != nullptr ) std::swap(container[i], values[i]);
+		}
+
+		// Now the original containers should still have the unchanged values
+		// but also contain the new values
+	}
+
+	template< typename core_t >
+	template< template <class...> class container_t, typename node_t >
+	ast::Pass< core_t >::resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
 		__pedantic_pass_assert( __visit_children() );
 		if( container.empty() ) return {};
@@ -293,12 +356,16 @@
 
 		bool mutated = false;
-		container_t< ast::ptr<node_t> > new_kids;
+		container_t<ptr<node_t>> new_kids;
 		for ( const node_t * node : container ) {
 			try {
 				__pedantic_pass_assert( node );
 				const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
-				if(new_stmt != node ) mutated = true;
-
-				new_kids.emplace_back( new_stmt );
+				if(new_stmt != node ) {
+					mutated = true;
+					new_kids.emplace_back( new_stmt );
+				} else {
+					new_kids.emplace_back( nullptr );
+				}
+
 			}
 			catch( SemanticErrorException &e ) {
@@ -306,8 +373,10 @@
 			}
 		}
+
+		__pedantic_pass_assert( new_kids.size() == container.size() );
 		pass_visitor_stats.depth--;
 		if ( ! errors.isEmpty() ) { throw errors; }
 
-		return mutated ? new_kids : container_t< ast::ptr<node_t> >();
+		return ast::Pass< core_t >::resultN<container_t, node_t>{ mutated,  new_kids };
 	}
 
@@ -327,9 +396,9 @@
 		auto new_val = call_accept( old_val );
 
-		static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
-
-		if( __pass::differs(old_val, new_val) ) {
+		static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
+
+		if( new_val.differs ) {
 			auto new_parent = __pass::mutate<core_t>(parent);
-			new_parent->*child = new_val;
+			new_val.apply(new_parent, child);
 			parent = new_parent;
 		}
@@ -353,7 +422,7 @@
 		static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
 
-		if( __pass::differs(old_val, new_val) ) {
+		if( new_val.differs ) {
 			auto new_parent = __pass::mutate<core_t>(parent);
-			new_parent->*child = new_val;
+			new_val.apply( new_parent, child );
 			parent = new_parent;
 		}
@@ -941,4 +1010,5 @@
 			const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
 			if(func != clause.target.func) mutated = true;
+			else func = nullptr;
 
 			std::vector<ptr<Expr>> new_args;
@@ -946,13 +1016,18 @@
 			for( const auto & arg : clause.target.args ) {
 				auto a = arg->accept(*this);
-				new_args.push_back( a );
-				if( a != arg ) mutated = true;
+				if( a != arg ) {
+					mutated = true;
+					new_args.push_back( a );
+				} else
+					new_args.push_back( nullptr );
 			}
 
 			const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
 			if(stmt != clause.stmt) mutated = true;
+			else stmt = nullptr;
 
 			const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
 			if(cond != clause.cond) mutated = true;
+			else cond = nullptr;
 
 			new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } );
@@ -961,5 +1036,14 @@
 		if(mutated) {
 			auto n = __pass::mutate<core_t>(node);
-			n->clauses = std::move( new_clauses );
+			for(size_t i = 0; i < new_clauses.size(); i++) {
+				if(new_clauses.at(i).target.func != nullptr) std::swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);
+
+				for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) {
+					if(new_clauses.at(i).target.args.at(j) != nullptr) std::swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));
+				}
+
+				if(new_clauses.at(i).stmt != nullptr) std::swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);
+				if(new_clauses.at(i).cond != nullptr) std::swap(n->clauses.at(i).cond, new_clauses.at(i).cond);
+			}
 			node = n;
 		}
@@ -969,7 +1053,7 @@
 		if(node->field) { \
 			auto nval = call_accept( node->field ); \
-			if(nval != node->field ) { \
+			if(nval.differs ) { \
 				auto nparent = __pass::mutate<core_t>(node); \
-				nparent->field = nval; \
+				nparent->field = nval.value; \
 				node = nparent; \
 			} \
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/Common/utility.h	(revision f8143a66ebf58b8335a0cd8bf5a0b1361a7cfd06)
@@ -371,4 +371,62 @@
 }
 
+template< typename T >
+struct enumerate_t {
+	template<typename val_t>
+	struct value_t {
+		val_t & val;
+		size_t idx;
+	};
+
+	template< typename iter_t, typename val_t >
+	struct iterator_t {
+		iter_t it;
+		size_t idx;
+
+		iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {}
+
+		value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; }
+
+		bool operator==(const iterator_t & o) const { return o.it == it; }
+		bool operator!=(const iterator_t & o) const { return o.it != it; }
+
+		iterator_t & operator++() {
+			it++;
+			idx++;
+			return *this;
+		}
+
+		using difference_type   = typename std::iterator_traits< iter_t >::difference_type;
+		using value_type        = value_t<val_t>;
+		using pointer           = value_t<val_t> *;
+		using reference         = value_t<val_t> &;
+		using iterator_category = std::forward_iterator_tag;
+	};
+
+	T & ref;
+
+	using iterator = iterator_t< typename T::iterator, typename T::value_type >;
+	using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >;
+
+	iterator begin() { return iterator( ref.begin(), 0 ); }
+	iterator end()   { return iterator( ref.end(), ref.size() ); }
+
+	const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); }
+	const_iterator end()   const { return const_iterator( ref.cend(), ref.size() ); }
+
+	const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); }
+	const_iterator cend()   const { return const_iterator( ref.cend(), ref.size() ); }
+};
+
+template< typename T >
+enumerate_t<T> enumerate( T & ref ) {
+	return enumerate_t< T >{ ref };
+}
+
+template< typename T >
+const enumerate_t< const T > enumerate( const T & ref ) {
+	return enumerate_t< const T >{ ref };
+}
+
 template< typename OutType, typename Range, typename Functor >
 OutType map_range( const Range& range, Functor&& functor ) {
