Index: src/AST/Attribute.hpp
===================================================================
--- src/AST/Attribute.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Attribute.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -50,16 +50,7 @@
 	/// Must be copied in ALL derived classes
 	template<typename node_t>
-	friend auto mutate(const node_t * node);
+	friend node_t * mutate(const node_t * node);
 };
 
-
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Attribute * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Attribute * node, Node::ref_type ref ) { node->decrement( ref ); }
 }
 
Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Convert.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -9,7 +9,7 @@
 // Author           : Thierry Delisle
 // Created On       : Thu May 09 15::37::05 2019
-// Last Modified By :
-// Last Modified On :
-// Update Count     :
+// Last Modified By : Andrew Beach
+// Last Modified On : Thu May 16 17:21:00 2019
+// Update Count     : 1
 //
 
@@ -74,19 +74,50 @@
 	ast::Node * node;
 
+	// Local Utilities:
+
+	template<typename NewT, typename OldT>
+	NewT * getAccept1( OldT old ) {
+		old->accept(*this);
+		return strict_dynamic_cast< NewT * >( node );
+	}
+
+#	define GET_ACCEPT_1(child, type) \
+		getAccept1< ast::type, decltype( old->child ) >( old->child )
+
+	template<typename NewT, typename OldC>
+	std::vector< ast::ptr<NewT> > getAcceptV( OldC& old ) {
+		std::vector< ast::ptr<NewT> > ret;
+		ret.reserve( old.size() );
+		for ( auto a : old ) {
+			a->accept( *this );
+			ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
+		}
+		return ret;
+	}
+
+#	define GET_ACCEPT_V(child, type) \
+		getAcceptV< ast::type, decltype( old->child ) >( old->child )
+
+	ast::Label make_label(Label* old) {
+		return ast::Label(
+			old->labelled->location,
+			old->name,
+			GET_ACCEPT_V(attributes, Attribute)
+		);
+	}
+
 	template<template <class...> class C>
 	C<ast::Label> make_labels(C<Label> olds) {
 		C<ast::Label> ret;
-		for(auto oldn : olds) {
-			auto old = &oldn; // to reuse the MACRO
-			ACCEPT_N(attr, attributes, Attribute)
-			ast::Label l(
-				{},
-				old->get_name(),
-				to<std::vector>::from( std::move( attr ) )
-			);
-			ret.push_back( l );
+		for (auto oldn : olds) {
+			ret.push_back( make_label( &oldn ) );
 		}
 		return ret;
 	}
+
+#	define GET_LABELS_V(labels) \
+		to<std::vector>::from( make_labels( std::move( labels ) ) )
+
+	// Now all the visit functions:
 
 	virtual void visit( ObjectDecl * old ) override final {
@@ -135,5 +166,5 @@
 		decl->parent = parent;
 		decl->body   = old->body;
-		decl->parameters = params;
+		decl->params = params;
 		decl->members    = members;
 		decl->extension  = old->extension;
@@ -158,5 +189,5 @@
 		decl->parent = parent;
 		decl->body   = old->body;
-		decl->parameters = params;
+		decl->params = params;
 		decl->members    = members;
 		decl->extension  = old->extension;
@@ -181,5 +212,5 @@
 		decl->parent = parent;
 		decl->body   = old->body;
-		decl->parameters = params;
+		decl->params = params;
 		decl->members    = members;
 		decl->extension  = old->extension;
@@ -204,5 +235,5 @@
 		decl->parent = parent;
 		decl->body   = old->body;
-		decl->parameters = params;
+		decl->params = params;
 		decl->members    = members;
 		decl->extension  = old->extension;
@@ -230,5 +261,5 @@
 
 		decl->assertions = asserts;
-		decl->parameters = params;
+		decl->params     = params;
 		decl->extension  = old->extension;
 		decl->uniqueId   = old->uniqueId;
@@ -258,89 +289,244 @@
 
 	virtual void visit( ExprStmt * old ) override final {
-		ACCEPT_1(expr, expr, Expr)
-		auto stmt = new ast::ExprStmt(
-			old->location,
-			expr
-		);
-		stmt->labels = to<std::vector>::from( make_labels( std::move( old->labels ) ) );
+		this->node = new ast::ExprStmt(
+			old->location,
+			GET_ACCEPT_1(expr, Expr),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( AsmStmt * old ) override final {
+		this->node = new ast::AsmStmt(
+			old->location,
+			old->voltile,
+			GET_ACCEPT_1(instruction, Expr),
+			GET_ACCEPT_V(output, Expr),
+			GET_ACCEPT_V(input, Expr),
+			GET_ACCEPT_V(clobber, ConstantExpr),
+			GET_LABELS_V(old->gotolabels),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( DirectiveStmt * old ) override final {
+		this->node = new ast::DirectiveStmt(
+			old->location,
+			old->directive,
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( IfStmt * old ) override final {
+		this->node = new ast::IfStmt(
+			old->location,
+			GET_ACCEPT_1(condition, Expr),
+			GET_ACCEPT_1(thenPart, Stmt),
+			GET_ACCEPT_1(elsePart, Stmt),
+			GET_ACCEPT_V(initialization, Stmt),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( SwitchStmt * old ) override final {
+		this->node = new ast::SwitchStmt(
+			old->location,
+			GET_ACCEPT_1(condition, Expr),
+			GET_ACCEPT_V(statements, Stmt),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( CaseStmt * old ) override final {
+		this->node = new ast::CaseStmt(
+			old->location,
+			GET_ACCEPT_1(condition, Expr),
+			GET_ACCEPT_V(stmts, Stmt),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( WhileStmt * old ) override final {
+		this->node = new ast::WhileStmt(
+			old->location,
+			GET_ACCEPT_1(condition, Expr),
+			GET_ACCEPT_1(body, Stmt),
+			GET_ACCEPT_V(initialization, Stmt),
+			old->isDoWhile,
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( ForStmt * old ) override final {
+		this->node = new ast::ForStmt(
+			old->location,
+			GET_ACCEPT_V(initialization, Stmt),
+			GET_ACCEPT_1(condition, Expr),
+			GET_ACCEPT_1(increment, Expr),
+			GET_ACCEPT_1(body, Stmt),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( BranchStmt * old ) override final {
+		if (old->computedTarget) {
+			this->node = new ast::BranchStmt(
+				old->location,
+				GET_ACCEPT_1(computedTarget, Expr),
+				GET_LABELS_V(old->labels)
+			);
+		} else {
+			ast::BranchStmt::Kind kind;
+			switch (old->type) {
+			#define CASE(n) \
+			case BranchStmt::n: \
+				kind = ast::BranchStmt::n; \
+				break
+			CASE(Goto);
+			CASE(Break);
+			CASE(Continue);
+			CASE(FallThrough);
+			CASE(FallThroughDefault);
+			#undef CASE
+			}
+
+			Label label = old->originalTarget;
+			auto stmt = new ast::BranchStmt(
+				old->location,
+				kind,
+				make_label(&label),
+				GET_LABELS_V(old->labels)
+			);
+			stmt->target = make_label(&old->target);
+			this->node = stmt;
+		}
+	}
+
+	virtual void visit( ReturnStmt * old ) override final {
+		this->node = new ast::ReturnStmt(
+			old->location,
+			GET_ACCEPT_1(expr, Expr),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( ThrowStmt * old ) override final {
+		ast::ThrowStmt::Kind kind;
+		switch (old->kind) {
+		case ThrowStmt::Terminate:
+			kind = ast::ThrowStmt::Terminate;
+			break;
+		case ThrowStmt::Resume:
+			kind = ast::ThrowStmt::Resume;
+			break;
+		}
+
+		this->node = new ast::ThrowStmt(
+			old->location,
+			kind,
+			GET_ACCEPT_1(expr, Expr),
+			GET_ACCEPT_1(target, Expr),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( TryStmt * old ) override final {
+		this->node = new ast::TryStmt(
+			old->location,
+			GET_ACCEPT_1(block, CompoundStmt),
+			GET_ACCEPT_V(handlers, CatchStmt),
+			GET_ACCEPT_1(finallyBlock, FinallyStmt),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( CatchStmt * old ) override final {
+		ast::CatchStmt::Kind kind;
+		switch (old->kind) {
+		case CatchStmt::Terminate:
+			kind = ast::CatchStmt::Terminate;
+			break;
+		case CatchStmt::Resume:
+			kind = ast::CatchStmt::Resume;
+			break;
+		}
+
+		this->node = new ast::CatchStmt(
+			old->location,
+			kind,
+			GET_ACCEPT_1(decl, Decl),
+			GET_ACCEPT_1(cond, Expr),
+			GET_ACCEPT_1(body, Stmt),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( FinallyStmt * old ) override final {
+		this->node = new ast::FinallyStmt(
+			old->location,
+			GET_ACCEPT_1(block, CompoundStmt),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( WaitForStmt * old ) override final {
+		ast::WaitForStmt * stmt = new ast::WaitForStmt(
+			old->location,
+			GET_LABELS_V(old->labels)
+		);
+
+		stmt->clauses.reserve( old->clauses.size() );
+		for (size_t i = 0 ; i < old->clauses.size() ; ++i) {
+			stmt->clauses.push_back({
+				ast::WaitForStmt::Target{
+					GET_ACCEPT_1(clauses[i].target.function, Expr),
+					GET_ACCEPT_V(clauses[i].target.arguments, Expr)
+				},
+				GET_ACCEPT_1(clauses[i].statement, Stmt),
+				GET_ACCEPT_1(clauses[i].condition, Expr)
+			});
+		}
+		stmt->timeout = {
+			GET_ACCEPT_1(timeout.time, Expr),
+			GET_ACCEPT_1(timeout.statement, Stmt),
+			GET_ACCEPT_1(timeout.condition, Expr),
+		};
+		stmt->orElse = {
+			GET_ACCEPT_1(timeout.statement, Stmt),
+			GET_ACCEPT_1(timeout.condition, Expr),
+		};
 
 		this->node = stmt;
 	}
 
-	virtual void visit( AsmStmt * ) override final {
-
-	}
-
-	virtual void visit( DirectiveStmt * ) override final {
-
-	}
-
-	virtual void visit( IfStmt * ) override final {
-
-	}
-
-	virtual void visit( WhileStmt * ) override final {
-
-	}
-
-	virtual void visit( ForStmt * ) override final {
-
-	}
-
-	virtual void visit( SwitchStmt * ) override final {
-
-	}
-
-	virtual void visit( CaseStmt * ) override final {
-
-	}
-
-	virtual void visit( BranchStmt * ) override final {
-
-	}
-
-	virtual void visit( ReturnStmt * ) override final {
-
-	}
-
-	virtual void visit( ThrowStmt * ) override final {
-
-	}
-
-	virtual void visit( TryStmt * ) override final {
-
-	}
-
-	virtual void visit( CatchStmt * ) override final {
-
-	}
-
-	virtual void visit( FinallyStmt * ) override final {
-
-	}
-
-	virtual void visit( WaitForStmt * ) override final {
-
-	}
-
-	virtual void visit( WithStmt * ) override final {
-
+	virtual void visit( WithStmt * old ) override final {
+		this->node = new ast::WithStmt(
+			old->location,
+			GET_ACCEPT_V(exprs, Expr),
+			GET_ACCEPT_1(stmt, Stmt),
+			GET_LABELS_V(old->labels)
+		);
 	}
 
 	virtual void visit( NullStmt * old ) override final {
-		auto stmt = new ast::NullStmt(
-			old->location,
-			to<std::vector>::from( make_labels( std::move( old->labels ) ) )
-		);
-
-		this->node = stmt;
-	}
-
-	virtual void visit( DeclStmt * ) override final {
-
-	}
-
-	virtual void visit( ImplicitCtorDtorStmt * ) override final {
-
+		this->node = new ast::NullStmt(
+			old->location,
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( DeclStmt * old ) override final {
+		this->node = new ast::DeclStmt(
+			old->location,
+			GET_ACCEPT_1(decl, Decl),
+			GET_LABELS_V(old->labels)
+		);
+	}
+
+	virtual void visit( ImplicitCtorDtorStmt * old ) override final {
+		this->node = new ast::ImplicitCtorDtorStmt(
+			old->location,
+			GET_ACCEPT_1(callStmt, Stmt),
+			GET_LABELS_V(old->labels)
+		);
 	}
 
@@ -592,5 +778,14 @@
 
 	}
+
+	virtual void visit( AttrExpr * ) override final {
+
+		assert( 0 );
+	}
 };
+
+#undef GET_LABELS_V
+#undef GET_ACCEPT_V
+#undef GET_ACCEPT_1
 
 #undef ACCEPT_N
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Decl.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -20,7 +20,10 @@
 #include <unordered_map>
 
+#include "Common/utility.h"
+
 #include "Fwd.hpp"             // for UniqueId
 #include "Init.hpp"
 #include "Node.hpp"            // for readonly
+#include "Type.hpp"            // for readonly
 #include "Parser/ParseNode.h"  // for DeclarationNode
 
@@ -47,6 +50,6 @@
 // --- FunctionDecl
 
-const Type * FunctionDecl::get_type() const override { return type.get(); }
-void FunctionDecl::set_type(Type * t) override { type = strict_dynamic_cast< FunctionType* >( t ); }
+const Type * FunctionDecl::get_type() const { return type.get(); }
+void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); }
 
 // --- TypeDecl
@@ -75,5 +78,5 @@
 			const ObjectDecl* field = strict_dynamic_cast< const ObjectDecl* >( member );
 			if ( field->init ) {
-				const SingleInit* init = strict_dynamic_cast< const SingleInit* >( field->init );
+				const SingleInit * init = strict_dynamic_cast< const SingleInit* >( field->init.get() );
 				auto result = eval( init->value );
 				if ( ! result.second ) {
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Decl.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -31,5 +31,5 @@
 
 // Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
 
 namespace ast {
@@ -341,38 +341,4 @@
 };
 
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Decl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class Decl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class DeclWithType * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class DeclWithType * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ObjectDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ObjectDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class FunctionDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class FunctionDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AggregateDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AggregateDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class StructDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class StructDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UnionDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UnionDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class EnumDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class EnumDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TraitDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TraitDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class NamedTypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class NamedTypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TypedefDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TypedefDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AsmDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AsmDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class StaticAssertDecl * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class StaticAssertDecl * node, Node::ref_type ref ) { node->decrement(ref); }
-
 }
 
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Expr.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -32,7 +32,7 @@
 // --- ApplicationExpr
 
-ApplicationExpr::ApplicationExpr( const CodeLocation & loc, const Expr * f, 
-	std::vector<ptr<Expr>> && as ) 
-: Expr( loc ), func( f ), args( std::move(args) ) {
+ApplicationExpr::ApplicationExpr( const CodeLocation & loc, const Expr * f,
+	std::vector<ptr<Expr>> && as )
+: Expr( loc ), func( f ), args( std::move(as) ) {
 	// ensure that `ApplicationExpr` result type is `FuncExpr`
 	const PointerType * pt = strict_dynamic_cast< const PointerType * >( f->result.get() );
@@ -48,6 +48,6 @@
 	assert( arg );
 
-	UntypedExpr * ret = new UntypedExpr{ 
-		loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } } 
+	UntypedExpr * ret = new UntypedExpr{
+		loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
 	};
 	if ( const Type * ty = arg->result ) {
@@ -59,5 +59,5 @@
 			ret->result = new ReferenceType{ base };
 		} else {
-			// references have been removed, in which case dereference returns an lvalue of the 
+			// references have been removed, in which case dereference returns an lvalue of the
 			// base type
 			ret->result.set_and_mutate( base )->set_lvalue( true );
@@ -112,5 +112,5 @@
 		} else {
 			// taking address of non-lvalue, must be a reference, loses one layer of reference
-			if ( const ReferenceType * refType = 
+			if ( const ReferenceType * refType =
 					dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
 				Type * res = addrType( refType->base );
@@ -118,5 +118,5 @@
 				result = res;
 			} else {
-				SemanticError( loc, arg->result, 
+				SemanticError( loc, arg->result,
 					"Attempt to take address of non-lvalue expression: " );
 			}
@@ -128,10 +128,10 @@
 
 // label address always has type `void*`
-LabelAddressExpr::LabelAddressExpr( const CodeLocation & loc, Label && a ) 
+LabelAddressExpr::LabelAddressExpr( const CodeLocation & loc, Label && a )
 : Expr( loc, new PointerType{ new VoidType{} } ), arg( a ) {}
 
 // --- CastExpr
 
-CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g ) 
+CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )
 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
 
@@ -169,5 +169,5 @@
 }
 
-VariableExpr * VariableExpr::functionPointer( 
+VariableExpr * VariableExpr::functionPointer(
 		const CodeLocation & loc, const FunctionDecl * decl ) {
 	// wrap usually-determined result type in a pointer
@@ -202,21 +202,21 @@
 
 ConstantExpr * ConstantExpr::from_bool( const CodeLocation & loc, bool b ) {
-	return new ConstantExpr{ 
+	return new ConstantExpr{
 		loc, new BasicType{ BasicType::Bool }, b ? "1" : "0", (unsigned long long)b };
 }
 
 ConstantExpr * ConstantExpr::from_char( const CodeLocation & loc, char c ) {
-	return new ConstantExpr{ 
+	return new ConstantExpr{
 		loc, new BasicType{ BasicType::Char }, std::to_string( c ), (unsigned long long)c };
 }
 
 ConstantExpr * ConstantExpr::from_int( const CodeLocation & loc, int i ) {
-	return new ConstantExpr{ 
+	return new ConstantExpr{
 		loc, new BasicType{ BasicType::SignedInt }, std::to_string( i ), (unsigned long long)i };
 }
 
 ConstantExpr * ConstantExpr::from_ulong( const CodeLocation & loc, unsigned long i ) {
-	return new ConstantExpr{ 
-		loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ), 
+	return new ConstantExpr{
+		loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ),
 		(unsigned long long)i };
 }
@@ -229,5 +229,5 @@
 	return new ConstantExpr{
 		loc,
-		new ArrayType{ 
+		new ArrayType{
 			new BasicType{ BasicType::Char, CV::Const },
 			ConstantExpr::from_int( loc, s.size() + 1 /* null terminator */ ),
@@ -258,12 +258,4 @@
 : Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), expr( nullptr ), type( t ) {}
 
-// --- UntypedOffsetofExpr
-
-UntypedOffsetofExpr::UntypedOffsetofExpr( 
-	const CodeLocation & loc, const Type * ty, const std::string & mem )
-: Expr( loc, new BasicType{ BasicType::LongUnsignedInt } ), type( ty ), member( mem ) {
-	assert( type );
-}
-
 // --- OffsetofExpr
 
@@ -277,6 +269,6 @@
 
 OffsetPackExpr::OffsetPackExpr( const CodeLocation & loc, const StructInstType * ty )
-: Expr( loc, new ArrayType{ 
-	new BasicType{ BasicType::LongUnsignedInt }, nullptr, FixedLen, DynamicDim } 
+: Expr( loc, new ArrayType{
+	new BasicType{ BasicType::LongUnsignedInt }, nullptr, FixedLen, DynamicDim }
 ), type( ty ) {
 	assert( type );
@@ -285,5 +277,5 @@
 // --- LogicalExpr
 
-LogicalExpr::LogicalExpr( 
+LogicalExpr::LogicalExpr(
 	const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia )
 : Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Expr.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -28,5 +28,5 @@
 
 // Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
 
 namespace ast {
@@ -133,5 +133,5 @@
 };
 
-/// The application of a function to a set of parameters. 
+/// The application of a function to a set of parameters.
 /// Post-resolver form of `UntypedExpr`
 class ApplicationExpr final : public Expr {
@@ -218,5 +218,5 @@
 	GeneratedFlag isGenerated;
 
-	CastExpr( const CodeLocation & loc, const Expr * a, const Type * to, 
+	CastExpr( const CodeLocation & loc, const Expr * a, const Type * to,
 		GeneratedFlag g = GeneratedCast ) : Expr( loc, to ), arg( a ), isGenerated( g ) {}
 	/// Cast-to-void
@@ -311,5 +311,5 @@
 		unsigned long long ival;
 		double dval;
-		
+
 		Val( unsigned long long i ) : ival( i ) {}
 		Val( double d ) : dval( d ) {}
@@ -318,10 +318,10 @@
 	std::string rep;
 
-	ConstantExpr( 
+	ConstantExpr(
 		const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v )
 	: Expr( loc, ty ), val( v ), rep( r ) {}
 	ConstantExpr( const CodeLocation & loc, const Type * ty, const std::string & r, double v )
 	: Expr( loc, ty ), val( v ), rep( r ) {}
-	
+
 	/// Gets the value of this constant as an integer
 	long long int intValue() const;
@@ -464,5 +464,5 @@
 	ptr<Expr> arg2;
 
-	CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 ) 
+	CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
 	: Expr( loc ), arg1( a1 ), arg2( a2 ) {}
 
@@ -754,85 +754,5 @@
 };
 
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Expr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class Expr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ApplicationExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ApplicationExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UntypedExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UntypedExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class NameExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class NameExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AddressExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AddressExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class LabelAddressExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class LabelAddressExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class CastExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class CastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class KeywordCastExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class KeywordCastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class VirtualCastExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class VirtualCastExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class MemberExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class MemberExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UntypedMemberExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UntypedMemberExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class VariableExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class VariableExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ConstantExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ConstantExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class SizeofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class SizeofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AlignofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AlignofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UntypedOffsetofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UntypedOffsetofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class OffsetofExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class OffsetofExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class OffsetPackExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class OffsetPackExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class LogicalExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class LogicalExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ConditionalExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ConditionalExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class CommaExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class CommaExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TypeExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TypeExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class AsmExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class AsmExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ImplicitCopyCtorExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ImplicitCopyCtorExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class ConstructorExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class ConstructorExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class CompoundLiteralExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class CompoundLiteralExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class RangeExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class RangeExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UntypedTupleExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UntypedTupleExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TupleExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TupleExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TupleIndexExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TupleIndexExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class TupleAssignExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class TupleAssignExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class StmtExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class StmtExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UniqueExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UniqueExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class UntypedInitExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class UntypedInitExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class InitExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class InitExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class DeletedExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class DeletedExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class DefaultArgExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class DefaultArgExpr * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class GenericExpr * node, Node::ref_type ref ) { node->increment(ref); }
-inline void decrement( const class GenericExpr * node, Node::ref_type ref ) { node->decrement(ref); }
+
 }
 
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Fwd.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -135,216 +135,4 @@
 std::string toString( const Node * );
 
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void decrement( const class Node * node, Node::ref_type ref ) { node->decrement(ref); }
-inline void increment( const class Node * node, Node::ref_type ref ) { node->increment(ref); }
-inline void increment( const class ParseNode *, Node::ref_type );
-inline void decrement( const class ParseNode *, Node::ref_type );
-inline void increment( const class Decl *, Node::ref_type );
-inline void decrement( const class Decl *, Node::ref_type );
-inline void increment( const class DeclWithType *, Node::ref_type );
-inline void decrement( const class DeclWithType *, Node::ref_type );
-inline void increment( const class ObjectDecl *, Node::ref_type );
-inline void decrement( const class ObjectDecl *, Node::ref_type );
-inline void increment( const class FunctionDecl *, Node::ref_type );
-inline void decrement( const class FunctionDecl *, Node::ref_type );
-inline void increment( const class AggregateDecl *, Node::ref_type );
-inline void decrement( const class AggregateDecl *, Node::ref_type );
-inline void increment( const class StructDecl *, Node::ref_type );
-inline void decrement( const class StructDecl *, Node::ref_type );
-inline void increment( const class UnionDecl *, Node::ref_type );
-inline void decrement( const class UnionDecl *, Node::ref_type );
-inline void increment( const class EnumDecl *, Node::ref_type );
-inline void decrement( const class EnumDecl *, Node::ref_type );
-inline void increment( const class TraitDecl *, Node::ref_type );
-inline void decrement( const class TraitDecl *, Node::ref_type );
-inline void increment( const class NamedTypeDecl *, Node::ref_type );
-inline void decrement( const class NamedTypeDecl *, Node::ref_type );
-inline void increment( const class TypeDecl *, Node::ref_type );
-inline void decrement( const class TypeDecl *, Node::ref_type );
-inline void increment( const class TypedefDecl *, Node::ref_type );
-inline void decrement( const class TypedefDecl *, Node::ref_type );
-inline void increment( const class AsmDecl *, Node::ref_type );
-inline void decrement( const class AsmDecl *, Node::ref_type );
-inline void increment( const class StaticAssertDecl *, Node::ref_type );
-inline void decrement( const class StaticAssertDecl *, Node::ref_type );
-inline void increment( const class Stmt *, Node::ref_type );
-inline void decrement( const class Stmt *, Node::ref_type );
-inline void increment( const class CompoundStmt *, Node::ref_type );
-inline void decrement( const class CompoundStmt *, Node::ref_type );
-inline void increment( const class ExprStmt *, Node::ref_type );
-inline void decrement( const class ExprStmt *, Node::ref_type );
-inline void increment( const class AsmStmt *, Node::ref_type );
-inline void decrement( const class AsmStmt *, Node::ref_type );
-inline void increment( const class DirectiveStmt *, Node::ref_type );
-inline void decrement( const class DirectiveStmt *, Node::ref_type );
-inline void increment( const class IfStmt *, Node::ref_type );
-inline void decrement( const class IfStmt *, Node::ref_type );
-inline void increment( const class WhileStmt *, Node::ref_type );
-inline void decrement( const class WhileStmt *, Node::ref_type );
-inline void increment( const class ForStmt *, Node::ref_type );
-inline void decrement( const class ForStmt *, Node::ref_type );
-inline void increment( const class SwitchStmt *, Node::ref_type );
-inline void decrement( const class SwitchStmt *, Node::ref_type );
-inline void increment( const class CaseStmt *, Node::ref_type );
-inline void decrement( const class CaseStmt *, Node::ref_type );
-inline void increment( const class BranchStmt *, Node::ref_type );
-inline void decrement( const class BranchStmt *, Node::ref_type );
-inline void increment( const class ReturnStmt *, Node::ref_type );
-inline void decrement( const class ReturnStmt *, Node::ref_type );
-inline void increment( const class ThrowStmt *, Node::ref_type );
-inline void decrement( const class ThrowStmt *, Node::ref_type );
-inline void increment( const class TryStmt *, Node::ref_type );
-inline void decrement( const class TryStmt *, Node::ref_type );
-inline void increment( const class CatchStmt *, Node::ref_type );
-inline void decrement( const class CatchStmt *, Node::ref_type );
-inline void increment( const class FinallyStmt *, Node::ref_type );
-inline void decrement( const class FinallyStmt *, Node::ref_type );
-inline void increment( const class WaitForStmt *, Node::ref_type );
-inline void decrement( const class WaitForStmt *, Node::ref_type );
-inline void increment( const class WithStmt *, Node::ref_type );
-inline void decrement( const class WithStmt *, Node::ref_type );
-inline void increment( const class DeclStmt *, Node::ref_type );
-inline void decrement( const class DeclStmt *, Node::ref_type );
-inline void increment( const class NullStmt *, Node::ref_type );
-inline void decrement( const class NullStmt *, Node::ref_type );
-inline void increment( const class ImplicitCtorDtorStmt *, Node::ref_type );
-inline void decrement( const class ImplicitCtorDtorStmt *, Node::ref_type );
-inline void increment( const class Expr *, Node::ref_type );
-inline void decrement( const class Expr *, Node::ref_type );
-inline void increment( const class ApplicationExpr *, Node::ref_type );
-inline void decrement( const class ApplicationExpr *, Node::ref_type );
-inline void increment( const class UntypedExpr *, Node::ref_type );
-inline void decrement( const class UntypedExpr *, Node::ref_type );
-inline void increment( const class NameExpr *, Node::ref_type );
-inline void decrement( const class NameExpr *, Node::ref_type );
-inline void increment( const class AddressExpr *, Node::ref_type );
-inline void decrement( const class AddressExpr *, Node::ref_type );
-inline void increment( const class LabelAddressExpr *, Node::ref_type );
-inline void decrement( const class LabelAddressExpr *, Node::ref_type );
-inline void increment( const class CastExpr *, Node::ref_type );
-inline void decrement( const class CastExpr *, Node::ref_type );
-inline void increment( const class KeywordCastExpr *, Node::ref_type );
-inline void decrement( const class KeywordCastExpr *, Node::ref_type );
-inline void increment( const class VirtualCastExpr *, Node::ref_type );
-inline void decrement( const class VirtualCastExpr *, Node::ref_type );
-inline void increment( const class MemberExpr *, Node::ref_type );
-inline void decrement( const class MemberExpr *, Node::ref_type );
-inline void increment( const class UntypedMemberExpr *, Node::ref_type );
-inline void decrement( const class UntypedMemberExpr *, Node::ref_type );
-inline void increment( const class VariableExpr *, Node::ref_type );
-inline void decrement( const class VariableExpr *, Node::ref_type );
-inline void increment( const class ConstantExpr *, Node::ref_type );
-inline void decrement( const class ConstantExpr *, Node::ref_type );
-inline void increment( const class SizeofExpr *, Node::ref_type );
-inline void decrement( const class SizeofExpr *, Node::ref_type );
-inline void increment( const class AlignofExpr *, Node::ref_type );
-inline void decrement( const class AlignofExpr *, Node::ref_type );
-inline void increment( const class UntypedOffsetofExpr *, Node::ref_type );
-inline void decrement( const class UntypedOffsetofExpr *, Node::ref_type );
-inline void increment( const class OffsetofExpr *, Node::ref_type );
-inline void decrement( const class OffsetofExpr *, Node::ref_type );
-inline void increment( const class OffsetPackExpr *, Node::ref_type );
-inline void decrement( const class OffsetPackExpr *, Node::ref_type );
-inline void increment( const class LogicalExpr *, Node::ref_type );
-inline void decrement( const class LogicalExpr *, Node::ref_type );
-inline void increment( const class ConditionalExpr *, Node::ref_type );
-inline void decrement( const class ConditionalExpr *, Node::ref_type );
-inline void increment( const class CommaExpr *, Node::ref_type );
-inline void decrement( const class CommaExpr *, Node::ref_type );
-inline void increment( const class TypeExpr *, Node::ref_type );
-inline void decrement( const class TypeExpr *, Node::ref_type );
-inline void increment( const class AsmExpr *, Node::ref_type );
-inline void decrement( const class AsmExpr *, Node::ref_type );
-inline void increment( const class ImplicitCopyCtorExpr *, Node::ref_type );
-inline void decrement( const class ImplicitCopyCtorExpr *, Node::ref_type );
-inline void increment( const class ConstructorExpr *, Node::ref_type );
-inline void decrement( const class ConstructorExpr *, Node::ref_type );
-inline void increment( const class CompoundLiteralExpr *, Node::ref_type );
-inline void decrement( const class CompoundLiteralExpr *, Node::ref_type );
-inline void increment( const class RangeExpr *, Node::ref_type );
-inline void decrement( const class RangeExpr *, Node::ref_type );
-inline void increment( const class UntypedTupleExpr *, Node::ref_type );
-inline void decrement( const class UntypedTupleExpr *, Node::ref_type );
-inline void increment( const class TupleExpr *, Node::ref_type );
-inline void decrement( const class TupleExpr *, Node::ref_type );
-inline void increment( const class TupleIndexExpr *, Node::ref_type );
-inline void decrement( const class TupleIndexExpr *, Node::ref_type );
-inline void increment( const class TupleAssignExpr *, Node::ref_type );
-inline void decrement( const class TupleAssignExpr *, Node::ref_type );
-inline void increment( const class StmtExpr *, Node::ref_type );
-inline void decrement( const class StmtExpr *, Node::ref_type );
-inline void increment( const class UniqueExpr *, Node::ref_type );
-inline void decrement( const class UniqueExpr *, Node::ref_type );
-inline void increment( const class UntypedInitExpr *, Node::ref_type );
-inline void decrement( const class UntypedInitExpr *, Node::ref_type );
-inline void increment( const class InitExpr *, Node::ref_type );
-inline void decrement( const class InitExpr *, Node::ref_type );
-inline void increment( const class DeletedExpr *, Node::ref_type );
-inline void decrement( const class DeletedExpr *, Node::ref_type );
-inline void increment( const class DefaultArgExpr *, Node::ref_type );
-inline void decrement( const class DefaultArgExpr *, Node::ref_type );
-inline void increment( const class GenericExpr *, Node::ref_type );
-inline void decrement( const class GenericExpr *, Node::ref_type );
-inline void increment( const class Type *, Node::ref_type );
-inline void decrement( const class Type *, Node::ref_type );
-inline void increment( const class VoidType *, Node::ref_type );
-inline void decrement( const class VoidType *, Node::ref_type );
-inline void increment( const class BasicType *, Node::ref_type );
-inline void decrement( const class BasicType *, Node::ref_type );
-inline void increment( const class PointerType *, Node::ref_type );
-inline void decrement( const class PointerType *, Node::ref_type );
-inline void increment( const class ArrayType *, Node::ref_type );
-inline void decrement( const class ArrayType *, Node::ref_type );
-inline void increment( const class ReferenceType *, Node::ref_type );
-inline void decrement( const class ReferenceType *, Node::ref_type );
-inline void increment( const class QualifiedType *, Node::ref_type );
-inline void decrement( const class QualifiedType *, Node::ref_type );
-inline void increment( const class FunctionType *, Node::ref_type );
-inline void decrement( const class FunctionType *, Node::ref_type );
-inline void increment( const class ReferenceToType *, Node::ref_type );
-inline void decrement( const class ReferenceToType *, Node::ref_type );
-inline void increment( const class StructInstType *, Node::ref_type );
-inline void decrement( const class StructInstType *, Node::ref_type );
-inline void increment( const class UnionInstType *, Node::ref_type );
-inline void decrement( const class UnionInstType *, Node::ref_type );
-inline void increment( const class EnumInstType *, Node::ref_type );
-inline void decrement( const class EnumInstType *, Node::ref_type );
-inline void increment( const class TraitInstType *, Node::ref_type );
-inline void decrement( const class TraitInstType *, Node::ref_type );
-inline void increment( const class TypeInstType *, Node::ref_type );
-inline void decrement( const class TypeInstType *, Node::ref_type );
-inline void increment( const class TupleType *, Node::ref_type );
-inline void decrement( const class TupleType *, Node::ref_type );
-inline void increment( const class TypeofType *, Node::ref_type );
-inline void decrement( const class TypeofType *, Node::ref_type );
-inline void increment( const class VarArgsType *, Node::ref_type );
-inline void decrement( const class VarArgsType *, Node::ref_type );
-inline void increment( const class ZeroType *, Node::ref_type );
-inline void decrement( const class ZeroType *, Node::ref_type );
-inline void increment( const class OneType *, Node::ref_type );
-inline void decrement( const class OneType *, Node::ref_type );
-inline void increment( const class GlobalScopeType *, Node::ref_type );
-inline void decrement( const class GlobalScopeType *, Node::ref_type );
-inline void increment( const class Designation *, Node::ref_type );
-inline void decrement( const class Designation *, Node::ref_type );
-inline void increment( const class Init *, Node::ref_type );
-inline void decrement( const class Init *, Node::ref_type );
-inline void increment( const class SingleInit *, Node::ref_type );
-inline void decrement( const class SingleInit *, Node::ref_type );
-inline void increment( const class ListInit *, Node::ref_type );
-inline void decrement( const class ListInit *, Node::ref_type );
-inline void increment( const class ConstructorInit *, Node::ref_type );
-inline void decrement( const class ConstructorInit *, Node::ref_type );
-inline void increment( const class Constant *, Node::ref_type );
-inline void decrement( const class Constant *, Node::ref_type );
-inline void increment( const class Attribute *, Node::ref_type );
-inline void decrement( const class Attribute *, Node::ref_type );
-inline void increment( const class TypeSubstitution *, Node::ref_type );
-inline void decrement( const class TypeSubstitution *, Node::ref_type );
-
 typedef unsigned int UniqueId;
 
Index: src/AST/Init.cpp
===================================================================
--- src/AST/Init.cpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Init.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -22,8 +22,8 @@
 namespace ast {
 
-ListInit::ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is, 
-	std::vector<ptr<Designation>>&& ds, bool mc)
+ListInit::ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is,
+	std::vector<ptr<Designation>>&& ds, ConstructFlag mc)
 : Init( loc, mc ), initializers( std::move(is) ), designations( std::move(ds) ) {
-	// handle common case where ListInit is created without designations by making an 
+	// handle common case where ListInit is created without designations by making an
 	// equivalent-length empty list
 	if ( designations.empty() ) {
@@ -32,5 +32,5 @@
 		}
 	}
-	
+
 	assertf( initializers.size() == designations.size(), "Created ListInit with mismatching "
 		"initializers (%zd) and designations (%zd)", initializers.size(), designations.size() );
Index: src/AST/Init.hpp
===================================================================
--- src/AST/Init.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Init.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -24,5 +24,5 @@
 
 // Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
 
 namespace ast {
@@ -58,5 +58,5 @@
 	const Init * accept( Visitor& v ) const override = 0;
 private:
-	const Init * clone() const override = 0;
+	Init * clone() const override = 0;
 	MUTATE_FRIEND
 };
@@ -122,18 +122,4 @@
 };
 
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Init * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Init * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class SingleInit * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class SingleInit * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ListInit * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ListInit * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ConstructorInit * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ConstructorInit * node, Node::ref_type ref ) { node->decrement( ref ); }
 }
 
Index: src/AST/LinkageSpec.cpp
===================================================================
--- src/AST/LinkageSpec.cpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/LinkageSpec.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -43,12 +43,12 @@
 
 	std::string name( Spec spec ) {
-		switch ( spec ) {
-		case Intrinsic:  return "intrinsic";
-		case C:          return "C";
-		case Cforall:    return "Cforall";
-		case AutoGen:    return "autogenerated cfa";
-		case Compiler:   return "compiler built-in";
-		case BuiltinCFA: return "cfa built-in";
-		case BuiltinC:   return "c built-in";
+		switch ( spec.val ) {
+		case Intrinsic.val:  return "intrinsic";
+		case C.val:          return "C";
+		case Cforall.val:    return "Cforall";
+		case AutoGen.val:    return "autogenerated cfa";
+		case Compiler.val:   return "compiler built-in";
+		case BuiltinCFA.val: return "cfa built-in";
+		case BuiltinC.val:   return "c built-in";
 		default:         return "<unnamed linkage spec>";
 		}
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
+++ src/AST/Node.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -0,0 +1,234 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Node.hpp --
+//
+// Author           : Thierry Delisle
+// Created On       : Thu May 16 14:16:00 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include "Node.hpp"
+#include "Fwd.hpp"
+#include "Decl.hpp"
+#include "Expr.hpp"
+#include "Stmt.hpp"
+#include "Type.hpp"
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); }
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
+
+template class ast::ptr_base< ast::Node, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Node, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ParseNode, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ParseNode, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Decl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Decl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DeclWithType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DeclWithType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ObjectDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ObjectDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::FunctionDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::FunctionDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AggregateDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AggregateDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::StructDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::StructDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UnionDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UnionDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::EnumDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::EnumDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TraitDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TraitDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::NamedTypeDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::NamedTypeDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypedefDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypedefDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AsmDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AsmDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::StaticAssertDecl, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::StaticAssertDecl, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Stmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Stmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CompoundStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CompoundStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ExprStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ExprStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AsmStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AsmStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DirectiveStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DirectiveStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::IfStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::IfStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::WhileStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::WhileStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ForStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ForStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CaseStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CaseStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ReturnStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ReturnStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ThrowStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ThrowStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CatchStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CatchStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::FinallyStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::FinallyStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DeclStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DeclStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::NullStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::NullStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ImplicitCtorDtorStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ImplicitCtorDtorStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Expr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Expr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ApplicationExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ApplicationExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::NameExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::NameExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AddressExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AddressExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::LabelAddressExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::LabelAddressExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CastExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CastExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::KeywordCastExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::KeywordCastExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::VirtualCastExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::VirtualCastExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::MemberExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::MemberExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedMemberExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedMemberExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::VariableExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::VariableExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ConstantExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ConstantExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::SizeofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::SizeofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AlignofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AlignofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedOffsetofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedOffsetofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::OffsetofExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::OffsetofExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::OffsetPackExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::OffsetPackExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::LogicalExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::LogicalExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ConditionalExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ConditionalExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CommaExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CommaExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::AsmExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::AsmExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ImplicitCopyCtorExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ImplicitCopyCtorExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ConstructorExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ConstructorExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CompoundLiteralExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CompoundLiteralExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::RangeExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::RangeExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedTupleExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedTupleExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TupleExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TupleExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TupleIndexExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TupleIndexExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TupleAssignExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TupleAssignExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::StmtExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::StmtExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UniqueExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UniqueExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UntypedInitExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UntypedInitExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::InitExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::InitExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DeletedExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DeletedExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::DefaultArgExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::DefaultArgExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::GenericExpr, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::GenericExpr, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Type, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Type, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::VoidType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::VoidType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::BasicType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::BasicType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::PointerType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::PointerType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ArrayType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ArrayType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ReferenceType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ReferenceType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::QualifiedType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::QualifiedType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::UnionInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::UnionInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::EnumInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::EnumInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TraitInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TraitInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeInstType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeInstType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TupleType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TupleType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeofType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeofType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::VarArgsType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::VarArgsType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ZeroType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ZeroType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::OneType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::OneType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::GlobalScopeType, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::GlobalScopeType, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Designation, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Designation, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Init, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Init, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::SingleInit, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::SingleInit, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ListInit, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ListInit, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::ConstructorInit, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::ConstructorInit, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Constant, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Constant, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::Attribute, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::Attribute, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::TypeSubstitution, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::TypeSubstitution, ast::Node::ref_type::strong >;
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Node.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -44,5 +44,16 @@
 	};
 
-	inline void increment(ref_type ref) const {
+private:
+	/// Make a copy of this node; should be overridden in subclass with more precise return type
+	virtual Node * clone() const = 0;
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend node_t * mutate(const node_t * node);
+
+	mutable size_t strong_count = 0;
+	mutable size_t weak_count = 0;
+
+	void increment(ref_type ref) const {
 		switch (ref) {
 			case ref_type::strong: strong_count++; break;
@@ -51,5 +62,5 @@
 	}
 
-	inline void decrement(ref_type ref) const {
+	void decrement(ast::Node::ref_type ref) const {
 		switch (ref) {
 			case ref_type::strong: strong_count--; break;
@@ -61,14 +72,7 @@
 		}
 	}
-private:
-	/// Make a copy of this node; should be overridden in subclass with more precise return type
-	virtual const Node * clone() const = 0;
 
-	/// Must be copied in ALL derived classes
-	template<typename node_t>
-	friend auto mutate(const node_t * node);
-
-	mutable size_t strong_count = 0;
-	mutable size_t weak_count = 0;
+	template< typename node_t, enum Node::ref_type ref_t >
+	friend class ptr_base;
 };
 
@@ -76,10 +80,6 @@
 // problems and be able to use auto return
 template<typename node_t>
-auto mutate( const node_t * node ) {
-	assertf(
-		node->strong_count >= 1,
-		"Error: attempting to mutate a node that appears to have been linked"
-	);
-	if (node->strong_count == 1) {
+node_t * mutate( const node_t * node ) {
+	if (node->strong_count <= 1) {
 		return const_cast<node_t *>(node);
 	}
@@ -100,15 +100,15 @@
 public:
 	ptr_base() : node(nullptr) {}
-	ptr_base( const node_t * n ) : node(n) { if( node ) increment(node, ref_t); }
-	~ptr_base() { if( node ) decrement(node, ref_t); }
+	ptr_base( const node_t * n ) : node(n) { if( node ) _inc(node); }
+	~ptr_base() { if( node ) _dec(node); }
 
 	template< enum Node::ref_type o_ref_t >
 	ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
-		if( node ) increment(node, ref_t);
+		if( node ) _inc(node);
 	}
 
 	template< enum Node::ref_type o_ref_t >
 	ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
-		if( node ) increment(node, ref_t);
+		if( node ) _inc(node);
 	}
 
@@ -147,5 +147,5 @@
 		assign( n );
 		// get mutable version of `n`
-		auto r = mutate( node ); 
+		auto r = mutate( node );
 		// re-assign mutable version in case `mutate()` produced a new pointer
 		assign( r );
@@ -157,8 +157,11 @@
 private:
 	void assign( const node_t * other ) {
-		if( other ) increment(other, ref_t);
-		if( node  ) decrement(node , ref_t);
+		if( other ) _inc(other);
+		if( node  ) _dec(node );
 		node = other;
 	}
+
+	void _inc( const node_t * other );
+	void _dec( const node_t * other );
 
 protected:
Index: src/AST/ParseNode.hpp
===================================================================
--- src/AST/ParseNode.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/ParseNode.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -34,14 +34,12 @@
 
 	ParseNode( const ParseNode& o ) = default;
+private:
+	ParseNode * clone() const override = 0;
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend node_t * mutate(const node_t * node);
 };
 
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class ParseNode * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ParseNode * node, Node::ref_type ref ) { node->decrement( ref ); }
 }
 
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Pass.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -133,5 +133,4 @@
 	const ast::Expr *             visit( const ast::OffsetofExpr         * ) override final;
 	const ast::Expr *             visit( const ast::OffsetPackExpr       * ) override final;
-	const ast::Expr *             visit( const ast::AttrExpr             * ) override final;
 	const ast::Expr *             visit( const ast::LogicalExpr          * ) override final;
 	const ast::Expr *             visit( const ast::ConditionalExpr      * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Pass.impl.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -19,4 +19,6 @@
 #include <type_traits>
 #include <unordered_map>
+
+#include "AST/TypeSubstitution.hpp"
 
 #define VISIT_START( node ) \
@@ -462,6 +464,6 @@
 	VISIT({
 		guard_indexer guard { * this };
-		maybe_accept( node, &StructDecl::parameters );
-		maybe_accept( node, &StructDecl::members    );
+		maybe_accept( node, &StructDecl::params  );
+		maybe_accept( node, &StructDecl::members );
 	})
 
@@ -483,6 +485,6 @@
 	VISIT({
 		guard_indexer guard { * this };
-		maybe_accept( node, &UnionDecl::parameters );
-		maybe_accept( node, &UnionDecl::members    );
+		maybe_accept( node, &UnionDecl::params  );
+		maybe_accept( node, &UnionDecl::members );
 	})
 
@@ -502,6 +504,6 @@
 	VISIT(
 		// unlike structs, traits, and unions, enums inject their members into the global scope
-		maybe_accept( node, &EnumDecl::parameters );
-		maybe_accept( node, &EnumDecl::members    );
+		maybe_accept( node, &EnumDecl::params  );
+		maybe_accept( node, &EnumDecl::members );
 	)
 
@@ -517,6 +519,6 @@
 	VISIT({
 		guard_indexer guard { *this };
-		maybe_accept( node, &TraitDecl::parameters );
-		maybe_accept( node, &TraitDecl::members    );
+		maybe_accept( node, &TraitDecl::params  );
+		maybe_accept( node, &TraitDecl::members );
 	})
 
@@ -534,6 +536,6 @@
 	VISIT({
 		guard_indexer guard { *this };
-		maybe_accept( node, &TypeDecl::parameters );
-		maybe_accept( node, &TypeDecl::base       );
+		maybe_accept( node, &TypeDecl::params );
+		maybe_accept( node, &TypeDecl::base   );
 	})
 
@@ -563,6 +565,6 @@
 	VISIT({
 		guard_indexer guard { *this };
-		maybe_accept( node, &TypedefDecl::parameters );
-		maybe_accept( node, &TypedefDecl::base       );
+		maybe_accept( node, &TypedefDecl::params );
+		maybe_accept( node, &TypedefDecl::base   );
 	})
 
@@ -688,4 +690,100 @@
 		maybe_accept( node, &WhileStmt::body  );
 	})
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// ForStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ForStmt * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		// for statements introduce a level of scope (for the initialization)
+		guard_indexer guard { *this };
+		maybe_accept( node, &ForStmt::inits );
+		maybe_accept( node, &ForStmt::cond  );
+		maybe_accept( node, &ForStmt::inc   );
+		maybe_accept( node, &ForStmt::body  );
+	})
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// SwitchStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SwitchStmt * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &SwitchStmt::cond  );
+		maybe_accept( node, &SwitchStmt::stmts );
+	)
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// CaseStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CaseStmt * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &CaseStmt::cond  );
+		maybe_accept( node, &CaseStmt::stmts );
+	)
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// BranchStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::BranchStmt * node ) {
+	VISIT_START( node );
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// ReturnStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ReturnStmt * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &ReturnStmt::expr );
+	)
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// ThrowStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ThrowStmt * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &ThrowStmt::expr   );
+		maybe_accept( node, &ThrowStmt::target );
+	)
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// TryStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::TryStmt * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &TryStmt::body     );
+		maybe_accept( node, &TryStmt::handlers );
+		maybe_accept( node, &TryStmt::finally  );
+	)
 
 	VISIT_END( Stmt, node );
Index: src/AST/Pass.proto.hpp
===================================================================
--- src/AST/Pass.proto.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Pass.proto.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -247,5 +247,5 @@
 		static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
 			ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
-			fwd->parameters = decl->parameters;
+			fwd->params = decl->params;
 			pass.indexer.addStruct( fwd );
 		}
@@ -257,5 +257,5 @@
 		static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
 			UnionDecl * fwd = new UnionDecl( decl->location, decl->name );
-			fwd->parameters = decl->parameters;
+			fwd->params = decl->params;
 			pass.indexer.addUnion( fwd );
 		}
Index: src/AST/Stmt.cpp
===================================================================
--- src/AST/Stmt.cpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Stmt.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -26,5 +26,5 @@
 
 // --- BranchStmt
-BranchStmt( const CodeLocation& loc, Kind kind, Label target, std::vector<Label>&& labels )
+BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, std::vector<Label>&& labels )
 : Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {
 	// Make sure a syntax error hasn't slipped through.
@@ -34,5 +34,5 @@
 const char * BranchStmt::kindNames[] = {
     "Goto", "Break", "Continue", "FallThrough", "FallThroughDefault"
-}
+};
 
 }
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Stmt.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -10,6 +10,6 @@
 // Created On       : Wed May  8 13:00:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Wed May 15 16:01:00 2019
-// Update Count     : 2
+// Last Modified On : Wed May 16 12:20:00 2019
+// Update Count     : 3
 //
 
@@ -27,5 +27,5 @@
 
 // Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
 
 namespace ast {
@@ -86,5 +86,6 @@
 	ptr<Expr> expr;
 
-	ExprStmt( const CodeLocation & loc, const Expr * e ) : Stmt(loc), expr(e) {}
+	ExprStmt( const CodeLocation& loc, const Expr* e, std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), expr(e) {}
 
 	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
@@ -404,52 +405,4 @@
 };
 
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Stmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Stmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class CompoundStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class CompoundStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ExprStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ExprStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class NullStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class NullStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-
 }
 
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Type.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -42,5 +42,5 @@
 	const Type * t;
 	const ReferenceType * r;
-	for ( t = this; (r = dynamic_cast<const ReferenceType *>() ); t = r->base );
+	for ( t = this; (r = dynamic_cast<const ReferenceType *>(t) ); t = r->base );
 	return t;
 }
@@ -103,5 +103,5 @@
 
 bool FunctionType::isTtype() const {
-	return containsTtype( returnVals ) || containsTtype( parameters );
+	return containsTtype( returns ) || containsTtype( params );
 }
 
@@ -109,5 +109,5 @@
 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
 	assertf( aggr(), "Must have aggregate to perform lookup" );
-	
+
 	std::vector<readonly<Decl>> found;
 	for ( const Decl * decl : aggr()->members ) {
@@ -119,6 +119,6 @@
 // --- StructInstType
 
-StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q = {}, 
-	std::vector<ptr<Attribute>>&& as = {} )
+StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
+	std::vector<ptr<Attribute>>&& as )
 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
 
@@ -127,6 +127,6 @@
 // --- UnionInstType
 
-UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q = {}, 
-	std::vector<ptr<Attribute>>&& as = {} )
+UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
+	std::vector<ptr<Attribute>>&& as )
 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
 
@@ -135,6 +135,6 @@
 // --- EnumInstType
 
-EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q = {}, 
-	std::vector<ptr<Attribute>>&& as = {} )
+EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
+	std::vector<ptr<Attribute>>&& as )
 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
 
@@ -152,21 +152,21 @@
 // --- TupleType
 
-TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} )
+TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
 : Type( q ), types( std::move(ts) ), members() {
-	// This constructor is awkward. `TupleType` needs to contain objects so that members can be 
-	// named, but members without initializer nodes end up getting constructors, which breaks 
-	// things. This happens because the object decls have to be visited so that their types are 
-	// kept in sync with the types listed here. Ultimately, the types listed here should perhaps 
-	// be eliminated and replaced with a list-view over members. The temporary solution is to 
-	// make a `ListInit` with `maybeConstructed = false`, so when the object is visited it is not 
+	// This constructor is awkward. `TupleType` needs to contain objects so that members can be
+	// named, but members without initializer nodes end up getting constructors, which breaks
+	// things. This happens because the object decls have to be visited so that their types are
+	// kept in sync with the types listed here. Ultimately, the types listed here should perhaps
+	// be eliminated and replaced with a list-view over members. The temporary solution is to
+	// make a `ListInit` with `maybeConstructed = false`, so when the object is visited it is not
 	// constructed. Potential better solutions include:
-	//   a) Separate `TupleType` from its declarations, into `TupleDecl` and `Tuple{Inst?}Type`, 
+	//   a) Separate `TupleType` from its declarations, into `TupleDecl` and `Tuple{Inst?}Type`,
 	//      similar to the aggregate types.
-	//   b) Separate initializer nodes better, e.g. add a `MaybeConstructed` node that is replaced 
+	//   b) Separate initializer nodes better, e.g. add a `MaybeConstructed` node that is replaced
 	//      by `genInit`, rather than the current boolean flag.
 	members.reserve( types.size() );
 	for ( const Type * ty : types ) {
 		members.emplace_back( new ObjectDecl{
-			CodeLocation{}, "", ty, new ListInit( CodeLocation{}, {}, {}, MaybeConstruct ), 
+			CodeLocation{}, "", ty, new ListInit( CodeLocation{}, {}, {}, MaybeConstruct ),
 			Storage::Classes{}, Linkage::Cforall } );
 	}
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/Type.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -30,5 +30,5 @@
 
 // Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND template<typename node_t> friend auto mutate(const node_t * node);
+#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
 
 namespace ast {
@@ -37,5 +37,5 @@
 public:
 	CV::Qualifiers qualifiers;
-	
+
 	Type( CV::Qualifiers q = {} ) : qualifiers(q) {}
 
@@ -80,5 +80,5 @@
 public:
 	VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
-	
+
 	unsigned size() const override { return 0; }
 	bool isVoid() const override { return true; }
@@ -171,5 +171,5 @@
 
 	PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
-	PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s, 
+	PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
 		CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
 
@@ -193,5 +193,5 @@
 	DimensionFlag isStatic;
 
-	ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s, 
+	ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
 		CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
 
@@ -233,5 +233,5 @@
 	ptr<Type> child;
 
-	QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} ) 
+	QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
 	: Type(q), parent(p), child(c) {}
 
@@ -249,5 +249,5 @@
 	ForallList forall;
 
-	ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {} ) 
+	ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {} )
 	: Type(q), forall(std::move(fs)) {}
 	ParameterizedType( CV::Qualifiers q ) : Type(q), forall() {}
@@ -267,5 +267,5 @@
 	std::vector<ptr<DeclWithType>> params;
 
-	/// Does the function accept a variable number of arguments following the arguments specified 
+	/// Does the function accept a variable number of arguments following the arguments specified
 	/// in the parameters list.
 	/// This could be because of
@@ -296,5 +296,5 @@
 	bool hoistType = false;
 
-	ReferenceToType( const std::string& n, CV::Qualifiers q = {}, 
+	ReferenceToType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ParameterizedType(q), params(), attributes(std::move(as)), name(n) {}
@@ -319,10 +319,10 @@
 	readonly<StructDecl> base;
 
-	StructInstType( const std::string& n, CV::Qualifiers q = {}, 
+	StructInstType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base() {}
-	StructInstType( const StructDecl * b, CV::Qualifiers q = {}, 
+	StructInstType( const StructDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} );
-	
+
 	bool isComplete() const override;
 
@@ -342,10 +342,10 @@
 	readonly<UnionDecl> base;
 
-	UnionInstType( const std::string& n, CV::Qualifiers q = {}, 
+	UnionInstType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base() {}
-	UnionInstType( const UnionDecl * b, CV::Qualifiers q = {}, 
+	UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} );
-	
+
 	bool isComplete() const override;
 
@@ -365,10 +365,10 @@
 	readonly<EnumDecl> base;
 
-	EnumInstType( const std::string& n, CV::Qualifiers q = {}, 
+	EnumInstType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base() {}
-	EnumInstType( const EnumDecl * b, CV::Qualifiers q = {}, 
+	EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} );
-	
+
 	bool isComplete() const override;
 
@@ -388,10 +388,10 @@
 	readonly<TraitDecl> base;
 
-	TraitInstType( const std::string& n, CV::Qualifiers q = {}, 
+	TraitInstType( const std::string& n, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base() {}
-	TraitInstType( const TraitDecl * b, CV::Qualifiers q = {}, 
+	TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} );
-	
+
 	// not meaningful for TraitInstType
 	bool isComplete() const override { assert(false); }
@@ -413,8 +413,8 @@
 	TypeVar::Kind kind;
 
-	TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 
+	TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
-	TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {}, 
+	TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
 	: ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
@@ -448,9 +448,9 @@
 	iterator begin() const { return types.begin(); }
 	iterator end() const { return types.end(); }
-	
+
 	unsigned size() const override { return types.size(); }
 
 	const Type * getComponent( unsigned i ) override {
-		assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", 
+		assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
 			i, size() );
 		return *(begin()+i);
@@ -469,5 +469,5 @@
 	enum Kind { Typeof, Basetypeof } kind;
 
-	TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} ) 
+	TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
 	: Type(q), expr(e), kind(k) {}
 
@@ -482,5 +482,5 @@
 public:
 	VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
-	
+
 	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
@@ -493,5 +493,5 @@
 public:
 	ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
-	
+
 	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
@@ -521,50 +521,4 @@
 	MUTATE_FRIEND
 };
-
-//=================================================================================================
-/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
-/// remove only if there is a better solution.
-/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
-/// forward declarations
-inline void increment( const class Type * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class Type * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class VoidType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class VoidType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class BasicType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class BasicType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class PointerType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class PointerType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ArrayType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ArrayType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ReferenceType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ReferenceType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class QualifiedType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class QualifiedType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class FunctionType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class FunctionType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ReferenceToType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ReferenceToType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class StructInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class StructInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class UnionInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class UnionInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class EnumInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class EnumInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TraitInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TraitInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TypeInstType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TypeInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TupleType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TupleType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class ZeroType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class ZeroType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class OneType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class OneType * node, Node::ref_type ref ) { node->decrement( ref ); }
-inline void increment( const class GlobalScopeType * node, Node::ref_type ref ) { node->increment( ref ); }
-inline void decrement( const class GlobalScopeType * node, Node::ref_type ref ) { node->decrement( ref ); }
 
 }
Index: src/AST/TypeSubstitution.cpp
===================================================================
--- src/AST/TypeSubstitution.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
+++ src/AST/TypeSubstitution.cpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -0,0 +1,221 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// TypeSubstitution.cc --
+//
+// Author           : Richard C. Bilson
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Thu Mar 16 15:54:35 2017
+// Update Count     : 4
+//
+
+#include "Type.hpp"   // for TypeInstType, Type, StructInstType, UnionInstType
+#include "TypeSubstitution.hpp"
+
+namespace ast {
+
+TypeSubstitution::TypeSubstitution() {
+}
+
+TypeSubstitution::TypeSubstitution( const TypeSubstitution &other ) : Node() {
+	initialize( other, *this );
+}
+
+TypeSubstitution::~TypeSubstitution() {
+	for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
+		delete( i->second );
+	}
+	for ( VarEnvType::iterator i = varEnv.begin(); i != varEnv.end(); ++i ) {
+		delete( i->second );
+	}
+}
+
+TypeSubstitution &TypeSubstitution::operator=( const TypeSubstitution &other ) {
+	if ( this == &other ) return *this;
+	initialize( other, *this );
+	return *this;
+}
+
+void TypeSubstitution::initialize( const TypeSubstitution &src, TypeSubstitution &dest ) {
+	dest.typeEnv.clear();
+	dest.varEnv.clear();
+	dest.add( src );
+}
+
+void TypeSubstitution::add( const TypeSubstitution &other ) {
+	for ( TypeEnvType::const_iterator i = other.typeEnv.begin(); i != other.typeEnv.end(); ++i ) {
+		typeEnv[ i->first ] = i->second;
+	} // for
+	for ( VarEnvType::const_iterator i = other.varEnv.begin(); i != other.varEnv.end(); ++i ) {
+		varEnv[ i->first ] = i->second;
+	} // for
+}
+
+void TypeSubstitution::add( std::string formalType, const Type *actualType ) {
+	typeEnv[ formalType ] = actualType;
+}
+
+void TypeSubstitution::remove( std::string formalType ) {
+	TypeEnvType::iterator i = typeEnv.find( formalType );
+	if ( i != typeEnv.end() ) {
+		typeEnv.erase( formalType );
+	} // if
+}
+
+const Type *TypeSubstitution::lookup( std::string formalType ) const {
+	TypeEnvType::const_iterator i = typeEnv.find( formalType );
+
+	// break on not in substitution set
+	if ( i == typeEnv.end() ) return 0;
+
+	// attempt to transitively follow TypeInstType links.
+	while ( const TypeInstType *actualType = i->second.as<TypeInstType>()) {
+		const std::string& typeName = actualType->name;
+
+		// break cycles in the transitive follow
+		if ( formalType == typeName ) break;
+
+		// Look for the type this maps to, returning previous mapping if none-such
+		i = typeEnv.find( typeName );
+		if ( i == typeEnv.end() ) return actualType;
+	}
+
+	// return type from substitution set
+	return i->second;
+}
+
+bool TypeSubstitution::empty() const {
+	return typeEnv.empty() && varEnv.empty();
+}
+
+namespace {
+	struct EnvTrimmer {
+		ptr<TypeSubstitution> env;
+		TypeSubstitution * newEnv;
+		EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
+		void previsit( TypeDecl * tyDecl ) {
+			// transfer known bindings for seen type variables
+			if ( const Type * t = env->lookup( tyDecl->name ) ) {
+				newEnv->add( tyDecl->name, t );
+			}
+		}
+	};
+} // namespace
+
+/// reduce environment to just the parts that are referenced in a given expression
+TypeSubstitution * TypeSubstitution::newFromExpr( const Expr * expr, const TypeSubstitution * env ) {
+	if ( env ) {
+		TypeSubstitution * newEnv = new TypeSubstitution();
+#if TIME_TO_CONVERT_PASSES
+		Pass<EnvTrimmer> trimmer( env, newEnv );
+		expr->accept( trimmer );
+#else
+		(void)expr;
+		(void)env;
+#endif
+		return newEnv;
+	}
+	return nullptr;
+}
+
+void TypeSubstitution::normalize() {
+#if TIME_TO_CONVERT_PASSES
+	PassVisitor<Substituter> sub( *this, true );
+	do {
+		sub.pass.subCount = 0;
+		sub.pass.freeOnly = true;
+		for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
+			i->second = i->second->acceptMutator( sub );
+		}
+	} while ( sub.pass.subCount );
+#endif
+}
+
+#if TIME_TO_CONVERT_PASSES
+
+Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
+	BoundVarsType::const_iterator bound = boundVars.find( inst->name );
+	if ( bound != boundVars.end() ) return inst;
+
+	TypeEnvType::const_iterator i = sub.typeEnv.find( inst->name );
+	if ( i == sub.typeEnv.end() ) {
+		return inst;
+	} else {
+		// cut off infinite loop for the case where a type is bound to itself.
+		// Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
+		// TODO: investigate preventing type variables from being bound to themselves in the first place.
+		if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {
+			if ( inst->name == replacement->name ) {
+				return inst;
+			}
+		}
+		// std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
+		subCount++;
+		Type * newtype = i->second->clone();
+		newtype->get_qualifiers() |= inst->get_qualifiers();
+		delete inst;
+		// Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
+		return newtype->acceptMutator( *visitor );
+	} // if
+}
+
+Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
+	VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
+	if ( i == sub.varEnv.end() ) {
+		return nameExpr;
+	} else {
+		subCount++;
+		delete nameExpr;
+		return i->second->clone();
+	} // if
+}
+
+void TypeSubstitution::Substituter::premutate( Type * type ) {
+	GuardValue( boundVars );
+	// bind type variables from forall-qualifiers
+	if ( freeOnly ) {
+		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
+			boundVars.insert( (*tyvar)->name );
+		} // for
+	} // if
+}
+
+template< typename TypeClass >
+void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
+	GuardValue( boundVars );
+	// bind type variables from forall-qualifiers
+	if ( freeOnly ) {
+		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
+			boundVars.insert( (*tyvar)->name );
+		} // for
+		// bind type variables from generic type instantiations
+		std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
+		if ( baseParameters && ! type->parameters.empty() ) {
+			for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
+				boundVars.insert( (*tyvar)->name );
+			} // for
+		} // if
+	} // if
+}
+
+void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
+	handleAggregateType( aggregateUseType );
+}
+
+void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
+	handleAggregateType( aggregateUseType );
+}
+
+#endif
+
+} // namespace ast
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
+++ src/AST/TypeSubstitution.hpp	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -0,0 +1,197 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// TypeSubstitution.h --
+//
+// Author           : Richard C. Bilson
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Apr 30 22:52:47 2019
+// Update Count     : 9
+//
+
+#pragma once
+
+#include <cassert>                 // for assert
+#include <list>                    // for list<>::iterator, _List_iterator
+#include <unordered_map>
+#include <unordered_set>
+#include <string>                  // for string, operator!=
+#include <utility>                 // for pair
+
+#include "Fwd.hpp"        // for UniqueId
+#include "ParseNode.hpp"
+#include "Type.hpp"       // for ptr<Type>
+#include "Common/SemanticError.h"  // for SemanticError
+#include "Visitor.hpp"
+#include "Decl.hpp"
+#include "Expr.hpp"
+
+namespace ast {
+
+class TypeSubstitution : public Node {
+  public:
+	TypeSubstitution();
+	template< typename FormalIterator, typename ActualIterator >
+	TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
+	TypeSubstitution( const TypeSubstitution &other );
+	virtual ~TypeSubstitution();
+
+	TypeSubstitution &operator=( const TypeSubstitution &other );
+
+	template< typename SynTreeClass > int apply( SynTreeClass *&input ) const;
+	template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) const;
+
+	void add( std::string formalType, const Type *actualType );
+	void add( const TypeSubstitution &other );
+	void remove( std::string formalType );
+	const Type *lookup( std::string formalType ) const;
+	bool empty() const;
+
+	template< typename FormalIterator, typename ActualIterator >
+	void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
+
+	/// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
+	static TypeSubstitution * newFromExpr( const Expr * expr, const TypeSubstitution * env );
+
+	void normalize();
+
+	const TypeSubstitution * accept( Visitor & v ) const override { return v.visit( this ); }
+
+	TypeSubstitution * clone() const override { return new TypeSubstitution( *this ); }
+
+  private:
+
+	// Mutator that performs the substitution
+	struct Substituter;
+
+	// TODO: worry about traversing into a forall-qualified function type or type decl with assertions
+
+	void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
+
+	template<typename pass_type>
+	friend class Pass;
+
+	typedef std::unordered_map< std::string, ptr<Type> > TypeEnvType;
+	typedef std::unordered_map< std::string, ptr<Expr> > VarEnvType;
+	TypeEnvType typeEnv;
+	VarEnvType varEnv;
+
+  public:
+	// has to come after declaration of typeEnv
+	auto begin()       -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
+	auto   end()       -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
+	auto begin() const -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
+	auto   end() const -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
+};
+
+template< typename FormalIterator, typename ActualIterator >
+void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
+	// FormalIterator points to a TypeDecl
+	// ActualIterator points to a Type
+	FormalIterator formalIt = formalBegin;
+	ActualIterator actualIt = actualBegin;
+	for ( ; formalIt != formalEnd; ++formalIt, ++actualIt ) {
+		if ( const TypeDecl *formal = formalIt->template as<TypeDecl>() ) {
+			if ( const TypeExpr *actual = actualIt->template as<TypeExpr>() ) {
+				if ( formal->name != "" ) {
+					typeEnv[ formal->name ] = actual->type;
+				} // if
+			} else {
+				SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ) );
+			} // if
+		} else {
+			// TODO: type check the formal and actual parameters
+			if ( (*formalIt)->name != "" ) {
+				varEnv[ (*formalIt)->name ] = *actualIt;
+			} // if
+		} // if
+	} // for
+}
+
+template< typename FormalIterator, typename ActualIterator >
+TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
+	add( formalBegin, formalEnd, actualBegin );
+}
+
+} // namespace ast
+
+// include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and
+// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
+#include "Pass.hpp"
+
+namespace ast {
+
+// definitition must happen after PassVisitor is included so that WithGuards can be used
+struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
+
+		Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
+
+#if TIME_TO_CONVERT_PASSES
+
+		Type * postmutate( TypeInstType * aggregateUseType );
+		Expression * postmutate( NameExpr * nameExpr );
+
+		/// Records type variable bindings from forall-statements
+		void premutate( Type * type );
+		/// Records type variable bindings from forall-statements and instantiations of generic types
+		template< typename TypeClass > void handleAggregateType( TypeClass * type );
+
+		void premutate( StructInstType * aggregateUseType );
+		void premutate( UnionInstType * aggregateUseType );
+
+#endif
+
+		const TypeSubstitution & sub;
+		int subCount = 0;
+		bool freeOnly;
+		typedef std::unordered_set< std::string > BoundVarsType;
+		BoundVarsType boundVars;
+
+};
+
+template< typename SynTreeClass >
+int TypeSubstitution::apply( SynTreeClass *&input ) const {
+	assert( input );
+	Pass<Substituter> sub( *this, false );
+	input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
+	assert( input );
+///	std::cerr << "substitution result is: ";
+///	newType->print( std::cerr );
+///	std::cerr << std::endl;
+	return sub.pass.subCount;
+}
+
+template< typename SynTreeClass >
+int TypeSubstitution::applyFree( SynTreeClass *&input ) const {
+	assert( input );
+	Pass<Substituter> sub( *this, true );
+	input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
+	assert( input );
+///	std::cerr << "substitution result is: ";
+///	newType->print( std::cerr );
+///	std::cerr << std::endl;
+	return sub.pass.subCount;
+}
+
+/// Instantiate each member of the context given the actual parameters specified, and store the
+/// instantiations for use by the indexer
+template< typename FormalIterator, typename ActualIterator, typename MemberIterator, typename OutputIterator >
+void applySubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actual, MemberIterator memberBegin, MemberIterator memberEnd, OutputIterator out ) {
+	TypeSubstitution sub = TypeSubstitution( formalBegin, formalEnd, actual );
+	for ( auto i = memberBegin; i != memberEnd; ++i ) {
+		sub.apply( *i );
+		*out++ = *i;
+	} // for
+}
+
+} // namespace ast
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/porting.md
===================================================================
--- src/AST/porting.md	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/AST/porting.md	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -48,5 +48,5 @@
       /// Must be copied in ALL derived classes
       template<typename node_t>
-      friend auto mutate(const node_t * node);
+      friend node_t * mutate(const node_t * node);
 
 All leaves of the `Node` inheritance tree are now declared `final`
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/Common/utility.h	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -463,12 +463,18 @@
 std::pair<long long int, bool> eval(Expression * expr);
 
-// -----------------------------------------------------------------------------
-/// Reorders the input range in-place so that the minimal-value elements according to the 
-/// comparator are in front; 
+namespace ast {
+	class Expr;
+}
+
+std::pair<long long int, bool> eval(const ast::Expr * expr);
+
+// -----------------------------------------------------------------------------
+/// Reorders the input range in-place so that the minimal-value elements according to the
+/// comparator are in front;
 /// returns the iterator after the last minimal-value element.
 template<typename Iter, typename Compare>
 Iter sort_mins( Iter begin, Iter end, Compare& lt ) {
 	if ( begin == end ) return end;
-	
+
 	Iter min_pos = begin;
 	for ( Iter i = begin + 1; i != end; ++i ) {
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/Parser/ExpressionNode.cc	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -62,5 +62,5 @@
 static inline bool checkB( char c ) { return c == 'b' || c == 'B'; }
 static inline bool checkX( char c ) { return c == 'x' || c == 'X'; }
-static inline bool checkN( char c ) { return c == 'n' || c == 'N'; }
+// static inline bool checkN( char c ) { return c == 'n' || c == 'N'; }
 
 void lnthSuffix( string & str, int & type, int & ltype ) {
@@ -217,6 +217,6 @@
 		} else {										// explicit length, (length_type)constant
 			ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
-			if ( ltype == 5 ) {							// pointer, intptr( (uintptr_t)constant ) 
-				ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) );								  
+			if ( ltype == 5 ) {							// pointer, intptr( (uintptr_t)constant )
+				ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) );
 			} // if
 		} // if
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision 9b4f3290a76fc499cac978b84cc1ab000bd8d6d0)
+++ src/SynTree/SynTree.h	(revision 8ff178d5ee06e2dd970d121edcf369bda332f653)
@@ -34,6 +34,4 @@
 class NamedTypeDecl;
 class TypeDecl;
-class FtypeDecl;
-class DtypeDecl;
 class TypedefDecl;
 class AsmDecl;
