Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Convert.cpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -47,8 +47,11 @@
 
 //================================================================================================
-namespace {
+namespace ast {
 
 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
 // allow us to use the same stratagy in the new ast.
+// xxx - since convert back pass works, this concern seems to be unnecessary.
+
+// these need to be accessed in new FixInit now
 ast::Type * sizeType = nullptr;
 ast::FunctionDecl * dereferenceOperator = nullptr;
@@ -63,4 +66,9 @@
 	using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >;
 	Cache cache;
+
+	// Statements can no longer be shared.
+	// however, since StmtExprResult is now implemented, need to still maintain
+	// readonly references.
+	Cache readonlyCache;
 
 	template<typename T>
@@ -154,12 +162,12 @@
 	}
 
-	const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
-		auto&& bfwd = get<Expression>().accept1( node->bitfieldWidth );
-		auto&& type = get<Type>().accept1( node->type );
-		auto&& init = get<Initializer>().accept1( node->init );
-		auto&& attr = get<Attribute>().acceptL( node->attributes );
+	const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {	
 		if ( inCache( node ) ) {
 			return nullptr;
 		}
+		auto bfwd = get<Expression>().accept1( node->bitfieldWidth );
+		auto type = get<Type>().accept1( node->type );
+		auto attr = get<Attribute>().acceptL( node->attributes );
+
 		auto decl = new ObjectDecl(
 			node->name,
@@ -168,9 +176,17 @@
 			bfwd,
 			type->clone(),
-			init,
+			nullptr, // prevent infinite loop
 			attr,
 			Type::FuncSpecifiers( node->funcSpec.val )
 		);
-		return declWithTypePostamble( decl, node );
+
+		// handles the case where node->init references itself
+		// xxx - does it really happen?
+		declWithTypePostamble(decl, node);
+		auto init = get<Initializer>().accept1( node->init );
+		decl->init = init;
+		
+		this->node = decl;
+		return nullptr;
 	}
 
@@ -205,8 +221,8 @@
 		decl->statements = get<CompoundStmt>().accept1( node->stmts );
 		decl->withExprs = get<Expression>().acceptL( node->withExprs );
-		if ( dereferenceOperator == node ) {
+		if ( ast::dereferenceOperator == node ) {
 			Validate::dereferenceOperator = decl;
 		}
-		if ( dtorStructDestroy == node ) {
+		if ( ast::dtorStructDestroy == node ) {
 			Validate::dtorStructDestroy = decl;
 		}
@@ -267,5 +283,5 @@
 		);
 
-		if ( dtorStruct == node ) {
+		if ( ast::dtorStruct == node ) {
 			Validate::dtorStruct = decl;
 		}
@@ -320,5 +336,7 @@
 
 	const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
-		cache.emplace( node, stmt );
+		// force statements in old tree to be unique.
+		// cache.emplace( node, stmt );
+		readonlyCache.emplace( node, stmt );
 		stmt->location = node->location;
 		stmt->labels = makeLabelL( stmt, node->labels );
@@ -337,5 +355,4 @@
 		if ( inCache( node ) ) return nullptr;
 		auto stmt = new ExprStmt( nullptr );
-		cache.emplace( node, stmt );
 		stmt->expr = get<Expression>().accept1( node->expr );
 		return stmtPostamble( stmt, node );
@@ -1011,7 +1028,6 @@
 		auto stmts = node->stmts;
 		// disable sharing between multiple StmtExprs explicitly.
-		if (inCache(stmts)) {
-			stmts = ast::deepCopy(stmts.get());
-		}
+		// this should no longer be true.
+
 		auto rslt = new StmtExpr(
 			get<CompoundStmt>().accept1(stmts)
@@ -1020,4 +1036,8 @@
 		rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
 		rslt->dtors       = get<Expression>().acceptL(node->dtors);
+		if (node->resultExpr) {
+			// this MUST be found by children visit
+			rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(node->resultExpr));
+		}
 
 		auto expr = visitBaseExpr( node, rslt );
@@ -1036,5 +1056,5 @@
 
 		auto expr = visitBaseExpr( node, rslt );
-		this->node = expr;
+		this->node = expr->clone();
 		return nullptr;
 	}
@@ -1126,5 +1146,5 @@
 		auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
 		// I believe this should always be a BasicType.
-		if ( sizeType == node ) {
+		if ( ast::sizeType == node ) {
 			Validate::SizeType = type;
 		}
@@ -1529,4 +1549,6 @@
 
 		// function type is now derived from parameter decls instead of storing them
+
+		/*
 		auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
 		ftype->params.reserve(paramVars.size());
@@ -1540,5 +1562,8 @@
 		}
 		ftype->forall = std::move(forall);
-		visitType(old->type, ftype);
+		*/
+
+		// can function type have attributes? seems not to be the case.
+		// visitType(old->type, ftype);
 
 		auto decl = new ast::FunctionDecl{
@@ -1546,4 +1571,5 @@
 			old->name,
 			// GET_ACCEPT_1(type, FunctionType),
+			std::move(forall),
 			std::move(paramVars),
 			std::move(returnVars),
@@ -1552,8 +1578,9 @@
 			{ old->linkage.val },
 			GET_ACCEPT_V(attributes, Attribute),
-			{ old->get_funcSpec().val }
+			{ old->get_funcSpec().val },
+			old->type->isVarArgs
 		};
 
-		decl->type = ftype;
+		// decl->type = ftype;
 		cache.emplace( old, decl );
 
@@ -1570,9 +1597,9 @@
 
 		if ( Validate::dereferenceOperator == old ) {
-			dereferenceOperator = decl;
+			ast::dereferenceOperator = decl;
 		}
 
 		if ( Validate::dtorStructDestroy == old ) {
-			dtorStructDestroy = decl;
+			ast::dtorStructDestroy = decl;
 		}
 	}
@@ -1599,5 +1626,5 @@
 
 		if ( Validate::dtorStruct == old ) {
-			dtorStruct = decl;
+			ast::dtorStruct = decl;
 		}
 	}
@@ -2531,5 +2558,5 @@
 		// I believe this should always be a BasicType.
 		if ( Validate::SizeType == old ) {
-			sizeType = type;
+			ast::sizeType = type;
 		}
 		visitType( old, type );
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Decl.cpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -48,4 +48,23 @@
 
 // --- FunctionDecl
+
+FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name, 
+		std::vector<ptr<TypeDecl>>&& forall,
+		std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
+		CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
+		std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
+	: DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
+	  stmts( stmts ) {
+		  FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs));
+		  for (auto & param : this->params) {
+			  ftype->params.emplace_back(param->get_type());
+		  }
+		  for (auto & ret : this->returns) {
+			  ftype->returns.emplace_back(ret->get_type());
+		  }
+		  ftype->forall = std::move(forall);
+		  this->type = ftype;
+	  }
+
 
 const Type * FunctionDecl::get_type() const { return type.get(); }
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Decl.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -131,10 +131,10 @@
 	std::vector< ptr<Expr> > withExprs;
 
-	FunctionDecl( const CodeLocation & loc, const std::string & name, 
+	FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
 		std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
 		CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
-		std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {})
-	: DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
-	  stmts( stmts ) {}
+		std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
+	// : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
+	//  stmts( stmts ) {}
 
 	const Type * get_type() const override;
Index: src/AST/DeclReplacer.cpp
===================================================================
--- src/AST/DeclReplacer.cpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/DeclReplacer.cpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -38,4 +38,14 @@
 			const ast::TypeInstType * previsit( const ast::TypeInstType * );
 		};
+
+		struct VarExprReplacer {
+		private:
+			const ExprMap & exprMap;
+			
+		public:
+			VarExprReplacer(const ExprMap & exprMap): exprMap (exprMap) {}
+
+			const Expr * postvisit (const VariableExpr *);
+		};
 	}
 
@@ -54,4 +64,9 @@
 		DeclMap declMap;
 		return replace( node, declMap, typeMap, debug );
+	}
+
+	const ast::Node * replace( const ast::Node * node, const ExprMap & exprMap) {
+		Pass<VarExprReplacer> replacer = {exprMap};
+		return node->accept( replacer );
 	}
 
@@ -88,4 +103,11 @@
 			return ninst;
 		}
+
+		const Expr * VarExprReplacer::postvisit( const VariableExpr * expr ) {
+			if (!exprMap.count(expr->var)) return expr;
+
+			return exprMap.at(expr->var);
+		}
+
 	}
 }
Index: src/AST/DeclReplacer.hpp
===================================================================
--- src/AST/DeclReplacer.hpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/DeclReplacer.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -23,12 +23,15 @@
 	class DeclWithType;
 	class TypeDecl;
+	class Expr;
 
 	namespace DeclReplacer {
 		using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
 		using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
+		using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;
 
 		const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
 		const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
 		const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
+		const Node * replace( const Node * node, const ExprMap & exprMap);
 	}
 }
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Expr.cpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -67,5 +67,5 @@
 // --- UntypedExpr
 
-UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, Expr * arg ) {
+UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, const Expr * arg ) {
 	assert( arg );
 
@@ -92,5 +92,5 @@
 }
 
-UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ) {
+UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ) {
 	assert( lhs && rhs );
 
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Expr.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -226,7 +226,7 @@
 
 	/// Creates a new dereference expression
-	static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );
+	static UntypedExpr * createDeref( const CodeLocation & loc, const Expr * arg );
 	/// Creates a new assignment expression
-	static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs );
+	static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs );
 
 	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
@@ -422,5 +422,5 @@
 		const CodeLocation & loc, const Type * ty, const std::string & r,
 			std::optional<unsigned long long> i )
-	: Expr( loc, ty ), rep( r ), ival( i ) {}
+	: Expr( loc, ty ), rep( r ), ival( i ), underlyer(ty) {}
 
 	/// Gets the integer value of this constant, if one is appropriate to its type.
@@ -617,5 +617,5 @@
 
 	ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
-	: Expr( loc, call->result ) { assert( call ); }
+	: Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); }
 
 	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
@@ -742,4 +742,6 @@
 	std::vector<ptr<Expr>> dtors;              ///< destructor(s) for return variable(s)
 
+	readonly<ExprStmt> resultExpr;
+
 	StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
 
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Fwd.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -137,3 +137,8 @@
 typedef unsigned int UniqueId;
 
+extern Type * sizeType;
+extern FunctionDecl * dereferenceOperator;
+extern StructDecl   * dtorStruct;
+extern FunctionDecl * dtorStructDestroy;
+
 }
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Node.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -49,4 +49,5 @@
 
 	bool unique() const { return strong_count == 1; }
+	bool isManaged() const {return strong_count > 0; }
 
 private:
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Pass.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -236,4 +236,8 @@
 	const ast::Expr * call_accept( const ast::Expr * );
 
+	// requests WithStmtsToAdd directly add to this statement, as if it is a compound.
+
+	const ast::Stmt * call_accept_as_compound(const ast::Stmt *);
+
 	template< typename node_t >
 	auto call_accept( const node_t * node ) -> typename std::enable_if<
@@ -257,4 +261,7 @@
 	template<typename node_t, typename parent_t, typename child_t>
 	void maybe_accept(const node_t * &, child_t parent_t::* child);
+
+	template<typename node_t, typename parent_t, typename child_t>
+	void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);
 
 private:
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/Pass.impl.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -167,4 +167,12 @@
 		__pedantic_pass_assert( stmt );
 
+		return stmt->accept( *this );
+	}
+
+	template< typename core_t >
+	const ast::Stmt * ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
+		__pedantic_pass_assert( __visit_children() );
+		__pedantic_pass_assert( stmt );
+
 		// add a few useful symbols to the scope
 		using __pass::empty;
@@ -324,4 +332,28 @@
 
 		auto new_val = call_accept( old_val );
+
+		static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
+
+		if( __pass::differs(old_val, new_val) ) {
+			auto new_parent = __pass::mutate<core_t>(parent);
+			new_parent->*child = new_val;
+			parent = new_parent;
+		}
+	}
+
+	template< typename core_t >
+	template<typename node_t, typename parent_t, typename child_t>
+	void ast::Pass< core_t >::maybe_accept_as_compound(
+		const node_t * & parent,
+		child_t parent_t::*child
+	) {
+		static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
+
+		if(__pass::skip(parent->*child)) return;
+		const auto & old_val = __pass::get(parent->*child, 0);
+
+		static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
+
+		auto new_val = call_accept_as_compound( old_val );
 
 		static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
@@ -703,6 +735,6 @@
 		maybe_accept( node, &IfStmt::inits    );
 		maybe_accept( node, &IfStmt::cond     );
-		maybe_accept( node, &IfStmt::thenPart );
-		maybe_accept( node, &IfStmt::elsePart );
+		maybe_accept_as_compound( node, &IfStmt::thenPart );
+		maybe_accept_as_compound( node, &IfStmt::elsePart );
 	})
 
@@ -721,5 +753,5 @@
 		maybe_accept( node, &WhileStmt::inits );
 		maybe_accept( node, &WhileStmt::cond  );
-		maybe_accept( node, &WhileStmt::body  );
+		maybe_accept_as_compound( node, &WhileStmt::body  );
 	})
 
@@ -736,8 +768,9 @@
 		// for statements introduce a level of scope (for the initialization)
 		guard_symtab guard { *this };
+		// xxx - old ast does not create WithStmtsToAdd scope for loop inits. should revisit this later.
 		maybe_accept( node, &ForStmt::inits );
 		maybe_accept( node, &ForStmt::cond  );
 		maybe_accept( node, &ForStmt::inc   );
-		maybe_accept( node, &ForStmt::body  );
+		maybe_accept_as_compound( node, &ForStmt::body  );
 	})
 
@@ -834,5 +867,5 @@
 		maybe_accept( node, &CatchStmt::decl );
 		maybe_accept( node, &CatchStmt::cond );
-		maybe_accept( node, &CatchStmt::body );
+		maybe_accept_as_compound( node, &CatchStmt::body );
 	})
 
Index: src/AST/SymbolTable.cpp
===================================================================
--- src/AST/SymbolTable.cpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/SymbolTable.cpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -335,11 +335,11 @@
 }
 
-/*
-void SymbolTable::addFunctionType( const FunctionType * ftype ) {
-	addTypes( ftype->forall );
-	addIds( ftype->returns );
-	addIds( ftype->params );
-}
-*/
+
+void SymbolTable::addFunction( const FunctionDecl * func ) {
+	addTypes( func->type->forall );
+	addIds( func->returns );
+	addIds( func->params );
+}
+
 
 void SymbolTable::lazyInitScope() {
Index: src/AST/SymbolTable.hpp
===================================================================
--- src/AST/SymbolTable.hpp	(revision 954c954fd6522dace325fb95ef0cfd3247c319c3)
+++ src/AST/SymbolTable.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
@@ -145,5 +145,5 @@
 
 	/// convenience function for adding all of the declarations in a function type to the indexer
-	// void addFunctionType( const FunctionType * ftype );
+	void addFunction( const FunctionDecl * );
 
 private:
