Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Convert.cpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -10,6 +10,6 @@
 // Created On       : Thu May 09 15::37::05 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri May 17 16:01:00 2019
-// Update Count     : 4
+// Last Modified On : Tue May 21 15:30:00 2019
+// Update Count     : 5
 //
 
@@ -108,56 +108,162 @@
 
 private:
+	void declPostamble( Declaration * decl, const ast::Decl * node ) {
+		decl->location = node->location;
+		// name comes from constructor
+		// linkage comes from constructor
+		decl->extension = node->extension;
+		decl->uniqueId = node->uniqueId;
+		// storageClasses comes from constructor
+		this->node = decl;
+	}
+
+	const ast::DeclWithType * declWithTypePostamble (
+			DeclarationWithType * decl, const ast::DeclWithType * node ) {
+		declPostamble( decl, node );
+		decl->mangleName = node->mangleName;
+		decl->scopeLevel = node->scopeLevel;
+		decl->asmName = get<Expression>().accept1( node->asmName );
+		// attributes comes from constructor
+		decl->isDeleted = node->isDeleted;
+		// fs comes from constructor
+		return nullptr;
+	}
+
 	const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
-		(void)node;
-		return nullptr;
+		auto decl = new ObjectDecl(
+			node->name,
+			Type::StorageClasses( node->storage.val ),
+			LinkageSpec::Spec( node->linkage.val ),
+			get<Expression>().accept1( node->bitfieldWidth ),
+			get<Type>().accept1( node->type ),
+			get<Initializer>().accept1( node->init ),
+			get<Attribute>().acceptL( node->attributes ),
+			Type::FuncSpecifiers( node->funcSpec.val )
+		);
+		return declWithTypePostamble( decl, node );
 	}
 
 	const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
-		(void)node;
+		auto decl = new FunctionDecl(
+			node->name,
+			Type::StorageClasses( node->storage.val ),
+			LinkageSpec::Spec( node->linkage.val ),
+			get<FunctionType>().accept1( node->type ),
+			get<CompoundStmt>().accept1( node->stmts ),
+			get<Attribute>().acceptL( node->attributes ),
+			Type::FuncSpecifiers( node->funcSpec.val )
+		);
+		decl->withExprs = get<Expression>().acceptL( node->withExprs );
+		return declWithTypePostamble( decl, node );
+	}
+
+	// NamedTypeDecl
+	const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) {
+		declPostamble( decl, node );
+		// base comes from constructor
+		decl->parameters = get<TypeDecl>().acceptL( node->params );
+		decl->assertions = get<DeclarationWithType>().acceptL( node->assertions );
+		return nullptr;
+	}
+
+	const ast::Decl * visit( const ast::TypeDecl * node ) override final {
+		TypeDecl::Kind kind;
+		switch (node->kind) {
+		case ast::TypeVar::Dtype:
+			kind = TypeDecl::Dtype;
+			break;
+		case ast::TypeVar::Ftype:
+			kind = TypeDecl::Ftype;
+			break;
+		case ast::TypeVar::Ttype:
+			kind = TypeDecl::Ttype;
+			break;
+		default:
+			assertf(false, "Invalid ast::TypeVar::Kind: %d\n", node->kind);
+		};
+		auto decl = new TypeDecl(
+			node->name,
+			Type::StorageClasses( node->storage.val ),
+			get<Type>().accept1( node->base ),
+			kind,
+			node->sized,
+			get<Type>().accept1( node->init )
+		);
+		return namedTypePostamble( decl, node );
+	}
+
+	const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
+		auto decl = new TypedefDecl(
+			node->name,
+			node->location,
+			Type::StorageClasses( node->storage.val ),
+            get<Type>().accept1( node->base ),
+			LinkageSpec::Spec( node->linkage.val )
+		);
+		return namedTypePostamble( decl, node );
+	}
+
+	const ast::Decl * aggregatePostamble( AggregateDecl * decl, const ast::AggregateDecl * node ) {
+		decl->members = get<Declaration>().acceptL( node->members );
+		decl->parameters = get<TypeDecl>().acceptL( node->params );
+		decl->body = node->body;
+		// attributes come from constructor
+		// TODO: Need caching for: decl->parent = node->parent;
 		return nullptr;
 	}
 
 	const ast::Decl * visit( const ast::StructDecl * node ) override final {
-		(void)node;
-		return nullptr;
+		auto decl = new StructDecl(
+			node->name,
+			node->kind,
+			get<Attribute>().acceptL( node->attributes ),
+			LinkageSpec::Spec( node->linkage.val )
+		);
+		return aggregatePostamble( decl, node );
 	}
 
 	const ast::Decl * visit( const ast::UnionDecl * node ) override final {
-		(void)node;
-		return nullptr;
+		auto decl = new UnionDecl(
+			node->name,
+			get<Attribute>().acceptL( node->attributes ),
+			LinkageSpec::Spec( node->linkage.val )
+		);
+		return aggregatePostamble( decl, node );
 	}
 
 	const ast::Decl * visit( const ast::EnumDecl * node ) override final {
-		(void)node;
-		return nullptr;
+		auto decl = new EnumDecl(
+			node->name,
+			get<Attribute>().acceptL( node->attributes ),
+			LinkageSpec::Spec( node->linkage.val )
+		);
+		return aggregatePostamble( decl, node );
 	}
 
 	const ast::Decl * visit( const ast::TraitDecl * node ) override final {
-		(void)node;
-		return nullptr;
-	}
-
-	const ast::Decl * visit( const ast::TypeDecl * node ) override final {
-		(void)node;
-		return nullptr;
-	}
-
-	const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
-		(void)node;
-		return nullptr;
+		auto decl = new TraitDecl(
+			node->name,
+			{},
+			LinkageSpec::Spec( node->linkage.val )
+		);
+		return aggregatePostamble( decl, node );
 	}
 
 	const ast::AsmDecl * visit( const ast::AsmDecl * node ) override final {
-		(void)node;
+		auto decl = new AsmDecl( get<AsmStmt>().accept1( node->stmt ) );
+		declPostamble( decl, node );
 		return nullptr;
 	}
 
 	const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) override final {
-		(void)node;
-		return nullptr;
-	}
-
-	const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
-		auto stmt = new CompoundStmt( get<Statement>().acceptL( node->kids ) );
+		auto decl = new StaticAssertDecl(
+			get<Expression>().accept1( node->cond ),
+			get<ConstantExpr>().accept1( node->msg )
+		);
+		declPostamble( decl, node );
+		return nullptr;
+	}
+
+	const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
 		stmt->location = node->location;
 		stmt->labels = makeLabelL( stmt, node->labels );
@@ -166,10 +272,13 @@
 	}
 
+	const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
+		auto stmt = new CompoundStmt( get<Statement>().acceptL( node->kids ) );
+		stmtPostamble( stmt, node );
+		return nullptr;
+	}
+
 	const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
 		auto stmt = new ExprStmt( get<Expression>().accept1( node->expr ) );
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -183,16 +292,10 @@
 			makeLabelL( nullptr, node->gotoLabels ) // What are these labelling?
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
 	const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
 		auto stmt = new DirectiveStmt( node->directive );
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -204,8 +307,5 @@
 			get<Statement>().acceptL( node->inits )
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -215,8 +315,5 @@
 			get<Statement>().acceptL( node->stmts )
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -227,8 +324,5 @@
 			node->isDefault()
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -241,8 +335,5 @@
 			node->isDoWhile
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -254,8 +345,5 @@
 			get<Statement>().accept1( node->body )
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -286,16 +374,10 @@
 			stmt->target = makeLabel( stmt, node->target );
 		}
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
 	const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
 		auto stmt = new ReturnStmt( get<Expression>().accept1( node->expr ) );
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -317,8 +399,5 @@
 			get<Expression>().accept1( node->target )
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -330,8 +409,5 @@
 			get<FinallyStmt>().accept1( node->finally )
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -354,16 +430,10 @@
 			get<Statement>().accept1( node->body )
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
 	const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
 		auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) );
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -373,6 +443,6 @@
 		for ( auto clause : node->clauses ) {
 			stmt->clauses.push_back({{
-					get<Expression>().accept1( clause.target.function ),
-					get<Expression>().acceptL( clause.target.arguments ),
+					get<Expression>().accept1( clause.target.func ),
+					get<Expression>().acceptL( clause.target.args ),
 				},
 				get<Statement>().accept1( clause.stmt ),
@@ -389,8 +459,5 @@
 			get<Expression>().accept1( node->orElse.cond ),
 		};
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -400,15 +467,10 @@
 			get<Statement>().accept1( node->stmt )
 		);
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
 	const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
 		auto stmt = new NullStmt();
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
+		stmtPostamble( stmt, node );
 		return nullptr;
 	}
@@ -416,8 +478,5 @@
 	const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
 		auto stmt = new DeclStmt( get<Declaration>().accept1( node->decl ) );
-		stmt->location = node->location;
-		stmt->labels = makeLabelL( stmt, node->labels );
-		this->node = stmt;
-		return nullptr;
+		return stmtPostamble( stmt, node );
 	}
 
@@ -427,16 +486,88 @@
 	}
 
+	TypeSubstitution * convertTypeSubstitution(const ast::TypeSubstitution * src) {
+
+		TypeSubstitution *rslt = new TypeSubstitution();
+
+		for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) {
+			rslt->add( src_i->first,
+			           get<Type>().accept1(src_i->second) );
+		}
+
+		for (decltype(src->beginVar()) src_i = src->beginVar(); src_i != src->endVar(); src_i++) {
+			rslt->addVar( src_i->first,
+			              get<Expression>().accept1(src_i->second) );
+		}
+
+		return rslt;
+	}
+
+	void convertInferUnion(std::map<UniqueId,ParamEntry> &tgtInferParams,
+						   std::vector<UniqueId>         &tgtResnSlots,
+						   const ast::Expr::InferUnion   &srcInferred ) {
+
+		assert( tgtInferParams.empty() );
+		assert( tgtResnSlots.empty() );
+
+		if ( srcInferred.mode == ast::Expr::InferUnion::Params ) {
+			const ast::InferredParams &srcParams = srcInferred.inferParamsConst();
+			for (auto srcParam : srcParams) {
+				tgtInferParams[srcParam.first] = ParamEntry(
+					srcParam.second.decl,
+					get<Type>().accept1(srcParam.second.actualType),
+					get<Type>().accept1(srcParam.second.formalType),
+					get<Expression>().accept1(srcParam.second.expr)
+				);
+			}
+		} else if ( srcInferred.mode == ast::Expr::InferUnion::Slots  ) {
+			const ast::ResnSlots &srcSlots = srcInferred.resnSlotsConst();
+			for (auto srcSlot : srcSlots) {
+				tgtResnSlots.push_back(srcSlot);
+			}
+		}
+	}
+
+	Expression * visitBaseExpr(const ast::Expr * src, Expression * tgt) {
+
+		tgt->location = src->location;
+
+		tgt->result = get<Type>().accept1(src->result);
+		tgt->env    = convertTypeSubstitution(src->env);
+
+		tgt->extension = src->extension;
+		convertInferUnion(tgt->inferParams, tgt->resnSlots, src->inferred);
+
+		return tgt;
+	}
+
 	const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new ApplicationExpr(
+				get<Expression>().accept1(node->func),
+				get<Expression>().acceptL(node->args)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new UntypedExpr(
+				get<Expression>().accept1(node->func),
+				get<Expression>().acceptL(node->args)
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
 
 	const ast::Expr * visit( const ast::NameExpr * node ) override final {
-		(void)node;
+		auto expr = visitBaseExpr( node,
+			new NameExpr(
+				node->name
+			)
+		);
+		this->node = expr;
 		return nullptr;
 	}
@@ -1236,13 +1367,31 @@
 			              getAccept1<ast::Expr>(old_i->second) );
 		}
-	}
-
-	void convertInferUnion(ast::Expr::InferUnion &nwInferred, InferredParams oldInferParams, const std::vector<UniqueId> &oldResnSlots) {
-		
-		(void) nwInferred;
-		(void) oldInferParams;
-		(void) oldResnSlots;
-		
-		// TODO
+
+		return rslt;
+	}
+
+	void convertInferUnion(ast::Expr::InferUnion               &newInferred,
+						   const std::map<UniqueId,ParamEntry> &oldInferParams,
+						   const std::vector<UniqueId>         &oldResnSlots) {
+
+		assert( oldInferParams.empty() || oldResnSlots.empty() );
+		assert( newInferred.mode == ast::Expr::InferUnion::Empty );
+
+		if ( !oldInferParams.empty() ) {
+			ast::InferredParams &tgt = newInferred.inferParams();
+			for (auto old : oldInferParams) {
+				tgt[old.first] = ast::ParamEntry(
+					old.second.decl,
+					getAccept1<ast::Type>(old.second.actualType),
+					getAccept1<ast::Type>(old.second.formalType),
+					getAccept1<ast::Expr>(old.second.expr)
+				);
+			}
+		} else if ( !oldResnSlots.empty() ) {
+			ast::ResnSlots &tgt = newInferred.resnSlots();
+			for (auto old : oldResnSlots) {
+				tgt.push_back(old);
+			}
+		}
 	}
 
@@ -1258,10 +1407,22 @@
 	}
 
-	virtual void visit( ApplicationExpr * ) override final {
-		// TODO
-	}
-
-	virtual void visit( UntypedExpr * ) override final {
-		// TODO
+	virtual void visit( ApplicationExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::ApplicationExpr(
+				old->location,
+				GET_ACCEPT_1(function, Expr),
+				GET_ACCEPT_V(args, Expr)
+			)
+		);
+	}
+
+	virtual void visit( UntypedExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::UntypedExpr(
+				old->location,
+				GET_ACCEPT_1(function, Expr),
+				GET_ACCEPT_V(args, Expr)
+			)
+		);
 	}
 
@@ -1275,6 +1436,12 @@
 	}
 
-	virtual void visit( CastExpr * ) override final {
-		// TODO ... (rest)
+	virtual void visit( CastExpr * old ) override final {
+		this->node = visitBaseExpr( old,
+			new ast::CastExpr(
+				old->location,
+				nullptr, // cast's "to" type is expr's result type; converted in visitBaseExpr
+				old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast
+			)
+		);
 	}
 
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Decl.cpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -81,5 +81,5 @@
 				auto result = eval( init->value );
 				if ( ! result.second ) {
-					SemanticError( init->location, toString( "Non-constexpr in initialization of "
+					SemanticError( init->location, ::toString( "Non-constexpr in initialization of "
 						"enumerator: ", field ) );
 				}
@@ -87,5 +87,5 @@
 			}
 			if ( enumValues.count( field->name ) != 0 ) {
-				SemanticError( location, toString( "Enum ", name, " has multiple members with the " 	"name ", field->name ) );
+				SemanticError( location, ::toString( "Enum ", name, " has multiple members with the " 	"name ", field->name ) );
 			}
 			enumValues[ field->name ] = crntVal;
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Decl.hpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -329,9 +329,9 @@
 class StaticAssertDecl : public Decl {
 public:
-	ptr<Expr> condition;
+	ptr<Expr> cond;
 	ptr<ConstantExpr> msg;   // string literal
 
 	StaticAssertDecl( const CodeLocation & loc, const Expr * condition, const ConstantExpr * msg )
-	: Decl( loc, "", {}, {} ), condition( condition ), msg( msg ) {}
+	: Decl( loc, "", {}, {} ), cond( condition ), msg( msg ) {}
 
 	const StaticAssertDecl * accept( Visitor &v ) const override { return v.visit( this ); }
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Expr.cpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -22,4 +22,5 @@
 #include "Stmt.hpp"
 #include "Type.hpp"
+#include "Common/utility.h"
 #include "Common/SemanticError.h"
 #include "GenPoly/Lvalue.h"        // for referencesPermissable
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Expr.hpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -106,4 +106,13 @@
 			case Params: assert(!"Cannot return to resnSlots from Params");
 			}
+			return *((ResnSlots*)nullptr);
+		}
+
+		const ResnSlots& resnSlotsConst() const {
+			if (mode == Slots) {
+				return data.resnSlots;
+			}
+			assert(!"Mode was not already resnSlots");
+			return *((ResnSlots*)nullptr);
 		}
 
@@ -114,4 +123,13 @@
 			case Params: return data.inferParams;
 			}
+			return *((InferredParams*)nullptr);
+		}
+
+		const InferredParams& inferParamsConst() const {
+			if (mode == Params) {
+				return data.inferParams;
+			}
+			assert(!"Mode was not already Params");
+			return *((InferredParams*)nullptr);
 		}
 	};
@@ -503,5 +521,5 @@
 };
 
-/// The application of a function to a set of parameters, along with a set of copy constructor 
+/// The application of a function to a set of parameters, along with a set of copy constructor
 /// calls, one for each argument
 class ImplicitCopyCtorExpr final : public Expr {
@@ -603,6 +621,6 @@
 };
 
-/// A multiple- or mass-assignment operation, or a tuple ctor/dtor expression. 
-/// multiple-assignment: both sides of the assignment have tuple type, 
+/// A multiple- or mass-assignment operation, or a tuple ctor/dtor expression.
+/// multiple-assignment: both sides of the assignment have tuple type,
 ///     e.g. `[a, b, c] = [d, e, f];`
 /// mass-assignment: left-hand side has tuple type and right-hand side does not:
@@ -612,8 +630,8 @@
 	ptr<StmtExpr> stmtExpr;
 
-	TupleAssignExpr( 
-		const CodeLocation & loc, std::vector<ptr<Expr>> && assigns, 
+	TupleAssignExpr(
+		const CodeLocation & loc, std::vector<ptr<Expr>> && assigns,
 		std::vector<ptr<ObjectDecl>> && tempDecls );
-	
+
 	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
 private:
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Fwd.hpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -131,9 +131,4 @@
 class TypeSubstitution;
 
-std::string toString( const Node * );
-
-template < typename ... Params >
-std::string toString( const Params & ... params );
-
 typedef unsigned int UniqueId;
 
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Node.cpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -16,4 +16,6 @@
 #include "Node.hpp"
 #include "Fwd.hpp"
+
+#include <iostream>
 
 #include "Attribute.hpp"
@@ -42,4 +44,11 @@
 	assign( r );
 	return r;
+}
+
+std::ostream & ast::operator<< ( std::ostream & out, const ast::Node * node ) {
+	(void)node;
+	#warning unimplemented
+	assertf(false, "Unimplemented");
+	return out;
 }
 
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Pass.impl.hpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Pass.impl.hpp --
+// ast::Pass.impl.hpp --
 //
 // Author           : Thierry Delisle
@@ -121,5 +121,5 @@
 	template< typename pass_t >
 	template< typename node_t >
-	auto Pass< pass_t >::call_accept( const node_t * node )
+	auto ast::Pass< pass_t >::call_accept( const node_t * node )
 		-> typename std::enable_if<
 				!std::is_base_of<ast::Expr, node_t>::value &&
@@ -139,5 +139,5 @@
 
 	template< typename pass_t >
-	const ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) {
+	const ast::Expr * ast::Pass< pass_t >::call_accept( const ast::Expr * expr ) {
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( expr );
@@ -152,5 +152,5 @@
 
 	template< typename pass_t >
-	const ast::Stmt * Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {
+	const ast::Stmt * ast::Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( stmt );
@@ -204,5 +204,5 @@
 	template< typename pass_t >
 	template< template <class...> class container_t >
-	container_t< ptr<Stmt> > Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
+	container_t< ptr<Stmt> > ast::Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
 		__pedantic_pass_assert( __visit_children() );
 		if( statements.empty() ) return {};
@@ -270,5 +270,5 @@
 	template< typename pass_t >
 	template< template <class...> class container_t, typename node_t >
-	container_t< ast::ptr<node_t> > Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
+	container_t< ast::ptr<node_t> > ast::Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
 		__pedantic_pass_assert( __visit_children() );
 		if( container.empty() ) return {};
@@ -301,5 +301,5 @@
 	template< typename pass_t >
 	template<typename node_t, typename parent_t, typename child_t>
-	void Pass< pass_t >::maybe_accept(
+	void ast::Pass< pass_t >::maybe_accept(
 		const node_t * & parent,
 		child_t parent_t::*child
@@ -571,5 +571,5 @@
 	__pass::indexer::addType( pass, 0, node );
 
-	maybe_accept( node, &TypedefDecl::assertions );
+	VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
 
 	VISIT_END( Decl, node );
@@ -596,6 +596,6 @@
 
 	VISIT(
-		maybe_accept( node, &StaticAssertDecl::condition );
-		maybe_accept( node, &StaticAssertDecl::msg       );
+		maybe_accept( node, &StaticAssertDecl::cond );
+		maybe_accept( node, &StaticAssertDecl::msg  );
 	)
 
@@ -626,5 +626,5 @@
 // ExprStmt
 template< typename pass_t >
-const ast::Stmt * ast::Pass< pass_t >::visit( const ExprStmt * node ) {
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ExprStmt * node ) {
 	VISIT_START( node );
 
@@ -666,4 +666,5 @@
 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::IfStmt * node ) {
 	VISIT_START( node );
+
 	VISIT({
 		// if statements introduce a level of scope (for the initialization)
@@ -674,4 +675,5 @@
 		maybe_accept( node, &IfStmt::elsePart );
 	})
+
 	VISIT_END( Stmt, node );
 }
@@ -680,5 +682,5 @@
 // WhileStmt
 template< typename pass_t >
-const ast::Stmt * ast::Pass< pass_t >::visit( const WhileStmt * node ) {
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WhileStmt * node ) {
 	VISIT_START( node );
 
@@ -832,4 +834,37 @@
 		// 	maybeAccept_impl( clause.condition, *this );
 		// }
+
+	VISIT({
+		std::vector<WaitForStmt::Clause> new_clauses;
+		new_clauses.reserve( node->clauses.size() );
+		bool mutated = false;
+		for( const auto & clause : node->clauses ) {
+
+			Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
+			if(func != clause.target.func) mutated = true;
+
+			std::vector<ptr<Expr>> new_args;
+			new_args.reserve(clause.target.args.size());
+			for( const auto & arg : clause.target.args ) {
+				auto a = arg->accept(*this);
+				new_args.push_back( a );
+				if( a != arg ) mutated = true;
+			}
+
+			Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
+			if(stmt != clause.stmt) mutated = true;
+
+			Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
+			if(cond != clause.cond) mutated = true;
+
+			new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } );
+		}
+
+		if(mutated) {
+			auto n = mutate(node);
+			n->clauses = std::move( new_clauses );
+			node = n;
+		}
+	})
 
 	#define maybe_accept(field) \
@@ -910,8 +945,888 @@
 }
 
-
-
-
-
+//--------------------------------------------------------------------------
+// ApplicationExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::ApplicationExpr * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		{
+			guard_indexer guard { *this };
+			maybe_accept( node, &ApplicationExpr::result );
+		}
+		maybe_accept( node, &ApplicationExpr::func );
+		maybe_accept( node, &ApplicationExpr::args );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// UntypedExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedExpr * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		{
+			guard_indexer guard { *this };
+			maybe_accept( node, &UntypedExpr::result );
+		}
+
+		maybe_accept( node, &UntypedExpr::args );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// NameExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::NameExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		guard_indexer guard { *this };
+		maybe_accept( node, &NameExpr::result );
+	})
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// CastExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::CastExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &CastExpr::result );
+		}
+		maybe_accept( node, &CastExpr::arg );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// KeywordCastExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::KeywordCastExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &KeywordCastExpr::result );
+		}
+		maybe_accept( node, &KeywordCastExpr::arg );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// VirtualCastExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::VirtualCastExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &VirtualCastExpr::result );
+		}
+		maybe_accept( node, &VirtualCastExpr::arg );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// AddressExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::AddressExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &AddressExpr::result );
+		}
+		maybe_accept( node, &AddressExpr::arg );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// LabelAddressExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::LabelAddressExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		guard_indexer guard { *this };
+		maybe_accept( node, &LabelAddressExpr::result );
+	})
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// UntypedMemberExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedMemberExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &UntypedMemberExpr::result );
+		}
+		maybe_accept( node, &UntypedMemberExpr::aggregate );
+		maybe_accept( node, &UntypedMemberExpr::member    );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// MemberExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::MemberExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &MemberExpr::result );
+		}
+		maybe_accept( node, &MemberExpr::aggregate );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// VariableExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::VariableExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		guard_indexer guard { *this };
+		maybe_accept( node, &VariableExpr::result );
+	})
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// ConstantExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstantExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		guard_indexer guard { *this };
+		maybe_accept( node, &ConstantExpr::result );
+	})
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// SizeofExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::SizeofExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &SizeofExpr::result );
+		}
+		if ( node->type ) {
+			maybe_accept( node, &SizeofExpr::type );
+		} else {
+			maybe_accept( node, &SizeofExpr::expr );
+		}
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// AlignofExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::AlignofExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &AlignofExpr::result );
+		}
+		if ( node->type ) {
+			maybe_accept( node, &AlignofExpr::type );
+		} else {
+			maybe_accept( node, &AlignofExpr::expr );
+		}
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// UntypedOffsetofExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedOffsetofExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &UntypedOffsetofExpr::result );
+		}
+		maybe_accept( node, &UntypedOffsetofExpr::type   );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// OffsetofExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetofExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &OffsetofExpr::result );
+		}
+		maybe_accept( node, &OffsetofExpr::type   );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// OffsetPackExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetPackExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &OffsetPackExpr::result );
+		}
+		maybe_accept( node, &OffsetPackExpr::type   );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// LogicalExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::LogicalExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &LogicalExpr::result );
+		}
+		maybe_accept( node, &LogicalExpr::arg1 );
+		maybe_accept( node, &LogicalExpr::arg2 );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// ConditionalExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConditionalExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &ConditionalExpr::result );
+		}
+		maybe_accept( node, &ConditionalExpr::arg1 );
+		maybe_accept( node, &ConditionalExpr::arg2 );
+		maybe_accept( node, &ConditionalExpr::arg3 );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// CommaExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::CommaExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &CommaExpr::result );
+		}
+		maybe_accept( node, &CommaExpr::arg1 );
+		maybe_accept( node, &CommaExpr::arg2 );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// TypeExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::TypeExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &TypeExpr::result );
+		}
+		maybe_accept( node, &TypeExpr::type );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// AsmExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::AsmExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &AsmExpr::result );
+		}
+		maybe_accept( node, &AsmExpr::inout      );
+		maybe_accept( node, &AsmExpr::constraint );
+		maybe_accept( node, &AsmExpr::operand    );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// ImplicitCopyCtorExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &ImplicitCopyCtorExpr::result );
+		}
+		maybe_accept( node, &ImplicitCopyCtorExpr::callExpr    );
+		maybe_accept( node, &ImplicitCopyCtorExpr::tempDecls   );
+		maybe_accept( node, &ImplicitCopyCtorExpr::returnDecls );
+		maybe_accept( node, &ImplicitCopyCtorExpr::dtors       );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// ConstructorExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstructorExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &ConstructorExpr::result );
+		}
+		maybe_accept( node, &ConstructorExpr::callExpr );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// CompoundLiteralExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::CompoundLiteralExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &CompoundLiteralExpr::result );
+		}
+		maybe_accept( node, &CompoundLiteralExpr::init );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// RangeExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::RangeExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &RangeExpr::result );
+		}
+		maybe_accept( node, &RangeExpr::low    );
+		maybe_accept( node, &RangeExpr::high   );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// UntypedTupleExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedTupleExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &UntypedTupleExpr::result );
+		}
+		maybe_accept( node, &UntypedTupleExpr::exprs  );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// TupleExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &TupleExpr::result );
+		}
+		maybe_accept( node, &TupleExpr::exprs  );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// TupleIndexExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleIndexExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &TupleIndexExpr::result );
+		}
+		maybe_accept( node, &TupleIndexExpr::tuple  );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// TupleAssignExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleAssignExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &TupleAssignExpr::result );
+		}
+		maybe_accept( node, &TupleAssignExpr::stmtExpr );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// StmtExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::StmtExpr * node ) {
+	VISIT_START( node );
+
+	VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr
+		// get the stmts that will need to be spliced in
+		auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
+		auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
+
+		// These may be modified by subnode but most be restored once we exit this statemnet.
+		ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( pass, 0) );
+		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
+		ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
+
+		{
+			guard_indexer guard { *this };
+			maybe_accept( node, &StmtExpr::result );
+		}
+		maybe_accept( node, &StmtExpr::stmts       );
+		maybe_accept( node, &StmtExpr::returnDecls );
+		maybe_accept( node, &StmtExpr::dtors       );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// UniqueExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::UniqueExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &UniqueExpr::result );
+		}
+		maybe_accept( node, &UniqueExpr::expr   );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// UntypedInitExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedInitExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &UntypedInitExpr::result );
+		}
+		maybe_accept( node, &UntypedInitExpr::expr   );
+		// not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// InitExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::InitExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &InitExpr::result );
+		}
+		maybe_accept( node, &InitExpr::expr   );
+		maybe_accept( node, &InitExpr::designation );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// DeletedExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::DeletedExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &DeletedExpr::result );
+		}
+		maybe_accept( node, &DeletedExpr::expr );
+		// don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// DefaultArgExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::DefaultArgExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &DefaultArgExpr::result );
+		}
+		maybe_accept( node, &DefaultArgExpr::expr );
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// GenericExpr
+template< typename pass_t >
+const ast::Expr * ast::Pass< pass_t >::visit( const ast::GenericExpr * node ) {
+	VISIT_START( node );
+
+	VISIT({
+			guard_indexer guard { *this };
+			maybe_accept( node, &GenericExpr::result );
+		}
+		maybe_accept( node, &GenericExpr::control );
+
+		std::vector<GenericExpr::Association> new_kids;
+		new_kids.reserve(node->associations.size());
+		bool mutated = false;
+		for( const auto & assoc : node->associations ) {
+			Type * type = nullptr;
+			if( assoc.type ) {
+				guard_indexer guard { *this };
+				type = assoc.type->accept( *this );
+				if( type != assoc.type ) mutated = true;
+			}
+			Expr * expr = nullptr;
+			if( assoc.expr ) {
+				expr = assoc.expr->accept( *this );
+				if( expr != assoc.expr ) mutated = true;
+			}
+			new_kids.emplace_back( type, expr );
+		}
+
+		if(mutated) {
+			auto n = mutate(node);
+			n->associations = std::move( new_kids );
+			node = n;
+		}
+	)
+
+	VISIT_END( Expr, node );
+}
+
+//--------------------------------------------------------------------------
+// VoidType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::VoidType * node ) {
+	VISIT_START( node );
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// BasicType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::BasicType * node ) {
+	VISIT_START( node );
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// PointerType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::PointerType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		// xxx - should PointerType visit/mutate dimension?
+		maybe_accept( node, &PointerType::base );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// ArrayType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::ArrayType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &ArrayType::dimension );
+		maybe_accept( node, &ArrayType::base );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// ReferenceType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::ReferenceType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &ReferenceType::base );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// QualifiedType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::QualifiedType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &QualifiedType::parent );
+		maybe_accept( node, &QualifiedType::child );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// FunctionType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::FunctionType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &FunctionType::forall  );
+		maybe_accept( node, &FunctionType::returns );
+		maybe_accept( node, &FunctionType::params  );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// StructInstType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::StructInstType * node ) {
+	VISIT_START( node );
+
+	__pass::indexer::addStruct( node->name, 0, pass );
+
+	VISIT({
+		guard_indexer guard { *this };
+		maybe_accept( node, &StructInstType::forall );
+		maybe_accept( node, &StructInstType::params );
+	})
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// UnionInstType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::UnionInstType * node ) {
+	VISIT_START( node );
+
+	__pass::indexer::addStruct( node->name, 0, pass );
+
+	{
+		guard_indexer guard { *this };
+		maybe_accept( node, &UnionInstType::forall );
+		maybe_accept( node, &UnionInstType::params );
+	}
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// EnumInstType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::EnumInstType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &EnumInstType::forall );
+		maybe_accept( node, &EnumInstType::params );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// TraitInstType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::TraitInstType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &TraitInstType::forall );
+		maybe_accept( node, &TraitInstType::params );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// TypeInstType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeInstType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &TypeInstType::forall );
+		maybe_accept( node, &TypeInstType::params );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// TupleType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::TupleType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &TupleType::types );
+		maybe_accept( node, &TupleType::members );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// TypeofType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeofType * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &TypeofType::expr );
+	)
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// VarArgsType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::VarArgsType * node ) {
+	VISIT_START( node );
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// ZeroType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::ZeroType * node ) {
+	VISIT_START( node );
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// OneType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::OneType * node ) {
+	VISIT_START( node );
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
+// GlobalScopeType
+template< typename pass_t >
+const ast::Type * ast::Pass< pass_t >::visit( const ast::GlobalScopeType * node ) {
+	VISIT_START( node );
+
+	VISIT_END( Type, node );
+}
+
+
+//--------------------------------------------------------------------------
+// Designation
+template< typename pass_t >
+const ast::Designation * ast::Pass< pass_t >::visit( const ast::Designation * node ) {
+	VISIT_START( node );
+
+	VISIT( maybe_accept( node, &Designation::designators ); )
+
+	VISIT_END( Designation, node );
+}
 
 //--------------------------------------------------------------------------
@@ -970,46 +1885,46 @@
 }
 
-//--------------------------------------------------------------------------
-// TypeSubstitution
-template< typename pass_t >
-const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {
-	VISIT_START( node );
-
-	VISIT(
-		{
-			bool mutated = false;
-			std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
-			for ( const auto & p : node->typeEnv ) {
-				guard_indexer guard { *this };
-				auto new_node = p.second->accept( *this );
-				if (new_node != p.second) mutated = false;
-				new_map.insert({ p.first, new_node });
-			}
-			if (mutated) {
-				auto new_node = mutate( node );
-				new_node->typeEnv.swap( new_map );
-				node = new_node;
-			}
-		}
-
-		{
-			bool mutated = false;
-			std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
-			for ( const auto & p : node->varEnv ) {
-				guard_indexer guard { *this };
-				auto new_node = p.second->accept( *this );
-				if (new_node != p.second) mutated = false;
-				new_map.insert({ p.first, new_node });
-			}
-			if (mutated) {
-				auto new_node = mutate( node );
-				new_node->varEnv.swap( new_map );
-				node = new_node;
-			}
-		}
-	)
-
-	VISIT_END( TypeSubstitution, node );
-}
+// //--------------------------------------------------------------------------
+// // TypeSubstitution
+// template< typename pass_t >
+// const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {
+// 	VISIT_START( node );
+
+// 	VISIT(
+// 		{
+// 			bool mutated = false;
+// 			std::unordered_map< std::string, ast::ptr< ast::Type > > new_map;
+// 			for ( const auto & p : node->typeEnv ) {
+// 				guard_indexer guard { *this };
+// 				auto new_node = p.second->accept( *this );
+// 				if (new_node != p.second) mutated = false;
+// 				new_map.insert({ p.first, new_node });
+// 			}
+// 			if (mutated) {
+// 				auto new_node = mutate( node );
+// 				new_node->typeEnv.swap( new_map );
+// 				node = new_node;
+// 			}
+// 		}
+
+// 		{
+// 			bool mutated = false;
+// 			std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map;
+// 			for ( const auto & p : node->varEnv ) {
+// 				guard_indexer guard { *this };
+// 				auto new_node = p.second->accept( *this );
+// 				if (new_node != p.second) mutated = false;
+// 				new_map.insert({ p.first, new_node });
+// 			}
+// 			if (mutated) {
+// 				auto new_node = mutate( node );
+// 				new_node->varEnv.swap( new_map );
+// 				node = new_node;
+// 			}
+// 		}
+// 	)
+
+// 	VISIT_END( TypeSubstitution, node );
+// }
 
 #undef VISIT_START
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/Stmt.hpp	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -330,6 +330,6 @@
 public:
 	struct Target {
-		ptr<Expr> function;
-		std::vector<ptr<Expr>> arguments;
+		ptr<Expr> func;
+		std::vector<ptr<Expr>> args;
 	};
 
Index: src/AST/module.mk
===================================================================
--- src/AST/module.mk	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/AST/module.mk	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -1,4 +1,3 @@
-######################### -*- Mode: Makefile-Gmake -*-
-########################
+######################### -*- Mode: Makefile-Gmake -*- ########################
 ##
 ## Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
@@ -17,7 +16,15 @@
 
 SRC_AST = \
-     AST/Convert.cpp \
-     AST/Node.cpp \
-     AST/TypeSubstitution.cpp 
+	AST/Attribute.cpp \
+	AST/Convert.cpp \
+	AST/Decl.cpp \
+	AST/DeclReplacer.cpp \
+	AST/Expr.cpp \
+	AST/Init.cpp \
+	AST/LinkageSpec.cpp \
+	AST/Node.cpp \
+	AST/Stmt.cpp \
+	AST/Type.cpp \
+	AST/TypeSubstitution.cpp
 
 
@@ -25,3 +32,2 @@
 SRC += $(SRC_AST)
 SRCDEMANGLE += $(SRC_AST)
-
Index: src/Common/Eval.cc
===================================================================
--- src/Common/Eval.cc	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/Common/Eval.cc	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -90,4 +90,9 @@
 }
 
+std::pair<long long int, bool> eval(const ast::Expr * expr) {
+	#warning not implemented
+	return { 0, false };
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/Makefile.am	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -37,4 +37,5 @@
 endif
 
+include AST/module.mk
 include CodeGen/module.mk
 include CodeTools/module.mk
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/Makefile.in	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -16,4 +16,7 @@
 
 ######################## -*- Mode: Makefile-Automake -*- ######################
+###############################################################################
+
+######################### -*- Mode: Makefile-Gmake -*- ########################
 ###############################################################################
 
@@ -162,18 +165,24 @@
 libdemangle_a_LIBADD =
 am__dirstamp = $(am__leading_dot)dirstamp
-am__objects_1 = CodeGen/CodeGenerator.$(OBJEXT) \
+am__objects_1 = AST/Attribute.$(OBJEXT) AST/Convert.$(OBJEXT) \
+	AST/Decl.$(OBJEXT) AST/DeclReplacer.$(OBJEXT) \
+	AST/Expr.$(OBJEXT) AST/Init.$(OBJEXT) \
+	AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
+	AST/Stmt.$(OBJEXT) AST/Type.$(OBJEXT) \
+	AST/TypeSubstitution.$(OBJEXT)
+am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \
 	CodeGen/FixMain.$(OBJEXT) CodeGen/GenType.$(OBJEXT) \
 	CodeGen/OperatorTable.$(OBJEXT)
-am__objects_2 = Common/Assert.$(OBJEXT) Common/Eval.$(OBJEXT) \
+am__objects_3 = Common/Assert.$(OBJEXT) Common/Eval.$(OBJEXT) \
 	Common/PassVisitor.$(OBJEXT) Common/SemanticError.$(OBJEXT) \
 	Common/Stats/Counter.$(OBJEXT) Common/Stats/Heap.$(OBJEXT) \
 	Common/Stats/Stats.$(OBJEXT) Common/Stats/Time.$(OBJEXT) \
 	Common/UniqueName.$(OBJEXT)
-am__objects_3 = ControlStruct/ForExprMutator.$(OBJEXT) \
+am__objects_4 = ControlStruct/ForExprMutator.$(OBJEXT) \
 	ControlStruct/LabelFixer.$(OBJEXT) \
 	ControlStruct/LabelGenerator.$(OBJEXT) \
 	ControlStruct/MLEMutator.$(OBJEXT) \
 	ControlStruct/Mutate.$(OBJEXT)
-am__objects_4 = ResolvExpr/AdjustExprType.$(OBJEXT) \
+am__objects_5 = ResolvExpr/AdjustExprType.$(OBJEXT) \
 	ResolvExpr/Alternative.$(OBJEXT) \
 	ResolvExpr/AlternativeFinder.$(OBJEXT) \
@@ -193,8 +202,8 @@
 	ResolvExpr/TypeEnvironment.$(OBJEXT) \
 	ResolvExpr/Unify.$(OBJEXT)
-am__objects_5 = SymTab/Autogen.$(OBJEXT) SymTab/FixFunction.$(OBJEXT) \
+am__objects_6 = SymTab/Autogen.$(OBJEXT) SymTab/FixFunction.$(OBJEXT) \
 	SymTab/Indexer.$(OBJEXT) SymTab/Mangler.$(OBJEXT) \
 	SymTab/ManglerCommon.$(OBJEXT) SymTab/Validate.$(OBJEXT)
-am__objects_6 = SynTree/Type.$(OBJEXT) SynTree/VoidType.$(OBJEXT) \
+am__objects_7 = SynTree/Type.$(OBJEXT) SynTree/VoidType.$(OBJEXT) \
 	SynTree/BasicType.$(OBJEXT) SynTree/PointerType.$(OBJEXT) \
 	SynTree/ArrayType.$(OBJEXT) SynTree/ReferenceType.$(OBJEXT) \
@@ -216,25 +225,25 @@
 	SynTree/TypeSubstitution.$(OBJEXT) SynTree/Attribute.$(OBJEXT) \
 	SynTree/DeclReplacer.$(OBJEXT)
-am__objects_7 = CompilationState.$(OBJEXT) $(am__objects_1) \
-	Concurrency/Keywords.$(OBJEXT) $(am__objects_2) \
-	$(am__objects_3) GenPoly/GenPoly.$(OBJEXT) \
+am__objects_8 = CompilationState.$(OBJEXT) $(am__objects_1) \
+	$(am__objects_2) Concurrency/Keywords.$(OBJEXT) \
+	$(am__objects_3) $(am__objects_4) GenPoly/GenPoly.$(OBJEXT) \
 	GenPoly/Lvalue.$(OBJEXT) InitTweak/GenInit.$(OBJEXT) \
 	InitTweak/InitTweak.$(OBJEXT) Parser/LinkageSpec.$(OBJEXT) \
-	$(am__objects_4) $(am__objects_5) SymTab/Demangle.$(OBJEXT) \
-	$(am__objects_6) Tuples/TupleAssignment.$(OBJEXT) \
+	$(am__objects_5) $(am__objects_6) SymTab/Demangle.$(OBJEXT) \
+	$(am__objects_7) Tuples/TupleAssignment.$(OBJEXT) \
 	Tuples/TupleExpansion.$(OBJEXT) Tuples/Explode.$(OBJEXT) \
 	Validate/HandleAttributes.$(OBJEXT)
-am_libdemangle_a_OBJECTS = $(am__objects_7)
+am_libdemangle_a_OBJECTS = $(am__objects_8)
 libdemangle_a_OBJECTS = $(am_libdemangle_a_OBJECTS)
 am__installdirs = "$(DESTDIR)$(cfa_cpplibdir)"
 PROGRAMS = $(cfa_cpplib_PROGRAMS)
-am__objects_8 = main.$(OBJEXT) MakeLibCfa.$(OBJEXT) \
-	CompilationState.$(OBJEXT) $(am__objects_1) \
+am__objects_9 = main.$(OBJEXT) MakeLibCfa.$(OBJEXT) \
+	CompilationState.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
 	CodeGen/Generate.$(OBJEXT) CodeGen/FixNames.$(OBJEXT) \
 	CodeTools/DeclStats.$(OBJEXT) \
 	CodeTools/ResolvProtoDump.$(OBJEXT) \
 	CodeTools/TrackLoc.$(OBJEXT) Concurrency/Keywords.$(OBJEXT) \
-	Concurrency/Waitfor.$(OBJEXT) $(am__objects_2) \
-	Common/DebugMalloc.$(OBJEXT) $(am__objects_3) \
+	Concurrency/Waitfor.$(OBJEXT) $(am__objects_3) \
+	Common/DebugMalloc.$(OBJEXT) $(am__objects_4) \
 	ControlStruct/ExceptTranslate.$(OBJEXT) GenPoly/Box.$(OBJEXT) \
 	GenPoly/GenPoly.$(OBJEXT) GenPoly/ScrubTyVars.$(OBJEXT) \
@@ -250,11 +259,11 @@
 	Parser/InitializerNode.$(OBJEXT) Parser/TypeData.$(OBJEXT) \
 	Parser/LinkageSpec.$(OBJEXT) Parser/parserutility.$(OBJEXT) \
-	$(am__objects_4) ResolvExpr/AlternativePrinter.$(OBJEXT) \
-	$(am__objects_5) $(am__objects_6) \
+	$(am__objects_5) ResolvExpr/AlternativePrinter.$(OBJEXT) \
+	$(am__objects_6) $(am__objects_7) \
 	Tuples/TupleAssignment.$(OBJEXT) \
 	Tuples/TupleExpansion.$(OBJEXT) Tuples/Explode.$(OBJEXT) \
 	Validate/HandleAttributes.$(OBJEXT) \
 	Virtual/ExpandCasts.$(OBJEXT)
-am____driver_cfa_cpp_OBJECTS = $(am__objects_8)
+am____driver_cfa_cpp_OBJECTS = $(am__objects_9)
 ___driver_cfa_cpp_OBJECTS = $(am____driver_cfa_cpp_OBJECTS)
 am__DEPENDENCIES_1 =
@@ -366,5 +375,5 @@
 ETAGS = etags
 CTAGS = ctags
-am__DIST_COMMON = $(srcdir)/CodeGen/module.mk \
+am__DIST_COMMON = $(srcdir)/AST/module.mk $(srcdir)/CodeGen/module.mk \
 	$(srcdir)/CodeTools/module.mk $(srcdir)/Common/module.mk \
 	$(srcdir)/Concurrency/module.mk \
@@ -526,25 +535,25 @@
 AUTOMAKE_OPTIONS = foreign subdir-objects
 ACLOCAL_AMFLAGS = -I automake
-SRC = main.cc MakeLibCfa.cc CompilationState.cc $(SRC_CODEGEN) \
-	CodeGen/Generate.cc CodeGen/FixNames.cc CodeTools/DeclStats.cc \
-	CodeTools/ResolvProtoDump.cc CodeTools/TrackLoc.cc \
-	Concurrency/Keywords.cc Concurrency/Waitfor.cc $(SRC_COMMON) \
-	Common/DebugMalloc.cc $(SRC_CONTROLSTRUCT) \
-	ControlStruct/ExceptTranslate.cc GenPoly/Box.cc \
-	GenPoly/GenPoly.cc GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc \
-	GenPoly/Specialize.cc GenPoly/FindFunction.cc \
-	GenPoly/InstantiateGeneric.cc InitTweak/GenInit.cc \
-	InitTweak/FixInit.cc InitTweak/FixGlobalInit.cc \
-	InitTweak/InitTweak.cc Parser/parser.yy Parser/lex.ll \
-	Parser/TypedefTable.cc Parser/ParseNode.cc \
-	Parser/DeclarationNode.cc Parser/ExpressionNode.cc \
-	Parser/StatementNode.cc Parser/InitializerNode.cc \
-	Parser/TypeData.cc Parser/LinkageSpec.cc \
-	Parser/parserutility.cc $(SRC_RESOLVEXPR) \
-	ResolvExpr/AlternativePrinter.cc $(SRC_SYMTAB) $(SRC_SYNTREE) \
-	Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
-	Tuples/Explode.cc Validate/HandleAttributes.cc \
-	Virtual/ExpandCasts.cc
-SRCDEMANGLE = CompilationState.cc $(SRC_CODEGEN) \
+SRC = main.cc MakeLibCfa.cc CompilationState.cc $(SRC_AST) \
+	$(SRC_CODEGEN) CodeGen/Generate.cc CodeGen/FixNames.cc \
+	CodeTools/DeclStats.cc CodeTools/ResolvProtoDump.cc \
+	CodeTools/TrackLoc.cc Concurrency/Keywords.cc \
+	Concurrency/Waitfor.cc $(SRC_COMMON) Common/DebugMalloc.cc \
+	$(SRC_CONTROLSTRUCT) ControlStruct/ExceptTranslate.cc \
+	GenPoly/Box.cc GenPoly/GenPoly.cc GenPoly/ScrubTyVars.cc \
+	GenPoly/Lvalue.cc GenPoly/Specialize.cc \
+	GenPoly/FindFunction.cc GenPoly/InstantiateGeneric.cc \
+	InitTweak/GenInit.cc InitTweak/FixInit.cc \
+	InitTweak/FixGlobalInit.cc InitTweak/InitTweak.cc \
+	Parser/parser.yy Parser/lex.ll Parser/TypedefTable.cc \
+	Parser/ParseNode.cc Parser/DeclarationNode.cc \
+	Parser/ExpressionNode.cc Parser/StatementNode.cc \
+	Parser/InitializerNode.cc Parser/TypeData.cc \
+	Parser/LinkageSpec.cc Parser/parserutility.cc \
+	$(SRC_RESOLVEXPR) ResolvExpr/AlternativePrinter.cc \
+	$(SRC_SYMTAB) $(SRC_SYNTREE) Tuples/TupleAssignment.cc \
+	Tuples/TupleExpansion.cc Tuples/Explode.cc \
+	Validate/HandleAttributes.cc Virtual/ExpandCasts.cc
+SRCDEMANGLE = CompilationState.cc $(SRC_AST) $(SRC_CODEGEN) \
 	Concurrency/Keywords.cc $(SRC_COMMON) $(SRC_CONTROLSTRUCT) \
 	GenPoly/GenPoly.cc GenPoly/Lvalue.cc InitTweak/GenInit.cc \
@@ -559,4 +568,17 @@
 @WITH_LIBTCMALLOC_TRUE@LIBTCMALLOC = -ltcmalloc
 @WITH_LIBTCMALLOC_TRUE@TCMALLOCFLAG = -DTCMALLOC
+SRC_AST = \
+	AST/Attribute.cpp \
+	AST/Convert.cpp \
+	AST/Decl.cpp \
+	AST/DeclReplacer.cpp \
+	AST/Expr.cpp \
+	AST/Init.cpp \
+	AST/LinkageSpec.cpp \
+	AST/Node.cpp \
+	AST/Stmt.cpp \
+	AST/Type.cpp \
+	AST/TypeSubstitution.cpp
+
 SRC_CODEGEN = \
 	CodeGen/CodeGenerator.cc \
@@ -667,6 +689,6 @@
 
 .SUFFIXES:
-.SUFFIXES: .cc .ll .lo .o .obj .yy
-$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Validate/module.mk $(srcdir)/Virtual/module.mk $(am__configure_deps)
+.SUFFIXES: .cc .cpp .ll .lo .o .obj .yy
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(srcdir)/AST/module.mk $(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Validate/module.mk $(srcdir)/Virtual/module.mk $(am__configure_deps)
 	@for dep in $?; do \
 	  case '$(am__configure_deps)' in \
@@ -688,5 +710,5 @@
 	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
 	esac;
-$(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Validate/module.mk $(srcdir)/Virtual/module.mk $(am__empty):
+$(srcdir)/AST/module.mk $(srcdir)/CodeGen/module.mk $(srcdir)/CodeTools/module.mk $(srcdir)/Concurrency/module.mk $(srcdir)/Common/module.mk $(srcdir)/ControlStruct/module.mk $(srcdir)/GenPoly/module.mk $(srcdir)/InitTweak/module.mk $(srcdir)/Parser/module.mk $(srcdir)/ResolvExpr/module.mk $(srcdir)/SymTab/module.mk $(srcdir)/SynTree/module.mk $(srcdir)/Tuples/module.mk $(srcdir)/Validate/module.mk $(srcdir)/Virtual/module.mk $(am__empty):
 
 $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
@@ -701,4 +723,26 @@
 clean-noinstLIBRARIES:
 	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+AST/$(am__dirstamp):
+	@$(MKDIR_P) AST
+	@: > AST/$(am__dirstamp)
+AST/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) AST/$(DEPDIR)
+	@: > AST/$(DEPDIR)/$(am__dirstamp)
+AST/Attribute.$(OBJEXT): AST/$(am__dirstamp) \
+	AST/$(DEPDIR)/$(am__dirstamp)
+AST/Convert.$(OBJEXT): AST/$(am__dirstamp) \
+	AST/$(DEPDIR)/$(am__dirstamp)
+AST/Decl.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
+AST/DeclReplacer.$(OBJEXT): AST/$(am__dirstamp) \
+	AST/$(DEPDIR)/$(am__dirstamp)
+AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
+AST/Init.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
+AST/LinkageSpec.$(OBJEXT): AST/$(am__dirstamp) \
+	AST/$(DEPDIR)/$(am__dirstamp)
+AST/Node.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
+AST/Stmt.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
+AST/Type.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
+AST/TypeSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
+	AST/$(DEPDIR)/$(am__dirstamp)
 CodeGen/$(am__dirstamp):
 	@$(MKDIR_P) CodeGen
@@ -1097,4 +1141,5 @@
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
+	-rm -f AST/*.$(OBJEXT)
 	-rm -f CodeGen/*.$(OBJEXT)
 	-rm -f CodeTools/*.$(OBJEXT)
@@ -1119,4 +1164,15 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MakeLibCfa.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Attribute.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Convert.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Decl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/DeclReplacer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Expr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Init.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/LinkageSpec.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Node.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Stmt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Type.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/TypeSubstitution.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/CodeGenerator.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@CodeGen/$(DEPDIR)/FixMain.Po@am__quote@
@@ -1261,4 +1317,28 @@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
 
+.cpp.o:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
 .ll.cc:
 	$(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
@@ -1393,4 +1473,6 @@
 	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
 	-rm -f ../driver/$(am__dirstamp)
+	-rm -f AST/$(DEPDIR)/$(am__dirstamp)
+	-rm -f AST/$(am__dirstamp)
 	-rm -f CodeGen/$(DEPDIR)/$(am__dirstamp)
 	-rm -f CodeGen/$(am__dirstamp)
@@ -1438,5 +1520,5 @@
 
 distclean: distclean-am
-	-rm -rf ./$(DEPDIR) CodeGen/$(DEPDIR) CodeTools/$(DEPDIR) Common/$(DEPDIR) Common/Stats/$(DEPDIR) Concurrency/$(DEPDIR) ControlStruct/$(DEPDIR) GenPoly/$(DEPDIR) InitTweak/$(DEPDIR) Parser/$(DEPDIR) ResolvExpr/$(DEPDIR) SymTab/$(DEPDIR) SynTree/$(DEPDIR) Tuples/$(DEPDIR) Validate/$(DEPDIR) Virtual/$(DEPDIR)
+	-rm -rf ./$(DEPDIR) AST/$(DEPDIR) CodeGen/$(DEPDIR) CodeTools/$(DEPDIR) Common/$(DEPDIR) Common/Stats/$(DEPDIR) Concurrency/$(DEPDIR) ControlStruct/$(DEPDIR) GenPoly/$(DEPDIR) InitTweak/$(DEPDIR) Parser/$(DEPDIR) ResolvExpr/$(DEPDIR) SymTab/$(DEPDIR) SynTree/$(DEPDIR) Tuples/$(DEPDIR) Validate/$(DEPDIR) Virtual/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
@@ -1484,5 +1566,5 @@
 
 maintainer-clean: maintainer-clean-am
-	-rm -rf ./$(DEPDIR) CodeGen/$(DEPDIR) CodeTools/$(DEPDIR) Common/$(DEPDIR) Common/Stats/$(DEPDIR) Concurrency/$(DEPDIR) ControlStruct/$(DEPDIR) GenPoly/$(DEPDIR) InitTweak/$(DEPDIR) Parser/$(DEPDIR) ResolvExpr/$(DEPDIR) SymTab/$(DEPDIR) SynTree/$(DEPDIR) Tuples/$(DEPDIR) Validate/$(DEPDIR) Virtual/$(DEPDIR)
+	-rm -rf ./$(DEPDIR) AST/$(DEPDIR) CodeGen/$(DEPDIR) CodeTools/$(DEPDIR) Common/$(DEPDIR) Common/Stats/$(DEPDIR) Concurrency/$(DEPDIR) ControlStruct/$(DEPDIR) GenPoly/$(DEPDIR) InitTweak/$(DEPDIR) Parser/$(DEPDIR) ResolvExpr/$(DEPDIR) SymTab/$(DEPDIR) SynTree/$(DEPDIR) Tuples/$(DEPDIR) Validate/$(DEPDIR) Virtual/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/Tuples/TupleExpansion.cc	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -353,4 +353,9 @@
 	}
 
+	const ast::TypeInstType * isTtype( const ast::Type * type ) {
+		#warning unimplemented
+		return nullptr;
+	}
+
 	namespace {
 		/// determines if impurity (read: side-effects) may exist in a piece of code. Currently gives a very crude approximation, wherein any function call expression means the code may be impure
Index: src/include/cassert
===================================================================
--- src/include/cassert	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/include/cassert	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -19,4 +19,9 @@
 
 #include_next <cassert>
+
+#include <string>
+
+template < typename ... Params >
+std::string toString( const Params & ... params );
 
 #ifdef NDEBUG
Index: src/main.cc
===================================================================
--- src/main.cc	(revision d1487780c1f67242d6e2063860a40cc32c2395ee)
+++ src/main.cc	(revision a83044fb86cf36e20d6c0f6fbc995d0b814fe1d7)
@@ -40,5 +40,4 @@
 #include "Common/Stats.h"
 #include "Common/PassVisitor.h"
-// #include "AST/Pass.hpp"
 #include "Common/SemanticError.h"           // for SemanticError
 #include "Common/UnimplementedError.h"      // for UnimplementedError
