Index: src/AST/CVQualifiers.hpp
===================================================================
--- src/AST/CVQualifiers.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
+++ src/AST/CVQualifiers.hpp	(revision 3d8d7a7db7135a81d66ceb79ddf7b61a8bbf0643)
@@ -60,8 +60,8 @@
 
 	bool operator== ( Qualifiers a, Qualifiers b ) {
-		return (a & EquivQualifiers) == (b & EquivQualifiers);
+		return (a.val & EquivQualifiers) == (b.val & EquivQualifiers);
 	}
 	bool operator!= ( Qualifiers a, Qualifiers b ) {
-		return (a & EquivQualifiers) != (b & EquivQualifiers);
+		return !(a == b);
 	}
 	bool operator<= ( Qualifiers a, Qualifiers b ) {
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
+++ src/AST/Decl.cpp	(revision 3d8d7a7db7135a81d66ceb79ddf7b61a8bbf0643)
@@ -45,9 +45,14 @@
 }
 
+// --- FunctionDecl
+
+const Type * FunctionDecl::get_type() const override { return type.get(); }
+void FunctionDecl::set_type(Type * t) override { type = strict_dynamic_cast< FunctionType* >( t ); }
+
 // --- TypeDecl
 
 std::string TypeDecl::typeString() const {
 	static const std::string kindNames[] = { "object type", "function type", "tuple type" };
-	assertf( sizeof(kindNames)/sizeof(kindNames[0]) == DeclarationNode::NoTypeClass-1, 
+	assertf( sizeof(kindNames)/sizeof(kindNames[0]) == DeclarationNode::NoTypeClass-1,
 		"typeString: kindNames is out of sync." );
 	assertf( kind < sizeof(kindNames)/sizeof(kindNames[0]), "TypeDecl's kind is out of bounds." );
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
+++ src/AST/Decl.hpp	(revision 3d8d7a7db7135a81d66ceb79ddf7b61a8bbf0643)
@@ -119,4 +119,5 @@
 };
 
+/// Object declaration `int foo()`
 class FunctionDecl : public DeclWithType {
 public:
@@ -131,6 +132,6 @@
 	  stmts( stmts ) {}
 
-	const Type * get_type() const override { return type.get(); }
-	void set_type(Type * t) override { type = strict_dynamic_cast< FunctionType* >( t ); }
+	const Type * get_type() const override;
+	void set_type(Type * t) override;
 
 	bool has_body() const { return stmts; }
@@ -189,5 +190,5 @@
 	TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b,
 		TypeVar::Kind k, bool s, Type* i = nullptr )
-	: NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ), 
+	: NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
 	  init( i ) {}
 
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
+++ src/AST/Pass.hpp	(revision 3d8d7a7db7135a81d66ceb79ddf7b61a8bbf0643)
@@ -29,4 +29,5 @@
 #include "AST/Init.hpp"
 #include "AST/Stmt.hpp"
+#include "AST/Type.hpp"
 
 #include "AST/Visitor.hpp"
@@ -189,5 +190,9 @@
 
 	template< typename node_t >
-	auto call_accept( const node_t * node ) -> decltype( node->accept(*this) );
+	auto call_accept( const node_t * node ) -> typename std::enable_if<
+				!std::is_base_of<ast::Expr, node_t>::value &&
+				!std::is_base_of<ast::Stmt, node_t>::value
+			, decltype( node->accept(*this) )
+		>::type;
 
 	template< template <class...> class container_t >
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
+++ src/AST/Pass.impl.hpp	(revision 3d8d7a7db7135a81d66ceb79ddf7b61a8bbf0643)
@@ -64,5 +64,5 @@
 
 			std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto {
-					return new DeclStmt( decl );
+					return new DeclStmt( decl->location, decl );
 				});
 			decls->clear();
@@ -119,5 +119,12 @@
 	template< typename pass_t >
 	template< typename node_t >
-	auto Pass< pass_t >::call_accept( const node_t * node ) -> decltype( node->accept(*this) ) {
+	auto Pass< pass_t >::call_accept( const node_t * node )
+		-> typename std::enable_if<
+				!std::is_base_of<ast::Expr, node_t>::value &&
+				!std::is_base_of<ast::Stmt, node_t>::value
+			, decltype( node->accept(*this) )
+		>::type
+
+	{
 		__pedantic_pass_assert( __visit_children() );
 		__pedantic_pass_assert( expr );
@@ -296,5 +303,5 @@
 		child_t parent_t::*child
 	) {
-		static_assert( std::is_base_of<parent_t, node_t>::value, "Error deductiing member object" );
+		static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
 
 		if(__pass::skip(parent->*child)) return;
@@ -424,5 +431,5 @@
 				new ast::ArrayType(
 					new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
-					nullptr, true, false
+					nullptr, VariableLen, DynamicDim
 				)
 			);
@@ -434,5 +441,5 @@
 				ValueGuard< bool > oldInFunction( inFunction );
 				inFunction = true;
-				maybe_accept( node, &FunctionDecl::statements );
+				maybe_accept( node, &FunctionDecl::stmts );
 				maybe_accept( node, &FunctionDecl::attributes );
 			)
@@ -537,5 +544,5 @@
 
 	VISIT(
-		maybe_accept( node, &TypeDecl::assertions, *this );
+		maybe_accept( node, &TypeDecl::assertions );
 
 		{
@@ -614,4 +621,74 @@
 }
 
+//--------------------------------------------------------------------------
+// ExprStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ExprStmt * node ) {
+	VISIT_START( node );
+
+	VISIT(
+		maybe_accept( node, &ExprStmt::expr );
+	)
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// AsmStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::AsmStmt * node ) {
+	VISIT_START( node )
+
+	VISIT(
+		maybe_accept( node, &AsmStmt::instruction );
+		maybe_accept( node, &AsmStmt::output      );
+		maybe_accept( node, &AsmStmt::input       );
+		maybe_accept( node, &AsmStmt::clobber     );
+	)
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// DirectiveStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DirectiveStmt * node ) {
+	VISIT_START( node )
+
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// IfStmt
+template< typename pass_t >
+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)
+		guard_indexer guard { *this };
+		maybe_accept( node, &IfStmt::inits    );
+		maybe_accept( node, &IfStmt::cond     );
+		maybe_accept( node, &IfStmt::thenPart );
+		maybe_accept( node, &IfStmt::elsePart );
+	})
+	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// WhileStmt
+template< typename pass_t >
+const ast::Stmt * ast::Pass< pass_t >::visit( const WhileStmt * node ) {
+	VISIT_START( node );
+
+	VISIT({
+		// while statements introduce a level of scope (for the initialization)
+		guard_indexer guard { *this };
+		maybe_accept( node, &WhileStmt::inits );
+		maybe_accept( node, &WhileStmt::cond  );
+		maybe_accept( node, &WhileStmt::body  );
+	})
+
+	VISIT_END( Stmt, node );
+}
 
 //--------------------------------------------------------------------------
@@ -667,5 +744,5 @@
 	)
 
-	VISIT_END( Attribute *, node );
+	VISIT_END( Attribute, node );
 }
 
Index: src/AST/Pass.proto.hpp
===================================================================
--- src/AST/Pass.proto.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
+++ src/AST/Pass.proto.hpp	(revision 3d8d7a7db7135a81d66ceb79ddf7b61a8bbf0643)
@@ -241,5 +241,5 @@
 		INDEXER_FUNC1( addUnion  , const UnionDecl *     );
 		INDEXER_FUNC1( addTrait  , const TraitDecl *     );
-		INDEXER_FUNC2( addWith   , const std::list< Expression * > &, const Node * );
+		INDEXER_FUNC2( addWith   , const std::list< ptr<Expr> > &, const Node * );
 
 		// A few extra functions have more complicated behaviour, they are hand written
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 89c2f7c92369856ac89bc39ac4e4671b2ac71fb3)
+++ src/AST/Stmt.hpp	(revision 3d8d7a7db7135a81d66ceb79ddf7b61a8bbf0643)
@@ -62,4 +62,8 @@
 private:
 	CompoundStmt* clone() const override { return new CompoundStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -73,4 +77,8 @@
 private:
 	NullStmt* clone() const override { return new NullStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -80,9 +88,13 @@
 	ptr<Expr> expr;
 
-	ExprStmt( const CodeLocation& loc, const Expr* e ) : Stmt(loc), expr(e) {}
+	ExprStmt( const CodeLocation & loc, const Expr * e ) : Stmt(loc), expr(e) {}
 
 	const Stmt * accept( Visitor& v ) const override { return v.visit( this ); }
 private:
 	ExprStmt * clone() const override { return new ExprStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -106,4 +118,8 @@
 private:
 	AsmStmt* clone() const override { return new AsmStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -119,4 +135,8 @@
 private:
 	DirectiveStmt* clone() const override { return new DirectiveStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -137,4 +157,8 @@
 private:
 	IfStmt* clone() const override { return new IfStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -151,4 +175,8 @@
 private:
 	SwitchStmt* clone() const override { return new SwitchStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -167,4 +195,8 @@
 private:
 	CaseStmt* clone() const override { return new CaseStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -184,4 +216,8 @@
 private:
 	WhileStmt* clone() const override { return new WhileStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -190,10 +226,10 @@
 	std::vector<ptr<Stmt>> inits;
 	ptr<Expr> cond;
-	ptr<Expr> increment;
+	ptr<Expr> inc;
 	ptr<Stmt> body;
 
 	ForStmt( const CodeLocation& loc, std::vector<ptr<Stmt>>&& inits, const Expr* cond,
-		const Expr* increment, const Stmt* body, std::vector<Label>&& labels = {} )
-	: Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), increment(increment),
+		const Expr* inc, const Stmt* body, std::vector<Label>&& labels = {} )
+	: Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc),
 	  body(body) {}
 
@@ -201,4 +237,8 @@
 private:
 	ForStmt* clone() const override { return new ForStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -225,4 +265,9 @@
 private:
 	BranchStmt* clone() const override { return new BranchStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
+
 	static const char * kindNames[kindEnd];
 };
@@ -238,4 +283,8 @@
 private:
 	ReturnStmt* clone() const override { return new ReturnStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -255,4 +304,8 @@
 private:
 	ThrowStmt* clone() const override { return new ThrowStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -271,4 +324,8 @@
 private:
 	TryStmt* clone() const override { return new TryStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -289,4 +346,8 @@
 private:
 	CatchStmt* clone() const override { return new CatchStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -302,4 +363,8 @@
 private:
 	FinallyStmt* clone() const override { return new FinallyStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -338,4 +403,8 @@
 private:
 	WaitForStmt* clone() const override { return new WaitForStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -352,4 +421,8 @@
 private:
 	WithStmt* clone() const override { return new WithStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -364,4 +437,8 @@
 private:
 	DeclStmt* clone() const override { return new DeclStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -377,4 +454,8 @@
 private:
 	ImplicitCtorDtorStmt* clone() const override { return new ImplicitCtorDtorStmt{ *this }; }
+
+	/// Must be copied in ALL derived classes
+	template<typename node_t>
+	friend auto mutate(const node_t * node);
 };
 
@@ -390,40 +471,40 @@
 inline void increment( const class ExprStmt * node, Node::ref_type ref ) { node->increment( ref ); }
 inline void decrement( const class ExprStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
 inline void increment( const class NullStmt * node, Node::ref_type ref ) { node->increment( ref ); }
 inline void decrement( const class NullStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
-// inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); }
-// inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
+inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); }
+inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
 
 }
