Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision cedb545ebaf1640ceff846f06b28f668acbd07cf)
+++ src/AST/Node.hpp	(revision 6a625dec0f64e84a53f9f54b9e3e180ce6265463)
@@ -32,4 +32,7 @@
 		}
 
+		template<typename node_t>
+		friend auto mutate(const node_t * node);
+
 	private:
 		size_t strong_ref = 0;
@@ -37,5 +40,40 @@
 	};
 
-	template< typename node_t, enum  Node::ref_type ref_t>
+	// Mutate a node, non-member function to avoid static type
+	// problems and be able to use auto return
+	template<typename node_t>
+	auto mutate(const node_t * node) {
+		assertf(
+			node->strong_count >= 1,
+			"Error: attempting to mutate a node that appears to have been linked"
+		);
+		if (node->strong_count == 1) {
+			return const_cast<node_t *>(node);
+		}
+
+		assertf(
+			node->weak_count == 0,
+			"Error: mutating node with weak references to it will invalided some references"
+		);
+		return node->clone();
+	}
+
+	// All accept routines should look as follows :
+	// virtual void accept( Visitor &v ) override {
+	// 	return v.visit(this);
+	// }
+	// Using the following wrapper to handle the node type
+	template< typename node_t >
+	auto visit_this( visitor & v, node_t * node ) {
+		ptr<node_t> p;
+		p.node = node;
+		auto r = v.visit(p);
+		p.node = nullptr;
+		return r;
+	}
+
+	// Base class for the smart pointer types
+	// should never really be used.
+	template< typename node_t, enum Node::ref_type ref_t>
 	class ptr_base {
 	public:
@@ -87,70 +125,7 @@
 
 	template< typename node_t >
-	class ptr : public ptr_base< node_t, Node::ref_type::strong > {
-	public:
-		typedef ptr_base< node_t, Node::ref_type::strong > base_t;
-
-		ptr() = default;
-		ptr( node_t node ) : base_t( node ) {}
-		~ptr() = default;
-
-		template< enum  Node::ref_type ref_t >
-		ptr( const ptr_base<node_t, ref_t> & o ) : base_t(o) {}
-
-		template< enum  Node::ref_type ref_t >
-		ptr( ptr_base<node_t, ref_t> && o ) : base_t( std::move(o) ) {}
-
-		template< enum  Node::ref_type o_ref_t >
-		ptr & operator=( const ptr_base<node_t, o_ref_t> & o ) {
-			base_t::operator=(o);
-			return *this;
-		}
-
-		template< enum  Node::ref_type o_ref_t >
-		ptr & operator=( ptr_base<node_t, o_ref_t> && o ) {
-			base_t::operator=(std::move(o));
-			return *this;
-		}
-
-		node_t * mutate() {
-			using base_t::node;
-			assert(node->strong_count);
-			if (node->strong_count == 1) {
-				return node;
-			}
-
-			assertf(node->weak_count == 0, "Error: mutating node with weak references to it will invalided some references");
-			auto n = new node_t(*node);
-			assign(n);
-			return node;
-		}
-	};
+	using ptr = ptr_base< node_t, Node::ref_type::strong >;
 
 	template< typename node_t >
-	class readonly : public ptr_base< node_t, Node::ref_type::weak > {
-	public:
-		typedef ptr_base< node_t, Node::ref_type::strong > base_t;
-
-		readonly() = default;
-		readonly( node_t node ) : base_t( node ) {}
-		~readonly() = default;
-
-		template< enum  Node::ref_type ref_t >
-		readonly( const ptr_base<node_t, ref_t> & o ) : base_t(o) {}
-
-		template< enum  Node::ref_type ref_t >
-		readonly( ptr_base<node_t, ref_t> && o ) : base_t( std::move(o) ) {}
-
-		template< enum  Node::ref_type o_ref_t >
-		readonly & operator=( const ptr_base<node_t, o_ref_t> & o ) {
-			base_t::operator=(o);
-			return *this;
-		}
-
-		template< enum  Node::ref_type o_ref_t >
-		readonly & operator=( ptr_base<node_t, o_ref_t> && o ) {
-			base_t::operator=(std::move(o));
-			return *this;
-		}
-	};
+	using readonly = ptr_base< node_t, Node::ref_type::weak >;
 }
