Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 335f2d883b176ca380bde3efee3ab1b59fab5f7b)
+++ src/AST/Print.cpp	(revision b0ec9711a35db17d11fd4733884f1d7ba52d3b68)
@@ -22,7 +22,5 @@
 #include "TypeSubstitution.hpp"
 
-#include "Common/utility.h" // for group_iterate
-
-using namespace std;
+#include "Common/utility.h"      // for group_iterate
 
 namespace ast {
@@ -30,8 +28,8 @@
 template <typename C, typename... T>
 constexpr auto make_array(T&&... values) ->
-	array<C,sizeof...(T)>
+	std::array<C,sizeof...(T)>
 {
-	return array<C,sizeof...(T)>{
-		forward<T>(values)...
+	return std::array<C,sizeof...(T)>{
+		std::forward<T>(values)...
 	};
 }
@@ -39,9 +37,8 @@
 class Printer : public Visitor {
 public:
-	ostream & os;
+	std::ostream & os;
 	Indenter indent;
-	bool short_mode;
-
-	Printer(ostream & os, Indenter indent, bool short_mode) : os( os ), indent( indent ), short_mode(short_mode) {}
+
+	Printer(std::ostream & os, Indenter indent) : os( os ), indent( indent ) {}
 
 private:
@@ -54,5 +51,5 @@
 				// need an endl after each element because it's not
 				// easy to know when each individual item should end
-				os << endl;
+				os << std::endl;
 			} // if
 		} // for
@@ -77,5 +74,5 @@
 
 	template<typename storage_t, size_t N>
-	void print(const storage_t & storage, const array<const char *, N> & Names ) {
+	void print(const storage_t & storage, const std::array<const char *, N> & Names ) {
 		if ( storage.any() ) {
 			for ( size_t i = 0; i < Names.size(); i += 1 ) {
@@ -99,63 +96,47 @@
 	}
 
-	void print( const ast::AggregateDecl * node ) {
-		os << node->typeString() << " " << node->name << ":";
-		if ( node->linkage != Linkage::Cforall ) {
-			os << " " << Linkage::name( node->linkage );
-		} // if
-		os << " with body : " << (node->body ? "yes " : "no ");
-
-		if ( ! node->params.empty() ) {
-			os << endl << indent << "... with parameters" << endl;
-			++indent;
-			printAll( node->params );
-			--indent;
-		} // if
-		if ( ! node->members.empty() ) {
-			os << endl << indent << "... with members" << endl;
-			++indent;
-			printAll( node->members );
-			--indent;
-		} // if
-		if ( ! node->attributes.empty() ) {
-			os << endl << indent << "... with attributes" << endl;
-			++indent;
-			printAll( node->attributes );
-			--indent;
-		} // if
-		os << endl;
-	}
-
-	void print( const ast::NamedTypeDecl * node ) {
-		if ( !node->name.empty() ) os << node->name << ": ";
-
-		if ( node->linkage != Linkage::Cforall ) {
-			os << Linkage::name( node->linkage ) << " ";
-		} // if
-		print( node->storage );
-		os << node->typeString();
-		if ( node->base ) {
-			os << " for ";
-			++indent;
-			node->base->accept( *this );
-			--indent;
-		} // if
-		if ( ! node->params.empty() ) {
-			os << endl << indent << "... with parameters" << endl;
-			++indent;
-			printAll( node->params );
-			--indent;
-		} // if
-		if ( ! node->assertions.empty() ) {
-			os << endl << indent << "... with assertions" << endl;
-			++indent;
-			printAll( node->assertions );
-			--indent;
-		} // if
+	void print( const ast::ParameterizedType::ForallList & forall ) {
+		if ( forall.empty() ) return;	
+		os << "forall" << std::endl;
+		++indent;
+		printAll( forall );
+		os << indent;
+		--indent;
+	}
+
+	void print( const std::vector<ptr<Attribute>> & attrs ) {
+		if ( attrs.empty() ) return;
+		os << "with attributes" << std::endl;
+		++indent;
+		printAll( attrs );
+		--indent;
+	}
+
+	void print( const std::vector<ptr<Expr>> & params ) {
+		if ( params.empty() ) return;
+		os << std::endl << indent << "... with parameters" << std::endl;
+		++indent;
+		printAll( params );
+		--indent;
+	}
+
+	void preprint( const ast::Type * node ) {
+		print( node->qualifiers );
+	}
+
+	void preprint( const ast::ParameterizedType * node ) {
+		print( node->forall );
+		print( node->qualifiers );
+	}
+
+	void preprint( const ast::ReferenceToType * node ) {
+		print( node->forall );
+		print( node->attributes );
+		print( node->qualifiers );
 	}
 
 public:
-	virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) {
-		if ( !node->name.empty() ) os << node->name << ": ";
+	virtual const ast::DeclWithType *     visit( const ast::ObjectDecl           * node ) {
+		if ( node->name != "" ) os << node->name << ": ";
 
 		if ( node->linkage != Linkage::Cforall ) {
@@ -176,14 +157,14 @@
 					? "maybe constructed"
 					: "not constructed"
-				) << ")" << endl << indent+1;
+				) << ")" << std::endl << indent+1;
 
 			++indent;
 			node->init->accept( *this );
 			--indent;
-			os << endl;
+			os << std::endl;
 		} // if
 
 		if ( ! node->attributes.empty() ) {
-			os << endl << indent << "... with attributes:" << endl;
+			os << std::endl << indent << "... with attributes:" << std::endl;
 			++indent;
 			printAll( node->attributes );
@@ -198,444 +179,496 @@
 	}
 
-	virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) {
-		if ( !node->name.empty() ) {
-			os << node->name << ": ";
-		} // if
-		if ( node->linkage != Linkage::Cforall ) {
-			os << Linkage::name( node->linkage ) << " ";
-		} // if
-
-		printAll( node->attributes );
-
-		print( node->storage );
-		print( node->funcSpec );
-
-		if ( node->type ) {
-			node->type->accept( *this );
+	virtual const ast::DeclWithType *     visit( const ast::FunctionDecl         * node ) {
+		return node;
+	}
+
+	virtual const ast::Decl *             visit( const ast::StructDecl           * node ) {
+		return node;
+	}
+
+	virtual const ast::Decl *             visit( const ast::UnionDecl            * node ) {
+		return node;
+	}
+
+	virtual const ast::Decl *             visit( const ast::EnumDecl             * node ) {
+		return node;
+	}
+
+	virtual const ast::Decl *             visit( const ast::TraitDecl            * node ) {
+		return node;
+	}
+
+	virtual const ast::Decl *             visit( const ast::TypeDecl             * node ) {
+		return node;
+	}
+
+	virtual const ast::Decl *             visit( const ast::TypedefDecl          * node ) {
+		return node;
+	}
+
+	virtual const ast::AsmDecl *          visit( const ast::AsmDecl              * node ) {
+		return node;
+	}
+
+	virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * node ) {
+		return node;
+	}
+
+	virtual const ast::CompoundStmt *     visit( const ast::CompoundStmt         * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::ExprStmt             * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::AsmStmt              * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::DirectiveStmt        * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::IfStmt               * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::WhileStmt            * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::ForStmt              * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::SwitchStmt           * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::CaseStmt             * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::BranchStmt           * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::ReturnStmt           * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::ThrowStmt            * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::TryStmt              * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::CatchStmt            * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::FinallyStmt          * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::WaitForStmt          * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::WithStmt             * node ) {
+		return node;
+	}
+
+	virtual const ast::NullStmt *         visit( const ast::NullStmt             * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::DeclStmt             * node ) {
+		return node;
+	}
+
+	virtual const ast::Stmt *             visit( const ast::ImplicitCtorDtorStmt * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::ApplicationExpr      * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::UntypedExpr          * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::NameExpr             * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::AddressExpr          * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::LabelAddressExpr     * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::CastExpr             * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::KeywordCastExpr      * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::VirtualCastExpr      * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::UntypedMemberExpr    * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::MemberExpr           * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::VariableExpr         * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::ConstantExpr         * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::SizeofExpr           * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::AlignofExpr          * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::UntypedOffsetofExpr  * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::OffsetofExpr         * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::OffsetPackExpr       * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::LogicalExpr          * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::ConditionalExpr      * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::CommaExpr            * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::TypeExpr             * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::AsmExpr              * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::ImplicitCopyCtorExpr * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::ConstructorExpr      * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::CompoundLiteralExpr  * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::RangeExpr            * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::UntypedTupleExpr     * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::TupleExpr            * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::TupleIndexExpr       * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::TupleAssignExpr      * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::StmtExpr             * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::UniqueExpr           * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::UntypedInitExpr      * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::InitExpr             * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::DeletedExpr          * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::DefaultArgExpr       * node ) {
+		return node;
+	}
+
+	virtual const ast::Expr *             visit( const ast::GenericExpr          * node ) {
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::VoidType             * node ) {
+		preprint( node );
+		os << "void";
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::BasicType            * node ) {
+		preprint( node );
+		os << ast::BasicType::typeNames[ node->kind ];
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::PointerType          * node ) {
+		preprint( node );
+		if ( ! node->isArray() ) {
+			os << "pointer to ";
 		} else {
-			os << "untyped entity ";
-		} // if
-
-		if ( node->stmts ) {
-			os << indent << "... with body" << endl << indent+1;
+			os << "decayed ";
+			if ( node->isStatic ) {
+				os << "static ";
+			}
+
+			if ( node->isVarLen ) {
+				os << "variable length array of ";
+			} else if ( node->dimension ) {
+				os << "array of ";
+				node->dimension->accept( *this );
+				os << " ";
+			}
+		}
+
+		if ( node->base ) {
+			node->base->accept( *this );
+		} else {
+			os << "UNDEFINED";
+		}
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::ArrayType            * node ) {
+		preprint( node );
+		if ( node->isStatic ) {
+			os << "static ";
+		}
+
+		if ( node->isVarLen ) {
+			os << "variable length array of ";
+		} else if ( node->dimension ) {
+			os << "array of ";
+		} else {
+			os << "open array of ";
+		}
+
+		if ( node->base ) {
+			node->base->accept( *this );
+		} else {
+			os << "UNDEFINED";
+		}
+
+		if ( node->dimension ) {
+			os << " with dimension of ";
+			node->dimension->accept( *this );
+		}
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::ReferenceType        * node ) {
+		preprint( node );
+
+		os << "reference to ";
+		if ( node->base ) {
+			node->base->accept( *this );
+		} else {
+			os << "UNDEFINED";
+		}
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::QualifiedType        * node ) {
+		preprint( node );
+
+		++indent;
+		os << "Qualified Type:" << std::endl << indent;
+		node->parent->accept( *this );
+		os << std::endl << indent;
+		node->child->accept( *this );
+		os << std::endl;
+		--indent;
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::FunctionType         * node ) {
+		preprint( node );
+
+		os << "function" << std::endl;
+		if ( ! node->params.empty() ) {
+			os << indent << "... with parameters" << std::endl;
 			++indent;
-			node->stmts->accept( *this );
-			--indent;
-		} // if
-		return node;
-	}
-
-	virtual const ast::Decl * visit( const ast::StructDecl * node ) {
-		print(node);
-		return node;
-	}
-
-	virtual const ast::Decl * visit( const ast::UnionDecl * node ) {
-		print(node);
-		return node;
-	}
-
-	virtual const ast::Decl * visit( const ast::EnumDecl * node ) {
-		print(node);
-		return node;
-	}
-
-	virtual const ast::Decl * visit( const ast::TraitDecl * node ) {
-		print(node);
-		return node;
-	}
-
-	virtual const ast::Decl * visit( const ast::TypeDecl * node ) {
-		print( node );
-		if ( node->init ) {
-			os << endl << indent << "with type initializer: ";
-			++indent;
-			node->init->accept( *this );
-			--indent;
-		}
-		return node;
-	}
-
-	virtual const ast::Decl * visit( const ast::TypedefDecl * node ) {
-		print( node );
-		return node;
-	}
-
-	virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) {
-		node->stmt->accept( *this );
-		return node;
-	}
-
-	virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) {
-		os << "Static Assert with condition: ";
-		++indent;
-		node->cond->accept( *this );
-		--indent;
-		os << endl << indent << "and message: ";
-		++indent;
-		node->msg->accept( *this );
-		--indent;
-		os << endl;
-		return node;
-	}
-
-	virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) {
-		os << "CompoundStmt" << endl;
-		++indent;
-		printAll( node->kids );
-		--indent;
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::ExprStmt * node ) {
-		++indent;
-		os << "Expression Statement:" << endl << indent;
-		node->expr->accept( *this );
-		--indent;
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::AsmStmt * node ) {
-		os << "Assembler Statement:" << endl;
-		++indent;
-		os << indent << "instruction: " << endl << indent;
-		node->instruction->accept( *this );
-		if ( ! node->output.empty() ) {
-			os << endl << indent+1 << "output: " << endl;
-			printAll( node->output );
-		} // if
-		if ( ! node->input.empty() ) {
-			os << indent+1 << "input: " << endl;
-			printAll( node->input );
-		} // if
-		if ( ! node->clobber.empty() ) {
-			os << indent+1 << "clobber: " << endl;
-			printAll( node->clobber );
-		} // if
-		--indent;
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) {
-		os << "GCC Directive:" << node->directive << endl;
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::IfStmt * node ) {
-		os << "If on condition: " << endl;
-		os << indent+1;
-		++indent;
-		node->cond->accept( *this );
-		--indent;
-
-		if ( !node->inits.empty() ) {
-			os << indent << "... with initialization: \n";
-			++indent;
-			for ( const Stmt * stmt : node->inits ) {
-				os << indent;
-				stmt->accept( *this );
+			printAll( node->params );
+			if ( node->isVarArgs ) {
+				os << indent << "and a variable number of other arguments" << std::endl;
 			}
 			--indent;
-			os << endl;
-		}
-
-		os << indent << "... then: " << endl;
-
+		} else if ( node->isVarArgs ) {
+			os << indent+1 << "accepting unspecified arguments" << std::endl;
+		}
+
+		os << indent << "... returning";
+		if ( node->returns.empty() ) {
+			os << " nothing" << std::endl;
+		} else {
+			os << std::endl;
+			++indent;
+			printAll( node->returns );
+			--indent;
+		}
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::StructInstType       * node ) {
+		preprint( node );
+
+		os << "instance of struct " << node->name;
+		if ( node->base ) {
+			os << " " << ( node->base->body ? "with" : "without" ) << " body";
+		}
+		print( node->params );
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::UnionInstType        * node ) {
+		preprint( node );
+
+		os << "instance of union " << node->name;
+		if ( node->base ) {
+			os << " " << ( node->base->body ? "with" : "without" ) << " body";
+		}
+		print( node->params );
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::EnumInstType         * node ) {
+		preprint( node );
+
+		os << "instance of enum " << node->name;
+		if ( node->base ) {
+			os << " " << ( node->base->body ? "with" : "without" ) << " body";
+		}
+		print( node->params );
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::TraitInstType        * node ) {
+		preprint( node );
+
+		os << "instance of trait " << node->name;
+		print( node->params );
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::TypeInstType         * node ) {
+		preprint( node );
+
+		os << "instance of type " << node->name 
+		   << " (" << (node->kind == ast::TypeVar::Ftype ? "" : "not ") << "function type)";
+		print( node->params );
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::TupleType            * node ) {
+		preprint( node );
+
+		os << "tuple of types" << std::endl;
 		++indent;
-		os << indent;
-		node->thenPart->accept( *this );
+		printAll( node->types );
 		--indent;
 
-		if ( node->elsePart != 0 ) {
-			os << indent << "... else: " << endl;
-			++indent;
-			os << indent;
-			node->elsePart->accept( *this );
-			--indent;
-		} // if
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::WhileStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::ForStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::CaseStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::BranchStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::TryStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::CatchStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::WithStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::NullStmt * visit( const ast::NullStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::DeclStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::UntypedExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::NameExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::AddressExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::CastExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::MemberExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::VariableExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::ConstantExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::SizeofExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::AlignofExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::LogicalExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::CommaExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::TypeExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::AsmExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::RangeExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::TupleExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::StmtExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::UniqueExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::InitExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::DeletedExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Expr * visit( const ast::GenericExpr * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::VoidType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::BasicType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::PointerType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::ArrayType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::ReferenceType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::QualifiedType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::FunctionType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::StructInstType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::UnionInstType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::EnumInstType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::TraitInstType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::TypeInstType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::TupleType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::TypeofType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::VarArgsType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::ZeroType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::OneType * node ) {
-		return node;
-	}
-
-	virtual const ast::Type * visit( const ast::GlobalScopeType * node ) {
-		return node;
-	}
-
-	virtual const ast::Designation * visit( const ast::Designation * node ) {
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::TypeofType           * node ) {
+		preprint( node );
+
+		if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
+		os << "type-of expression ";
+		if ( node->expr ) {
+			node->expr->accept( *this );
+		} else {
+			os << "UNDEFINED";
+		}
+
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::VarArgsType          * node ) {
+		preprint( node );
+		os << "builtin var args pack";
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::ZeroType             * node ) {
+		preprint( node );
+		os << "zero_t";
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::OneType              * node ) {
+		preprint( node );
+		os << "one_t";
+		return node;
+	}
+
+	virtual const ast::Type *             visit( const ast::GlobalScopeType      * node ) {
+		preprint( node );
+		os << "Global Scope Type";
+		return node;
+	}
+
+	virtual const ast::Designation *      visit( const ast::Designation          * node ) {
 		if ( node->designators.empty() ) return node;
 		os << "... designated by: " << std::endl;
@@ -650,5 +683,5 @@
 	}
 
-	virtual const ast::Init * visit( const ast::SingleInit * node ) {
+	virtual const ast::Init *             visit( const ast::SingleInit           * node ) {
 		os << "Simple Initializer: ";
 		node->value->accept( *this );
@@ -656,5 +689,5 @@
 	}
 
-	virtual const ast::Init * visit( const ast::ListInit * node ) {
+	virtual const ast::Init *             visit( const ast::ListInit             * node ) {
 		os << "Compound initializer: " << std::endl;
 		++indent;
@@ -674,5 +707,5 @@
 	}
 
-	virtual const ast::Init * visit( const ast::ConstructorInit * node ) {
+	virtual const ast::Init *             visit( const ast::ConstructorInit      * node ) {
 		os << "Constructor initializer: " << std::endl;
 		if ( node->ctor ) {
@@ -699,5 +732,5 @@
 	}
 
-	virtual const ast::Attribute * visit( const ast::Attribute * node ) {
+	virtual const ast::Attribute *        visit( const ast::Attribute            * node ) {
 		if ( node->empty() ) return node;
 		os << "Attribute with name: " << node->name;
@@ -710,5 +743,5 @@
 	}
 
-	virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) {
+	virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * node ) {
 		os << indent << "Types:" << std::endl;
 		for ( const auto& i : *node ) {
@@ -732,11 +765,6 @@
 };
 
-void print( ostream & os, const ast::Node * node, Indenter indent ) {
-	Printer printer { os, indent, false };
-	node->accept(printer);
-}
-
-void printShort( ostream & os, const ast::Node * node, Indenter indent ) {
-	Printer printer { os, indent, true };
+void print( std::ostream & os, const ast::Node * node, Indenter indent ) {
+	Printer printer { os, indent };
 	node->accept(printer);
 }
@@ -745,6 +773,6 @@
 // The size here needs to be explicit but at least the compiler will produce an error
 // if the wrong size is specified
-constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
-constexpr array<const char*, 5> Printer::Names::StorageClasses;
-constexpr array<const char*, 6> Printer::Names::Qualifiers;
+constexpr std::array<const char*, 3> Printer::Names::FuncSpecifiers;
+constexpr std::array<const char*, 5> Printer::Names::StorageClasses;
+constexpr std::array<const char*, 6> Printer::Names::Qualifiers;
 }
