Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision b3f252a219989f7ab8f2f00efbcad32b69910b55)
+++ src/Common/PassVisitor.h	(revision e0886dba1ec9ab949bb8d227feb423286cb7057c)
@@ -7,4 +7,6 @@
 #include "SynTree/Mutator.h"
 #include "SynTree/Visitor.h"
+
+#include "SymTab/Indexer.h"
 
 #include "SynTree/Initializer.h"
@@ -265,4 +267,23 @@
 
 	void set_visit_children( bool& ref ) { bool_ref * ptr = visit_children_impl(pass, 0); if(ptr) ptr->set( ref ); }
+
+	void indexerScopeEnter  ()                             { indexer_impl_enterScope  ( pass, 0       ); }
+	void indexerScopeLeave  ()                             { indexer_impl_leaveScope  ( pass, 0       ); }
+	void indexerAddId       ( DeclarationWithType * node ) { indexer_impl_addId       ( pass, 0, node ); }
+	void indexerAddType     ( NamedTypeDecl       * node ) { indexer_impl_addType     ( pass, 0, node ); }
+	void indexerAddStruct   ( const std::string   & id   ) { indexer_impl_addStruct   ( pass, 0, id   ); }
+	void indexerAddStruct   ( StructDecl          * node ) { indexer_impl_addStruct   ( pass, 0, node ); }
+	void indexerAddStructFwd( StructDecl          * node ) { indexer_impl_addStructFwd( pass, 0, node ); }
+	void indexerAddEnum     ( EnumDecl            * node ) { indexer_impl_addEnum     ( pass, 0, node ); }
+	void indexerAddUnion    ( const std::string   & id   ) { indexer_impl_addUnion    ( pass, 0, id   ); }
+	void indexerAddUnion    ( UnionDecl           * node ) { indexer_impl_addUnion    ( pass, 0, node ); }
+	void indexerAddUnionFwd ( UnionDecl           * node ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
+	void indexerAddTrait    ( TraitDecl           * node ) { indexer_impl_addTrait    ( pass, 0, node ); }
+
+	template< typename TreeType, typename VisitorType >
+	friend inline void indexerScopedAccept( TreeType * tree, VisitorType &visitor );
+
+	template< typename TreeType, typename VisitorType >
+	friend inline void indexerScopedMutate( TreeType *& tree, VisitorType &visitor );
 };
 
@@ -296,5 +317,7 @@
 protected:
 	WithDeclsToAdd() = default;
-	~WithDeclsToAdd() = default;
+	~WithDeclsToAdd() {
+		assert( declsToAddBefore.empty() );
+	}
 
 public:
@@ -351,3 +374,12 @@
 };
 
+class WithIndexer {
+protected:
+	WithIndexer() {}
+	~WithIndexer() {}
+
+public:
+	SymTab::Indexer indexer;
+};
+
 #include "PassVisitor.impl.h"
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision b3f252a219989f7ab8f2f00efbcad32b69910b55)
+++ src/Common/PassVisitor.impl.h	(revision e0886dba1ec9ab949bb8d227feb423286cb7057c)
@@ -101,4 +101,42 @@
 }
 
+template< typename Container, typename VisitorType >
+inline void maybeAccept( Container &container, VisitorType &visitor ) {
+	SemanticError errors;
+	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
+		try {
+			if ( *i ) {
+				(*i)->accept( visitor );
+			}
+		} catch( SemanticError &e ) {
+			e.set_location( (*i)->location );
+			errors.append( e );
+		}
+	}
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	}
+}
+
+template< typename Container, typename MutatorType >
+inline void maybeMutateRef( Container &container, MutatorType &mutator ) {
+	SemanticError errors;
+	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
+		try {
+			if ( *i ) {
+///		    *i = (*i)->acceptMutator( mutator );
+				*i = dynamic_cast< typename Container::value_type >( (*i)->acceptMutator( mutator ) );
+				assert( *i );
+			} // if
+		} catch( SemanticError &e ) {
+			e.set_location( (*i)->location );
+			errors.append( e );
+		} // try
+	} // for
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	} // if
+}
+
 template< typename pass_type >
 template< typename func_t >
@@ -230,48 +268,314 @@
 
 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
+//========================================================================================================================================================================
+//========================================================================================================================================================================
+//========================================================================================================================================================================
+//========================================================================================================================================================================
+//========================================================================================================================================================================
+//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------------
+// ObjectDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ObjectDecl * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->type         , *this );
+	maybeAccept        ( node->init         , *this );
+	maybeAccept        ( node->bitfieldWidth, *this );
+
+	if ( node->name != "" ) {
+		indexerAddId( node );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+DeclarationWithType * PassVisitor< pass_type >::mutate( ObjectDecl * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->type         , *this );
+	maybeMutateRef     ( node->init         , *this );
+	maybeMutateRef     ( node->bitfieldWidth, *this );
+
+	if ( node->name != "" ) {
+		indexerAddId( node );
+	}
+
+	MUTATE_END( DeclarationWithType, node );
+}
+
+//--------------------------------------------------------------------------
+// FunctionDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( FunctionDecl * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	if ( node->name != "" ) {
+		indexerAddId( node );
+	}
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->type, *this );
+		maybeAccept( node->statements, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+DeclarationWithType * PassVisitor< pass_type >::mutate( FunctionDecl * node ) {
+	MUTATE_START( node );
+
+	if ( node->name != "" ) {
+		indexerAddId( node );
+	}
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->type, *this );
+		maybeMutateRef( node->statements, *this );
+	}
+
+	MUTATE_END( DeclarationWithType, node );
+}
+
+//--------------------------------------------------------------------------
+// StructDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( StructDecl * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	// make up a forward declaration and add it before processing the members
+	// needs to be on the heap because addStruct saves the pointer
+	indexerAddStructFwd( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->parameters, *this );
+		maybeAccept( node->members   , *this );
+	}
+
+	// this addition replaces the forward declaration
+	indexerAddStruct( node );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
+	MUTATE_START( node );
+
+	// make up a forward declaration and add it before processing the members
+	// needs to be on the heap because addStruct saves the pointer
+	indexerAddStructFwd( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->parameters, *this );
+		maybeMutateRef( node->members   , *this );
+	}
+
+	// this addition replaces the forward declaration
+	indexerAddStruct( node );
+
+	MUTATE_END( Declaration, node );
+}
+
+//--------------------------------------------------------------------------
+// UnionDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( UnionDecl * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	// make up a forward declaration and add it before processing the members
+	indexerAddUnionFwd( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->parameters, *this );
+		maybeAccept( node->members   , *this );
+	}
+
+	indexerAddUnion( node );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( UnionDecl * node ) {
+	MUTATE_START( node );
+
+	// make up a forward declaration and add it before processing the members
+	indexerAddUnionFwd( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->parameters, *this );
+		maybeMutateRef( node->members   , *this );
+	}
+
+	indexerAddUnion( node );
+
+	MUTATE_END( Declaration, node );
+}
+
+//--------------------------------------------------------------------------
+// EnumDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( EnumDecl * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerAddEnum( node );
+
+	// unlike structs, contexts, and unions, enums inject their members into the global scope
+	maybeAccept( node->parameters, *this );
+	maybeAccept( node->members   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( EnumDecl * node ) {
+	MUTATE_START( node );
+
+	indexerAddEnum( node );
+
+	// unlike structs, contexts, and unions, enums inject their members into the global scope
+	maybeMutateRef( node->parameters, *this );
+	maybeMutateRef( node->members   , *this );
+
+	MUTATE_END( Declaration, node );
+}
+
+//--------------------------------------------------------------------------
+// TraitDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TraitDecl * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->parameters, *this );
+		maybeAccept( node->members   , *this );
+	}
+
+	indexerAddTrait( node );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( TraitDecl * node ) {
+	MUTATE_START( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->parameters, *this );
+		maybeMutateRef( node->members   , *this );
+	}
+
+	indexerAddTrait( node );
+
+	MUTATE_END( Declaration, node );
+}
+
+//--------------------------------------------------------------------------
+// TypeDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TypeDecl * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->parameters, *this );
+		maybeAccept( node->base      , *this );
+	}
+
+	indexerAddType( node );
+
+	maybeAccept( node->assertions, *this );
+
+	indexerScopedAccept( node->init, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+TypeDecl * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
+	MUTATE_START( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->parameters, *this );
+		maybeMutateRef( node->base      , *this );
+	}
+
+	indexerAddType( node );
+
+	maybeMutateRef( node->assertions, *this );
+
+	indexerScopedMutate( node->init, *this );
+
+	MUTATE_END( TypeDecl, node );
+}
+
+//--------------------------------------------------------------------------
+// TypedefDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TypedefDecl * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->parameters, *this );
+		maybeAccept( node->base      , *this );
+	}
+
+	indexerAddType( node );
+
+	maybeAccept( node->assertions, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( TypedefDecl * node ) {
+	MUTATE_START( node );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef     ( node->parameters, *this );
+		maybeMutateRef( node->base      , *this );
+	}
+
+	indexerAddType( node );
+
+	maybeMutateRef( node->assertions, *this );
+
+	MUTATE_END( Declaration, node );
+}
+
+//--------------------------------------------------------------------------
+// AsmDecl
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( AsmDecl * node ) {
-	VISIT_BODY( node );
+	VISIT_START( node );
+
+	maybeAccept( node->stmt, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+AsmDecl * PassVisitor< pass_type >::mutate( AsmDecl * node ) {
+	MUTATE_START( node );
+
+	maybeMutateRef( node->stmt, *this );
+
+	MUTATE_END( AsmDecl, node );
 }
 
@@ -281,9 +585,9 @@
 void PassVisitor< pass_type >::visit( CompoundStmt * node ) {
 	VISIT_START( node );
-	call_beginScope();
-
-	visitStatementList( node->get_kids() );
-
-	call_endScope();
+	{
+		auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
+		visitStatementList( node->kids );
+	}
 	VISIT_END( node );
 }
@@ -292,9 +596,9 @@
 CompoundStmt * PassVisitor< pass_type >::mutate( CompoundStmt * node ) {
 	MUTATE_START( node );
-	call_beginScope();
-
-	mutateStatementList( node->get_kids() );
-
-	call_endScope();
+	{
+		auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
+		mutateStatementList( node->kids );
+	}
 	MUTATE_END( CompoundStmt, node );
 }
@@ -306,5 +610,5 @@
 	VISIT_START( node );
 
-	visitExpression( node->get_expr() );
+	visitExpression( node->expr );
 
 	VISIT_END( node );
@@ -315,5 +619,5 @@
 	MUTATE_START( node );
 
-	node->set_expr( mutateExpression( node->get_expr() ) );
+	node->expr = mutateExpression( node->expr );
 
 	MUTATE_END( Statement, node );
@@ -338,7 +642,7 @@
 	VISIT_START( node );
 
-	visitExpression( node->get_condition() );
-	node->set_thenPart ( visitStatement( node->get_thenPart() ) );
-	node->set_elsePart ( visitStatement( node->get_elsePart() ) );
+	visitExpression( node->condition );
+	node->thenPart = visitStatement( node->thenPart );
+	node->elsePart = visitStatement( node->elsePart );
 
 	VISIT_END( node );
@@ -348,9 +652,10 @@
 Statement * PassVisitor< pass_type >::mutate( IfStmt * node ) {
 	MUTATE_START( node );
-
-	node->set_condition( mutateExpression( node->get_condition() ) );
-	node->set_thenPart ( mutateStatement ( node->get_thenPart()  ) );
-	node->set_elsePart ( mutateStatement ( node->get_elsePart()  ) );
-
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		node->condition = mutateExpression( node->condition );
+		node->thenPart  = mutateStatement ( node->thenPart  );
+		node->elsePart  = mutateStatement ( node->elsePart  );
+	}
 	MUTATE_END( Statement, node );
 }
@@ -362,6 +667,6 @@
 	VISIT_START( node );
 
-	visitExpression( node->get_condition() );
-	node->set_body( visitStatement( node->get_body() ) );
+	visitExpression( node->condition );
+	node->body = visitStatement( node->body );
 
 	VISIT_END( node );
@@ -372,6 +677,6 @@
 	MUTATE_START( node );
 
-	node->set_condition( mutateExpression( node->get_condition() ) );
-	node->set_body( mutateStatement( node->get_body() ) );
+	node->condition = mutateExpression( node->condition );
+	node->body      = mutateStatement ( node->body      );
 
 	MUTATE_END( Statement, node );
@@ -383,10 +688,11 @@
 void PassVisitor< pass_type >::visit( ForStmt * node ) {
 	VISIT_START( node );
-
-	acceptAll( node->get_initialization(), *this );
-	visitExpression( node->get_condition() );
-	visitExpression( node->get_increment() );
-	node->set_body( visitStatement( node->get_body() ) );
-
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->initialization, *this );
+		visitExpression( node->condition );
+		visitExpression( node->increment );
+		node->body = visitStatement( node->body );
+	}
 	VISIT_END( node );
 }
@@ -395,10 +701,11 @@
 Statement * PassVisitor< pass_type >::mutate( ForStmt * node ) {
 	MUTATE_START( node );
-
-	mutateAll( node->get_initialization(), *this );
-	node->set_condition( mutateExpression( node->get_condition() ) );
-	node->set_increment( mutateExpression( node->get_increment() ) );
-	node->set_body( mutateStatement( node->get_body() ) );
-
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->initialization, *this );
+		node->condition = mutateExpression( node->condition );
+		node->increment = mutateExpression( node->increment );
+		node->body      = mutateStatement ( node->body      );
+	}
 	MUTATE_END( Statement, node );
 }
@@ -410,6 +717,6 @@
 	VISIT_START( node );
 
-	visitExpression( node->get_condition() );
-	visitStatementList( node->get_statements() );
+	visitExpression   ( node->condition  );
+	visitStatementList( node->statements );
 
 	VISIT_END( node );
@@ -420,6 +727,6 @@
 	MUTATE_START( node );
 
-	node->set_condition( mutateExpression( node->get_condition() ) );
-	mutateStatementList( node->get_statements() );
+	node->condition = mutateExpression( node->condition );
+	mutateStatementList( node->statements );
 
 	MUTATE_END( Statement, node );
@@ -432,6 +739,6 @@
 	VISIT_START( node );
 
-	visitExpression( node->get_condition() );
-	visitStatementList( node->get_statements() );
+	visitExpression   ( node->condition );
+	visitStatementList( node->stmts     );
 
 	VISIT_END( node );
@@ -442,6 +749,6 @@
 	MUTATE_START( node );
 
-	node->set_condition(  mutateExpression( node->get_condition() ) );
-	mutateStatementList( node->get_statements() );
+	node->condition = mutateExpression( node->condition );
+	mutateStatementList( node->stmts );
 
 	MUTATE_END( Statement, node );
@@ -466,5 +773,5 @@
 	VISIT_START( node );
 
-	visitExpression( node->get_expr() );
+	visitExpression( node->expr );
 
 	VISIT_END( node );
@@ -475,5 +782,5 @@
 	MUTATE_START( node );
 
-	node->set_expr( mutateExpression( node->get_expr() ) );
+	node->expr = mutateExpression( node->expr );
 
 	MUTATE_END( Statement, node );
@@ -499,7 +806,7 @@
 	VISIT_START( node );
 
-	maybeAccept( node->get_block(), *this );
-	acceptAll( node->get_catchers(), *this );
-	maybeAccept( node->get_finally(), *this );
+	maybeAccept( node->block       , *this );
+	maybeAccept  ( node->handlers    , *this );
+	maybeAccept( node->finallyBlock, *this );
 
 	VISIT_END( node );
@@ -510,7 +817,7 @@
 	MUTATE_START( node );
 
-	node->set_block(  maybeMutate( node->get_block(), *this ) );
-	mutateAll( node->get_catchers(), *this );
-	node->set_finally( maybeMutate( node->get_finally(), *this ) );
+	maybeMutateRef( node->block       , *this );
+	maybeMutateRef     ( node->handlers    , *this );
+	maybeMutateRef( node->finallyBlock, *this );
 
 	MUTATE_END( Statement, node );
@@ -522,9 +829,10 @@
 void PassVisitor< pass_type >::visit( CatchStmt * node ) {
 	VISIT_START( node );
-
-	maybeAccept( node->get_decl(), *this );
-	node->set_cond( visitExpression( node->get_cond() ) );
-	node->set_body( visitStatement( node->get_body() ) );
-
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->decl, *this );
+		node->cond = visitExpression( node->cond );
+		node->body = visitStatement ( node->body );
+	}
 	VISIT_END( node );
 }
@@ -533,9 +841,10 @@
 Statement * PassVisitor< pass_type >::mutate( CatchStmt * node ) {
 	MUTATE_START( node );
-
-	node->set_decl( maybeMutate( node->get_decl(), *this ) );
-	node->set_cond( mutateExpression( node->get_cond() ) );
-	node->set_body( mutateStatement( node->get_body() ) );
-
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->decl, *this );
+		node->cond = mutateExpression( node->cond );
+		node->body = mutateStatement ( node->body );
+	}
 	MUTATE_END( Statement, node );
 }
@@ -605,10 +914,23 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ApplicationExpr * node ) {
-	VISIT_BODY( node );
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result  , *this );
+	maybeAccept        ( node->function, *this );
+	maybeAccept          ( node->args    , *this );
+
+	VISIT_END( node );
 }
 
 template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( ApplicationExpr * node ) {
-	MUTATE_BODY( Expression, node );
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env     , *this );
+	indexerScopedMutate( node->result  , *this );
+	maybeMutateRef     ( node->function, *this );
+	maybeMutateRef          ( node->args    , *this );
+
+	MUTATE_END( Expression, node );
 }
 
@@ -620,7 +942,7 @@
 
 	// maybeAccept( node->get_env(), *this );
-	maybeAccept( node->get_result(), *this );
-
-	for ( auto expr : node->get_args() ) {
+	indexerScopedAccept( node->result, *this );
+
+	for ( auto expr : node->args ) {
 		visitExpression( expr );
 	}
@@ -633,8 +955,8 @@
 	MUTATE_START( node );
 
-	node->set_env( maybeMutate( node->get_env(), *this ) );
-	node->set_result( maybeMutate( node->get_result(), *this ) );
-
-	for ( auto& expr : node->get_args() ) {
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+
+	for ( auto& expr : node->args ) {
 		expr = mutateExpression( expr );
 	}
@@ -643,146 +965,692 @@
 }
 
+//--------------------------------------------------------------------------
+// NameExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( NameExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( NameExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// CastExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( CastExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->arg   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( CastExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->arg   , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// VirtualCastExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( VirtualCastExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept( node->arg, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( VirtualCastExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->arg   , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// AddressExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( AddressExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->arg   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( AddressExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->arg   , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// LabelAddressExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( LabelAddressExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( LabelAddressExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// UntypedMemberExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( UntypedMemberExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result   , *this );
+	maybeAccept        ( node->aggregate, *this );
+	maybeAccept        ( node->member   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UntypedMemberExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env      , *this );
+	indexerScopedMutate( node->result   , *this );
+	maybeMutateRef     ( node->aggregate, *this );
+	maybeMutateRef     ( node->member   , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// MemberExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( MemberExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result   , *this );
+	maybeAccept        ( node->aggregate, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( MemberExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env      , *this );
+	indexerScopedMutate( node->result   , *this );
+	maybeMutateRef     ( node->aggregate, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// VariableExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( VariableExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( VariableExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// ConstantExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ConstantExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result   , *this );
+	maybeAccept        ( &node->constant, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ConstantExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	node->constant = *maybeMutate( &node->constant, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// SizeofExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( SizeofExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeAccept( node->type, *this );
+	} else {
+		maybeAccept( node->expr, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( SizeofExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeMutateRef( node->type, *this );
+	} else {
+		maybeMutateRef( node->expr, *this );
+	}
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// AlignofExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( AlignofExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeAccept( node->type, *this );
+	} else {
+		maybeAccept( node->expr, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( AlignofExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeMutateRef( node->type, *this );
+	} else {
+		maybeMutateRef( node->expr, *this );
+	}
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// UntypedOffsetofExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( UntypedOffsetofExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->type  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UntypedOffsetofExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->type  , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// OffsetofExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( OffsetofExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->type  , *this );
+	maybeAccept        ( node->member, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( OffsetofExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->type  , *this );
+	maybeMutateRef     ( node->member, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// OffsetPackExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( OffsetPackExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->type  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( OffsetPackExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->type  , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// AttrExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( AttrExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeAccept( node->type, *this );
+	} else {
+		maybeAccept( node->expr, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( AttrExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeMutateRef( node->type, *this );
+	} else {
+		maybeMutateRef( node->expr, *this );
+	}
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// LogicalExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( LogicalExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->arg1  , *this );
+	maybeAccept        ( node->arg2  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( LogicalExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->arg1  , *this );
+	maybeMutateRef     ( node->arg2  , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// ConditionalExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ConditionalExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->arg1  , *this );
+	maybeAccept        ( node->arg2  , *this );
+	maybeAccept        ( node->arg3  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ConditionalExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->arg1  , *this );
+	maybeMutateRef     ( node->arg2  , *this );
+	maybeMutateRef     ( node->arg3  , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// CommaExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( CommaExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->arg1  , *this );
+	maybeAccept        ( node->arg2  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( CommaExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->arg1  , *this );
+	maybeMutateRef     ( node->arg2  , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// TypeExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TypeExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->type, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( TypeExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->type  , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// AsmExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( AsmExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result    , *this );
+	maybeAccept        ( node->inout     , *this );
+	maybeAccept        ( node->constraint, *this );
+	maybeAccept        ( node->operand   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( AsmExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env       , *this );
+	indexerScopedMutate( node->result    , *this );
+	maybeMutateRef     ( node->inout     , *this );
+	maybeMutateRef     ( node->constraint, *this );
+	maybeMutateRef     ( node->operand   , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// ImplicitCopyCtorExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ImplicitCopyCtorExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result     , *this );
+	maybeAccept        ( node->callExpr   , *this );
+	maybeAccept          ( node->tempDecls  , *this );
+	maybeAccept          ( node->returnDecls, *this );
+	maybeAccept          ( node->dtors      , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ImplicitCopyCtorExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env        , *this );
+	indexerScopedMutate( node->result     , *this );
+	maybeMutateRef     ( node->callExpr   , *this );
+	maybeMutateRef          ( node->tempDecls  , *this );
+	maybeMutateRef          ( node->returnDecls, *this );
+	maybeMutateRef          ( node->dtors      , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// ConstructorExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ConstructorExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result  , *this );
+	maybeAccept        ( node->callExpr, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ConstructorExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env     , *this );
+	indexerScopedMutate( node->result  , *this );
+	maybeMutateRef     ( node->callExpr, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// CompoundLiteralExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( CompoundLiteralExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result     , *this );
+	maybeAccept        ( node->initializer, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( CompoundLiteralExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env        , *this );
+	indexerScopedMutate( node->result     , *this );
+	maybeMutateRef     ( node->initializer, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// RangeExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( RangeExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->low   , *this );
+	maybeAccept        ( node->high  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( RangeExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->low   , *this );
+	maybeMutateRef     ( node->high  , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// UntypedTupleExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( UntypedTupleExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept          ( node->exprs , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UntypedTupleExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef          ( node->exprs , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// TupleExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TupleExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept          ( node->exprs , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( TupleExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef          ( node->exprs , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// TupleIndexExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TupleIndexExpr * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->tuple , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( TupleIndexExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->tuple , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// TupleAssignExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TupleAssignExpr * node ) {
-	VISIT_BODY( node );
-}
-
-//--------------------------------------------------------------------------
-// UntypedExpr
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result  , *this );
+	maybeAccept        ( node->stmtExpr, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( TupleAssignExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env     , *this );
+	indexerScopedMutate( node->result  , *this );
+	maybeMutateRef     ( node->stmtExpr, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// StmtExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( StmtExpr * node ) {
@@ -794,5 +1662,8 @@
 	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
 
-	Visitor::visit( node );
+	indexerScopedAccept( node->result     , *this );
+	maybeAccept        ( node->statements , *this );
+	maybeAccept          ( node->returnDecls, *this );
+	maybeAccept          ( node->dtors      , *this );
 
 	VISIT_END( node );
@@ -808,12 +1679,33 @@
 	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
 
-	Mutator::mutate( node );
-
-	MUTATE_END( Expression, node );
-}
-
+	indexerScopedMutate( node->result     , *this );
+	maybeMutateRef     ( node->statements , *this );
+	maybeMutateRef          ( node->returnDecls, *this );
+	maybeMutateRef          ( node->dtors      , *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
+// UniqueExpr
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( UniqueExpr * node ) {
-	VISIT_BODY( node );
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept        ( node->expr  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UniqueExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env   , *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutateRef     ( node->expr  , *this );
+
+	MUTATE_END( Expression, node );
 }
 
@@ -848,14 +1740,70 @@
 }
 
+//--------------------------------------------------------------------------
+// StructInstType
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( StructInstType * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerAddStruct( node->name );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->forall    , *this );
+		maybeAccept( node->parameters, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( StructInstType * node ) {
+	MUTATE_START( node );
+
+	indexerAddStruct( node->name );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->forall    , *this );
+		maybeMutateRef( node->parameters, *this );
+	}
+
+	MUTATE_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// UnionInstType
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( UnionInstType * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	indexerAddStruct( node->name );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeAccept( node->forall    , *this );
+		maybeAccept( node->parameters, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( UnionInstType * node ) {
+	MUTATE_START( node );
+
+	indexerAddStruct( node->name );
+
+	{
+		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		maybeMutateRef( node->forall    , *this );
+		maybeMutateRef( node->parameters, *this );
+	}
+
+	MUTATE_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// EnumInstType
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( EnumInstType * node ) {
@@ -864,8 +1812,32 @@
 
 template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( EnumInstType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// TraitInstType
+template< typename pass_type >
 void PassVisitor< pass_type >::visit( TraitInstType * node ) {
-	VISIT_BODY( node );
-}
-
+	VISIT_START( node );
+
+	maybeAccept( node->forall    , *this );
+	maybeAccept( node->parameters, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( TraitInstType * node ) {
+	MUTATE_START( node );
+
+	maybeMutateRef( node->forall    , *this );
+	maybeMutateRef( node->parameters, *this );
+
+	MUTATE_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// TypeInstType
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TypeInstType * node ) {
@@ -904,5 +1876,5 @@
 
 //--------------------------------------------------------------------------
-// UntypedExpr
+// SingleInit
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( SingleInit * node ) {
@@ -944,195 +1916,4 @@
 
 //---------------------------------------------------------------------------------------------------------------
-
-template< typename pass_type >
-DeclarationWithType * PassVisitor< pass_type >::mutate( ObjectDecl * node ) {
-	MUTATE_BODY( DeclarationWithType, node );
-}
-
-template< typename pass_type >
-DeclarationWithType * PassVisitor< pass_type >::mutate( FunctionDecl * node ) {
-	MUTATE_BODY( DeclarationWithType, node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
-	MUTATE_BODY( Declaration, node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( UnionDecl * node ) {
-	MUTATE_BODY( Declaration, node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( EnumDecl * node ) {
-	MUTATE_BODY( Declaration, node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( TraitDecl * node ) {
-	MUTATE_BODY( Declaration, node );
-}
-
-template< typename pass_type >
-TypeDecl * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
-	MUTATE_BODY( TypeDecl, node );
-}
-
-template< typename pass_type >
-Declaration * PassVisitor< pass_type >::mutate( TypedefDecl * node ) {
-	MUTATE_BODY( Declaration, node );
-}
-
-template< typename pass_type >
-AsmDecl * PassVisitor< pass_type >::mutate( AsmDecl * node ) {
-	MUTATE_BODY( AsmDecl, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( NameExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( AddressExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( LabelAddressExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( CastExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( VirtualCastExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UntypedMemberExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( MemberExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( VariableExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ConstantExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( SizeofExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( AlignofExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UntypedOffsetofExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( OffsetofExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( OffsetPackExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( AttrExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( LogicalExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ConditionalExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( CommaExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( TypeExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( AsmExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ImplicitCopyCtorExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( ConstructorExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( CompoundLiteralExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( RangeExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UntypedTupleExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( TupleExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( TupleIndexExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( TupleAssignExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
-template< typename pass_type >
-Expression * PassVisitor< pass_type >::mutate( UniqueExpr * node ) {
-	MUTATE_BODY( Expression, node );
-}
-
 template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( VoidType * node ) {
@@ -1166,24 +1947,4 @@
 
 template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( StructInstType * node ) {
-	MUTATE_BODY( Type, node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( UnionInstType * node ) {
-	MUTATE_BODY( Type, node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( EnumInstType * node ) {
-	MUTATE_BODY( Type, node );
-}
-
-template< typename pass_type >
-Type * PassVisitor< pass_type >::mutate( TraitInstType * node ) {
-	MUTATE_BODY( Type, node );
-}
-
-template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( TypeInstType * node ) {
 	MUTATE_BODY( Type, node );
Index: src/Common/PassVisitor.proto.h
===================================================================
--- src/Common/PassVisitor.proto.h	(revision b3f252a219989f7ab8f2f00efbcad32b69910b55)
+++ src/Common/PassVisitor.proto.h	(revision e0886dba1ec9ab949bb8d227feb423286cb7057c)
@@ -41,5 +41,4 @@
 };
 
-
 class bool_ref {
 public:
@@ -59,4 +58,27 @@
 	bool * m_ref;
 };
+
+template< typename TreeType, typename VisitorType >
+inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor ) {
+	// auto guard = makeFuncGuard(
+	// 	[&visitor]() { visitor.indexerScopeEnter(); },
+	// 	[&visitor]() { visitor.indexerScopeLeave(); }
+	// );
+	maybeAccept( tree, visitor );
+}
+
+template< typename TreeType, typename MutatorType >
+inline void indexerScopedMutate( TreeType *& tree, MutatorType & mutator ) {
+	// auto guard = makeFuncGuard(
+	// 	[&mutator]() { mutator.indexerScopeEnter(); },
+	// 	[&mutator]() { mutator.indexerScopeLeave(); }
+	// );
+	tree = maybeMutate( tree, mutator );
+}
+
+template< typename TreeType, typename MutatorType >
+inline void maybeMutateRef( TreeType *& tree, MutatorType & mutator ) {
+	tree = maybeMutate( tree, mutator );
+}
 
 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -93,4 +115,5 @@
 static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
 
+//---------------------------------------------------------
 // Mutate
 template<typename pass_type, typename node_type>
@@ -111,4 +134,5 @@
 static inline return_type postmutate_impl( __attribute__((unused)) pass_type& pass, node_type * node, __attribute__((unused)) long unused ) { return node; }
 
+//---------------------------------------------------------
 // Begin/End scope
 template<typename pass_type>
@@ -129,4 +153,5 @@
 static inline void end_scope_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) {}
 
+//---------------------------------------------------------
 // Fields
 #define FIELD_PTR( type, name )                                                                                                        \
@@ -145,2 +170,78 @@
 FIELD_PTR( at_cleanup_t, at_cleanup )
 FIELD_PTR( PassVisitor<pass_type> * const, visitor )
+
+//---------------------------------------------------------
+// Indexer
+template<typename pass_type>
+static inline auto indexer_impl_enterScope( pass_type & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) {
+	// pass.indexer.enterScope();
+}
+
+template<typename pass_type>
+static inline auto indexer_impl_enterScope( pass_type &, int ) {}
+
+template<typename pass_type>
+static inline auto indexer_impl_leaveScope( pass_type & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) {
+	// pass.indexer.leaveScope();
+}
+
+template<typename pass_type>
+static inline auto indexer_impl_leaveScope( pass_type &, int ) {}
+
+
+#define INDEXER_FUNC( func, type )                                                                                             \
+template<typename pass_type>                                                                                                   \
+static inline auto indexer_impl_##func ( pass_type & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {   \
+	/*pass.indexer.func( arg );*/                                                                                                \
+}                                                                                                                              \
+                                                                                                                               \
+template<typename pass_type>                                                                                                   \
+static inline void indexer_impl_##func ( pass_type &, long, type ) {}                                                          \
+
+INDEXER_FUNC( addId     , DeclarationWithType * );
+INDEXER_FUNC( addType   , NamedTypeDecl *       );
+INDEXER_FUNC( addStruct , StructDecl *          );
+INDEXER_FUNC( addEnum   , EnumDecl *            );
+INDEXER_FUNC( addUnion  , UnionDecl *           );
+INDEXER_FUNC( addTrait  , TraitDecl *           );
+
+
+template<typename pass_type>
+static inline auto indexer_impl_addStructFwd( pass_type & pass, int, StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
+	// StructDecl * fwd = new StructDecl( decl->name );
+	// cloneAll( decl->parameters, fwd->parameters );
+	// pass.indexer.addStruct( fwd );
+}
+
+template<typename pass_type>
+static inline auto indexer_impl_addStructFwd( pass_type &, int, StructDecl * ) {}
+
+template<typename pass_type>
+static inline auto indexer_impl_addUnionFwd( pass_type & pass, int, UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
+	// UnionDecl * fwd = new UnionDecl( decl->name );
+	// cloneAll( decl->parameters, fwd->parameters );
+	// pass.indexer.addUnion( fwd );
+}
+
+template<typename pass_type>
+static inline auto indexer_impl_addUnionFwd( pass_type &, int, UnionDecl * ) {}
+
+template<typename pass_type>
+static inline auto indexer_impl_addStruct( pass_type & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) {
+	// if ( ! pass.indexer.lookupStruct( str ) ) {
+	// 	pass.indexer.addStruct( str );
+	// }
+}
+
+template<typename pass_type>
+static inline auto indexer_impl_addStruct( pass_type &, int, const std::string & ) {}
+
+template<typename pass_type>
+static inline auto indexer_impl_addUnion( pass_type & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) {
+	// if ( ! pass.indexer.lookupUnion( str ) ) {
+	// 	pass.indexer.addUnion( str );
+	// }
+}
+
+template<typename pass_type>
+static inline auto indexer_impl_addUnion( pass_type &, int, const std::string & ) {}
