Index: src/AST/AssertAcyclic.cpp
===================================================================
--- src/AST/AssertAcyclic.cpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
+++ src/AST/AssertAcyclic.cpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -0,0 +1,51 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// AssertAcyclic.cpp -- Check that ast::ptr does not form a cycle.
+//
+// Author           : Andrew Beach
+// Created On       : Thu Jun 06 15:00:00 2019
+// Last Modified By : Andrew Beach
+// Last Modified On : Thu Jun 06 15:00:00 2019
+// Update Count     : 0
+//
+
+#include "AssertAcyclic.hpp"
+
+#include "AST/Pass.hpp"
+
+namespace {
+
+class NoStrongCyclesCore : public ast::WithGuards {
+    std::vector<const ast::Node *> parents;
+public:
+	void previsit ( const ast::Node * node ) {
+		for (auto & p : parents) {
+			assert(p != node);
+		}
+		parents.push_back(node);
+		GuardAction( [this]() { parents.pop_back(); } );
+	}
+};
+
+}
+
+namespace ast {
+
+void assertAcyclic( const std::list< ast::ptr< ast::Decl > > translationUnit ) {
+   	Pass<NoStrongCyclesCore> visitor;
+	for ( auto & decl : translationUnit ) {
+		decl->accept( visitor );
+	}
+}
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/AssertAcyclic.hpp
===================================================================
--- src/AST/AssertAcyclic.hpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
+++ src/AST/AssertAcyclic.hpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -0,0 +1,35 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// AssertAcyclic.hpp -- Check that ast::ptr does not form a cycle.
+//
+// Author           : Andrew Beach
+// Created On       : Thr May 6 15:00:00 2019
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr May 6 15:00:00 2019
+// Update Count     : 0
+//
+
+#pragma once
+
+#include <list>
+
+#include "Node.hpp"
+namespace ast {
+    class Decl;
+};
+
+namespace ast {
+
+void assertAcyclic( const std::list< ast::ptr< ast::Decl > > translationUnit );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/AST/Node.hpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -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/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/AST/Pass.hpp	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -201,4 +201,5 @@
 	container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
 
+public:
 	/// Logic to call the accept and mutate the parent if needed, delegates call to accept
 	template<typename node_t, typename parent_t, typename child_t>
Index: src/AST/module.mk
===================================================================
--- src/AST/module.mk	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/AST/module.mk	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -16,4 +16,5 @@
 
 SRC_AST = \
+	AST/AssertAcyclic.cpp \
 	AST/Attribute.cpp \
 	AST/Convert.cpp \
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/Makefile.in	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -165,12 +165,12 @@
 libdemangle_a_LIBADD =
 am__dirstamp = $(am__leading_dot)dirstamp
-am__objects_1 = AST/Attribute.$(OBJEXT) AST/Convert.$(OBJEXT) \
-	AST/Decl.$(OBJEXT) AST/DeclReplacer.$(OBJEXT) \
-	AST/Expr.$(OBJEXT) AST/GenericSubstitution.$(OBJEXT) \
-	AST/Init.$(OBJEXT) AST/LinkageSpec.$(OBJEXT) \
-	AST/Node.$(OBJEXT) AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) \
-	AST/Stmt.$(OBJEXT) AST/SymbolTable.$(OBJEXT) \
-	AST/Type.$(OBJEXT) AST/TypeEnvironment.$(OBJEXT) \
-	AST/TypeSubstitution.$(OBJEXT)
+am__objects_1 = AST/AssertAcyclic.$(OBJEXT) AST/Attribute.$(OBJEXT) \
+	AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \
+	AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \
+	AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \
+	AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
+	AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) AST/Stmt.$(OBJEXT) \
+	AST/SymbolTable.$(OBJEXT) AST/Type.$(OBJEXT) \
+	AST/TypeEnvironment.$(OBJEXT) AST/TypeSubstitution.$(OBJEXT)
 am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \
 	CodeGen/FixMain.$(OBJEXT) CodeGen/GenType.$(OBJEXT) \
@@ -577,4 +577,5 @@
 @WITH_LIBTCMALLOC_TRUE@TCMALLOCFLAG = -DTCMALLOC
 SRC_AST = \
+	AST/AssertAcyclic.cpp \
 	AST/Attribute.cpp \
 	AST/Convert.cpp \
@@ -744,4 +745,6 @@
 	@$(MKDIR_P) AST/$(DEPDIR)
 	@: > AST/$(DEPDIR)/$(am__dirstamp)
+AST/AssertAcyclic.$(OBJEXT): AST/$(am__dirstamp) \
+	AST/$(DEPDIR)/$(am__dirstamp)
 AST/Attribute.$(OBJEXT): AST/$(am__dirstamp) \
 	AST/$(DEPDIR)/$(am__dirstamp)
@@ -1193,4 +1196,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MakeLibCfa.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/AssertAcyclic.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Attribute.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Convert.Po@am__quote@
Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/ResolvExpr/CurrentObject.cc	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -20,4 +20,7 @@
 #include <string>                      // for string, operator<<, allocator
 
+#include "AST/Expr.hpp"                // for InitAlternative
+#include "AST/Init.hpp"                // for Designation
+#include "AST/Node.hpp"                // for readonly
 #include "Common/Indenter.h"           // for Indenter, operator<<
 #include "Common/SemanticError.h"      // for SemanticError
@@ -579,4 +582,48 @@
 } // namespace ResolvExpr
 
+namespace ast {
+
+	/// Iterates members of a type by initializer
+	class MemberIterator {
+	public:
+		virtual ~MemberIterator() {}
+
+		/// retrieve the list of possible (Type,Designation) pairs for the current position in the 
+		/// current object
+		virtual std::vector< InitAlternative > operator* () const = 0;
+	
+	protected:
+		/// helper for operator*; aggregates must add designator to each init alternative, but 
+		/// adding designators in operator* creates duplicates
+		virtual std::vector< InitAlternative > first() const = 0;
+	};
+
+	/// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
+	class SimpleIterator final : public MemberIterator {
+		CodeLocation location;
+		readonly< Type > type = nullptr;
+	public:
+		SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
+
+		std::vector< InitAlternative > operator* () const override { return first(); }
+
+	protected:
+		std::vector< InitAlternative > first() const override {
+			if ( type ) return { InitAlternative{ type, new Designation{ location } } };
+			return {};
+		}
+	};
+
+	CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
+		objStack.emplace_back( new SimpleIterator{ loc, type } );
+	}
+
+	std::vector< InitAlternative > CurrentObject::getOptions() {
+		PRINT( std::cerr << "____getting current options" << std::endl; )
+		assertf( ! objStack.empty(), "objstack empty in getOptions" );
+		return **objStack.back();
+	}
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/ResolvExpr/CurrentObject.h
===================================================================
--- src/ResolvExpr/CurrentObject.h	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/ResolvExpr/CurrentObject.h	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -17,5 +17,9 @@
 
 #include <list>   // for list
+#include <memory> // for unique_ptr
 #include <stack>  // for stack
+#include <vector>
+
+#include "Common/CodeLocation.h"
 
 class Designation;
@@ -52,4 +56,27 @@
 } // 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 CodeLocation & loc, const Type * type );
+
+		/// produces a list of alternatives (Type *, Designation *) for the current sub-object's 
+		/// initializer.
+		std::vector< InitAlternative > getOptions();
+	};
+} // namespace ast
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/ResolvExpr/ResolveAssertions.cc
===================================================================
--- src/ResolvExpr/ResolveAssertions.cc	(revision 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/ResolvExpr/ResolveAssertions.cc	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -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 0b73f0cd5f12dd95097dbdf9ad89a93ff3d695da)
+++ src/ResolvExpr/Resolver.cc	(revision 9151fcb2f97c8e6683dc78350cba0cf2dda098f4)
@@ -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,10 +1095,43 @@
 			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
 		ast::ptr< ast::Expr > findKindExpression(
-			const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 
-			std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
+			const ast::Expr * untyped, const ast::SymbolTable & symtab, 
+			std::function<bool(const Candidate &)> pred = anyCandidate, 
+			const std::string & kind = "", ResolvMode mode = {}
 		) {
 			if ( ! untyped ) return {};
@@ -1094,4 +1140,16 @@
 			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 );
+			removeExtraneousCast( newExpr, symtab );
+			return newExpr;
 		}
 
@@ -1115,5 +1173,5 @@
 			const ast::Expr * untyped, const ast::SymbolTable & symtab 
 		) {
-			return findKindExpression( untyped, symtab, "condition", hasIntegralType );
+			return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
 		}
 	}
@@ -1125,5 +1183,5 @@
 
 		ast::ptr< ast::Type > functionReturn = nullptr;
-		// ast::CurrentObject currentObject = nullptr;
+		ast::CurrentObject currentObject;
 		bool inEnumDecl = false;
 
@@ -1141,16 +1199,16 @@
 		void previsit( const ast::PointerType * );
 
-		void previsit( const ast::ExprStmt * );
-		void 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 * );
-		void previsit( const ast::ReturnStmt * );
-		void previsit( const ast::ThrowStmt * );
-		void previsit( const ast::CatchStmt * );
+		const ast::ExprStmt *   previsit( const ast::ExprStmt * );
+		const ast::AsmExpr *    previsit( const ast::AsmExpr * );
+		const ast::AsmStmt *    previsit( const ast::AsmStmt * );
+		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 * );
+		const ast::ReturnStmt * previsit( const ast::ReturnStmt * );
+		const ast::ThrowStmt *  previsit( const ast::ThrowStmt * );
+		const ast::CatchStmt *  previsit( const ast::CatchStmt * );
 		void previsit( const ast::WaitForStmt * );
 
@@ -1196,7 +1254,18 @@
 
 	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->location, 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{ 
+				objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
+		}
 	}
 
@@ -1210,94 +1279,155 @@
 		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);
-	}
-
-	void Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)asmStmt;
-		assert(false);
-	}
-
-	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);
-	}
-
-	void Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)returnStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)throwStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)catchStmt;
-		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;
+	}
+
+	const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
+		visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
+		visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
+		visit_children = false;
+		return asmStmt;
+	}
+
+	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->location, switchStmt->cond->result };
+		return switchStmt;
+	}
+
+	const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
+		if ( caseStmt->cond ) {
+			std::vector< ast::InitAlternative > initAlts = currentObject.getOptions();
+			assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
+				"expression." );
+			
+			const ast::Expr * untyped = 
+				new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
+			ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab );
+			
+			// case condition cannot have a cast in C, so it must be removed here, regardless of 
+			// whether it would perform a conversion.
+			if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
+				ast::ptr< ast::TypeSubstitution > env = castExpr->env;
+				newExpr.set_and_mutate( castExpr->arg )->env = env;
+			}
+			
+			caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr );
+		}
+		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;
+	}
+
+	const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
+		visit_children = false;
+		if ( returnStmt->expr ) {
+			returnStmt = ast::mutate_field(
+				returnStmt, &ast::ReturnStmt::expr, 
+				findSingleExpression( returnStmt->expr, functionReturn, symtab ) );
+		}
+		return returnStmt;
+	}
+
+	const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
+		visit_children = false;
+		if ( throwStmt->expr ) {
+			const ast::StructDecl * exceptionDecl = 
+				symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" );
+			assert( exceptionDecl );
+			ast::ptr< ast::Type > exceptType = 
+				new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
+			throwStmt = ast::mutate_field(
+				throwStmt, &ast::ThrowStmt::expr, 
+				findSingleExpression( throwStmt->expr, exceptType, symtab ) );
+		}
+		return throwStmt;
+	}
+
+	const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
+		if ( catchStmt->cond ) {
+			ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
+			catchStmt = ast::mutate_field( 
+				catchStmt, &ast::CatchStmt::cond, 
+				findSingleExpression( catchStmt->cond, boolType, symtab ) );
+		}
+		return catchStmt;
 	}
 
