Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision b73bd709bb788f60341596dfaa40285cf1dc0a13)
+++ src/Common/PassVisitor.impl.h	(revision 4c03e638fae9819012408e0e7c32bfc6407e0c16)
@@ -44,23 +44,89 @@
 }
 
-typedef std::list< Statement * > StmtList_t;
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visitStatementList( std::list< Statement * > & statements ) {
+typedef std::list< Statement   * > StmtList_t;
+typedef std::list< Declaration * > DeclList_t;
+
+template<typename iterator_t>
+static inline void splice( iterator_t it, DeclList_t * decls ) {
+	std::transform(
+		decls->begin(),
+		decls->end(),
+		it,
+		[](Declaration * decl) -> auto {
+			return new DeclStmt( noLabels, decl );
+		}
+	);
+	decls->clear();
+}
+
+template< typename pass_type >
+static inline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) {
+
+	DeclList_t* beforeDecls = visitor.get_beforeDecls();
+	DeclList_t* afterDecls  = visitor.get_afterDecls();
+
+	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
+		// splice in new declarations after previous decl
+		if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }	
+
+		if ( i == decls.end() ) break;
+
+		// run mutator on declaration
+		maybeAccept( *i, visitor );
+
+		// splice in new declarations before current decl
+		if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
+	}
+}
+
+template< typename pass_type >
+static inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {
+
+	DeclList_t* beforeDecls = mutator.get_beforeDecls();
+	DeclList_t* afterDecls  = mutator.get_afterDecls();
+
+	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
+		// splice in new declarations after previous decl
+		if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }	
+
+		if ( i == decls.end() ) break;
+
+		// run mutator on declaration
+		*i = maybeMutate( *i, mutator );
+
+		// splice in new declarations before current decl
+		if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
+	}
+}
+
+template< typename pass_type >
+template< typename func_t >
+void PassVisitor< pass_type >::handleStatementList( std::list< Statement * > & statements, func_t func ) {
 	SemanticError errors;
 
 	StmtList_t* beforeStmts = get_beforeStmts();
 	StmtList_t* afterStmts  = get_afterStmts();
+	DeclList_t* beforeDecls = get_beforeDecls();
+	DeclList_t* afterDecls  = get_afterDecls();
 
 	for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
+
+		if ( !empty( afterDecls ) ) { splice( std::inserter( statements, i ), afterDecls ); }
 		if ( !empty( afterStmts ) ) { statements.splice( i, *afterStmts ); }
+
 		try {
-			(*i)->accept( *this );
+			func( *i );
+			assert(( empty( beforeStmts ) && empty( afterStmts ))
+			    || ( empty( beforeDecls ) && empty( afterDecls )) );
+
 		} catch ( SemanticError &e ) {
 			errors.append( e );
 		}
+
+		if ( !empty( beforeDecls ) ) { splice( std::inserter( statements, i ), beforeDecls ); }
 		if ( !empty( beforeStmts ) ) { statements.splice( i, *beforeStmts ); }
 	}
 
+	if ( !empty( afterDecls ) ) { splice( std::back_inserter( statements ), afterDecls); }
 	if ( !empty( afterStmts ) ) { statements.splice( statements.end(), *afterStmts ); }
 	if ( !errors.isEmpty() ) { throw errors; }
@@ -68,41 +134,44 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visitStatementList( std::list< Statement * > & statements ) {
+	handleStatementList( statements, [this]( Statement * stmt) {
+		stmt->accept( *this );
+	});
+}
+
+template< typename pass_type >
 void PassVisitor< pass_type >::mutateStatementList( std::list< Statement * > & statements ) {
-	SemanticError errors;
+	handleStatementList( statements, [this]( Statement *& stmt) {
+		stmt = stmt->acceptMutator( *this );
+	});
+}
+
+
+template< typename pass_type >
+template< typename func_t >
+Statement * PassVisitor< pass_type >::handleStatement( Statement * stmt, func_t func ) {
+	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
+	ValueGuardPtr< TypeSubstitution * >  oldEnv        ( get_env_ptr    () );
+	ValueGuardPtr< DeclList_t >          oldBeforeDecls( get_beforeDecls() );
+	ValueGuardPtr< DeclList_t >          oldAfterDecls ( get_afterDecls () );
+	ValueGuardPtr< StmtList_t >          oldBeforeStmts( get_beforeStmts() );
+	ValueGuardPtr< StmtList_t >          oldAfterStmts ( get_afterStmts () );
+
+	Statement *newStmt = func( stmt );
 
 	StmtList_t* beforeStmts = get_beforeStmts();
 	StmtList_t* afterStmts  = get_afterStmts();
-
-	for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
-		if ( !empty( afterStmts ) ) { statements.splice( i, *afterStmts ); }
-		try {
-			*i = (*i)->acceptMutator( *this );
-		} catch ( SemanticError &e ) {
-			errors.append( e );
-		}
-		if ( !empty( beforeStmts ) ) { statements.splice( i, *beforeStmts ); }
-	}
-
-	if ( !empty( afterStmts ) ) { statements.splice( statements.end(), *afterStmts ); }
-	if ( !errors.isEmpty() ) { throw errors; }
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::visitStatement( Statement * stmt ) {
-	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
-	ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
-	ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
-	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
-
-	maybeAccept( stmt, *this );
-
-	StmtList_t* beforeStmts = get_beforeStmts();
-	StmtList_t* afterStmts  = get_afterStmts();
-
-	if( empty(beforeStmts) && empty(afterStmts) ) { return stmt; }
+	DeclList_t* beforeDecls = get_beforeDecls();
+	DeclList_t* afterDecls  = get_afterDecls();
+
+	if( empty(beforeStmts) && empty(afterStmts) && empty(beforeDecls) && empty(afterDecls) ) { return newStmt; }
+	assert(( empty( beforeStmts ) && empty( afterStmts ))
+	    || ( empty( beforeDecls ) && empty( afterDecls )) );
 
 	CompoundStmt *compound = new CompoundStmt( noLabels );
+	if( !empty(beforeDecls) ) { splice( std::back_inserter( compound->get_kids() ), beforeDecls ); }
 	if( !empty(beforeStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *beforeStmts ); }
-	compound->get_kids().push_back( stmt );
+	compound->get_kids().push_back( newStmt );
+	if( !empty(afterDecls) ) { splice( std::back_inserter( compound->get_kids() ), afterDecls ); }
 	if( !empty(afterStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *afterStmts ); }
 	return compound;
@@ -110,29 +179,22 @@
 
 template< typename pass_type >
+Statement * PassVisitor< pass_type >::visitStatement( Statement * stmt ) {
+	return handleStatement( stmt, [this]( Statement * stmt ) {
+		maybeAccept( stmt, *this ); 
+		return stmt;
+	});
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutateStatement( Statement * stmt ) {
-	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
-	ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
-	ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
-	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
-
-	Statement *newStmt = maybeMutate( stmt, *this );
-
-	StmtList_t* beforeStmts = get_beforeStmts();
-	StmtList_t* afterStmts  = get_afterStmts();
-
-	if( empty(beforeStmts) && empty(afterStmts) ) { return newStmt; }
-
-	CompoundStmt *compound = new CompoundStmt( noLabels );
-	if( !empty(beforeStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *beforeStmts ); }
-	compound->get_kids().push_back( newStmt );
-	if( !empty(afterStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *afterStmts ); }
-	return compound;
-}
-
-
-
-template< typename pass_type >
-void PassVisitor< pass_type >::visitExpression( Expression * expr ) {
-	if( !expr ) return;
+	return handleStatement( stmt, [this]( Statement * stmt ) {
+	 	return maybeMutate( stmt, *this );
+	});
+}
+
+template< typename pass_type >
+template< typename func_t >
+Expression * PassVisitor< pass_type >::handleExpression( Expression * expr, func_t func ) {
+	if( !expr ) return nullptr;
 
 	auto env_ptr = get_env_ptr();
@@ -140,20 +202,23 @@
 		*env_ptr = expr->get_env();
 	}
-	// xxx - should env be cloned (or moved) onto the result of the mutate?
-	expr->accept( *this );
+
+	// should env be cloned (or moved) onto the result of the mutate?
+	return func( expr );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::visitExpression( Expression * expr ) {
+	return handleExpression(expr, [this]( Expression * expr ) {
+		expr->accept( *this );
+		return expr;
+	});		
 }
 
 template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutateExpression( Expression * expr ) {
-	if( !expr ) return nullptr;
-
-	auto env_ptr = get_env_ptr();
-	if ( env_ptr && expr->get_env() ) {
-		*env_ptr = expr->get_env();
-	}
-	// xxx - should env be cloned (or moved) onto the result of the mutate?
-	return expr->acceptMutator( *this );
-}
-
+	return handleExpression(expr, [this]( Expression * expr ) {
+		return expr->acceptMutator( *this );
+	});
+}
 
 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -233,9 +298,7 @@
 void PassVisitor< pass_type >::visit( ExprStmt * node ) {
 	VISIT_START( node );
-	call_beginScope();
 
 	visitExpression( node->get_expr() );
 
-	call_endScope();
 	VISIT_END( node );
 }
@@ -250,7 +313,14 @@
 }
 
+//--------------------------------------------------------------------------
+// AsmStmt
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( AsmStmt * node ) {
 	VISIT_BODY( node );
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( AsmStmt * node ) {
+	MUTATE_BODY( Statement, node );
 }
 
@@ -302,5 +372,5 @@
 
 //--------------------------------------------------------------------------
-// WhileStmt
+// ForStmt
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ForStmt * node ) {
@@ -371,7 +441,14 @@
 }
 
+//--------------------------------------------------------------------------
+// BranchStmt
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( BranchStmt * node ) {
 	VISIT_BODY( node );
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( BranchStmt * node ) {
+	MUTATE_BODY( Statement, node );
 }
 
@@ -417,4 +494,5 @@
 	maybeAccept( node->get_block(), *this );
 	acceptAll( node->get_catchers(), *this );
+	maybeAccept( node->get_finally(), *this );
 
 	VISIT_END( node );
@@ -427,4 +505,5 @@
 	node->set_block(  maybeMutate( node->get_block(), *this ) );
 	mutateAll( node->get_catchers(), *this );
+	node->set_finally( maybeMutate( node->get_finally(), *this ) );
 
 	MUTATE_END( Statement, node );
@@ -437,6 +516,7 @@
 	VISIT_START( node );
 
+	maybeAccept( node->get_decl(), *this );
+	node->set_cond( visitExpression( node->get_cond() ) );
 	node->set_body( visitStatement( node->get_body() ) );
-	maybeAccept( node->get_decl(), *this );
 
 	VISIT_END( node );
@@ -447,6 +527,7 @@
 	MUTATE_START( node );
 
-	node->set_body(  mutateStatement( node->get_body() ) );
-	node->set_decl(  maybeMutate( node->get_decl(), *this ) );
+	node->set_decl( maybeMutate( node->get_decl(), *this ) );
+	node->set_cond( mutateExpression( node->get_cond() ) );
+	node->set_body( mutateStatement( node->get_body() ) );
 
 	MUTATE_END( Statement, node );
@@ -840,14 +921,4 @@
 
 template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( AsmStmt * node ) {
-	MUTATE_BODY( Statement, node );
-}
-
-template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( BranchStmt * node ) {
-	MUTATE_BODY( Statement, node );
-}
-
-template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( FinallyStmt * node ) {
 	MUTATE_BODY( Statement, node );
