Index: src/Tuples/TupleExpansionNew.cpp
===================================================================
--- src/Tuples/TupleExpansionNew.cpp	(revision 01d433e240fc8d7981952c4466b62350e4df4263)
+++ src/Tuples/TupleExpansionNew.cpp	(revision 01d433e240fc8d7981952c4466b62350e4df4263)
@@ -0,0 +1,69 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// TupleExpansionNew.cpp --
+//
+// Author           : Henry Xue
+// Created On       : Wed Aug 18 12:54:02 2021
+// Last Modified By : Henry Xue
+// Last Modified On : Wed Aug 18 12:54:02 2021
+// Update Count     : 1
+//
+
+// Currently not working due to unresolved issues with UniqueExpr
+
+#include "Tuples.h"
+
+namespace Tuples {
+namespace {
+	struct UniqueExprExpander final : public ast::WithDeclsToAdd<> {
+		const ast::Expr * postvisit( const ast::UniqueExpr * unqExpr );
+		std::map< int, const ast::Expr * > decls; // not vector, because order added may not be increasing order
+	};
+} // namespace
+
+void expandUniqueExpr( ast::TranslationUnit & translationUnit ) {
+	ast::Pass< UniqueExprExpander >::run( translationUnit );
+}
+
+namespace {
+	const ast::Expr * UniqueExprExpander::postvisit( const ast::UniqueExpr * unqExpr ) {
+		const CodeLocation loc = unqExpr->location;
+		const int id = unqExpr->id;
+
+		// on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID,
+		// and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable.
+		if ( ! decls.count( id ) ) {
+			ast::ptr< ast::Expr > assignUnq;
+			ast::ptr< ast::VariableExpr > var = unqExpr->var;
+			if ( unqExpr->object ) {
+				// an object was generated to represent this unique expression -- it should be added to the list of declarations now
+				declsToAddBefore.push_back( unqExpr->object.as< ast::Decl >() );
+				// deep copy required due to unresolved issues with UniqueExpr
+				assignUnq = ast::UntypedExpr::createAssign( loc, var, ast::deepCopy( unqExpr->expr.get() ) );
+			} else {
+				ast::ptr< ast::Expr > expr = unqExpr->expr;
+				ast::ptr< ast::CommaExpr > commaExpr = expr.strict_as< ast::CommaExpr >();
+				assignUnq = commaExpr->arg1;
+			}
+			auto finished = new ast::ObjectDecl( loc, toString( "_unq", id, "_finished_" ), new ast::BasicType( ast::BasicType::Kind::Bool ),
+				new ast::SingleInit( loc, ast::ConstantExpr::from_int( loc, 0 ) ), {}, ast::Linkage::Cforall );
+			declsToAddBefore.push_back( finished );
+			// (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
+			// This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code.
+			auto assignFinished = ast::UntypedExpr::createAssign( loc, new ast::VariableExpr( loc, finished ),
+				ast::ConstantExpr::from_int( loc, 1 ) );
+			auto condExpr = new ast::ConditionalExpr( loc, new ast::VariableExpr( loc, finished ), var,
+				new ast::CommaExpr( loc, new ast::CommaExpr( loc, assignUnq, assignFinished ), var ) );
+			condExpr->result = var->result;
+			condExpr->env = unqExpr->env;
+			decls[id] = condExpr;
+		}
+		//delete unqExpr;
+		return decls[id];
+	}
+} // namespace
+} // namespace Tuples
Index: src/Tuples/Tuples.h
===================================================================
--- src/Tuples/Tuples.h	(revision 6d63c14bef6152412ad943edc5281ed7b0908568)
+++ src/Tuples/Tuples.h	(revision 01d433e240fc8d7981952c4466b62350e4df4263)
@@ -45,4 +45,5 @@
 	/// replaces UniqueExprs with a temporary variable and one call
 	void expandUniqueExpr( std::list< Declaration * > & translationUnit );
+	void expandUniqueExpr( ast::TranslationUnit & translationUnit );
 
 	/// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
Index: src/Tuples/module.mk
===================================================================
--- src/Tuples/module.mk	(revision 6d63c14bef6152412ad943edc5281ed7b0908568)
+++ src/Tuples/module.mk	(revision 01d433e240fc8d7981952c4466b62350e4df4263)
@@ -20,4 +20,5 @@
 	Tuples/TupleAssignment.cc \
 	Tuples/TupleExpansion.cc \
+	Tuples/TupleExpansionNew.cpp \
 	Tuples/Tuples.cc \
 	Tuples/Tuples.h
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 6d63c14bef6152412ad943edc5281ed7b0908568)
+++ src/main.cc	(revision 01d433e240fc8d7981952c4466b62350e4df4263)
@@ -374,4 +374,13 @@
 
 			PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
+
+			// fix ObjectDecl - replaces ConstructorInit nodes
+			if ( ctorinitp ) {
+				dump( move( transUnit ) );
+				return EXIT_SUCCESS;
+			} // if
+
+			// Currently not working due to unresolved issues with UniqueExpr
+			PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
 			translationUnit = convert( move( transUnit ) );
 		} else {
@@ -383,13 +392,13 @@
 
 			PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
+
+			// fix ObjectDecl - replaces ConstructorInit nodes
+			if ( ctorinitp ) {
+				dump ( translationUnit );
+				return EXIT_SUCCESS;
+			} // if
+
+			PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
 		}
-
-		// fix ObjectDecl - replaces ConstructorInit nodes
-		if ( ctorinitp ) {
-			dump ( translationUnit );
-			return EXIT_SUCCESS;
-		} // if
-
-		PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
 
 		PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
