Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision ac9ca967fc4b0004f809382a113690d4c01cae00)
+++ src/Tuples/TupleExpansion.cc	(revision bf32bb8a6509388bf221983b0b4c4c8620ff76b9)
@@ -31,9 +31,15 @@
 namespace Tuples {
 	namespace {
+		class MemberTupleExpander : public Mutator {
+		public:
+			typedef Mutator Parent;
+			virtual Expression * mutate( UntypedMemberExpr * memberExpr );
+		};
+
 		class UniqueExprExpander : public GenPoly::DeclMutator {
 		public:
 			typedef GenPoly::DeclMutator Parent;
 			virtual Expression * mutate( UniqueExpr * unqExpr );
-			std::map< Expression *, ObjectDecl * > decls;
+			std::map< int, ObjectDecl * > decls; // not vector, because order added may not be increasing order
 		};
 
@@ -73,4 +79,9 @@
 	}
 
+	void expandMemberTuples( std::list< Declaration * > & translationUnit ) {
+		MemberTupleExpander expander;
+		mutateAll( translationUnit, expander );
+	}
+
 	void expandUniqueExpr( std::list< Declaration * > & translationUnit ) {
 		UniqueExprExpander unqExpander;
@@ -92,14 +103,49 @@
 	}
 
+	namespace {
+		/// given a expression representing the member and an expression representing the aggregate,
+		/// reconstructs a flattened UntypedMemberExpr with the right precedence
+		Expression * reconstructMemberExpr( Expression * member, UniqueExpr * aggr ) {
+			if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( member ) ) {
+				// construct a new UntypedMemberExpr with the correct structure , and recursively
+				// expand that member expression.
+				MemberTupleExpander expander;
+				UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member(), new UntypedMemberExpr( memberExpr->get_aggregate(), aggr->clone() ) );
+
+				memberExpr->set_member(nullptr);
+				memberExpr->set_aggregate(nullptr);
+				delete memberExpr;
+				return newMemberExpr->acceptMutator( expander );
+			} else {
+				// not a member expression, so there is nothing to do but attach and return
+				return new UntypedMemberExpr( member, aggr->clone() );
+			}
+		}
+	}
+
+	Expression * MemberTupleExpander::mutate( UntypedMemberExpr * memberExpr ) {
+		if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * > ( memberExpr->get_member() ) ) {
+			UniqueExpr * unqExpr = new UniqueExpr( memberExpr->get_aggregate()->clone() );
+			for ( Expression *& expr : tupleExpr->get_exprs() ) {
+				expr = reconstructMemberExpr( expr, unqExpr );
+			}
+			delete unqExpr;
+			return tupleExpr;
+		} else {
+			return memberExpr;
+		}
+	}
+
 	Expression * UniqueExprExpander::mutate( UniqueExpr * unqExpr ) {
 		static UniqueName tempNamer( "_unq_expr_" );
 		unqExpr = safe_dynamic_cast< UniqueExpr * > ( Parent::mutate( unqExpr ) );
-		if ( ! decls.count( unqExpr->get_expr() ) ) {
+		if ( ! decls.count( unqExpr->get_id() ) ) {
 			// xxx - it's possible (likely?) that expressions can appear in the wrong order because of this. Need to ensure they're placed in the correct location.
+			// xxx - is it possible to make the decl's type const?
 			ObjectDecl * decl = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, unqExpr->get_result()->clone(), new SingleInit( unqExpr->get_expr()->clone() ) );
-			decls[unqExpr->get_expr()] = decl;
+			decls[unqExpr->get_id()] = decl;
 			addDeclaration( decl );
 		}
-		return new VariableExpr( decls[unqExpr->get_expr()] );
+		return new VariableExpr( decls[unqExpr->get_id()] );
 	}
 
@@ -176,8 +222,11 @@
 
 	Expression * TupleExprExpander::mutate( TupleExpr * tupleExpr ) {
+		// recursively expand sub-tuple-expressions
+		tupleExpr = safe_dynamic_cast<TupleExpr *>(Parent::mutate(tupleExpr));
 		Type * result = tupleExpr->get_result();
 		std::list< Expression * > exprs = tupleExpr->get_exprs();
 		assert( result );
 
+		// remove data from shell and delete it
 		tupleExpr->set_result( nullptr );
 		tupleExpr->get_exprs().clear();
Index: src/Tuples/Tuples.h
===================================================================
--- src/Tuples/Tuples.h	(revision ac9ca967fc4b0004f809382a113690d4c01cae00)
+++ src/Tuples/Tuples.h	(revision bf32bb8a6509388bf221983b0b4c4c8620ff76b9)
@@ -30,12 +30,18 @@
 
 	// TupleExpansion.cc
+	/// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate
+	void expandMemberTuples( std::list< Declaration * > & translationUnit );
+
+	/// replaces tuple-related elements, such as TupleType, TupleExpr, TupleAssignExpr, etc.
 	void expandTuples( std::list< Declaration * > & translationUnit );
 
-  void expandUniqueExpr( std::list< Declaration * > & translationUnit );
+	/// replaces UniqueExprs with a temporary variable and one call
+	void expandUniqueExpr( std::list< Declaration * > & translationUnit );
 
-  /// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
-  Type * makeTupleType( const std::list< Expression * > & exprs );
+	/// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
+	Type * makeTupleType( const std::list< Expression * > & exprs );
 
-  bool maybeImpure( Expression * expr );
+	/// returns true if the expression may contain side-effects.
+	bool maybeImpure( Expression * expr );
 
 
