Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/CodeGen/CodeGenerator.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -1088,4 +1088,7 @@
 } // namespace CodeGen
 
+
+unsigned Indenter::tabsize = 2;
+
 std::ostream & operator<<( std::ostream & out, const BaseSyntaxNode * node ) {
 	if ( node ) {
Index: src/Common/Indenter.h
===================================================================
--- src/Common/Indenter.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/Common/Indenter.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -18,7 +18,9 @@
 
 struct Indenter {
-	Indenter( unsigned int amt = 2 ) : amt( amt ) {}
-	unsigned int amt = 2;  // amount 1 level increases indent by (i.e. how much to increase by in operator++)
-	unsigned int indent = 0;
+	static unsigned tabsize;
+
+	Indenter( unsigned int amt = tabsize, unsigned int indent = 0 ) : amt( amt ), indent( indent ) {}
+	unsigned int amt;  // amount 1 level increases indent by (i.e. how much to increase by in operator++)
+	unsigned int indent;
 
 	Indenter & operator+=(int nlevels) { indent += amt*nlevels; return *this; }
@@ -30,5 +32,5 @@
 };
 
-inline std::ostream & operator<<( std::ostream & out, Indenter & indent ) {
+inline std::ostream & operator<<( std::ostream & out, const Indenter & indent ) {
 	return out << std::string(indent.indent, ' ');
 }
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/Common/utility.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -28,4 +28,6 @@
 #include <cassert>
 
+#include "Common/Indenter.h"
+
 template< typename T >
 static inline T * maybeClone( const T *orig ) {
@@ -75,9 +77,9 @@
 
 template< typename Container >
-void printAll( const Container &container, std::ostream &os, int indent = 0 ) {
+void printAll( const Container &container, std::ostream &os, Indenter indent = {} ) {
 	for ( typename Container::const_iterator i = container.begin(); i != container.end(); ++i ) {
 		if ( *i ) {
-			os << std::string( indent,  ' ' );
-			(*i)->print( os, indent + 2 );
+			os << indent;
+			(*i)->print( os, indent );
 			// need an endl after each element because it's not easy to know when each individual item should end
 			os << std::endl;
@@ -351,14 +353,16 @@
 template< typename T1, typename T2 >
 struct group_iterate_t {
+private:
+	std::tuple<T1, T2> args;
+public:
 	group_iterate_t( bool skipBoundsCheck, const T1 & v1, const T2 & v2 ) : args(v1, v2) {
 		assertf(skipBoundsCheck || v1.size() == v2.size(), "group iteration requires containers of the same size: <%zd, %zd>.", v1.size(), v2.size());
 	};
 
+	typedef std::tuple<decltype(*std::get<0>(args).begin()), decltype(*std::get<1>(args).begin())> value_type;
+	typedef decltype(std::get<0>(args).begin()) T1Iter;
+	typedef decltype(std::get<1>(args).begin()) T2Iter;
+
 	struct iterator {
-		typedef typename std::remove_reference<T1>::type T1val;
-		typedef typename std::remove_reference<T2>::type T2val;
-		typedef std::tuple<typename T1val::value_type &, typename T2val::value_type &> value_type;
-		typedef typename T1val::iterator T1Iter;
-		typedef typename T2val::iterator T2Iter;
 		typedef std::tuple<T1Iter, T2Iter> IterTuple;
 		IterTuple it;
@@ -370,9 +374,7 @@
 		value_type operator*() const { return std::tie( *std::get<0>(it), *std::get<1>(it) ); }
 	};
+
 	iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin() ); }
 	iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end() ); }
-
-private:
-	std::tuple<T1, T2> args;
 };
 
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/GenPoly/Box.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -600,5 +600,5 @@
 
 			// add size/align for generic types to parameter list
-			if ( ! appExpr->get_function()->has_result() ) return;
+			if ( ! appExpr->get_function()->result ) return;
 			FunctionType *funcType = getFunctionType( appExpr->get_function()->get_result() );
 			assert( funcType );
@@ -714,5 +714,5 @@
 
 		void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
-			assertf( arg->has_result(), "arg does not have result: %s", toString( arg ).c_str() );
+			assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
 			if ( isPolyType( param, exprTyVars ) ) {
 				Type * newType = arg->get_result()->clone();
@@ -965,5 +965,5 @@
 				if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
 					if ( varExpr->get_var()->get_name() == "?[?]" ) {
-						assert( appExpr->has_result() );
+						assert( appExpr->result );
 						assert( appExpr->get_args().size() == 2 );
 						Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
@@ -999,5 +999,5 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "*?" ) {
-						assert( appExpr->has_result() );
+						assert( appExpr->result );
 						assert( ! appExpr->get_args().empty() );
 						if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) {
@@ -1016,5 +1016,5 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "?++" || varExpr->get_var()->get_name() == "?--" ) {
-						assert( appExpr->has_result() );
+						assert( appExpr->result );
 						assert( appExpr->get_args().size() == 1 );
 						if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
@@ -1036,5 +1036,5 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "++?" || varExpr->get_var()->get_name() == "--?" ) {
-						assert( appExpr->has_result() );
+						assert( appExpr->result );
 						assert( appExpr->get_args().size() == 1 );
 						if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
@@ -1042,5 +1042,5 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
-						assert( appExpr->has_result() );
+						assert( appExpr->result );
 						assert( appExpr->get_args().size() == 2 );
 						Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
@@ -1068,5 +1068,5 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "?+=?" || varExpr->get_var()->get_name() == "?-=?" ) {
-						assert( appExpr->has_result() );
+						assert( appExpr->result );
 						assert( appExpr->get_args().size() == 2 );
 						Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env );
@@ -1162,13 +1162,13 @@
 		void Pass1::premutate( AddressExpr * ) { visit_children = false; }
 		Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
-			assert( addrExpr->get_arg()->has_result() && ! addrExpr->get_arg()->get_result()->isVoid() );
+			assert( addrExpr->get_arg()->result && ! addrExpr->get_arg()->get_result()->isVoid() );
 
 			bool needs = false;
 			if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) {
-				if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
+				if ( expr->result && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
 					if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
 						if ( name->get_name() == "*?" ) {
 							if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
-								assert( appExpr->get_function()->has_result() );
+								assert( appExpr->get_function()->result );
 								FunctionType *function = getFunctionType( appExpr->get_function()->get_result() );
 								assert( function );
Index: src/GenPoly/FindFunction.cc
===================================================================
--- src/GenPoly/FindFunction.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/GenPoly/FindFunction.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -18,4 +18,5 @@
 #include <utility>                      // for pair
 
+#include "Common/PassVisitor.h"         // for PassVisitor
 #include "Common/SemanticError.h"       // for SemanticError
 #include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
@@ -27,10 +28,11 @@
 
 namespace GenPoly {
-	class FindFunction : public Mutator {
+	class FindFunction : public WithGuards, public WithVisitorRef<FindFunction>, public WithShortCircuiting {
 	  public:
 		FindFunction( std::list< FunctionType* > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate );
 
-		virtual Type *mutate( FunctionType *functionType );
-		virtual Type *mutate( PointerType *pointerType );
+		void premutate( FunctionType * functionType );
+		Type * postmutate( FunctionType * functionType );
+		void premutate( PointerType * pointerType );
 	  private:
 		void handleForall( const Type::ForallList &forall );
@@ -43,10 +45,10 @@
 
 	void findFunction( Type *type, std::list< FunctionType* > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
-		FindFunction finder( functions, tyVars, false, predicate );
+		PassVisitor<FindFunction> finder( functions, tyVars, false, predicate );
 		type->acceptMutator( finder );
 	}
 
 	void findAndReplaceFunction( Type *&type, std::list< FunctionType* > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
-		FindFunction finder( functions, tyVars, true, predicate );
+		PassVisitor<FindFunction> finder( functions, tyVars, true, predicate );
 		type = type->acceptMutator( finder );
 	}
@@ -57,6 +59,6 @@
 
 	void FindFunction::handleForall( const Type::ForallList &forall ) {
-		for ( Type::ForallList::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
-			TyVarMap::iterator var = tyVars.find( (*i)->get_name() );
+		for ( const Declaration * td : forall ) {
+			TyVarMap::iterator var = tyVars.find( td->name );
 			if ( var != tyVars.end() ) {
 				tyVars.erase( var->first );
@@ -65,8 +67,12 @@
 	}
 
-	Type * FindFunction::mutate( FunctionType *functionType ) {
-		tyVars.beginScope();
+	void FindFunction::premutate( FunctionType * functionType ) {
+		visit_children = false;
+		GuardScope( tyVars );
 		handleForall( functionType->get_forall() );
-		mutateAll( functionType->get_returnVals(), *this );
+		mutateAll( functionType->get_returnVals(), *visitor );
+	}
+
+	Type * FindFunction::postmutate( FunctionType * functionType ) {
 		Type *ret = functionType;
 		if ( predicate( functionType, tyVars ) ) {
@@ -77,14 +83,10 @@
 			} // if
 		} // if
-		tyVars.endScope();
 		return ret;
 	}
 
-	Type * FindFunction::mutate( PointerType *pointerType ) {
-		tyVars.beginScope();
+	void FindFunction::premutate( PointerType * pointerType ) {
+		GuardScope( tyVars );
 		handleForall( pointerType->get_forall() );
-		Type *ret = Mutator::mutate( pointerType );
-		tyVars.endScope();
-		return ret;
 	}
 } // namespace GenPoly
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/GenPoly/Specialize.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -147,5 +147,5 @@
 
 	Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
-		assertf( actual->has_result(), "attempting to specialize an untyped expression" );
+		assertf( actual->result, "attempting to specialize an untyped expression" );
 		if ( needsSpecialization( formalType, actual->get_result(), env ) ) {
 			if ( FunctionType *funType = getFunctionType( formalType ) ) {
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/InitTweak/FixInit.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -390,5 +390,5 @@
 			assert( env );
 			CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
-			assert( arg->has_result() );
+			assert( arg->result );
 			Type * result = arg->get_result();
 			if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
@@ -552,6 +552,5 @@
 				Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
 				// move env from callExpr to retExpr
-				retExpr->set_env( callExpr->get_env() );
-				callExpr->set_env( nullptr );
+				std::swap( retExpr->env, callExpr->env );
 				return retExpr;
 			} else {
@@ -811,4 +810,6 @@
 			GuardValue( labelVars );
 			labelVars.clear();
+			// LabelFinder does not recurse into FunctionDecl, so need to visit
+			// its children manually.
 			maybeAccept( funcDecl->type, finder );
 			maybeAccept( funcDecl->statements, finder );
@@ -1126,5 +1127,5 @@
 			static UniqueName tempNamer( "_tmp_ctor_expr" );
 			// xxx - is the size check necessary?
-			assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 );
+			assert( ctorExpr->result && ctorExpr->get_result()->size() == 1 );
 
 			// xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/Parser/ExpressionNode.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -87,5 +87,5 @@
 		} else {
 			assertf( false, "internal error, bad integral length %s", str.c_str() );
-		} // if		
+		} // if
 		posn += 1;
 	} // if
@@ -397,5 +397,5 @@
 
 NameExpr * build_varref( const string * name ) {
-	NameExpr * expr = new NameExpr( *name, nullptr );
+	NameExpr * expr = new NameExpr( *name );
 	delete name;
 	return expr;
@@ -488,5 +488,5 @@
 	list< Expression * > args;
 	buildMoveList( expr_node, args );
-	return new UntypedExpr( maybeMoveBuild< Expression >(function), args, nullptr );
+	return new UntypedExpr( maybeMoveBuild< Expression >(function), args );
 } // build_func
 
Index: src/ResolvExpr/AdjustExprType.cc
===================================================================
--- src/ResolvExpr/AdjustExprType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/ResolvExpr/AdjustExprType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -14,4 +14,5 @@
 //
 
+#include "Common/PassVisitor.h"
 #include "SymTab/Indexer.h"       // for Indexer
 #include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Kind::Ftype
@@ -21,25 +22,26 @@
 
 namespace ResolvExpr {
-	class AdjustExprType : public Mutator {
-		typedef Mutator Parent;
-		using Parent::mutate;
+	class AdjustExprType : public WithShortCircuiting {
 	  public:
 		AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer );
+		void premutate( VoidType * ) { visit_children = false; }
+		void premutate( BasicType * ) { visit_children = false; }
+		void premutate( PointerType * ) { visit_children = false; }
+		void premutate( FunctionType * ) { visit_children = false; }
+		void premutate( StructInstType * ) { visit_children = false; }
+		void premutate( UnionInstType * ) { visit_children = false; }
+		void premutate( EnumInstType * ) { visit_children = false; }
+		void premutate( TraitInstType * ) { visit_children = false; }
+		void premutate( TypeInstType * ) { visit_children = false; }
+		void premutate( TupleType * ) { visit_children = false; }
+		void premutate( VarArgsType * ) { visit_children = false; }
+		void premutate( ZeroType * ) { visit_children = false; }
+		void premutate( OneType * ) { visit_children = false; }
+
+		Type * postmutate( ArrayType *arrayType );
+		Type * postmutate( FunctionType *functionType );
+		Type * postmutate( TypeInstType *aggregateUseType );
+
 	  private:
-		virtual Type* mutate( VoidType *voidType );
-		virtual Type* mutate( BasicType *basicType );
-		virtual Type* mutate( PointerType *pointerType );
-		virtual Type* mutate( ArrayType *arrayType );
-		virtual Type* mutate( FunctionType *functionType );
-		virtual Type* mutate( StructInstType *aggregateUseType );
-		virtual Type* mutate( UnionInstType *aggregateUseType );
-		virtual Type* mutate( EnumInstType *aggregateUseType );
-		virtual Type* mutate( TraitInstType *aggregateUseType );
-		virtual Type* mutate( TypeInstType *aggregateUseType );
-		virtual Type* mutate( TupleType *tupleType );
-		virtual Type* mutate( VarArgsType *varArgsType );
-		virtual Type* mutate( ZeroType *zeroType );
-		virtual Type* mutate( OneType *oneType );
-
 		const TypeEnvironment &env;
 		const SymTab::Indexer &indexer;
@@ -47,5 +49,5 @@
 
 	void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-		AdjustExprType adjuster( env, indexer );
+		PassVisitor<AdjustExprType> adjuster( env, indexer );
 		Type *newType = type->acceptMutator( adjuster );
 		type = newType;
@@ -56,45 +58,17 @@
 	}
 
-	Type *AdjustExprType::mutate( VoidType *voidType ) {
-		return voidType;
-	}
-
-	Type *AdjustExprType::mutate( BasicType *basicType ) {
-		return basicType;
-	}
-
-	Type *AdjustExprType::mutate( PointerType *pointerType ) {
-		return pointerType;
-	}
-
-	Type *AdjustExprType::mutate( ArrayType *arrayType ) {
+	Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
 		// need to recursively mutate the base type in order for multi-dimensional arrays to work.
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ) );
+		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base );
+		arrayType->base = nullptr;
 		delete arrayType;
 		return pointerType;
 	}
 
-	Type *AdjustExprType::mutate( FunctionType *functionType ) {
-		PointerType *pointerType = new PointerType( Type::Qualifiers(), functionType );
-		return pointerType;
+	Type * AdjustExprType::postmutate( FunctionType * functionType ) {
+		return new PointerType( Type::Qualifiers(), functionType );
 	}
 
-	Type *AdjustExprType::mutate( StructInstType *aggregateUseType ) {
-		return aggregateUseType;
-	}
-
-	Type *AdjustExprType::mutate( UnionInstType *aggregateUseType ) {
-		return aggregateUseType;
-	}
-
-	Type *AdjustExprType::mutate( EnumInstType *aggregateUseType ) {
-		return aggregateUseType;
-	}
-
-	Type *AdjustExprType::mutate( TraitInstType *aggregateUseType ) {
-		return aggregateUseType;
-	}
-
-	Type *AdjustExprType::mutate( TypeInstType *typeInst ) {
+	Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
 		EqvClass eqvClass;
 		if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
@@ -113,20 +87,4 @@
 		return typeInst;
 	}
-
-	Type *AdjustExprType::mutate( TupleType *tupleType ) {
-		return tupleType;
-	}
-
-	Type *AdjustExprType::mutate( VarArgsType *varArgsType ) {
-		return varArgsType;
-	}
-
-	Type *AdjustExprType::mutate( ZeroType *zeroType ) {
-		return zeroType;
-	}
-
-	Type *AdjustExprType::mutate( OneType *oneType ) {
-		return oneType;
-	}
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Alternative.cc
===================================================================
--- src/ResolvExpr/Alternative.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/ResolvExpr/Alternative.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -66,17 +66,17 @@
 	}
 
-	void Alternative::print( std::ostream &os, int indent ) const {
-		os << std::string( indent, ' ' ) << "Cost " << cost << ": ";
+	void Alternative::print( std::ostream &os, Indenter indent ) const {
+		os << "Cost " << cost << ": ";
 		if ( expr ) {
-			expr->print( os, indent );
-			os << "(types:" << std::endl;
-			os << std::string( indent+4, ' ' );
-			expr->get_result()->print( os, indent + 4 );
-			os << std::endl << ")" << std::endl;
+			expr->print( os, indent+1 );
+			os << std::endl << indent << "(types:" << std::endl;
+			os << indent+1;
+			expr->result->print( os, indent+1 );
+			os << std::endl << indent << ")" << std::endl;
 		} else {
 			os << "Null expression!" << std::endl;
 		} // if
-		os << std::string( indent, ' ' ) << "Environment: ";
-		env.print( os, indent+2 );
+		os << indent << "Environment: ";
+		env.print( os, indent+1 );
 		os << std::endl;
 	}
Index: src/ResolvExpr/Alternative.h
===================================================================
--- src/ResolvExpr/Alternative.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/ResolvExpr/Alternative.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -39,5 +39,5 @@
 		~Alternative();
 
-		void print( std::ostream &os, int indent = 0 ) const;
+		void print( std::ostream &os, Indenter indent = {} ) const;
 
 		Cost cost;
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -75,5 +75,6 @@
 
 	namespace {
-		void printAlts( const AltList &list, std::ostream &os, int indent = 0 ) {
+		void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 ) {
+			Indenter indent = { Indenter::tabsize, indentAmt };
 			for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
 				i->print( os, indent );
@@ -195,8 +196,8 @@
 				AltList winners;
 				findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
-				stream << "Cannot choose between " << winners.size() << " alternatives for expression ";
+				stream << "Cannot choose between " << winners.size() << " alternatives for expression\n";
 				expr->print( stream );
-				stream << "Alternatives are:";
-				printAlts( winners, stream, 8 );
+				stream << "Alternatives are:\n";
+				printAlts( winners, stream, 1 );
 				throw SemanticError( stream.str() );
 			}
@@ -728,5 +729,5 @@
 		PRINT(
 			std::cerr << "known function ops:" << std::endl;
-			printAlts( funcOpFinder.alternatives, std::cerr, 8 );
+			printAlts( funcOpFinder.alternatives, std::cerr, 1 );
 		)
 
@@ -838,5 +839,5 @@
 	bool isLvalue( Expression *expr ) {
 		// xxx - recurse into tuples?
-		return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
+		return expr->result && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
 	}
 
@@ -972,5 +973,5 @@
 		PRINT( std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl; )
 		for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
-			VariableExpr newExpr( *i, nameExpr->get_argName() );
+			VariableExpr newExpr( *i );
 			alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
 			PRINT(
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -18,4 +18,5 @@
 #include <cassert>               // for assert
 
+#include "Common/PassVisitor.h"  // for PassVisitor
 #include "Resolver.h"            // for resolveInVoidContext
 #include "SynTree/Expression.h"  // for Expression
@@ -41,8 +42,9 @@
 	}
 
-	class ResolveTypeof : public Mutator {
+	class ResolveTypeof : public WithShortCircuiting {
 	  public:
 		ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
-		Type *mutate( TypeofType *typeofType );
+		void premutate( TypeofType *typeofType );
+		Type * postmutate( TypeofType *typeofType );
 
 	  private:
@@ -50,20 +52,24 @@
 	};
 
-	Type *resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
-		ResolveTypeof mutator( indexer );
+	Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
+		PassVisitor<ResolveTypeof> mutator( indexer );
 		return type->acceptMutator( mutator );
 	}
 
-	Type *ResolveTypeof::mutate( TypeofType *typeofType ) {
+	void ResolveTypeof::premutate( TypeofType * ) {
+		visit_children = false;
+	}
+
+	Type * ResolveTypeof::postmutate( TypeofType *typeofType ) {
 #if 0
-		std::cout << "resolving typeof: ";
-		typeofType->print( std::cout );
-		std::cout << std::endl;
+		std::cerr << "resolving typeof: ";
+		typeofType->print( std::cerr );
+		std::cerr << std::endl;
 #endif
-		if ( typeofType->get_expr() ) {
-			Expression *newExpr = resolveInVoidContext( typeofType->get_expr(), indexer );
-			assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() );
-			Type *newType = newExpr->get_result();
-			newExpr->set_result( nullptr );
+		if ( typeofType->expr ) {
+			Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
+			assert( newExpr->result && ! newExpr->result->isVoid() );
+			Type * newType = newExpr->result;
+			newExpr->result = nullptr;
 			delete typeofType;
 			delete newExpr;
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -68,11 +68,11 @@
 	}
 
-	void EqvClass::print( std::ostream &os, int indent ) const {
-		os << std::string( indent, ' ' ) << "( ";
+	void EqvClass::print( std::ostream &os, Indenter indent ) const {
+		os << "( ";
 		std::copy( vars.begin(), vars.end(), std::ostream_iterator< std::string >( os, " " ) );
 		os << ")";
 		if ( type ) {
 			os << " -> ";
-			type->print( os, indent );
+			type->print( os, indent+1 );
 		} // if
 		if ( ! allowWidening ) {
@@ -144,5 +144,5 @@
 	}
 
-	void TypeEnvironment::print( std::ostream &os, int indent ) const {
+	void TypeEnvironment::print( std::ostream &os, Indenter indent ) const {
 		for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
 			i->print( os, indent );
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/ResolvExpr/TypeEnvironment.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -68,5 +68,5 @@
 		EqvClass &operator=( const EqvClass &other );
 		~EqvClass();
-		void print( std::ostream &os, int indent = 0 ) const;
+		void print( std::ostream &os, Indenter indent = {} ) const;
 	};
 
@@ -80,5 +80,5 @@
 		void makeSubstitution( TypeSubstitution &result ) const;
 		bool isEmpty() const { return env.empty(); }
-		void print( std::ostream &os, int indent = 0 ) const;
+		void print( std::ostream &os, Indenter indent = {} ) const;
 		void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
 		void simpleCombine( const TypeEnvironment &second );
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/ResolvExpr/Unify.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -22,4 +22,5 @@
 #include <utility>                // for pair
 
+#include "Common/PassVisitor.h"   // for PassVisitor
 #include "FindOpenVars.h"         // for findOpenVars
 #include "Parser/LinkageSpec.h"   // for C
@@ -537,10 +538,11 @@
 	/// If this isn't done then argument lists can have wildly different
 	/// size and structure, when they should be compatible.
-	struct TtypeExpander : public Mutator {
-		TypeEnvironment & env;
-		TtypeExpander( TypeEnvironment & env ) : env( env ) {}
-		Type * mutate( TypeInstType * typeInst ) {
+	struct TtypeExpander : public WithShortCircuiting {
+		TypeEnvironment & tenv;
+		TtypeExpander( TypeEnvironment & tenv ) : tenv( tenv ) {}
+		void premutate( TypeInstType * ) { visit_children = false; }
+		Type * postmutate( TypeInstType * typeInst ) {
 			EqvClass eqvClass;
-			if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
+			if ( tenv.lookup( typeInst->get_name(), eqvClass ) ) {
 				if ( eqvClass.data.kind == TypeDecl::Ttype ) {
 					// expand ttype parameter into its actual type
@@ -560,5 +562,5 @@
 		dst.clear();
 		for ( DeclarationWithType * dcl : src ) {
-			TtypeExpander expander( env );
+			PassVisitor<TtypeExpander> expander( env );
 			dcl->acceptMutator( expander );
 			std::list< Type * > types;
@@ -750,5 +752,5 @@
 			std::list<Type *> types1, types2;
 
-			TtypeExpander expander( env );
+			PassVisitor<TtypeExpander> expander( env );
 			flat1->acceptMutator( expander );
 			flat2->acceptMutator( expander );
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SymTab/FixFunction.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -26,8 +26,9 @@
 	FixFunction::FixFunction() : isVoid( false ) {}
 
-	DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) {
+
+	DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) {
 		// can't delete function type because it may contain assertions, so transfer ownership to new object
-		ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ), 0, functionDecl->get_attributes() );
-		functionDecl->get_attributes().clear();
+		ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
+		functionDecl->attributes.clear();
 		functionDecl->type = nullptr;
 		delete functionDecl;
@@ -35,59 +36,29 @@
 	}
 
-	Type * FixFunction::mutate(VoidType *voidType) {
-		isVoid = true;
-		return voidType;
-	}
-
-	Type * FixFunction::mutate(BasicType *basicType) {
-		return basicType;
-	}
-
-	Type * FixFunction::mutate(PointerType *pointerType) {
-		return pointerType;
-	}
-
-	Type * FixFunction::mutate(ArrayType *arrayType) {
+	Type * FixFunction::postmutate(ArrayType *arrayType) {
 		// need to recursively mutate the base type in order for multi-dimensional arrays to work.
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
+		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
+		arrayType->base = nullptr;
+		arrayType->dimension = nullptr;
 		delete arrayType;
 		return pointerType;
 	}
 
-	Type * FixFunction::mutate(StructInstType *aggregateUseType) {
-		return aggregateUseType;
+	void FixFunction::premutate(VoidType *) {
+		isVoid = true;
 	}
 
-	Type * FixFunction::mutate(UnionInstType *aggregateUseType) {
-		return aggregateUseType;
-	}
-
-	Type * FixFunction::mutate(EnumInstType *aggregateUseType) {
-		return aggregateUseType;
-	}
-
-	Type * FixFunction::mutate(TraitInstType *aggregateUseType) {
-		return aggregateUseType;
-	}
-
-	Type * FixFunction::mutate(TypeInstType *aggregateUseType) {
-		return aggregateUseType;
-	}
-
-	Type * FixFunction::mutate(TupleType *tupleType) {
-		return tupleType;
-	}
-
-	Type * FixFunction::mutate(VarArgsType *varArgsType) {
-		return varArgsType;
-	}
-
-	Type * FixFunction::mutate(ZeroType *zeroType) {
-		return zeroType;
-	}
-
-	Type * FixFunction::mutate(OneType *oneType) {
-		return oneType;
-	}
+	void FixFunction::premutate(FunctionDecl *) { visit_children = false; }
+	void FixFunction::premutate(BasicType *) { visit_children = false; }
+	void FixFunction::premutate(PointerType *) { visit_children = false; }
+	void FixFunction::premutate(StructInstType *) { visit_children = false; }
+	void FixFunction::premutate(UnionInstType *) { visit_children = false; }
+	void FixFunction::premutate(EnumInstType *) { visit_children = false; }
+	void FixFunction::premutate(TraitInstType *) { visit_children = false; }
+	void FixFunction::premutate(TypeInstType *) { visit_children = false; }
+	void FixFunction::premutate(TupleType *) { visit_children = false; }
+	void FixFunction::premutate(VarArgsType *) { visit_children = false; }
+	void FixFunction::premutate(ZeroType *) { visit_children = false; }
+	void FixFunction::premutate(OneType *) { visit_children = false; }
 } // namespace SymTab
 
Index: src/SymTab/FixFunction.h
===================================================================
--- src/SymTab/FixFunction.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SymTab/FixFunction.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -16,32 +16,31 @@
 #pragma once
 
-#include "SynTree/Mutator.h"  // for Mutator
-#include "SynTree/SynTree.h"  // for Types
+#include "Common/PassVisitor.h" // for PassVisitor
+#include "SynTree/SynTree.h"    // for Types
 
 namespace SymTab {
 	/// Replaces function and array types by equivalent pointer types.
-	class FixFunction : public Mutator {
+	class FixFunction : public WithShortCircuiting {
 		typedef Mutator Parent;
 	  public:
 		FixFunction();
 
-		bool get_isVoid() const { return isVoid; }
-		void set_isVoid( bool newValue ) { isVoid = newValue; }
-	  private:
-		virtual DeclarationWithType* mutate(FunctionDecl *functionDecl);
+		void premutate(FunctionDecl *functionDecl);
+		DeclarationWithType* postmutate(FunctionDecl *functionDecl);
 
-		virtual Type* mutate(VoidType *voidType);
-		virtual Type* mutate(BasicType *basicType);
-		virtual Type* mutate(PointerType *pointerType);
-		virtual Type* mutate(ArrayType *arrayType);
-		virtual Type* mutate(StructInstType *aggregateUseType);
-		virtual Type* mutate(UnionInstType *aggregateUseType);
-		virtual Type* mutate(EnumInstType *aggregateUseType);
-		virtual Type* mutate(TraitInstType *aggregateUseType);
-		virtual Type* mutate(TypeInstType *aggregateUseType);
-		virtual Type* mutate(TupleType *tupleType);
-		virtual Type* mutate(VarArgsType *varArgsType);
-		virtual Type* mutate(ZeroType *zeroType);
-		virtual Type* mutate(OneType *oneType);
+		Type * postmutate(ArrayType * arrayType);
+
+		void premutate(VoidType * voidType);
+		void premutate(BasicType * basicType);
+		void premutate(PointerType * pointerType);
+		void premutate(StructInstType * aggregateUseType);
+		void premutate(UnionInstType * aggregateUseType);
+		void premutate(EnumInstType * aggregateUseType);
+		void premutate(TraitInstType * aggregateUseType);
+		void premutate(TypeInstType * aggregateUseType);
+		void premutate(TupleType * tupleType);
+		void premutate(VarArgsType * varArgsType);
+		void premutate(ZeroType * zeroType);
+		void premutate(OneType * oneType);
 
 		bool isVoid;
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SymTab/Validate.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -369,8 +369,8 @@
 			DWTIterator begin( dwts.begin() ), end( dwts.end() );
 			if ( begin == end ) return;
-			FixFunction fixer;
+			PassVisitor<FixFunction> fixer;
 			DWTIterator i = begin;
 			*i = (*i)->acceptMutator( fixer );
-			if ( fixer.get_isVoid() ) {
+			if ( fixer.pass.isVoid ) {
 				DWTIterator j = i;
 				++i;
@@ -383,7 +383,7 @@
 				++i;
 				for ( ; i != end; ++i ) {
-					FixFunction fixer;
+					PassVisitor<FixFunction> fixer;
 					*i = (*i)->acceptMutator( fixer );
-					if ( fixer.get_isVoid() ) {
+					if ( fixer.pass.isVoid ) {
 						throw SemanticError( "invalid type void in function type ", func );
 					} // if
@@ -597,7 +597,7 @@
 			// apply FixFunction to every assertion to check for invalid void type
 			for ( DeclarationWithType *& assertion : type->assertions ) {
-				FixFunction fixer;
+				PassVisitor<FixFunction> fixer;
 				assertion = assertion->acceptMutator( fixer );
-				if ( fixer.get_isVoid() ) {
+				if ( fixer.pass.isVoid ) {
 					throw SemanticError( "invalid type void in assertion of function ", node );
 				} // if
Index: src/SynTree/AddressExpr.cc
===================================================================
--- src/SynTree/AddressExpr.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/AddressExpr.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -33,5 +33,5 @@
 	Type * addrType( Type * type ) {
 		if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
-			return new ReferenceType( refType->get_qualifiers(), addrType( refType->get_base() ) );
+			return new ReferenceType( refType->get_qualifiers(), addrType( refType->base ) );
 		} else {
 			return new PointerType( Type::Qualifiers(), type->clone() );
@@ -40,13 +40,13 @@
 }
 
-AddressExpr::AddressExpr( Expression *arg, Expression *_aname ) : Expression( _aname ), arg( arg ) {
-	if ( arg->has_result() ) {
-		if ( arg->get_result()->get_lvalue() ) {
+AddressExpr::AddressExpr( Expression *arg ) : Expression(), arg( arg ) {
+	if ( arg->result ) {
+		if ( arg->result->get_lvalue() ) {
 			// lvalue, retains all layers of reference and gains a pointer inside the references
-			set_result( addrType( arg->get_result() ) );
+			set_result( addrType( arg->result ) );
 		} else {
 			// taking address of non-lvalue -- must be a reference, loses one layer of reference
-			ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( arg->get_result() );
-			set_result( addrType( refType->get_base() ) );
+			ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( arg->result );
+			set_result( addrType( refType->base ) );
 		}
 		// result of & is never an lvalue
@@ -62,9 +62,9 @@
 }
 
-void AddressExpr::print( std::ostream &os, int indent ) const {
+void AddressExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Address of:" << std::endl;
 	if ( arg ) {
-		os << std::string( indent+2, ' ' );
-		arg->print( os, indent+2 );
+		os << indent+1;
+		arg->print( os, indent+1 );
 	} // if
 }
@@ -77,6 +77,6 @@
 LabelAddressExpr::~LabelAddressExpr() {}
 
-void LabelAddressExpr::print( std::ostream & os, int indent ) const {
-	os << "Address of label:" << std::endl << std::string( indent+2, ' ' ) << arg;
+void LabelAddressExpr::print( std::ostream & os, Indenter ) const {
+	os << "Address of label:" << arg;
 }
 
Index: src/SynTree/AggregateDecl.cc
===================================================================
--- src/SynTree/AggregateDecl.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/AggregateDecl.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -41,38 +41,38 @@
 }
 
-void AggregateDecl::print( std::ostream &os, int indent ) const {
+void AggregateDecl::print( std::ostream &os, Indenter indent ) const {
 	using std::string;
 	using std::endl;
 
-	os << typeString() << " " << get_name() << ":";
+	os << typeString() << " " << name << ":";
 	if ( get_linkage() != LinkageSpec::Cforall ) {
-		os << " " << LinkageSpec::linkageName( get_linkage() );
+		os << " " << LinkageSpec::linkageName( linkage );
 	} // if
-	os << " with body " << has_body() << endl;
+	os << " with body " << has_body();
 
 	if ( ! parameters.empty() ) {
-		os << endl << string( indent+2, ' ' ) << "with parameters" << endl;
-		printAll( parameters, os, indent+4 );
+		os << endl << indent << "... with parameters" << endl;
+		printAll( parameters, os, indent+1 );
 	} // if
 	if ( ! members.empty() ) {
-		os << endl << string( indent+2, ' ' ) << "with members" << endl;
-		printAll( members, os, indent+4 );
+		os << endl << indent << "... with members" << endl;
+		printAll( members, os, indent+1 );
 	} // if
 	if ( ! attributes.empty() ) {
-		os << endl << string( indent+2, ' ' ) << "with attributes" << endl;
-		printAll( attributes, os, indent+4 );
+		os << endl << indent << "... with attributes" << endl;
+		printAll( attributes, os, indent+1 );
 	} // if
+	os << endl;
 }
 
-void AggregateDecl::printShort( std::ostream &os, int indent ) const {
+void AggregateDecl::printShort( std::ostream &os, Indenter indent ) const {
 	using std::string;
 	using std::endl;
 
-	os << typeString() << " " << get_name();
-	os << string( indent+2, ' ' ) << "with body " << has_body() << endl;
+	os << typeString() << " " << name << " with body " << has_body() << endl;
 
 	if ( ! parameters.empty() ) {
-		os << endl << string( indent+2, ' ' ) << "with parameters" << endl;
-		printAll( parameters, os, indent+4 );
+		os << indent << "... with parameters" << endl;
+		printAll( parameters, os, indent+1 );
 	} // if
 }
Index: src/SynTree/ApplicationExpr.cc
===================================================================
--- src/SynTree/ApplicationExpr.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/ApplicationExpr.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -55,5 +55,5 @@
 	set_result( ResolvExpr::extractResultType( function ) );
 
-	assert( has_result() );
+	assert( result );
 }
 
@@ -68,24 +68,25 @@
 }
 
-void printInferParams( const InferredParams & inferParams, std::ostream &os, int indent, int level ) {
+void printInferParams( const InferredParams & inferParams, std::ostream &os, Indenter indent, int level ) {
 	if ( ! inferParams.empty() ) {
-		os << std::string(indent, ' ') << "with inferred parameters " << level << ":" << std::endl;
+		os << indent << "with inferred parameters " << level << ":" << std::endl;
 		for ( InferredParams::const_iterator i = inferParams.begin(); i != inferParams.end(); ++i ) {
-			os << std::string(indent+2, ' ');
-			Declaration::declFromId( i->second.decl )->printShort( os, indent+2 );
+			os << indent+1;
+			Declaration::declFromId( i->second.decl )->printShort( os, indent+1 );
 			os << std::endl;
-			printInferParams( *i->second.inferParams, os, indent+2, level+1 );
+			printInferParams( *i->second.inferParams, os, indent+1, level+1 );
 		} // for
 	} // if
 }
 
-void ApplicationExpr::print( std::ostream &os, int indent ) const {
-	os << "Application of" << std::endl << std::string(indent+2, ' ');
-	function->print( os, indent+2 );
+void ApplicationExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Application of" << std::endl << indent+1;
+	function->print( os, indent+1 );
+	os << std::endl;
 	if ( ! args.empty() ) {
-		os << std::string( indent, ' ' ) << "to arguments" << std::endl;
-		printAll( args, os, indent+2 );
+		os << indent << "... to arguments" << std::endl;
+		printAll( args, os, indent+1 );
 	} // if
-	printInferParams( inferParams, os, indent+2, 0 );
+	printInferParams( inferParams, os, indent+1, 0 );
 	Expression::print( os, indent );
 }
Index: src/SynTree/ArrayType.cc
===================================================================
--- src/SynTree/ArrayType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/ArrayType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -39,5 +39,5 @@
 }
 
-void ArrayType::print( std::ostream &os, int indent ) const {
+void ArrayType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	if ( isStatic ) {
Index: src/SynTree/AttrType.cc
===================================================================
--- src/SynTree/AttrType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/AttrType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// AttrType.cc.cc -- 
+// AttrType.cc.cc --
 //
 // Author           : Richard C. Bilson
@@ -42,5 +42,5 @@
 }
 
-void AttrType::print( std::ostream &os, int indent ) const {
+void AttrType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	os << "attribute " << name << " applied to ";
Index: src/SynTree/Attribute.cc
===================================================================
--- src/SynTree/Attribute.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Attribute.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -28,5 +28,5 @@
 }
 
-void Attribute::print( std::ostream &os, int indent ) const {
+void Attribute::print( std::ostream &os, Indenter indent ) const {
   using std::endl;
   using std::string;
@@ -36,5 +36,5 @@
     if ( ! parameters.empty() ) {
       os << " with parameters: " << endl;
-      printAll( parameters, os, indent );
+      printAll( parameters, os, indent+1 );
     }
   }
Index: src/SynTree/Attribute.h
===================================================================
--- src/SynTree/Attribute.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Attribute.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -46,5 +46,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Attribute * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
Index: src/SynTree/BaseSyntaxNode.h
===================================================================
--- src/SynTree/BaseSyntaxNode.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/BaseSyntaxNode.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -17,4 +17,5 @@
 
 #include "Common/CodeLocation.h"
+#include "Common/Indenter.h"
 class Visitor;
 class Mutator;
@@ -29,5 +30,11 @@
 	virtual void accept( Visitor & v ) = 0;
 	virtual BaseSyntaxNode * acceptMutator( Mutator & m ) = 0;
-	virtual void print( std::ostream & os, int indent = 0 ) const = 0;
+  /// Notes:
+  /// * each node is responsible for indenting its children.
+  /// * Expressions should not finish with a newline, since the expression's parent has better information.
+	virtual void print( std::ostream & os, Indenter indent = {} ) const = 0;
+  void print( std::ostream & os, unsigned int indent ) {
+    print( os, Indenter{ Indenter::tabsize, indent });
+  }
 };
 
Index: src/SynTree/BasicType.cc
===================================================================
--- src/SynTree/BasicType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/BasicType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// BasicType.cc -- 
+// BasicType.cc --
 //
 // Author           : Richard C. Bilson
@@ -24,5 +24,5 @@
 BasicType::BasicType( const Type::Qualifiers &tq, Kind bt, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), kind( bt ) {}
 
-void BasicType::print( std::ostream &os, int indent ) const {
+void BasicType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	os << BasicType::typeNames[ kind ];
Index: src/SynTree/CommaExpr.cc
===================================================================
--- src/SynTree/CommaExpr.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/CommaExpr.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -21,6 +21,6 @@
 #include "Type.h"            // for Type
 
-CommaExpr::CommaExpr( Expression *arg1, Expression *arg2, Expression *_aname )
-		: Expression( _aname ), arg1( arg1 ), arg2( arg2 ) {
+CommaExpr::CommaExpr( Expression *arg1, Expression *arg2 )
+		: Expression(), arg1( arg1 ), arg2( arg2 ) {
 	// xxx - result of a comma expression is never an lvalue, so should set lvalue
 	// to false on all result types. Actually doing this causes some strange things
@@ -39,11 +39,11 @@
 }
 
-void CommaExpr::print( std::ostream &os, int indent ) const {
+void CommaExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Comma Expression:" << std::endl;
-	os << std::string( indent+2, ' ' );
-	arg1->print( os, indent+2 );
+	os << (indent+1);
+	arg1->print( os, indent+1 );
 	os << std::endl;
-	os << std::string( indent+2, ' ' );
-	arg2->print( os, indent+2 );
+	os << (indent+1);
+	arg2->print( os, indent+1 );
 	Expression::print( os, indent );
 }
Index: src/SynTree/CompoundStmt.cc
===================================================================
--- src/SynTree/CompoundStmt.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/CompoundStmt.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -73,7 +73,7 @@
 }
 
-void CompoundStmt::print( std::ostream &os, int indent ) const {
-	os << "CompoundStmt" << endl ;
-	printAll( kids, os, indent + 2 );
+void CompoundStmt::print( std::ostream &os, Indenter indent ) const {
+	os << "CompoundStmt" << endl;
+	printAll( kids, os, indent+1 );
 }
 
Index: src/SynTree/Constant.cc
===================================================================
--- src/SynTree/Constant.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Constant.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -71,5 +71,5 @@
 }
 
-void Constant::print( std::ostream &os, int indent ) const {
+void Constant::print( std::ostream &os, Indenter ) const {
 	os << "(" << rep << " " << val.ival;
 	if ( type ) {
Index: src/SynTree/Constant.h
===================================================================
--- src/SynTree/Constant.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Constant.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -57,5 +57,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Constant * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = 0 ) const;
   private:
 	Type * type;
Index: src/SynTree/DeclStmt.cc
===================================================================
--- src/SynTree/DeclStmt.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/DeclStmt.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -33,5 +33,5 @@
 }
 
-void DeclStmt::print( std::ostream &os, int indent ) const {
+void DeclStmt::print( std::ostream &os, Indenter indent ) const {
 	assert( decl != 0 );
 	os << "Declaration of ";
Index: src/SynTree/Declaration.cc
===================================================================
--- src/SynTree/Declaration.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Declaration.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -70,9 +70,9 @@
 }
 
-void AsmDecl::print( std::ostream &os, int indent ) const {
+void AsmDecl::print( std::ostream &os, Indenter indent ) const {
 	stmt->print( os, indent );
 }
 
-void AsmDecl::printShort( std::ostream &os, int indent ) const {
+void AsmDecl::printShort( std::ostream &os, Indenter indent ) const {
 	stmt->print( os, indent );
 }
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Declaration.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -64,6 +64,6 @@
 	virtual void accept( Visitor &v ) override = 0;
 	virtual Declaration *acceptMutator( Mutator &m ) override = 0;
-	virtual void print( std::ostream &os, int indent = 0 ) const override = 0;
-	virtual void printShort( std::ostream &os, int indent = 0 ) const = 0;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
+	virtual void printShort( std::ostream &os, Indenter indent = {} ) const = 0;
 
 	static void dumpIds( std::ostream &os );
@@ -142,6 +142,6 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
-	virtual void printShort( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
+	virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -170,6 +170,6 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
-	virtual void printShort( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
+	virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -193,6 +193,6 @@
 
 	virtual NamedTypeDecl *clone() const override = 0;
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
-	virtual void printShort( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
+	virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -235,5 +235,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 
   private:
@@ -276,6 +276,6 @@
 	AggregateDecl * set_body( bool body ) { AggregateDecl::body = body; return this; }
 
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
-	virtual void printShort( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
+	virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
   protected:
 	virtual std::string typeString() const = 0;
@@ -355,6 +355,6 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual AsmDecl *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
-	virtual void printShort( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
+	virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
 };
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Expression.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -33,32 +33,26 @@
 #include "GenPoly/Lvalue.h"
 
-Expression::Expression( Expression *_aname ) : result( 0 ), env( 0 ), argName( _aname ) {}
-
-Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), argName( maybeClone( other.get_argName() ) ), extension( other.extension ) {
+Expression::Expression() : result( 0 ), env( 0 ) {}
+
+Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ) {
 }
 
 Expression::~Expression() {
 	delete env;
-	delete argName;	// xxx -- there's a problem in cloning ConstantExpr I still don't know how to fix
 	delete result;
 }
 
-void Expression::print( std::ostream &os, int indent ) const {
+void Expression::print( std::ostream &os, Indenter indent ) const {
 	if ( env ) {
-		os << std::string( indent, ' ' ) << "with environment:" << std::endl;
-		env->print( os, indent+2 );
+		os << std::endl << indent << "... with environment:" << std::endl;
+		env->print( os, indent+1 );
 	} // if
 
-	if ( argName ) {
-		os << std::string( indent, ' ' ) << "with designator:";
-		argName->print( os, indent+2 );
+	if ( extension ) {
+		os << std::endl << indent << "... with extension:";
 	} // if
-
-	if ( extension ) {
-		os << std::string( indent, ' ' ) << "with extension:";
-	} // if
-}
-
-ConstantExpr::ConstantExpr( Constant _c, Expression *_aname ) : Expression( _aname ), constant( _c ) {
+}
+
+ConstantExpr::ConstantExpr( Constant _c ) : Expression(), constant( _c ) {
 	set_result( constant.get_type()->clone() );
 }
@@ -69,5 +63,5 @@
 ConstantExpr::~ConstantExpr() {}
 
-void ConstantExpr::print( std::ostream &os, int indent ) const {
+void ConstantExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "constant expression " ;
 	constant.print( os );
@@ -75,5 +69,5 @@
 }
 
-VariableExpr::VariableExpr( DeclarationWithType *_var, Expression *_aname ) : Expression( _aname ), var( _var ) {
+VariableExpr::VariableExpr( DeclarationWithType *_var ) : Expression(), var( _var ) {
 	assert( var );
 	assert( var->get_type() );
@@ -96,20 +90,17 @@
 }
 
-void VariableExpr::print( std::ostream &os, int indent ) const {
+void VariableExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Variable Expression: ";
-
-	Declaration *decl = get_var();
-	if ( decl != 0) decl->printShort(os, indent + 2);
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-SizeofExpr::SizeofExpr( Expression *expr_, Expression *_aname ) :
-		Expression( _aname ), expr(expr_), type(0), isType(false) {
+	var->printShort(os, indent);
+	Expression::print( os, indent );
+}
+
+SizeofExpr::SizeofExpr( Expression *expr_ ) :
+		Expression(), expr(expr_), type(0), isType(false) {
 	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
-SizeofExpr::SizeofExpr( Type *type_, Expression *_aname ) :
-		Expression( _aname ), expr(0), type(type_), isType(true) {
+SizeofExpr::SizeofExpr( Type *type_ ) :
+		Expression(), expr(0), type(type_), isType(true) {
 	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
@@ -124,23 +115,18 @@
 }
 
-void SizeofExpr::print( std::ostream &os, int indent) const {
+void SizeofExpr::print( std::ostream &os, Indenter indent) const {
 	os << "Sizeof Expression on: ";
-
-	if (isType)
-		type->print(os, indent + 2);
-	else
-		expr->print(os, indent + 2);
-
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-AlignofExpr::AlignofExpr( Expression *expr_, Expression *_aname ) :
-		Expression( _aname ), expr(expr_), type(0), isType(false) {
+	if (isType) type->print(os, indent+1);
+	else expr->print(os, indent+1);
+	Expression::print( os, indent );
+}
+
+AlignofExpr::AlignofExpr( Expression *expr_ ) :
+		Expression(), expr(expr_), type(0), isType(false) {
 	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
-AlignofExpr::AlignofExpr( Type *type_, Expression *_aname ) :
-		Expression( _aname ), expr(0), type(type_), isType(true) {
+AlignofExpr::AlignofExpr( Type *type_ ) :
+		Expression(), expr(0), type(type_), isType(true) {
 	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
@@ -155,18 +141,14 @@
 }
 
-void AlignofExpr::print( std::ostream &os, int indent) const {
+void AlignofExpr::print( std::ostream &os, Indenter indent) const {
 	os << "Alignof Expression on: ";
-
-	if (isType)
-		type->print(os, indent + 2);
-	else
-		expr->print(os, indent + 2);
-
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-UntypedOffsetofExpr::UntypedOffsetofExpr( Type *type_, const std::string &member_, Expression *_aname ) :
-		Expression( _aname ), type(type_), member(member_) {
+	if (isType) type->print(os, indent+1);
+	else expr->print(os, indent+1);
+	Expression::print( os, indent );
+}
+
+UntypedOffsetofExpr::UntypedOffsetofExpr( Type *type, const std::string &member ) :
+		Expression(), type(type), member(member) {
+	assert( type );
 	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
@@ -179,19 +161,14 @@
 }
 
-void UntypedOffsetofExpr::print( std::ostream &os, int indent) const {
-	os << std::string( indent, ' ' ) << "Untyped Offsetof Expression on member " << member << " of ";
-
-	if ( type ) {
-		type->print(os, indent + 2);
-	} else {
-		os << "<NULL>";
-	}
-
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-OffsetofExpr::OffsetofExpr( Type *type_, DeclarationWithType *member_, Expression *_aname ) :
-		Expression( _aname ), type(type_), member(member_) {
+void UntypedOffsetofExpr::print( std::ostream &os, Indenter indent) const {
+	os << "Untyped Offsetof Expression on member " << member << " of ";
+	type->print(os, indent+1);
+	Expression::print( os, indent );
+}
+
+OffsetofExpr::OffsetofExpr( Type *type, DeclarationWithType *member ) :
+		Expression(), type(type), member(member) {
+	assert( member );
+	assert( type );
 	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
@@ -204,26 +181,12 @@
 }
 
-void OffsetofExpr::print( std::ostream &os, int indent) const {
-	os << std::string( indent, ' ' ) << "Offsetof Expression on member ";
-
-	if ( member ) {
-		os << member->get_name();
-	} else {
-		os << "<NULL>";
-	}
-
-	os << " of ";
-
-	if ( type ) {
-		type->print(os, indent + 2);
-	} else {
-		os << "<NULL>";
-	}
-
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-OffsetPackExpr::OffsetPackExpr( StructInstType *type_, Expression *aname_ ) : Expression( aname_ ), type( type_ ) {
+void OffsetofExpr::print( std::ostream &os, Indenter indent) const {
+	os << "Offsetof Expression on member " << member->name << " of ";
+	type->print(os, indent+1);
+	Expression::print( os, indent );
+}
+
+OffsetPackExpr::OffsetPackExpr( StructInstType *type ) : Expression(), type( type ) {
+	assert( type );
 	set_result( new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, false, false ) );
 }
@@ -233,23 +196,16 @@
 OffsetPackExpr::~OffsetPackExpr() { delete type; }
 
-void OffsetPackExpr::print( std::ostream &os, int indent ) const {
-	os << std::string( indent, ' ' ) << "Offset pack expression on ";
-
-	if ( type ) {
-		type->print(os, indent + 2);
-	} else {
-		os << "<NULL>";
-	}
-
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-AttrExpr::AttrExpr( Expression *attr, Expression *expr_, Expression *_aname ) :
-		Expression( _aname ), attr( attr ), expr(expr_), type(0), isType(false) {
-}
-
-AttrExpr::AttrExpr( Expression *attr, Type *type_, Expression *_aname ) :
-		Expression( _aname ), attr( attr ), expr(0), type(type_), isType(true) {
+void OffsetPackExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Offset pack expression on ";
+	type->print(os, indent+1);
+	Expression::print( os, indent );
+}
+
+AttrExpr::AttrExpr( Expression *attr, Expression *expr_ ) :
+		Expression(), attr( attr ), expr(expr_), type(0), isType(false) {
+}
+
+AttrExpr::AttrExpr( Expression *attr, Type *type_ ) :
+		Expression(), attr( attr ), expr(0), type(type_), isType(true) {
 }
 
@@ -264,25 +220,20 @@
 }
 
-void AttrExpr::print( std::ostream &os, int indent) const {
+void AttrExpr::print( std::ostream &os, Indenter indent) const {
 	os << "Attr ";
-	attr->print( os, indent + 2 );
+	attr->print( os, indent+1);
 	if ( isType || expr ) {
 		os << "applied to: ";
-
-		if (isType)
-			type->print(os, indent + 2);
-		else
-			expr->print(os, indent + 2);
+		if (isType) type->print(os, indent+1);
+		else expr->print(os, indent+1);
 	} // if
-
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-CastExpr::CastExpr( Expression *arg_, Type *toType, Expression *_aname ) : Expression( _aname ), arg(arg_) {
+	Expression::print( os, indent );
+}
+
+CastExpr::CastExpr( Expression *arg_, Type *toType ) : Expression(), arg(arg_) {
 	set_result(toType);
 }
 
-CastExpr::CastExpr( Expression *arg_, Expression *_aname ) : Expression( _aname ), arg(arg_) {
+CastExpr::CastExpr( Expression *arg_ ) : Expression(), arg(arg_) {
 	set_result( new VoidType( Type::Qualifiers() ) );
 }
@@ -295,15 +246,14 @@
 }
 
-void CastExpr::print( std::ostream &os, int indent ) const {
-	os << "Cast of:" << std::endl << std::string( indent+2, ' ' );
-	arg->print(os, indent+2);
-	os << std::endl << std::string( indent, ' ' ) << "to:" << std::endl;
-	os << std::string( indent+2, ' ' );
+void CastExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Cast of:" << std::endl << indent+1;
+	arg->print(os, indent+1);
+	os << std::endl << indent << "... to:";
 	if ( result->isVoid() ) {
-		os << "nothing";
+		os << " nothing";
 	} else {
-		result->print( os, indent+2 );
+		os << std::endl << indent+1;
+		result->print( os, indent+1 );
 	} // if
-	os << std::endl;
 	Expression::print( os, indent );
 }
@@ -320,20 +270,21 @@
 }
 
-void VirtualCastExpr::print( std::ostream &os, int indent ) const {
-	os << "Virtual Cast of:" << std::endl << std::string( indent+2, ' ' );
-	arg->print(os, indent+2);
-	os << std::endl << std::string( indent, ' ' ) << "to:" << std::endl;
-	os << std::string( indent+2, ' ' );
+void VirtualCastExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Virtual Cast of:" << std::endl << indent+1;
+	arg->print(os, indent+1);
+	os << std::endl << indent << "... to:";
 	if ( ! result ) {
-		os << "unknown";
+		os << " unknown";
 	} else {
-		result->print( os, indent+2 );
+		os << std::endl << indent+1;
+		result->print( os, indent+1 );
 	} // if
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-UntypedMemberExpr::UntypedMemberExpr( Expression * _member, Expression *_aggregate, Expression *_aname ) :
-		Expression( _aname ), member(_member), aggregate(_aggregate) {}
+	Expression::print( os, indent );
+}
+
+UntypedMemberExpr::UntypedMemberExpr( Expression * member, Expression *aggregate ) :
+		Expression(), member(member), aggregate(aggregate) {
+	assert( aggregate );
+}
 
 UntypedMemberExpr::UntypedMemberExpr( const UntypedMemberExpr &other ) :
@@ -346,17 +297,9 @@
 }
 
-void UntypedMemberExpr::print( std::ostream &os, int indent ) const {
-	os << "Untyped Member Expression, with field: " << std::endl;
-	os << std::string( indent+2, ' ' );
-	get_member()->print(os, indent+4);
-	os << std::string( indent+2, ' ' );
-
-	Expression *agg = get_aggregate();
-	os << "from aggregate: " << std::endl;
-	if (agg != 0) {
-		os << std::string( indent + 4, ' ' );
-		agg->print(os, indent + 4);
-	}
-	os << std::string( indent+2, ' ' );
+void UntypedMemberExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Untyped Member Expression, with field: " << std::endl << indent+1;
+	member->print(os, indent+1 );
+	os << indent << "... from aggregate: " << std::endl << indent+1;
+	aggregate->print(os, indent+1);
 	Expression::print( os, indent );
 }
@@ -377,6 +320,8 @@
 
 
-MemberExpr::MemberExpr( DeclarationWithType *_member, Expression *_aggregate, Expression *_aname ) :
-		Expression( _aname ), member(_member), aggregate(_aggregate) {
+MemberExpr::MemberExpr( DeclarationWithType *member, Expression *aggregate ) :
+		Expression(), member(member), aggregate(aggregate) {
+	assert( member );
+	assert( aggregate );
 
 	TypeSubstitution sub( makeSub( aggregate->get_result() ) );
@@ -396,24 +341,15 @@
 }
 
-void MemberExpr::print( std::ostream &os, int indent ) const {
+void MemberExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Member Expression, with field: " << std::endl;
-
-	assert( member );
-	os << std::string( indent + 2, ' ' );
-	member->print( os, indent + 2 );
-	os << std::endl;
-
-	Expression *agg = get_aggregate();
-	os << std::string( indent, ' ' ) << "from aggregate: " << std::endl;
-	if (agg != 0) {
-		os << std::string( indent + 2, ' ' );
-		agg->print(os, indent + 2);
-	}
-	os << std::string( indent+2, ' ' );
-	Expression::print( os, indent );
-}
-
-UntypedExpr::UntypedExpr( Expression *_function, const std::list<Expression *> &_args, Expression *_aname ) :
-		Expression( _aname ), function(_function), args(_args) {}
+	os << indent+1;
+	member->print( os, indent+1 );
+	os << std::endl << indent << "... from aggregate: " << std::endl << indent+1;
+	aggregate->print(os, indent + 1);
+	Expression::print( os, indent );
+}
+
+UntypedExpr::UntypedExpr( Expression *function, const std::list<Expression *> &args ) :
+		Expression(), function(function), args(args) {}
 
 UntypedExpr::UntypedExpr( const UntypedExpr &other ) :
@@ -456,24 +392,16 @@
 
 
-void UntypedExpr::print( std::ostream &os, int indent ) const {
+void UntypedExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Applying untyped: " << std::endl;
-	os << std::string( indent+2, ' ' );
-	function->print(os, indent + 2);
-	os << std::string( indent, ' ' ) << "...to: " << std::endl;
-	printAll(args, os, indent + 2);
-	Expression::print( os, indent );
-}
-
-void UntypedExpr::printArgs( std::ostream &os, int indent ) const {
-	std::list<Expression *>::const_iterator i;
-	for (i = args.begin(); i != args.end(); i++) {
-		os << std::string(indent, ' ' );
-		(*i)->print(os, indent);
-	}
-}
-
-NameExpr::NameExpr( std::string _name, Expression *_aname ) : Expression( _aname ), name(_name) {
-	assertf(_name != "0", "Zero is not a valid name\n");
-	assertf(_name != "1", "One is not a valid name\n");
+	os << indent+1;
+	function->print(os, indent+1);
+	os << std::endl << indent << "...to: " << std::endl;
+	printAll(args, os, indent+1);
+	Expression::print( os, indent );
+}
+
+NameExpr::NameExpr( std::string name ) : Expression(), name(name) {
+	assertf(name != "0", "Zero is not a valid name");
+	assertf(name != "1", "One is not a valid name");
 }
 
@@ -483,11 +411,11 @@
 NameExpr::~NameExpr() {}
 
-void NameExpr::print( std::ostream &os, int indent ) const {
-	os << "Name: " << get_name() << std::endl;
-	Expression::print( os, indent );
-}
-
-LogicalExpr::LogicalExpr( Expression *arg1_, Expression *arg2_, bool andp, Expression *_aname ) :
-		Expression( _aname ), arg1(arg1_), arg2(arg2_), isAnd(andp) {
+void NameExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Name: " << get_name();
+	Expression::print( os, indent );
+}
+
+LogicalExpr::LogicalExpr( Expression *arg1_, Expression *arg2_, bool andp ) :
+		Expression(), arg1(arg1_), arg2(arg2_), isAnd(andp) {
 	set_result( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
 }
@@ -502,15 +430,14 @@
 }
 
-void LogicalExpr::print( std::ostream &os, int indent )const {
-	os << "Short-circuited operation (" << (isAnd?"and":"or") << ") on: ";
+void LogicalExpr::print( std::ostream &os, Indenter indent )const {
+	os << "Short-circuited operation (" << (isAnd ? "and" : "or") << ") on: ";
 	arg1->print(os);
 	os << " and ";
 	arg2->print(os);
-	os << std::endl;
-	Expression::print( os, indent );
-}
-
-ConditionalExpr::ConditionalExpr( Expression *arg1_, Expression *arg2_, Expression *arg3_, Expression *_aname ) :
-		Expression( _aname ), arg1(arg1_), arg2(arg2_), arg3(arg3_) {}
+	Expression::print( os, indent );
+}
+
+ConditionalExpr::ConditionalExpr( Expression * arg1, Expression * arg2, Expression * arg3 ) :
+		Expression(), arg1(arg1), arg2(arg2), arg3(arg3) {}
 
 ConditionalExpr::ConditionalExpr( const ConditionalExpr &other ) :
@@ -524,15 +451,11 @@
 }
 
-void ConditionalExpr::print( std::ostream &os, int indent ) const {
-	os << "Conditional expression on: " << std::endl;
-	os << std::string( indent+2, ' ' );
-	arg1->print( os, indent+2 );
-	os << std::string( indent, ' ' ) << "First alternative:" << std::endl;
-	os << std::string( indent+2, ' ' );
-	arg2->print( os, indent+2 );
-	os << std::string( indent, ' ' ) << "Second alternative:" << std::endl;
-	os << std::string( indent+2, ' ' );
-	arg3->print( os, indent+2 );
-	os << std::endl;
+void ConditionalExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Conditional expression on: " << std::endl << indent+1;
+	arg1->print( os, indent+1 );
+	os << indent << "First alternative:" << std::endl << indent+1;
+	arg2->print( os, indent+1 );
+	os << indent << "Second alternative:" << std::endl << indent+1;
+	arg3->print( os, indent+1 );
 	Expression::print( os, indent );
 }
@@ -541,9 +464,9 @@
 
 
-void AsmExpr::print( std::ostream &os, int indent ) const {
+void AsmExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Asm Expression: " << std::endl;
-	if ( inout ) inout->print( os, indent + 2 );
-	if ( constraint ) constraint->print( os, indent + 2 );
-	if ( operand ) operand->print( os, indent + 2 );
+	if ( inout ) inout->print( os, indent+1 );
+	if ( constraint ) constraint->print( os, indent+1 );
+	if ( operand ) operand->print( os, indent+1 );
 }
 
@@ -551,5 +474,5 @@
 ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( ApplicationExpr * callExpr ) : callExpr( callExpr ) {
 	assert( callExpr );
-	assert( callExpr->has_result() );
+	assert( callExpr->result );
 	set_result( callExpr->get_result()->clone() );
 }
@@ -569,13 +492,11 @@
 }
 
-void ImplicitCopyCtorExpr::print( std::ostream &os, int indent ) const {
-	os <<  "Implicit Copy Constructor Expression: " << std::endl;
-	assert( callExpr );
-	os << std::string( indent+2, ' ' );
-	callExpr->print( os, indent + 2 );
-	os << std::endl << std::string( indent, ' ' ) << "with temporaries:" << std::endl;
-	printAll(tempDecls, os, indent+2);
-	os << std::endl << std::string( indent, ' ' ) << "with return temporaries:" << std::endl;
-	printAll(returnDecls, os, indent+2);
+void ImplicitCopyCtorExpr::print( std::ostream &os, Indenter indent ) const {
+	os <<  "Implicit Copy Constructor Expression: " << std::endl << indent+1;
+	callExpr->print( os, indent+1 );
+	os << std::endl << indent << "... with temporaries:" << std::endl;
+	printAll( tempDecls, os, indent+1 );
+	os << std::endl << indent << "... with return temporaries:" << std::endl;
+	printAll( returnDecls, os, indent+1 );
 	Expression::print( os, indent );
 }
@@ -587,5 +508,5 @@
 	Expression * arg = InitTweak::getCallArg( callExpr, 0 );
 	assert( arg );
-	set_result( maybeClone( arg->get_result() ) );
+	set_result( maybeClone( arg->result ) );
 }
 
@@ -597,8 +518,6 @@
 }
 
-void ConstructorExpr::print( std::ostream &os, int indent ) const {
-	os <<  "Constructor Expression: " << std::endl;
-	assert( callExpr );
-	os << std::string( indent+2, ' ' );
+void ConstructorExpr::print( std::ostream &os, Indenter indent ) const {
+	os <<  "Constructor Expression: " << std::endl << indent+1;
 	callExpr->print( os, indent + 2 );
 	Expression::print( os, indent );
@@ -618,10 +537,9 @@
 }
 
-void CompoundLiteralExpr::print( std::ostream &os, int indent ) const {
-	os << "Compound Literal Expression: " << std::endl;
-	os << std::string( indent+2, ' ' );
-	get_result()->print( os, indent + 2 );
-	os << std::string( indent+2, ' ' );
-	initializer->print( os, indent + 2 );
+void CompoundLiteralExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Compound Literal Expression: " << std::endl << indent+1;
+	result->print( os, indent+1 );
+	os << indent+1;
+	initializer->print( os, indent+1 );
 	Expression::print( os, indent );
 }
@@ -629,5 +547,5 @@
 RangeExpr::RangeExpr( Expression *low, Expression *high ) : low( low ), high( high ) {}
 RangeExpr::RangeExpr( const RangeExpr &other ) : Expression( other ), low( other.low->clone() ), high( other.high->clone() ) {}
-void RangeExpr::print( std::ostream &os, int indent ) const {
+void RangeExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Range Expression: ";
 	low->print( os, indent );
@@ -659,14 +577,14 @@
 	deleteAll( returnDecls );
 }
-void StmtExpr::print( std::ostream &os, int indent ) const {
-	os << "Statement Expression: " << std::endl << std::string( indent, ' ' );
-	statements->print( os, indent+2 );
+void StmtExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Statement Expression: " << std::endl << indent+1;
+	statements->print( os, indent+1 );
 	if ( ! returnDecls.empty() ) {
-		os << std::string( indent+2, ' ' ) << "with returnDecls: ";
-		printAll( returnDecls, os, indent+2 );
+		os << indent+1 << "... with returnDecls: ";
+		printAll( returnDecls, os, indent+1 );
 	}
 	if ( ! dtors.empty() ) {
-		os << std::string( indent+2, ' ' ) << "with dtors: ";
-		printAll( dtors, os, indent+2 );
+		os << indent+1 << "... with dtors: ";
+		printAll( dtors, os, indent+1 );
 	}
 	Expression::print( os, indent );
@@ -690,10 +608,10 @@
 	delete var;
 }
-void UniqueExpr::print( std::ostream &os, int indent ) const {
-	os << "Unique Expression with id:" << id << std::endl << std::string( indent+2, ' ' );
-	get_expr()->print( os, indent+2 );
-	if ( get_object() ) {
-		os << std::string( indent+2, ' ' ) << "with decl: ";
-		get_object()->printShort( os, indent+2 );
+void UniqueExpr::print( std::ostream &os, Indenter indent ) const {
+	os << "Unique Expression with id:" << id << std::endl << indent+1;
+	expr->print( os, indent+1 );
+	if ( object ) {
+		os << indent << "... with decl: ";
+		get_object()->printShort( os, indent+1 );
 	}
 	Expression::print( os, indent );
@@ -713,12 +631,12 @@
 }
 
-void UntypedInitExpr::print( std::ostream & os, int indent ) const {
-	os << "Untyped Init Expression" << std::endl << std::string( indent+2, ' ' );
-	expr->print( os, indent+2 );
+void UntypedInitExpr::print( std::ostream & os, Indenter indent ) const {
+	os << "Untyped Init Expression" << std::endl << indent+1;
+	expr->print( os, indent+1 );
 	if ( ! initAlts.empty() ) {
 		for ( const InitAlternative & alt : initAlts ) {
-			os << std::string( indent+2, ' ' ) <<  "InitAlternative: ";
-			alt.type->print( os, indent+2 );
-			alt.designation->print( os, indent+2 );
+			os << indent+1 <<  "InitAlternative: ";
+			alt.type->print( os, indent+1 );
+			alt.designation->print( os, indent+1 );
 		}
 	}
@@ -734,9 +652,9 @@
 }
 
-void InitExpr::print( std::ostream & os, int indent ) const {
-	os << "Init Expression" << std::endl << std::string( indent+2, ' ' );
-	expr->print( os, indent+2 );
-	os << std::string( indent+2, ' ' ) << "with designation: ";
-	designation->print( os, indent+2 );
+void InitExpr::print( std::ostream & os, Indenter indent ) const {
+	os << "Init Expression" << std::endl << indent+1;
+	expr->print( os, indent+1 );
+	os << indent+1 << "... with designation: ";
+	designation->print( os, indent+1 );
 }
 
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Expression.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -36,8 +36,7 @@
 	Type * result;
 	TypeSubstitution * env;
-	Expression * argName; // if expression is used as an argument, it can be "designated" by this name
 	bool extension = false;
 
-	Expression( Expression * _aname = nullptr );
+	Expression();
 	Expression( const Expression & other );
 	virtual ~Expression();
@@ -46,10 +45,7 @@
 	const Type * get_result() const { return result; }
 	void set_result( Type * newValue ) { result = newValue; }
-	bool has_result() const { return result != nullptr; }
 
 	TypeSubstitution * get_env() const { return env; }
 	void set_env( TypeSubstitution * newValue ) { env = newValue; }
-	Expression * get_argName() const { return argName; }
-	void set_argName( Expression * name ) { argName = name; }
 	bool get_extension() const { return extension; }
 	Expression * set_extension( bool exten ) { extension = exten; return this; }
@@ -58,5 +54,5 @@
 	virtual void accept( Visitor & v ) override = 0;
 	virtual Expression * acceptMutator( Mutator & m ) override = 0;
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -101,5 +97,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -112,5 +108,5 @@
 	std::list<Expression*> args;
 
-	UntypedExpr( Expression * function, const std::list<Expression *> & args = std::list< Expression * >(), Expression *_aname = nullptr );
+	UntypedExpr( Expression * function, const std::list<Expression *> & args = std::list< Expression * >() );
 	UntypedExpr( const UntypedExpr & other );
 	virtual ~UntypedExpr();
@@ -119,5 +115,4 @@
 	void set_function( Expression * newValue ) { function = newValue; }
 
-	void set_args( std::list<Expression *> & listArgs ) { args = listArgs; }
 	std::list<Expression*>::iterator begin_args() { return args.begin(); }
 	std::list<Expression*>::iterator end_args() { return args.end(); }
@@ -130,6 +125,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
-	virtual void printArgs(std::ostream & os, int indent = 0) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -139,5 +133,5 @@
 	std::string name;
 
-	NameExpr( std::string name, Expression *_aname = nullptr );
+	NameExpr( std::string name );
 	NameExpr( const NameExpr & other );
 	virtual ~NameExpr();
@@ -149,5 +143,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -160,5 +154,5 @@
 	Expression * arg;
 
-	AddressExpr( Expression * arg, Expression *_aname = nullptr );
+	AddressExpr( Expression * arg );
 	AddressExpr( const AddressExpr & other );
 	virtual ~AddressExpr();
@@ -170,5 +164,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -186,5 +180,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -194,6 +188,6 @@
 	Expression * arg;
 
-	CastExpr( Expression * arg, Expression *_aname = nullptr );
-	CastExpr( Expression * arg, Type * toType, Expression *_aname = nullptr );
+	CastExpr( Expression * arg );
+	CastExpr( Expression * arg, Type * toType );
 	CastExpr( const CastExpr & other );
 	virtual ~CastExpr();
@@ -205,5 +199,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -223,5 +217,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -232,5 +226,5 @@
 	Expression * aggregate;
 
-	UntypedMemberExpr( Expression * member, Expression * aggregate, Expression *_aname = nullptr );
+	UntypedMemberExpr( Expression * member, Expression * aggregate );
 	UntypedMemberExpr( const UntypedMemberExpr & other );
 	virtual ~UntypedMemberExpr();
@@ -244,5 +238,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -254,5 +248,5 @@
 	Expression * aggregate;
 
-	MemberExpr( DeclarationWithType * member, Expression * aggregate, Expression *_aname = nullptr );
+	MemberExpr( DeclarationWithType * member, Expression * aggregate );
 	MemberExpr( const MemberExpr & other );
 	virtual ~MemberExpr();
@@ -266,5 +260,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -275,5 +269,5 @@
 	DeclarationWithType * var;
 
-	VariableExpr( DeclarationWithType * var, Expression *_aname = nullptr );
+	VariableExpr( DeclarationWithType * var );
 	VariableExpr( const VariableExpr & other );
 	virtual ~VariableExpr();
@@ -287,5 +281,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -295,5 +289,5 @@
 	Constant constant;
 
-	ConstantExpr( Constant constant, Expression *_aname = nullptr );
+	ConstantExpr( Constant constant );
 	ConstantExpr( const ConstantExpr & other );
 	virtual ~ConstantExpr();
@@ -305,5 +299,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -315,7 +309,7 @@
 	bool isType;
 
-	SizeofExpr( Expression * expr, Expression *_aname = nullptr );
+	SizeofExpr( Expression * expr );
 	SizeofExpr( const SizeofExpr & other );
-	SizeofExpr( Type * type, Expression *_aname = nullptr );
+	SizeofExpr( Type * type );
 	virtual ~SizeofExpr();
 
@@ -330,5 +324,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -340,7 +334,7 @@
 	bool isType;
 
-	AlignofExpr( Expression * expr, Expression *_aname = nullptr );
+	AlignofExpr( Expression * expr );
 	AlignofExpr( const AlignofExpr & other );
-	AlignofExpr( Type * type, Expression *_aname = nullptr );
+	AlignofExpr( Type * type );
 	virtual ~AlignofExpr();
 
@@ -355,5 +349,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -364,5 +358,5 @@
 	std::string member;
 
-	UntypedOffsetofExpr( Type * type, const std::string & member, Expression *_aname = nullptr );
+	UntypedOffsetofExpr( Type * type, const std::string & member );
 	UntypedOffsetofExpr( const UntypedOffsetofExpr & other );
 	virtual ~UntypedOffsetofExpr();
@@ -376,5 +370,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -385,5 +379,5 @@
 	DeclarationWithType * member;
 
-	OffsetofExpr( Type * type, DeclarationWithType * member, Expression *_aname = nullptr );
+	OffsetofExpr( Type * type, DeclarationWithType * member );
 	OffsetofExpr( const OffsetofExpr & other );
 	virtual ~OffsetofExpr();
@@ -397,5 +391,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -405,5 +399,5 @@
 	StructInstType * type;
 
-	OffsetPackExpr( StructInstType * type_, Expression * aname_ = 0 );
+	OffsetPackExpr( StructInstType * type );
 	OffsetPackExpr( const OffsetPackExpr & other );
 	virtual ~OffsetPackExpr();
@@ -415,5 +409,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -426,7 +420,7 @@
 	bool isType;
 
-	AttrExpr(Expression * attr, Expression * expr, Expression *_aname = nullptr );
+	AttrExpr(Expression * attr, Expression * expr );
 	AttrExpr( const AttrExpr & other );
-	AttrExpr( Expression * attr, Type * type, Expression *_aname = nullptr );
+	AttrExpr( Expression * attr, Type * type );
 	virtual ~AttrExpr();
 
@@ -443,5 +437,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -452,5 +446,5 @@
 	Expression * arg2;
 
-	LogicalExpr( Expression * arg1, Expression * arg2, bool andp = true, Expression *_aname = nullptr );
+	LogicalExpr( Expression * arg1, Expression * arg2, bool andp = true );
 	LogicalExpr( const LogicalExpr & other );
 	virtual ~LogicalExpr();
@@ -465,5 +459,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 
   private:
@@ -478,5 +472,5 @@
 	Expression * arg3;
 
-	ConditionalExpr( Expression * arg1, Expression * arg2, Expression * arg3, Expression *_aname = nullptr );
+	ConditionalExpr( Expression * arg1, Expression * arg2, Expression * arg3 );
 	ConditionalExpr( const ConditionalExpr & other );
 	virtual ~ConditionalExpr();
@@ -492,5 +486,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -501,5 +495,5 @@
 	Expression * arg2;
 
-	CommaExpr( Expression * arg1, Expression * arg2, Expression *_aname = nullptr );
+	CommaExpr( Expression * arg1, Expression * arg2 );
 	CommaExpr( const CommaExpr & other );
 	virtual ~CommaExpr();
@@ -513,5 +507,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -531,5 +525,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -557,5 +551,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 
 	// https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
@@ -585,5 +579,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -603,5 +597,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -621,5 +615,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -640,5 +634,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -648,5 +642,5 @@
 	std::list<Expression*> exprs;
 
-	UntypedTupleExpr( const std::list< Expression * > & exprs, Expression *_aname = nullptr );
+	UntypedTupleExpr( const std::list< Expression * > & exprs );
 	UntypedTupleExpr( const UntypedTupleExpr & other );
 	virtual ~UntypedTupleExpr();
@@ -657,5 +651,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -665,5 +659,5 @@
 	std::list<Expression*> exprs;
 
-	TupleExpr( const std::list< Expression * > & exprs, Expression *_aname = nullptr );
+	TupleExpr( const std::list< Expression * > & exprs );
 	TupleExpr( const TupleExpr & other );
 	virtual ~TupleExpr();
@@ -674,5 +668,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -695,5 +689,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -703,5 +697,5 @@
 	StmtExpr * stmtExpr = nullptr;
 
-	TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname = nullptr );
+	TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls );
 	TupleAssignExpr( const TupleAssignExpr & other );
 	virtual ~TupleAssignExpr();
@@ -713,5 +707,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -736,5 +730,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -763,5 +757,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 
 private:
@@ -797,5 +791,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -818,5 +812,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
Index: src/SynTree/FunctionDecl.cc
===================================================================
--- src/SynTree/FunctionDecl.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/FunctionDecl.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -63,22 +63,22 @@
 }
 
-void FunctionDecl::print( std::ostream &os, int indent ) const {
+void FunctionDecl::print( std::ostream &os, Indenter indent ) const {
 	using std::endl;
 	using std::string;
 
-	if ( get_name() != "" ) {
-		os << get_name() << ": ";
+	if ( name != "" ) {
+		os << name << ": ";
 	} // if
-	if ( get_linkage() != LinkageSpec::Cforall ) {
-		os << LinkageSpec::linkageName( get_linkage() ) << " ";
+	if ( linkage != LinkageSpec::Cforall ) {
+		os << LinkageSpec::linkageName( linkage ) << " ";
 	} // if
 
-	printAll( get_attributes(), os, indent );
+	printAll( attributes, os, indent );
 
 	get_storageClasses().print( os );
 	get_funcSpec().print( os );
 
-	if ( get_type() ) {
-		get_type()->print( os, indent );
+	if ( type ) {
+		type->print( os, indent );
 	} else {
 		os << "untyped entity ";
@@ -86,25 +86,22 @@
 
 	if ( statements ) {
-		os << string( indent + 2, ' ' ) << "with body " << endl;
-		os << string( indent + 4, ' ' );
-		statements->print( os, indent + 4 );
+		os << indent << "... with body " << endl << indent+1;
+		statements->print( os, indent+1 );
 	} // if
 }
 
-void FunctionDecl::printShort( std::ostream &os, int indent ) const {
+void FunctionDecl::printShort( std::ostream &os, Indenter indent ) const {
 	using std::endl;
 	using std::string;
 
-	if ( get_name() != "" ) {
-		os << get_name() << ": ";
+	if ( name != "" ) {
+		os << name << ": ";
 	} // if
-
-	// xxx - should printShort print attributes?
 
 	get_storageClasses().print( os );
 	get_funcSpec().print( os );
 
-	if ( get_type() ) {
-		get_type()->print( os, indent );
+	if ( type ) {
+		type->print( os, indent );
 	} else {
 		os << "untyped entity ";
Index: src/SynTree/FunctionType.cc
===================================================================
--- src/SynTree/FunctionType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/FunctionType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -51,5 +51,5 @@
 }
 
-void FunctionType::print( std::ostream &os, int indent ) const {
+void FunctionType::print( std::ostream &os, Indenter indent ) const {
 	using std::string;
 	using std::endl;
@@ -58,18 +58,18 @@
 	os << "function" << endl;
 	if ( ! parameters.empty() ) {
-		os << string( indent + 2, ' ' ) << "with parameters" << endl;
-		printAll( parameters, os, indent + 4 );
+		os << indent << "... with parameters" << endl;
+		printAll( parameters, os, indent+1 );
 		if ( isVarArgs ) {
-			os << string( indent + 4, ' ' ) << "and a variable number of other arguments" << endl;
+			os << indent+1 << "and a variable number of other arguments" << endl;
 		} // if
 	} else if ( isVarArgs ) {
-		os << string( indent + 4, ' ' ) << "accepting unspecified arguments" << endl;
+		os << indent+1 << "accepting unspecified arguments" << endl;
 	} // if
-	os << string( indent + 2, ' ' ) << "returning ";
+	os << indent << "... returning ";
 	if ( returnVals.empty() ) {
-		os << endl << string( indent + 4, ' ' ) << "nothing " << endl;
+		os << "nothing " << endl;
 	} else {
 		os << endl;
-		printAll( returnVals, os, indent + 4 );
+		printAll( returnVals, os, indent+1 );
 	} // if
 }
Index: src/SynTree/Initializer.cc
===================================================================
--- src/SynTree/Initializer.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Initializer.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -38,12 +38,12 @@
 }
 
-void Designation::print( std::ostream &os, int indent ) const {
+void Designation::print( std::ostream &os, Indenter indent ) const {
 	if ( ! designators.empty() ) {
-		os << std::string(indent + 2, ' ' ) << "designated by: " << std::endl;
-		for ( std::list < Expression * >::const_iterator i = designators.begin(); i != designators.end(); i++ ) {
-			os << std::string(indent + 4, ' ' );
-			( *i )->print(os, indent + 4 );
+		os << "... designated by: " << std::endl;
+		for ( const Expression * d : designators ) {
+			os << indent+1;
+			d->print(os, indent+1 );
+			os << std::endl;
 		}
-		os << std::endl;
 	} // if
 }
@@ -64,8 +64,7 @@
 }
 
-void SingleInit::print( std::ostream &os, int indent ) const {
-	os << std::string(indent, ' ' ) << "Simple Initializer: " << std::endl;
-	os << std::string(indent+4, ' ' );
-	value->print( os, indent+4 );
+void SingleInit::print( std::ostream &os, Indenter indent ) const {
+	os << "Simple Initializer: ";
+	value->print( os, indent );
 }
 
@@ -93,13 +92,16 @@
 }
 
-void ListInit::print( std::ostream &os, int indent ) const {
-	os << std::string(indent, ' ') << "Compound initializer:  " << std::endl;
-	for ( Designation * d : designations ) {
-		d->print( os, indent + 2 );
-	}
-
-	for ( const Initializer * init : initializers ) {
-		init->print( os, indent + 2 );
+void ListInit::print( std::ostream &os, Indenter indent ) const {
+	os << "Compound initializer: " << std::endl;
+	for ( auto p : group_iterate( designations, initializers ) ) {
+		const Designation * d = std::get<0>(p);
+		const Initializer * init = std::get<1>(p);
+		os << indent+1;
+		init->print( os, indent+1 );
 		os << std::endl;
+		if ( ! d->designators.empty() ) {
+			os << indent+1;
+			d->print( os, indent+1 );
+		}
 	}
 }
@@ -116,22 +118,19 @@
 }
 
-void ConstructorInit::print( std::ostream &os, int indent ) const {
-	os << std::endl << std::string(indent, ' ') << "Constructor initializer: " << std::endl;
+void ConstructorInit::print( std::ostream &os, Indenter indent ) const {
+	os << "Constructor initializer: " << std::endl;
 	if ( ctor ) {
-		os << std::string(indent+2, ' ');
-		os << "initially constructed with ";
-		ctor->print( os, indent+4 );
+		os << indent << "... initially constructed with ";
+		ctor->print( os, indent+1 );
 	} // if
 
 	if ( dtor ) {
-		os << std::string(indent+2, ' ');
-		os << "destructed with ";
-		dtor->print( os, indent+4 );
+		os << indent << "... destructed with ";
+		dtor->print( os, indent+1 );
 	}
 
 	if ( init ) {
-		os << std::string(indent+2, ' ');
-		os << "with fallback C-style initializer: ";
-		init->print( os, indent+4 );
+		os << indent << "... with fallback C-style initializer: ";
+		init->print( os, indent+1 );
 	}
 }
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Initializer.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -40,5 +40,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Designation * acceptMutator( Mutator &m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -57,5 +57,5 @@
 	virtual void accept( Visitor &v ) override = 0;
 	virtual Initializer *acceptMutator( Mutator &m ) override = 0;
-	virtual void print( std::ostream &os, int indent = 0 ) const override = 0;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
   private:
 	bool maybeConstructed;
@@ -78,5 +78,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -106,5 +106,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -135,5 +135,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 
   private:
Index: src/SynTree/NamedTypeDecl.cc
===================================================================
--- src/SynTree/NamedTypeDecl.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/NamedTypeDecl.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -38,12 +38,11 @@
 }
 
-void NamedTypeDecl::print( std::ostream &os, int indent ) const {
+void NamedTypeDecl::print( std::ostream &os, Indenter indent ) const {
 	using namespace std;
 
-	if ( get_name() != "" ) {
-		os << get_name() << ": ";
-	} // if
-	if ( get_linkage() != LinkageSpec::Cforall ) {
-		os << LinkageSpec::linkageName( get_linkage() ) << " ";
+	if ( name != "" ) os << name << ": ";
+
+	if ( linkage != LinkageSpec::Cforall ) {
+		os << LinkageSpec::linkageName( linkage ) << " ";
 	} // if
 	get_storageClasses().print( os );
@@ -51,31 +50,29 @@
 	if ( base ) {
 		os << " for ";
-		base->print( os, indent );
+		base->print( os, indent+1 );
 	} // if
 	if ( ! parameters.empty() ) {
-		os << endl << string( indent, ' ' ) << "with parameters" << endl;
-		printAll( parameters, os, indent+2 );
+		os << endl << indent << "... with parameters" << endl;
+		printAll( parameters, os, indent+1 );
 	} // if
 	if ( ! assertions.empty() ) {
-		os << endl << string( indent, ' ' ) << "with assertions" << endl;
-		printAll( assertions, os, indent+2 );
+		os << endl << indent << "... with assertions" << endl;
+		printAll( assertions, os, indent+1 );
 	} // if
 }
 
-void NamedTypeDecl::printShort( std::ostream &os, int indent ) const {
+void NamedTypeDecl::printShort( std::ostream &os, Indenter indent ) const {
 	using namespace std;
 
-	if ( get_name() != "" ) {
-		os << get_name() << ": ";
-	} // if
+	if ( name != "" ) os << name << ": ";
 	get_storageClasses().print( os );
 	os << typeString();
 	if ( base ) {
 		os << " for ";
-		base->print( os, indent );
+		base->print( os, indent+1 );
 	} // if
 	if ( ! parameters.empty() ) {
-		os << endl << string( indent, ' ' ) << "with parameters" << endl;
-		printAll( parameters, os, indent+2 );
+		os << endl << indent << "... with parameters" << endl;
+		printAll( parameters, os, indent+1 );
 	} // if
 }
Index: src/SynTree/ObjectDecl.cc
===================================================================
--- src/SynTree/ObjectDecl.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/ObjectDecl.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -44,19 +44,15 @@
 }
 
-void ObjectDecl::print( std::ostream &os, int indent ) const {
-	if ( get_name() != "" ) {
-		os << get_name() << ": ";
+void ObjectDecl::print( std::ostream &os, Indenter indent ) const {
+	if ( name != "" ) os << name << ": ";
+
+	if ( linkage != LinkageSpec::Cforall ) {
+		os << LinkageSpec::linkageName( linkage ) << " ";
 	} // if
-
-	if ( get_linkage() != LinkageSpec::Cforall ) {
-		os << LinkageSpec::linkageName( get_linkage() ) << " ";
-	} // if
-
-	printAll( get_attributes(), os, indent );
 
 	get_storageClasses().print( os );
 
-	if ( get_type() ) {
-		get_type()->print( os, indent );
+	if ( type ) {
+		type->print( os, indent );
 	} else {
 		os << " untyped entity ";
@@ -64,18 +60,21 @@
 
 	if ( init ) {
-		os << " with initializer " << std::endl;
-		init->print( os, indent+2 );
-		os << std::endl << std::string(indent+2, ' ');
-		os << "maybeConstructed? " << init->get_maybeConstructed();
+		os << " with initializer (" << (init->get_maybeConstructed() ? "maybe constructed" : "not constructed") << ")" << std::endl << indent+1;
+		init->print( os, indent+1 );
+		os << std::endl;
 	} // if
 
+	if ( ! attributes.empty() ) {
+		os << std::endl << indent << "... with attributes: " << std::endl;
+		printAll( attributes, os, indent+1 );
+	}
+
 	if ( bitfieldWidth ) {
-		os << std::string(indent, ' ');
-		os << " with bitfield width ";
+		os << indent << " with bitfield width ";
 		bitfieldWidth->print( os );
 	} // if
 }
 
-void ObjectDecl::printShort( std::ostream &os, int indent ) const {
+void ObjectDecl::printShort( std::ostream &os, Indenter indent ) const {
 #if 0
 	if ( get_mangleName() != "") {
@@ -83,14 +82,10 @@
 	} else
 #endif
-	if ( get_name() != "" ) {
-		os << get_name() << ": ";
-	} // if
-
-	// xxx - should printShort print attributes?
+	if ( name != "" ) os << name << ": ";
 
 	get_storageClasses().print( os );
 
-	if ( get_type() ) {
-		get_type()->print( os, indent );
+	if ( type ) {
+		type->print( os, indent );
 	} else {
 		os << "untyped entity ";
Index: src/SynTree/PointerType.cc
===================================================================
--- src/SynTree/PointerType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/PointerType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -41,5 +41,5 @@
 }
 
-void PointerType::print( std::ostream &os, int indent ) const {
+void PointerType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	if ( ! is_array() ) {
Index: src/SynTree/ReferenceToType.cc
===================================================================
--- src/SynTree/ReferenceToType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/ReferenceToType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -14,5 +14,4 @@
 //
 
-#include <stddef.h>          // for NULL
 #include <cassert>           // for assert
 #include <list>              // for list, _List_const_iterator, list<>::cons...
@@ -38,5 +37,5 @@
 }
 
-void ReferenceToType::print( std::ostream &os, int indent ) const {
+void ReferenceToType::print( std::ostream &os, Indenter indent ) const {
 	using std::endl;
 
@@ -44,6 +43,6 @@
 	os << "instance of " << typeString() << " " << name << " ";
 	if ( ! parameters.empty() ) {
-		os << endl << std::string( indent, ' ' ) << "with parameters" << endl;
-		printAll( parameters, os, indent+2 );
+		os << endl << indent << "... with parameters" << endl;
+		printAll( parameters, os, indent+1 );
 	} // if
 }
@@ -65,5 +64,5 @@
 
 std::list<TypeDecl*>* StructInstType::get_baseParameters() {
-	if ( ! baseStruct ) return NULL;
+	if ( ! baseStruct ) return nullptr;
 	return &baseStruct->get_parameters();
 }
@@ -76,14 +75,14 @@
 }
 
-void StructInstType::print( std::ostream &os, int indent ) const {
+void StructInstType::print( std::ostream &os, Indenter indent ) const {
 	using std::endl;
 
-	if ( baseStruct == NULL ) ReferenceToType::print( os, indent );
+	if ( baseStruct == nullptr ) ReferenceToType::print( os, indent );
 	else {
 		Type::print( os, indent );
 		os << "instance of " << typeString() << " " << name << " with body " << baseStruct->has_body() << " ";
 		if ( ! parameters.empty() ) {
-			os << endl << std::string( indent, ' ' ) << "with parameters" << endl;
-			printAll( parameters, os, indent+2 );
+			os << endl << indent << "... with parameters" << endl;
+			printAll( parameters, os, indent+1 );
 		} // if
 	} // if
@@ -97,5 +96,5 @@
 
 std::list< TypeDecl * > * UnionInstType::get_baseParameters() {
-	if ( ! baseUnion ) return NULL;
+	if ( ! baseUnion ) return nullptr;
 	return &baseUnion->get_parameters();
 }
@@ -108,14 +107,14 @@
 }
 
-void UnionInstType::print( std::ostream &os, int indent ) const {
+void UnionInstType::print( std::ostream &os, Indenter indent ) const {
 	using std::endl;
 
-	if ( baseUnion == NULL ) ReferenceToType::print( os, indent );
+	if ( baseUnion == nullptr ) ReferenceToType::print( os, indent );
 	else {
 		Type::print( os, indent );
 		os << "instance of " << typeString() << " " << name << " with body " << baseUnion->has_body() << " ";
 		if ( ! parameters.empty() ) {
-			os << endl << std::string( indent, ' ' ) << "with parameters" << endl;
-			printAll( parameters, os, indent+2 );
+			os << endl << indent << "... with parameters" << endl;
+			printAll( parameters, os, indent+1 );
 		} // if
 	} // if
@@ -166,5 +165,5 @@
 bool TypeInstType::isComplete() const { return baseType->isComplete(); }
 
-void TypeInstType::print( std::ostream &os, int indent ) const {
+void TypeInstType::print( std::ostream &os, Indenter indent ) const {
 	using std::endl;
 
@@ -172,6 +171,6 @@
 	os << "instance of " << typeString() << " " << get_name() << " (" << ( isFtype ? "" : "not" ) << " function type) ";
 	if ( ! parameters.empty() ) {
-		os << endl << std::string( indent, ' ' ) << "with parameters" << endl;
-		printAll( parameters, os, indent+2 );
+		os << endl << indent << "... with parameters" << endl;
+		printAll( parameters, os, indent+1 );
 	} // if
 }
Index: src/SynTree/ReferenceType.cc
===================================================================
--- src/SynTree/ReferenceType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/ReferenceType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -35,5 +35,5 @@
 }
 
-void ReferenceType::print( std::ostream &os, int indent ) const {
+void ReferenceType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	os << "reference to ";
Index: src/SynTree/Statement.cc
===================================================================
--- src/SynTree/Statement.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Statement.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -34,5 +34,13 @@
 Statement::Statement( std::list<Label> labels ) : labels( labels ) {}
 
-void Statement::print( __attribute__((unused)) std::ostream &, __attribute__((unused)) int indent ) const {}
+void Statement::print( std::ostream & os, Indenter ) const {
+	if ( ! labels.empty() ) {
+		os << "Labels: {";
+		for ( const Label & l : labels ) {
+			os << l << ",";
+		}
+		os << "}" << endl;
+	}
+}
 
 Statement::~Statement() {}
@@ -46,7 +54,7 @@
 }
 
-void ExprStmt::print( std::ostream &os, int indent ) const {
-	os << "Expression Statement:" << endl << std::string( indent + 2, ' ' );
-	expr->print( os, indent + 2 );
+void ExprStmt::print( std::ostream &os, Indenter indent ) const {
+	os << "Expression Statement:" << endl << indent+1;
+	expr->print( os, indent+1 );
 }
 
@@ -67,19 +75,19 @@
 }
 
-void AsmStmt::print( std::ostream &os, int indent ) const {
+void AsmStmt::print( std::ostream &os, Indenter indent ) const {
 	os << "Assembler Statement:" << endl;
-	os << std::string( indent, ' ' ) << "instruction: " << endl << std::string( indent, ' ' );
-	instruction->print( os, indent + 2 );
+	os << indent+1 << "instruction: " << endl << indent;
+	instruction->print( os, indent+1 );
 	if ( ! output.empty() ) {
-		os << endl << std::string( indent, ' ' ) << "output: " << endl;
-		printAll( output, os, indent + 2 );
+		os << endl << indent+1 << "output: " << endl;
+		printAll( output, os, indent+1 );
 	} // if
 	if ( ! input.empty() ) {
-		os << std::string( indent, ' ' ) << "input: " << endl << std::string( indent, ' ' );
-		printAll( input, os, indent + 2 );
+		os << indent+1 << "input: " << endl;
+		printAll( input, os, indent+1 );
 	} // if
 	if ( ! clobber.empty() ) {
-		os << std::string( indent, ' ' ) << "clobber: " << endl;
-		printAll( clobber, os, indent + 2 );
+		os << indent+1 << "clobber: " << endl;
+		printAll( clobber, os, indent+1 );
 	} // if
 }
@@ -103,9 +111,9 @@
 }
 
-void BranchStmt::print( std::ostream &os, int indent ) const {
-	os << string( indent, ' ' ) << "Branch (" << brType[type] << ")" << endl ;
-	if ( target != "" ) os << string( indent+2, ' ' ) << "with target: " << target << endl;
-	if ( originalTarget != "" ) os << string( indent+2, ' ' ) << "with original target: " << originalTarget << endl;
-	if ( computedTarget != nullptr ) os << string( indent+2, ' ' ) << "with computed target: " << computedTarget << endl;
+void BranchStmt::print( std::ostream &os, Indenter indent ) const {
+	os << "Branch (" << brType[type] << ")" << endl ;
+	if ( target != "" ) os << indent+1 << "with target: " << target << endl;
+	if ( originalTarget != "" ) os << indent+1 << "with original target: " << originalTarget << endl;
+	if ( computedTarget != nullptr ) os << indent+1 << "with computed target: " << computedTarget << endl;
 }
 
@@ -118,9 +126,9 @@
 }
 
-void ReturnStmt::print( std::ostream &os, int indent ) const {
-	os <<  "Return Statement, returning: ";
-	if ( expr != 0 ) {
-		os << endl << string( indent+2, ' ' );
-		expr->print( os, indent + 2 );
+void ReturnStmt::print( std::ostream &os, Indenter indent ) const {
+	os << "Return Statement, returning: ";
+	if ( expr != nullptr ) {
+		os << endl << indent+1;
+		expr->print( os, indent+1 );
 	}
 	os << endl;
@@ -142,27 +150,27 @@
 }
 
-void IfStmt::print( std::ostream &os, int indent ) const {
-	os << "If on condition: " << endl ;
-	os << string( indent+4, ' ' );
-	condition->print( os, indent + 4 );
+void IfStmt::print( std::ostream &os, Indenter indent ) const {
+	os << "If on condition: " << endl;
+	os << indent+1;
+	condition->print( os, indent+1 );
 
 	if ( !initialization.empty() ) {
-		os << string( indent + 2, ' ' ) << "initialization: \n";
-		for ( std::list<Statement *>::const_iterator it = initialization.begin(); it != initialization.end(); ++it ) {
-			os << string( indent + 4, ' ' );
-			(*it)->print( os, indent + 4 );
+		os << indent << "... with initialization: \n";
+		for ( const Statement * stmt : initialization ) {
+			os << indent+1;
+			stmt->print( os, indent+1 );
 		}
 		os << endl;
 	}
 
-	os << string( indent+2, ' ' ) << "... then: " << endl;
-
-	os << string( indent+4, ' ' );
-	thenPart->print( os, indent + 4 );
+	os << indent << "... then: " << endl;
+
+	os << indent+1;
+	thenPart->print( os, indent+1 );
 
 	if ( elsePart != 0 ) {
-		os << string( indent+2, ' ' ) << "... else: " << endl;
-		os << string( indent+4, ' ' );
-		elsePart->print( os, indent + 4 );
+		os << indent << "... else: " << endl;
+		os << indent+1;
+		elsePart->print( os, indent+1 );
 	} // if
 }
@@ -183,21 +191,17 @@
 }
 
-void SwitchStmt::print( std::ostream &os, int indent ) const {
+void SwitchStmt::print( std::ostream &os, Indenter indent ) const {
 	os << "Switch on condition: ";
 	condition->print( os );
 	os << endl;
 
-	// statements
-	std::list<Statement *>::const_iterator i;
-	for ( i = statements.begin(); i != statements.end(); i++)
-		(*i)->print( os, indent + 4 );
-
-	//for_each( statements.begin(), statements.end(), mem_fun( bind1st(&Statement::print ), os ));
+	for ( const Statement * stmt : statements ) {
+		stmt->print( os, indent+1 );
+	}
 }
 
 CaseStmt::CaseStmt( std::list<Label> labels, Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) :
 	Statement( labels ), condition( condition ), stmts( statements ), _isDefault( deflt ) {
-	if ( isDefault() && condition != 0 )
-		throw SemanticError("default with conditions");
+	if ( isDefault() && condition != 0 ) throw SemanticError("default case with condition: ", condition);
 }
 
@@ -216,19 +220,15 @@
 }
 
-void CaseStmt::print( std::ostream &os, int indent ) const {
-	os << string( indent, ' ' );
-
-	if ( isDefault() )
-		os << "Default ";
+void CaseStmt::print( std::ostream &os, Indenter indent ) const {
+	if ( isDefault() ) os << "Default ";
 	else {
 		os << "Case ";
-		condition->print( os );
-	} // if
-
-	os << endl;
-
-	std::list<Statement *>::const_iterator i;
-	for ( i = stmts.begin(); i != stmts.end(); i++)
-		(*i )->print( os, indent + 4 );
+		condition->print( os, indent );
+	} // if
+	os << endl;
+
+	for ( Statement * stmt : stmts ) {
+		stmt->print( os, indent+1 );
+	}
 }
 
@@ -246,11 +246,11 @@
 }
 
-void WhileStmt::print( std::ostream &os, int indent ) const {
+void WhileStmt::print( std::ostream &os, Indenter indent ) const {
 	os << "While on condition: " << endl ;
-	condition->print( os, indent + 4 );
-
-	os << string( indent, ' ' ) << ".... with body: " << endl;
-
-	if ( body != 0 ) body->print( os, indent + 4 );
+	condition->print( os, indent+1 );
+
+	os << indent << "... with body: " << endl;
+
+	if ( body != 0 ) body->print( os, indent+1 );
 }
 
@@ -272,37 +272,31 @@
 }
 
-void ForStmt::print( std::ostream &os, int indent ) const {
-	os << "Labels: {";
-	for ( std::list<Label>::const_iterator it = get_labels().begin(); it != get_labels().end(); ++it) {
-		os << *it << ",";
-	}
-	os << "}" << endl;
-
-	os << string( indent, ' ' ) << "For Statement" << endl ;
-
-	os << string( indent + 2, ' ' ) << "initialization: \n";
-	for ( std::list<Statement *>::const_iterator it = initialization.begin(); it != initialization.end(); ++it ) {
-		os << string( indent + 4, ' ' );
-		(*it)->print( os, indent + 4 );
-	}
-
-	os << "\n" << string( indent + 2, ' ' ) << "condition: \n";
-	if ( condition != 0 ) {
-		os << string( indent + 4, ' ' );
-		condition->print( os, indent + 4 );
-	}
-
-	os << "\n" << string( indent + 2, ' ' ) << "increment: \n";
-	if ( increment != 0 ) {
-		os << string( indent + 4, ' ' );
-		increment->print( os, indent + 4 );
-	}
-
-	os << "\n" << string( indent + 2, ' ' ) << "statement block: \n";
+void ForStmt::print( std::ostream &os, Indenter indent ) const {
+	Statement::print( os, indent ); // print labels
+
+	os << "For Statement" << endl;
+
+	if ( ! initialization.empty() ) {
+		os << indent << "... initialization: \n";
+		for ( Statement * stmt : initialization ) {
+			os << indent+1;
+			stmt->print( os, indent+1 );
+		}
+	}
+
+	if ( condition != nullptr ) {
+		os << indent << "... condition: \n" << indent+1;
+		condition->print( os, indent+1 );
+	}
+
+	if ( increment != nullptr ) {
+		os << "\n" << indent << "... increment: \n" << indent+1;
+		increment->print( os, indent+1 );
+	}
+
 	if ( body != 0 ) {
-		os << string( indent + 4, ' ' );
-		body->print( os, indent + 4 );
-	}
-
+		os << "\n" << indent << "... with body: \n" << indent+1;
+		body->print( os, indent+1 );
+	}
 	os << endl;
 }
@@ -322,13 +316,11 @@
 }
 
-void ThrowStmt::print( std::ostream &os, int indent) const {
+void ThrowStmt::print( std::ostream &os, Indenter indent) const {
+	if ( target ) os << "Non-Local ";
+	os << "Throw Statement, raising: ";
+	expr->print(os, indent+1);
 	if ( target ) {
-		os << "Non-Local ";
-	}
-	os << "Throw Statement, raising: ";
-	expr->print(os, indent + 4);
-	if ( target ) {
-		os << "At: ";
-		target->print(os, indent + 4);
+		os << "... at: ";
+		target->print(os, indent+1);
 	}
 }
@@ -348,21 +340,20 @@
 }
 
-void TryStmt::print( std::ostream &os, int indent ) const {
+void TryStmt::print( std::ostream &os, Indenter indent ) const {
 	os << "Try Statement" << endl;
-	os << string( indent + 2, ' ' ) << "with block:" << endl;
-	os << string( indent + 4, ' ' );
-	block->print( os, indent + 4 );
+	os << indent << "... with block:" << endl << indent+1;
+	block->print( os, indent+1 );
 
 	// handlers
-	os << string( indent + 2, ' ' ) << "and handlers:" << endl;
-	for ( std::list<CatchStmt *>::const_iterator i = handlers.begin(); i != handlers.end(); i++) {
-		os << string( indent + 4, ' ' );
-		(*i )->print( os, indent + 4 );
+	os << indent << "... and handlers:" << endl;
+	for ( const CatchStmt * stmt : handlers ) {
+		os << indent+1;
+		stmt->print( os, indent+1 );
 	}
 
 	// finally block
 	if ( finallyBlock != 0 ) {
-		os << string( indent + 2, ' ' ) << "and finally:" << endl;
-		finallyBlock->print( os, indent + 4 );
+		os << indent << "... and finally:" << endl << indent+1;
+		finallyBlock->print( os, indent+1 );
 	} // if
 }
@@ -370,4 +361,5 @@
 CatchStmt::CatchStmt( std::list<Label> labels, Kind kind, Declaration *decl, Expression *cond, Statement *body ) :
 	Statement( labels ), kind ( kind ), decl ( decl ), cond ( cond ), body( body ) {
+		assertf( decl, "Catch clause must have a declaration." );
 }
 
@@ -381,26 +373,19 @@
 }
 
-void CatchStmt::print( std::ostream &os, int indent ) const {
+void CatchStmt::print( std::ostream &os, Indenter indent ) const {
 	os << "Catch " << ((Terminate == kind) ? "Terminate" : "Resume") << " Statement" << endl;
 
-	os << string( indent + 2, ' ' ) << "... catching: ";
-	if ( decl ) {
-		decl->printShort( os, indent + 4 );
-		os << endl;
-	}
-	else
-		os << string( indent + 4 , ' ' ) << ">>> Error:  this catch clause must have a declaration <<<" << endl;
+	os << indent << "... catching: ";
+	decl->printShort( os, indent+1 );
+	os << endl;
 
 	if ( cond ) {
-		os << string( indent + 2, ' ' ) << "with conditional:" << endl;
-		os << string( indent + 4, ' ' );
-		cond->print( os, indent + 4 );
-	}
-	else
-		os << string( indent + 2, ' ' ) << "with no conditional" << endl;
-
-	os << string( indent + 2, ' ' ) << "with block:" << endl;
-	os << string( indent + 4, ' ' );
-	body->print( os, indent + 4 );
+		os << indent << "... with conditional:" << endl << indent+1;
+		cond->print( os, indent+1 );
+	}
+
+	os << indent << "... with block:" << endl;
+	os << indent+1;
+	body->print( os, indent+1 );
 }
 
@@ -417,9 +402,8 @@
 }
 
-void FinallyStmt::print( std::ostream &os, int indent ) const {
+void FinallyStmt::print( std::ostream &os, Indenter indent ) const {
 	os << "Finally Statement" << endl;
-	os << string( indent + 2, ' ' ) << "with block:" << endl;
-	os << string( indent + 4, ' ' );
-	block->print( os, indent + 4 );
+	os << indent << "... with block:" << endl << indent+1;
+	block->print( os, indent+1 );
 }
 
@@ -465,8 +449,7 @@
 }
 
-void WaitForStmt::print( std::ostream &os, int indent ) const {
+void WaitForStmt::print( std::ostream &os, Indenter indent ) const {
 	os << "Waitfor Statement" << endl;
-	os << string( indent + 2, ' ' ) << "with block:" << endl;
-	os << string( indent + 4, ' ' );
+	os << indent << "... with block:" << endl << indent+1;
 	// block->print( os, indent + 4 );
 }
@@ -475,6 +458,6 @@
 NullStmt::NullStmt() : Statement( std::list<Label>() ) {}
 
-void NullStmt::print( std::ostream &os, __attribute__((unused)) int indent ) const {
-	os << "Null Statement" << endl ;
+void NullStmt::print( std::ostream &os, Indenter ) const {
+	os << "Null Statement" << endl;
 }
 
@@ -490,8 +473,8 @@
 }
 
-void ImplicitCtorDtorStmt::print( std::ostream &os, int indent ) const {
+void ImplicitCtorDtorStmt::print( std::ostream &os, Indenter indent ) const {
 	os << "Implicit Ctor Dtor Statement" << endl;
-	os << string( indent + 2, ' ' ) << "with Ctor/Dtor: ";
-	callStmt->print( os, indent + 2);
+	os << indent << "... with Ctor/Dtor: ";
+	callStmt->print( os, indent+1);
 	os << endl;
 }
Index: src/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Statement.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -46,5 +46,5 @@
 	virtual void accept( Visitor &v ) override = 0;
 	virtual Statement *acceptMutator( Mutator &m ) override = 0;
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -65,5 +65,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual CompoundStmt *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -76,5 +76,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual NullStmt *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -93,5 +93,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -124,5 +124,5 @@
 	virtual void accept( Visitor & v ) { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -150,5 +150,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -171,5 +171,5 @@
 
 	virtual SwitchStmt *clone() const override { return new SwitchStmt( *this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 
 };
@@ -199,5 +199,5 @@
 
 	virtual CaseStmt *clone() const override { return new CaseStmt( *this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
   private:
 	bool _isDefault;
@@ -225,5 +225,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -251,5 +251,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -280,5 +280,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
   private:
 	static const char *brType[];
@@ -299,5 +299,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -323,5 +323,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -346,5 +346,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -374,5 +374,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -391,5 +391,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -428,5 +428,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 
 };
@@ -448,5 +448,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
@@ -470,5 +470,5 @@
 	virtual void accept( Visitor &v ) override { v.visit( this ); }
 	virtual Statement *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const override;
+	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
 };
 
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/TupleExpr.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -28,5 +28,5 @@
 #include "Type.h"               // for TupleType, Type
 
-UntypedTupleExpr::UntypedTupleExpr( const std::list< Expression * > & exprs, Expression *_aname ) : Expression( _aname ), exprs( exprs ) {
+UntypedTupleExpr::UntypedTupleExpr( const std::list< Expression * > & exprs ) : Expression(), exprs( exprs ) {
 }
 
@@ -39,11 +39,11 @@
 }
 
-void UntypedTupleExpr::print( std::ostream &os, int indent ) const {
+void UntypedTupleExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Untyped Tuple:" << std::endl;
-	printAll( exprs, os, indent+2 );
+	printAll( exprs, os, indent+1 );
 	Expression::print( os, indent );
 }
 
-TupleExpr::TupleExpr( const std::list< Expression * > & exprs, Expression *_aname ) : Expression( _aname ), exprs( exprs ) {
+TupleExpr::TupleExpr( const std::list< Expression * > & exprs ) : Expression(), exprs( exprs ) {
 	set_result( Tuples::makeTupleType( exprs ) );
 }
@@ -57,7 +57,7 @@
 }
 
-void TupleExpr::print( std::ostream &os, int indent ) const {
+void TupleExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Tuple:" << std::endl;
-	printAll( exprs, os, indent+2 );
+	printAll( exprs, os, indent+1 );
 	Expression::print( os, indent );
 }
@@ -78,13 +78,13 @@
 }
 
-void TupleIndexExpr::print( std::ostream &os, int indent ) const {
+void TupleIndexExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Tuple Index Expression, with tuple:" << std::endl;
-	os << std::string( indent+2, ' ' );
-	tuple->print( os, indent+2 );
-	os << std::string( indent+2, ' ' ) << "with index: " << index << std::endl;
+	os << indent+1;
+	tuple->print( os, indent+1 );
+	os << indent+1 << "with index: " << index << std::endl;
 	Expression::print( os, indent );
 }
 
-TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname ) : Expression( _aname ) {
+TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls ) : Expression() {
 	// convert internally into a StmtExpr which contains the declarations and produces the tuple of the assignments
 	set_result( Tuples::makeTupleType( assigns ) );
@@ -109,8 +109,8 @@
 }
 
-void TupleAssignExpr::print( std::ostream &os, int indent ) const {
+void TupleAssignExpr::print( std::ostream &os, Indenter indent ) const {
 	os << "Tuple Assignment Expression, with stmt expr:" << std::endl;
-	os << std::string( indent+2, ' ' );
-	stmtExpr->print( os, indent+4 );
+	os << indent+1;
+	stmtExpr->print( os, indent+1 );
 	Expression::print( os, indent );
 }
Index: src/SynTree/TupleType.cc
===================================================================
--- src/SynTree/TupleType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/TupleType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -48,8 +48,8 @@
 }
 
-void TupleType::print( std::ostream &os, int indent ) const {
+void TupleType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	os << "tuple of types" << std::endl;
-	printAll( types, os, indent+2 );
+	printAll( types, os, indent+1 );
 }
 
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Type.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -75,5 +75,5 @@
 	Type * type;
 	ReferenceType * ref;
-	for ( type = this; (ref = dynamic_cast<ReferenceType *>( type )); type = ref->get_base() );
+	for ( type = this; (ref = dynamic_cast<ReferenceType *>( type )); type = ref->base );
 	return type;
 }
@@ -81,14 +81,14 @@
 int Type::referenceDepth() const { return 0; }
 
-void Type::print( std::ostream &os, int indent ) const {
+void Type::print( std::ostream &os, Indenter indent ) const {
 	if ( ! forall.empty() ) {
 		os << "forall" << std::endl;
-		printAll( forall, os, indent + 4 );
-		os << std::string( indent+2, ' ' );
+		printAll( forall, os, indent+1 );
+		os << ++indent;
 	} // if
 
 	if ( ! attributes.empty() ) {
-		os << endl << string( indent+2, ' ' ) << "with attributes" << endl;
-		printAll( attributes, os, indent+4 );
+		os << "with attributes" << endl;
+		printAll( attributes, os, indent+1 );
 	} // if
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/Type.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -181,5 +181,5 @@
 	virtual void accept( Visitor & v ) = 0;
 	virtual Type *acceptMutator( Mutator & m ) = 0;
-	virtual void print( std::ostream & os, int indent = 0 ) const;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
 };
 
@@ -198,5 +198,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -240,5 +240,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 
 	bool isInteger() const;
@@ -275,5 +275,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -303,5 +303,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -327,5 +327,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -354,5 +354,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -376,5 +376,5 @@
 	virtual void accept( Visitor & v ) override = 0;
 	virtual Type *acceptMutator( Mutator & m ) override = 0;
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 
 	virtual void lookup( __attribute__((unused)) const std::string & name, __attribute__((unused)) std::list< Declaration* > & foundDecls ) const {}
@@ -410,5 +410,5 @@
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
   private:
 	virtual std::string typeString() const override;
@@ -442,5 +442,5 @@
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
   private:
 	virtual std::string typeString() const override;
@@ -514,5 +514,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
   private:
 	virtual std::string typeString() const override;
@@ -551,5 +551,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -570,5 +570,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -599,5 +599,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -613,5 +613,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -625,5 +625,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -637,5 +637,5 @@
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, int indent = 0 ) const override;
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
Index: src/SynTree/TypeDecl.cc
===================================================================
--- src/SynTree/TypeDecl.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/TypeDecl.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -41,9 +41,9 @@
 }
 
-void TypeDecl::print( std::ostream &os, int indent ) const {
+void TypeDecl::print( std::ostream &os, Indenter indent ) const {
   NamedTypeDecl::print( os, indent );
   if ( init ) {
-    os << std::endl << std::string( indent, ' ' ) << "with type initializer: ";
-    init->print( os, indent + 2 );
+    os << std::endl << indent << "with type initializer: ";
+    init->print( os, indent + 1 );
   }
 }
Index: src/SynTree/TypeExpr.cc
===================================================================
--- src/SynTree/TypeExpr.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/TypeExpr.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -30,5 +30,5 @@
 }
 
-void TypeExpr::print( std::ostream &os, int indent ) const {
+void TypeExpr::print( std::ostream &os, Indenter indent ) const {
 	if ( type ) type->print( os, indent );
 	Expression::print( os, indent );
Index: src/SynTree/TypeSubstitution.cc
===================================================================
--- src/SynTree/TypeSubstitution.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/TypeSubstitution.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -243,15 +243,15 @@
 }
 
-void TypeSubstitution::print( std::ostream &os, int indent ) const {
-	os << std::string( indent, ' ' ) << "Types:" << std::endl;
+void TypeSubstitution::print( std::ostream &os, Indenter indent ) const {
+	os << indent << "Types:" << std::endl;
 	for ( TypeEnvType::const_iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
-		os << std::string( indent+2, ' ' ) << i->first << " -> ";
-		i->second->print( os, indent+4 );
+		os << indent+1 << i->first << " -> ";
+		i->second->print( os, indent+2 );
 		os << std::endl;
 	} // for
-	os << std::string( indent, ' ' ) << "Non-types:" << std::endl;
+	os << indent << "Non-types:" << std::endl;
 	for ( VarEnvType::const_iterator i = varEnv.begin(); i != varEnv.end(); ++i ) {
-		os << std::string( indent+2, ' ' ) << i->first << " -> ";
-		i->second->print( os, indent+4 );
+		os << indent+1 << i->first << " -> ";
+		i->second->print( os, indent+2 );
 		os << std::endl;
 	} // for
Index: src/SynTree/TypeSubstitution.h
===================================================================
--- src/SynTree/TypeSubstitution.h	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/TypeSubstitution.h	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -61,5 +61,5 @@
 	TypeSubstitution * acceptMutator( Mutator & mutator );
 
-	void print( std::ostream &os, int indent = 0 ) const;
+	void print( std::ostream &os, Indenter indent = {} ) const;
 	TypeSubstitution *clone() const { return new TypeSubstitution( *this ); }
   private:
Index: src/SynTree/TypeofType.cc
===================================================================
--- src/SynTree/TypeofType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/TypeofType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// TypeofType.cc -- 
+// TypeofType.cc --
 //
 // Author           : Richard C. Bilson
@@ -33,5 +33,5 @@
 }
 
-void TypeofType::print( std::ostream &os, int indent ) const {
+void TypeofType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	os << "type-of expression ";
Index: src/SynTree/VarArgsType.cc
===================================================================
--- src/SynTree/VarArgsType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/VarArgsType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -25,5 +25,5 @@
 VarArgsType::VarArgsType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
 
-void VarArgsType::print( std::ostream &os, int indent ) const {
+void VarArgsType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	os << "builtin var args pack";
Index: src/SynTree/VoidType.cc
===================================================================
--- src/SynTree/VoidType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/VoidType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// VoidType.cc -- 
+// VoidType.cc --
 //
 // Author           : Richard C. Bilson
@@ -24,5 +24,5 @@
 }
 
-void VoidType::print( std::ostream &os, int indent ) const {
+void VoidType::print( std::ostream &os, Indenter indent ) const {
 	Type::print( os, indent );
 	os << "void ";
Index: src/SynTree/ZeroOneType.cc
===================================================================
--- src/SynTree/ZeroOneType.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/SynTree/ZeroOneType.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -25,5 +25,5 @@
 ZeroType::ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
 
-void ZeroType::print( std::ostream &os, __attribute__((unused)) int indent ) const {
+void ZeroType::print( std::ostream &os, Indenter ) const {
 	os << "zero_t";
 }
@@ -33,5 +33,5 @@
 OneType::OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes ) : Type( tq, attributes ) {}
 
-void OneType::print( std::ostream &os, __attribute__((unused)) int indent ) const {
+void OneType::print( std::ostream &os, Indenter ) const {
 	os << "one_t";
 }
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/Tuples/TupleAssignment.cc	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -84,5 +84,5 @@
 	bool isTuple( Expression *expr ) {
 		if ( ! expr ) return false;
-		assert( expr->has_result() );
+		assert( expr->result );
 		return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
 	}
@@ -238,5 +238,5 @@
 
 	ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) {
-		assert( expr->has_result() && ! expr->get_result()->isVoid() );
+		assert( expr->result && ! expr->get_result()->isVoid() );
 		ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
 		// if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
Index: src/libcfa/concurrency/monitor
===================================================================
--- src/libcfa/concurrency/monitor	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/libcfa/concurrency/monitor	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -88,4 +88,8 @@
 };
 
+void ?{}(__condition_node_t & this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info );
+void ?{}(__condition_criterion_t & this );
+void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner );
+
 void ?{}( __condition_blocked_queue_t & );
 void append( __condition_blocked_queue_t *, __condition_node_t * );
Index: src/tests/.expect/castError.txt
===================================================================
--- src/tests/.expect/castError.txt	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/tests/.expect/castError.txt	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -1,40 +1,36 @@
-castError.c:7:1 error: Cannot choose between 3 alternatives for expression Cast of:
+castError.c:7:1 error: Cannot choose between 3 alternatives for expression
+Cast of:
   Name: f
+... to:
+  charAlternatives are:
+Cost ( 1, 0, 0, 0 ): Cast of:
+     Variable Expression: f: function
+       accepting unspecified arguments
+     ... returning nothing 
 
-to:
-  char
-Alternatives are:        Cost ( 1, 0, 0, 0 ): Cast of:
-          Variable Expression: f: function
-                accepting unspecified arguments
-              returning 
-                nothing 
+   ... to:
+     char
+ (types:
+   char
+ )
+ Environment: 
+
+Cost ( 1, 0, 0, 0 ): Cast of:
+     Variable Expression: f: signed int
+   ... to:
+     char
+ (types:
+   char
+ )
+ Environment: 
+
+Cost ( 1, 0, 0, 0 ): Cast of:
+     Variable Expression: f: double
+   ... to:
+     char
+ (types:
+   char
+ )
+ Environment: 
 
 
-        to:
-          char
-(types:
-            char
-)
-        Environment: 
-
-        Cost ( 1, 0, 0, 0 ): Cast of:
-          Variable Expression: f: signed int
-
-        to:
-          char
-(types:
-            char
-)
-        Environment: 
-
-        Cost ( 1, 0, 0, 0 ): Cast of:
-          Variable Expression: f: double
-
-        to:
-          char
-(types:
-            char
-)
-        Environment: 
-
-
Index: src/tests/.expect/references.txt
===================================================================
--- src/tests/.expect/references.txt	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
+++ src/tests/.expect/references.txt	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -0,0 +1,11 @@
+3 3 1
+12 12 1
+12 12 1 1
+Default constructing a Y
+Copy constructing a Y
+Copy constructing a Y
+Copy constructing a Y
+Destructing a Y
+Destructing a Y
+Destructing a Y
+Destructing a Y
Index: src/tests/.expect/scopeErrors.txt
===================================================================
--- src/tests/.expect/scopeErrors.txt	(revision 36287658877ad4515daf7a0416e24dbc3b1fa9ce)
+++ src/tests/.expect/scopeErrors.txt	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -1,10 +1,12 @@
 scopeErrors.c:2:1 error: duplicate object definition for thisIsAnError: signed int
 scopeErrors.c:20:1 error: duplicate function definition for butThisIsAnError: function
-  with parameters
-    double
-  returning 
-    _retval_butThisIsAnError:       Attribute with name: unused
-double
-  with body 
-    CompoundStmt
+... with parameters
+  double
+... returning 
+  _retval_butThisIsAnError: double
+  ... with attributes: 
+    Attribute with name: unused
 
+... with body 
+  CompoundStmt
+
Index: src/tests/references.c
===================================================================
--- src/tests/references.c	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
+++ src/tests/references.c	(revision b7778c1cd7cf62cf31c36b436f009461a44b2e07)
@@ -0,0 +1,63 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// references.c --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Aug 23 16:11:50 2017
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Aug 23 16:12:03
+// Update Count     : 2
+//
+
+struct Y { int i; };
+void ?{}(Y & y) { printf("Default constructing a Y\n"); }
+void ?{}(Y & y, Y other) { printf("Copy constructing a Y\n"); }
+void ^?{}(Y & y) { printf("Destructing a Y\n"); }
+Y ?=?(Y & y, Y other) { printf("Assigning a Y\n"); return y; }
+
+struct X { Y & r; Y y; };
+void ?{}(X & x) {
+	// ensure that r is not implicitly constructed
+}
+void ?{}(X & x, X other) {
+	// ensure that r is not implicitly constructed
+}
+void ^?{}(X & x) {
+	// ensure that r is not implicitly destructed
+}
+X ?=?(X & x, X other) { return x; }
+
+// test user-defined reference-returning function
+int & toref( int * p ) { return *p; }
+// test user-defined reference-parameter function
+int * toptr( int & r ) { return &r; }
+
+int main() {
+	int x = 123456, *p1 = &x, **p2 = &p1, ***p3 = &p2,
+		&r1 = x,    &&r2 = r1,   &&&r3 = r2;
+	***p3 = 3;                          // change x
+	**p3 = &x;                          // change p1
+	*p3 = &p1;                          // change p2
+	int y, z, & ar[3] = { x, y, z };    // initialize array of references
+
+	// test that basic reference properties are true - r1 should be an alias for x
+	printf("%d %d %d\n", x, r1, &x == &r1);
+	r1 = 12;
+	printf("%d %d %d\n", x, r1, &x == &r1);
+
+	// test that functions using basic references work
+	printf("%d %d %d %d\n", toref(&x), toref(p1), toptr(r1) == toptr(x), toptr(r1) == &x);
+
+	// test that reference members are not implicitly constructed/destructed/assigned
+	X x1, x2 = x1;
+	x1 = x2;
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// End: //
+
