Index: src/AST/Chain.hpp
===================================================================
--- src/AST/Chain.hpp	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
+++ src/AST/Chain.hpp	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -0,0 +1,63 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Chain.hpp --
+//
+// Author           : Thierry Delisle
+// Created On       : Wed Jun 05 14:11:52 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include "Node.hpp"
+
+namespace ast {
+
+template<typename T>
+struct _chain_mutator;
+
+template<typename node_t, Node::ref_type ref_t>
+struct _chain_mutator<ptr_base<node_t, ref_t>>;
+
+template<template <class...> class container_t, typename node_t, Node::ref_type ref_t>
+struct _chain_mutator<container_t<ptr_base<node_t, ref_t>>>;
+
+template<typename node_t, Node::ref_type ref_t>
+struct _chain_mutator<ptr_base<node_t, ref_t>> {
+	ptr_base<node_t, ref_t> & base;
+
+	template<typename actual_node_t, typename child_t>
+	auto operator()( child_t actual_node_t::*child ) {
+		auto n = mutate(base.get());
+		actual_node_t * node = strict_dynamic_cast<actual_node_t *>(n);
+		base = node;
+		return _chain_mutator< typename std::remove_reference< decltype(node->*child) >::type >{node->*child};
+	}
+
+	node_t * operator->() {
+		auto n = mutate(base.get());
+		base = n;
+		return n;
+	}
+};
+
+template<template <class...> class container_t, typename node_t, Node::ref_type ref_t>
+struct _chain_mutator<container_t<ptr_base<node_t, ref_t>>> {
+	container_t<ptr_base<node_t, ref_t>> & base;
+
+	auto operator[]( size_t i ) {
+		return _chain_mutator<ptr_base<node_t, ref_t>>{base[i]};
+	}
+};
+
+
+template< typename node_t, Node::ref_type ref_t >
+auto chain_mutate( ptr_base<node_t, ref_t> & base ) {
+	return _chain_mutator<ptr_base<node_t, ref_t>>{ base };
+}
+
+}
Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 99d45847f7626033f67b33afdf3e149972c747b0)
+++ src/AST/Convert.cpp	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -749,5 +749,9 @@
 			break;
 		case ast::ConstantExpr::String:
-			rslt = new ConstantExpr{Constant::from_string( node->rep )};
+			rslt = new ConstantExpr{Constant{
+				get<Type>().accept1( node->result ),
+				node->rep,
+				(long long unsigned int)0
+			}};
 			break;
 		}
@@ -2150,5 +2154,6 @@
 				GET_ACCEPT_1(result, Type),
 				old->constant.get_value(),
-				(unsigned long long) old->intValue()
+				(unsigned long long) old->intValue(),
+				ast::ConstantExpr::Kind::Integer
 			);
 		} else if (isFloatlikeConstantType(old->result)) {
@@ -2160,7 +2165,10 @@
 			);
 		} else if (isStringlikeConstantType(old->result)) {
-			rslt = ast::ConstantExpr::from_string(
-				old->location,
-				old->constant.get_value()
+			rslt = new ast::ConstantExpr(
+				old->location,
+				GET_ACCEPT_1(result, Type),
+				old->constant.get_value(),
+				0,
+				ast::ConstantExpr::Kind::String
 			);
 		}
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision 99d45847f7626033f67b33afdf3e149972c747b0)
+++ src/AST/Node.cpp	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -34,4 +34,7 @@
 template< typename node_t, enum ast::Node::ref_type ref_t >
 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base<node_t, ref_t>::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); }
 
 template< typename node_t, enum ast::Node::ref_type ref_t >
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 99d45847f7626033f67b33afdf3e149972c747b0)
+++ src/AST/Node.hpp	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -46,4 +46,6 @@
 	};
 
+	bool unique() const { return strong_count == 1; }
+
 private:
 	/// Make a copy of this node; should be overridden in subclass with more precise return type
@@ -56,8 +58,9 @@
 	mutable size_t strong_count = 0;
 	mutable size_t weak_count = 0;
+	mutable bool was_ever_strong = false;
 
 	void increment(ref_type ref) const {
 		switch (ref) {
-			case ref_type::strong: strong_count++; break;
+			case ref_type::strong: strong_count++; was_ever_strong = true; break;
 			case ref_type::weak  : weak_count  ++; break;
 		}
@@ -176,13 +179,13 @@
 	}
 
-	const node_t * get() const { return  node; }
-	const node_t * operator->() const { return  node; }
-	const node_t & operator* () const { return *node; }
-	explicit operator bool() const { return node; }
-	operator const node_t * () const { return node; }
+	const node_t * get() const { _check(); return  node; }
+	const node_t * operator->() const { _check(); return  node; }
+	const node_t & operator* () const { _check(); return *node; }
+	explicit operator bool() const { _check(); return node; }
+	operator const node_t * () const { _check(); return node; }
 
 	/// wrapper for convenient access to dynamic_cast
 	template<typename o_node_t>
-	const o_node_t * as() const { return dynamic_cast<const o_node_t *>(node); }
+	const o_node_t * as() const { _check(); return dynamic_cast<const o_node_t *>(node); }
 
 	/// wrapper for convenient access to strict_dynamic_cast
@@ -208,4 +211,5 @@
 	void _inc( const node_t * other );
 	void _dec( const node_t * other );
+	void _check() const;
 
 protected:
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 99d45847f7626033f67b33afdf3e149972c747b0)
+++ src/ResolvExpr/Resolver.cc	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -29,4 +29,5 @@
 #include "typeops.h"                     // for extractResultType
 #include "Unify.h"                       // for unify
+#include "AST/Chain.hpp"
 #include "AST/Decl.hpp"
 #include "AST/Init.hpp"
@@ -410,8 +411,8 @@
 
 	void Resolver_old::previsit( ObjectDecl * objectDecl ) {
-		// To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 
-		// class-variable initContext is changed multiple time because the LHS is analysed twice. 
-		// The second analysis changes initContext because of a function type can contain object 
-		// declarations in the return and parameter types. So each value of initContext is 
+		// To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
+		// class-variable initContext is changed multiple time because the LHS is analysed twice.
+		// The second analysis changes initContext because of a function type can contain object
+		// declarations in the return and parameter types. So each value of initContext is
 		// retained, so the type on the first analysis is preserved and used for selecting the RHS.
 		GuardValue( currentObject );
@@ -450,5 +451,5 @@
 
 	void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
-		// default value expressions have an environment which shouldn't be there and trips up 
+		// default value expressions have an environment which shouldn't be there and trips up
 		// later passes.
 		// xxx - it might be necessary to somehow keep the information from this environment, but I
@@ -1118,14 +1119,14 @@
 	}
 
-	class Resolver_new final 
-	: public ast::WithSymbolTable, public ast::WithGuards, 
-	  public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting, 
+	class Resolver_new final
+	: public ast::WithSymbolTable, public ast::WithGuards,
+	  public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,
 	  public ast::WithStmtsToAdd<> {
-	
+
 		ast::ptr< ast::Type > functionReturn = nullptr;
 		// ast::CurrentObject currentObject = nullptr;
 		bool inEnumDecl = false;
 
-	public: 
+	public:
 		Resolver_new() = default;
 		Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
@@ -1170,19 +1171,22 @@
 
 	const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) {
-		// default value expressions have an environment which shouldn't be there and trips up 
+		// default value expressions have an environment which shouldn't be there and trips up
 		// later passes.
 		ast::ptr< ast::FunctionDecl > ret = functionDecl;
 		for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
 			const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
-			
+
 			if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
 				if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
 					if ( init->value->env == nullptr ) continue;
 					// clone initializer minus the initializer environment
-					strict_dynamic_cast< ast::SingleInit * >(
-						strict_dynamic_cast< ast::ObjectDecl * >( 
-							ret.get_and_mutate()->type.get_and_mutate()->params[i].get_and_mutate()
-						)->init.get_and_mutate()
-					)->value.get_and_mutate()->env = nullptr;
+					ast::chain_mutate( ret )
+						( &ast::FunctionDecl::type )
+							( &ast::FunctionType::params )[i]
+								( &ast::ObjectDecl::init )
+									( &ast::SingleInit::value )->env = nullptr;
+
+					assert( functionDecl != ret.get() || functionDecl->unique() );
+					assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env );
 				}
 			}
Index: src/SynTree/BaseSyntaxNode.h
===================================================================
--- src/SynTree/BaseSyntaxNode.h	(revision 99d45847f7626033f67b33afdf3e149972c747b0)
+++ src/SynTree/BaseSyntaxNode.h	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -41,7 +41,4 @@
   /// * Expressions should not finish with a newline, since the expression's parent has better information.
 	virtual void print( std::ostream & os, Indenter indent = {} ) const = 0;
-  // void print( std::ostream & os, unsigned int indent ) {
-  //   print( os, Indenter{ indent });
-  // }
 };
 
Index: src/SynTree/DeclReplacer.cc
===================================================================
--- src/SynTree/DeclReplacer.cc	(revision 99d45847f7626033f67b33afdf3e149972c747b0)
+++ src/SynTree/DeclReplacer.cc	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -30,4 +30,7 @@
 			bool debug;
 		public:
+			size_t replaced;
+
+		public:
 			DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
 
@@ -45,4 +48,7 @@
 			bool debug;
 		public:
+			size_t replaced;
+
+		public:
 			ExprDeclReplacer( const ExprMap & exprMap, bool debug = false );
 
@@ -52,26 +58,28 @@
 	}
 
-	void replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
+	size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
 		PassVisitor<DeclReplacer> replacer( declMap, typeMap, debug );
 		maybeAccept( node, replacer );
+		return replacer.pass.replaced;
 	}
 
-	void replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug ) {
+	size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug ) {
 		TypeMap typeMap;
-		replace( node, declMap, typeMap, debug );
+		return replace( node, declMap, typeMap, debug );
 	}
 
-	void replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug ) {
+	size_t replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug ) {
 		DeclMap declMap;
-		replace( node, declMap, typeMap, debug );
+		return replace( node, declMap, typeMap, debug );
 	}
 
-	void replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug ) {
+	size_t replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug ) {
 		PassVisitor<ExprDeclReplacer> replacer( exprMap, debug );
 		node = maybeMutate( node, replacer );
+		return replacer.pass.replaced;
 	}
 
 	namespace {
-		DeclReplacer::DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug ) : declMap( declMap ), typeMap( typeMap ) , debug( debug ) {}
+		DeclReplacer::DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug ) : declMap( declMap ), typeMap( typeMap ) , debug( debug ), replaced( 0 ) {}
 
 		// replace variable with new node from decl map
@@ -79,4 +87,5 @@
 			// xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
 			if ( declMap.count( varExpr->var ) ) {
+				replaced++;
 				auto replacement = declMap.at( varExpr->var );
 				if ( debug ) {
@@ -89,4 +98,5 @@
 		void DeclReplacer::previsit( TypeInstType * inst ) {
 			if ( typeMap.count( inst->baseType ) ) {
+				replaced++;
 				auto replacement = typeMap.at( inst->baseType );
 				if ( debug ) {
@@ -97,8 +107,9 @@
 		}
 
-		ExprDeclReplacer::ExprDeclReplacer( const ExprMap & exprMap, bool debug ) : exprMap( exprMap ), debug( debug ) {}
+		ExprDeclReplacer::ExprDeclReplacer( const ExprMap & exprMap, bool debug ) : exprMap( exprMap ), debug( debug ), replaced( 0 ) {}
 
 		Expression * ExprDeclReplacer::postmutate( VariableExpr * varExpr ) {
 			if ( exprMap.count( varExpr->var ) ) {
+				replaced++;
 				Expression * replacement = exprMap.at( varExpr->var )->clone();
 				if ( debug ) {
Index: src/SynTree/DeclReplacer.h
===================================================================
--- src/SynTree/DeclReplacer.h	(revision 99d45847f7626033f67b33afdf3e149972c747b0)
+++ src/SynTree/DeclReplacer.h	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -28,9 +28,9 @@
 	typedef std::map< DeclarationWithType *, Expression * > ExprMap;
 
-	void replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug = false );
-	void replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug = false );
-	void replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
+	size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, bool debug = false );
+	size_t replace( BaseSyntaxNode * node, const TypeMap & typeMap, bool debug = false );
+	size_t replace( BaseSyntaxNode * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
 
-	void replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug = false);
+	size_t replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug = false);
 	template<typename T>
 		void replace( T *& node, const ExprMap & exprMap, bool debug = false ) {
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 99d45847f7626033f67b33afdf3e149972c747b0)
+++ src/main.cc	(revision 3cd5fdde9ed74eb5131706e7f87dc45dcdd63a34)
@@ -10,6 +10,6 @@
 // Created On       : Fri May 15 23:12:02 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri May  3 16:10:52 2019
-// Update Count     : 599
+// Last Modified On : Wed Jun  5 13:48:41 2019
+// Update Count     : 600
 //
 
@@ -406,5 +406,5 @@
 
 
-static const char optstring[] = ":hlLmNn:pP:S:twW:D:F:";
+static const char optstring[] = ":hlLmNnpP:S:twW:D:F:";
 
 enum { PreludeDir = 128 };
