Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision f46bfd2ff00d79d3459719a6fb78190275e35e0f)
+++ src/AST/Node.hpp	(revision 1a4323ef209668602a57f374c8cbda3c31f45452)
@@ -18,4 +18,5 @@
 #include <cassert>
 #include <iosfwd>
+#include <type_traits> // for remove_reference
 
 #include "Common/ErrorObjects.h"  // for SemanticErrorException
@@ -82,6 +83,6 @@
 };
 
-// Mutate a node, non-member function to avoid static type
-// problems and be able to use auto return
+/// Mutate a node, non-member function to avoid static type
+/// problems and be able to use auto return
 template<typename node_t>
 node_t * mutate( const node_t * node ) {
@@ -95,4 +96,18 @@
 	);
 	return node->clone();
+}
+
+/// Mutate a node field (only clones if not equal to existing value)
+template<typename node_t, typename field_t>
+const node_t * mutate_field( 
+	const node_t * node, 
+	typename std::remove_const<typename std::remove_reference<field_t>::type>::type node_t::* field,
+	field_t&& val 
+) {
+	if ( node->*field == val ) return node;
+	
+	node_t * ret = mutate( node );
+	ret->*field = std::forward< field_t >( val );
+	return ret;
 }
 
Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision f46bfd2ff00d79d3459719a6fb78190275e35e0f)
+++ src/ResolvExpr/CurrentObject.cc	(revision 1a4323ef209668602a57f374c8cbda3c31f45452)
@@ -579,4 +579,26 @@
 } // namespace ResolvExpr
 
+namespace ast {
+
+	/// Iterates members of a type by initializer
+	class MemberIterator {
+	public:
+		virtual ~MemberIterator() {}
+	};
+
+	/// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
+	class SimpleIterator final : public MemberIterator {
+		const Type * type = nullptr;
+	public:
+		SimpleIterator( const Type * t ) : type( t ) {}
+	};
+
+	CurrentObject::CurrentObject( const ast::Type * type ) : objStack() {
+		objStack.emplace_back( new SimpleIterator{ type } );
+	}
+
+	#warning ast::CurrentObject port incomplete
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/ResolvExpr/CurrentObject.h
===================================================================
--- src/ResolvExpr/CurrentObject.h	(revision f46bfd2ff00d79d3459719a6fb78190275e35e0f)
+++ src/ResolvExpr/CurrentObject.h	(revision 1a4323ef209668602a57f374c8cbda3c31f45452)
@@ -17,5 +17,7 @@
 
 #include <list>   // for list
+#include <memory> // for unique_ptr
 #include <stack>  // for stack
+#include <vector>
 
 class Designation;
@@ -52,4 +54,23 @@
 } // namespace ResolvExpr
 
+namespace ast {
+	// AST class types
+	class Designation;
+	class InitAlternative;
+	class Type;
+
+	// forward declaration of internal detail
+	class MemberIterator;
+
+	/// Builds initializer lists in resolution
+	class CurrentObject final {
+		std::vector< std::shared_ptr<MemberIterator> > objStack;
+	
+	public:
+		CurrentObject() = default;
+		CurrentObject( const Type * type );
+	};
+} // namespace ast
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/ResolvExpr/ResolveAssertions.cc
===================================================================
--- src/ResolvExpr/ResolveAssertions.cc	(revision f46bfd2ff00d79d3459719a6fb78190275e35e0f)
+++ src/ResolvExpr/ResolveAssertions.cc	(revision 1a4323ef209668602a57f374c8cbda3c31f45452)
@@ -342,5 +342,7 @@
 
 	/// Limit to depth of recursion of assertion satisfaction
-	static const int recursionLimit = /* 10 */ 4;
+	static const int recursionLimit = 4;
+	/// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of
+	static const int deferLimit = 10;
 
 	void resolveAssertions( Alternative& alt, const SymTab::Indexer& indexer, AltList& out, std::list<std::string>& errors ) {
@@ -369,6 +371,6 @@
 						ss << tabs << "Unsatisfiable alternative:\n";
 						resn.alt.print( ss, ++tabs );
-						ss << --tabs << "Could not satisfy assertion:\n";
-						assn.decl->print( ss, ++tabs );
+						ss << (tabs-1) << "Could not satisfy assertion:\n";
+						assn.decl->print( ss, tabs );
 						
 						errors.emplace_back( ss.str() );
@@ -384,4 +386,18 @@
 						new_resns.emplace_back( std::move(resn), IterateState );
 					}
+				} else if ( resn.deferred.size() > deferLimit ) {
+					// too many deferred assertions to attempt mutual compatibility
+					Indenter tabs{ 3 };
+					std::ostringstream ss;
+					ss << tabs << "Unsatisfiable alternative:\n";
+					resn.alt.print( ss, ++tabs );
+					ss << (tabs-1) << "Too many non-unique satisfying assignments for "
+						"assertions:\n";
+					for ( const auto& d : resn.deferred ) {
+						d.decl->print( ss, tabs );
+					}
+
+					errors.emplace_back( ss.str() );
+					goto nextResn;
 				} else {
 					// resolve deferred assertions by mutual compatibility
@@ -395,6 +411,5 @@
 						ss << tabs << "Unsatisfiable alternative:\n";
 						resn.alt.print( ss, ++tabs );
-						ss << --tabs << "No mutually-compatible satisfaction for assertions:\n";
-						++tabs;
+						ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n";
 						for ( const auto& d : resn.deferred ) {
 							d.decl->print( ss, tabs );
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision f46bfd2ff00d79d3459719a6fb78190275e35e0f)
+++ src/ResolvExpr/Resolver.cc	(revision 1a4323ef209668602a57f374c8cbda3c31f45452)
@@ -165,5 +165,5 @@
 		void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
 			if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
-				if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
+				if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
 					// cast is to the same type as its argument, so it's unnecessary -- remove it
 					expr = castExpr->arg;
@@ -965,8 +965,11 @@
 		}
 
+		/// always-accept candidate filter
+		bool anyCandidate( const Candidate & ) { return true; }
+
 		/// Calls the CandidateFinder and finds the single best candidate
 		CandidateRef findUnfinishedKindExpression(
 			const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 
-			std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
+			std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
 		) {
 			if ( ! untyped ) return nullptr;
@@ -1056,7 +1059,6 @@
 				) {
 					// generated cast is the same type as its argument, remove it after keeping env
-					ast::ptr<ast::Expr> arg = castExpr->arg;
-					arg.get_and_mutate()->env = castExpr->env;
-					return arg;
+					return ast::mutate_field( 
+						castExpr->arg.get(), &ast::Expr::env, castExpr->env );
 				}
 				return castExpr;
@@ -1068,4 +1070,15 @@
 			}
 		};
+
+		/// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
+		void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
+			if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
+				if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
+					// cast is to the same type as its argument, remove it
+					ast::ptr< ast::TypeSubstitution > env = castExpr->env;
+					expr.set_and_mutate( castExpr->arg )->env = env;
+				}
+			}
+		}
 
 		/// Establish post-resolver invariants for expressions
@@ -1082,5 +1095,37 @@
 			StripCasts_new::strip( expr );
 		}
-		
+
+		/// Find the expression candidate that is the unique best match for `untyped` in a `void`
+		/// context.
+		ast::ptr< ast::Expr > resolveInVoidContext(
+			const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
+		) {
+			assertf( expr, "expected a non-null expression" );
+			
+			// set up and resolve expression cast to void
+			ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr };
+			CandidateRef choice = findUnfinishedKindExpression( 
+				untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
+			
+			// a cast expression has either 0 or 1 interpretations (by language rules);
+			// if 0, an exception has already been thrown, and this code will not run
+			const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
+			env = std::move( choice->env );
+
+			return castExpr->arg;
+		}
+
+		/// Resolve `untyped` to the expression whose candidate is the best match for a `void` 
+		/// context.
+		ast::ptr< ast::Expr > findVoidExpression( 
+			const ast::Expr * untyped, const ast::SymbolTable & symtab
+		) {
+			resetTyVarRenaming();
+			ast::TypeEnvironment env;
+			ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
+			finishExpr( newExpr, env, untyped->env );
+			return newExpr;
+		}
+
 		/// resolve `untyped` to the expression whose candidate satisfies `pred` with the 
 		/// lowest cost, returning the resolved version
@@ -1094,4 +1139,17 @@
 			finishExpr( choice->expr, choice->env, untyped->env );
 			return std::move( choice->expr );
+		}
+
+		/// Resolve `untyped` to the single expression whose candidate is the best match for the 
+		/// given type.
+		ast::ptr< ast::Expr > findSingleExpression(
+			const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
+		) {
+			assert( untyped && type );
+			const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
+			ast::ptr< ast::Expr > newExpr = 
+				findKindExpression( castExpr, symtab, "", anyCandidate );
+			removeExtraneousCast( newExpr, symtab );
+			return newExpr;
 		}
 
@@ -1125,5 +1183,5 @@
 
 		ast::ptr< ast::Type > functionReturn = nullptr;
-		// ast::CurrentObject currentObject = nullptr;
+		ast::CurrentObject currentObject = nullptr;
 		bool inEnumDecl = false;
 
@@ -1141,13 +1199,13 @@
 		void previsit( const ast::PointerType * );
 
-		void previsit( const ast::ExprStmt * );
-		void previsit( const ast::AsmExpr * );
+		const ast::ExprStmt * previsit( const ast::ExprStmt * );
+		const ast::AsmExpr * previsit( const ast::AsmExpr * );
 		void previsit( const ast::AsmStmt * );
-		void previsit( const ast::IfStmt * );
-		void previsit( const ast::WhileStmt * );
-		void previsit( const ast::ForStmt * );
-		void previsit( const ast::SwitchStmt * );
-		void previsit( const ast::CaseStmt * );
-		void previsit( const ast::BranchStmt * );
+		const ast::IfStmt * previsit( const ast::IfStmt * );
+		const ast::WhileStmt * previsit( const ast::WhileStmt * );
+		const ast::ForStmt * previsit( const ast::ForStmt * );
+		const ast::SwitchStmt * previsit( const ast::SwitchStmt * );
+		const ast::CaseStmt * previsit( const ast::CaseStmt * );
+		const ast::BranchStmt * previsit( const ast::BranchStmt * );
 		void previsit( const ast::ReturnStmt * );
 		void previsit( const ast::ThrowStmt * );
@@ -1196,7 +1254,17 @@
 
 	void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
-		#warning unimplemented; Resolver port in progress
-		(void)objectDecl;
-		assert(false);
+		// To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()], 
+		// class-variable `initContext` is changed multiple times because the LHS is analyzed 
+		// twice. The second analysis changes `initContext` because a function type can contain 
+		// object declarations in the return and parameter types. Therefore each value of 
+		// `initContext` is retained so the type on the first analysis is preserved and used for 
+		// selecting the RHS.
+		GuardValue( currentObject );
+		currentObject = ast::CurrentObject{ objectDecl->get_type() };
+		if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
+			// enumerator initializers should not use the enum type to initialize, since the 
+			// enum type is still incomplete at this point. Use `int` instead.
+			currentObject = ast::CurrentObject{ new ast::BasicType{ ast::BasicType::SignedInt } };
+		}
 	}
 
@@ -1210,34 +1278,44 @@
 		const ast::StaticAssertDecl * assertDecl 
 	) {
-		ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab );
-		if ( cond == assertDecl->cond ) return assertDecl;
+		return ast::mutate_field( 
+			assertDecl, &ast::StaticAssertDecl::cond, 
+			findIntegralExpression( assertDecl->cond, symtab ) );
+	}
+
+	template< typename PtrType >
+	void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
+		#warning unimplemented; needs support for new Validate::SizeType global
+		(void)type; (void)symtab;
+		assert( false );
+	}
+
+	void Resolver_new::previsit( const ast::ArrayType * at ) {
+		handlePtrType( at, symtab );
+	}
+
+	void Resolver_new::previsit( const ast::PointerType * pt ) {
+		handlePtrType( pt, symtab );
+	}
+
+	const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
+		visit_children = false;
+		assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
 		
-		ast::StaticAssertDecl * ret = mutate( assertDecl );
-		ret->cond = cond;
-		return ret;
-	}
-
-	void Resolver_new::previsit( const ast::ArrayType * at ) {
-		#warning unimplemented; Resolver port in progress
-		(void)at;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::PointerType * pt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)pt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)exprStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
-		#warning unimplemented; Resolver port in progress
-		(void)asmExpr;
-		assert(false);
+		return ast::mutate_field( 
+			exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
+	}
+
+	const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
+		visit_children = false;
+
+		asmExpr = ast::mutate_field( 
+			asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
+		
+		if ( asmExpr->inout ) {
+			asmExpr = ast::mutate_field(
+				asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) );
+		}
+		
+		return asmExpr;
 	}
 
@@ -1248,38 +1326,57 @@
 	}
 
-	void Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)ifStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)whileStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::ForStmt * forStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)forStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)switchStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)caseStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)branchStmt;
-		assert(false);
+	const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
+		return ast::mutate_field(
+			ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
+	}
+
+	const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
+		return ast::mutate_field( 
+			whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) );
+	}
+
+	const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {
+		if ( forStmt->cond ) {
+			forStmt = ast::mutate_field(
+				forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
+		}
+
+		if ( forStmt->inc ) {
+			forStmt = ast::mutate_field(
+				forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
+		}
+
+		return forStmt;
+	}
+
+	const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
+		GuardValue( currentObject );
+		switchStmt = ast::mutate_field(
+			switchStmt, &ast::SwitchStmt::cond, 
+			findIntegralExpression( switchStmt->cond, symtab ) );
+		currentObject = ast::CurrentObject{ switchStmt->cond->result };
+		return switchStmt;
+	}
+
+	const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
+		if ( caseStmt->cond ) {
+			#warning unimplemented, depends on currentObject implementation
+			assert(false);
+		}
+		return caseStmt;
+	}
+
+	const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
+		visit_children = false;
+		// must resolve the argument of a computed goto
+		if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
+			// computed goto argument is void*
+			branchStmt = ast::mutate_field(
+				branchStmt, &ast::BranchStmt::computedTarget, 
+				findSingleExpression( 
+					branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 
+					symtab ) );
+		}
+		return branchStmt;
 	}
 
