Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/CodeGen/CodeGenerator.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -656,4 +656,10 @@
 	}
 
+	void CodeGenerator::visit( StmtExpr * stmtExpr ) {
+		output << "(";
+		stmtExpr->get_statements()->accept( *this );
+		output << ")";
+	}
+
 	//*** Statements
 	void CodeGenerator::visit( CompoundStmt * compoundStmt ) {
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/CodeGen/CodeGenerator.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -73,4 +73,5 @@
 		virtual void visit( TypeExpr *typeExpr );
 		virtual void visit( AsmExpr * );
+		virtual void visit( StmtExpr * );
 
 		//*** Statements
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/InitTweak/InitTweak.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -449,10 +449,10 @@
 		// virtual void visit( LogicalExpr *logicalExpr );
 		// virtual void visit( ConditionalExpr *conditionalExpr );
-		virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
-		virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
 		virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
 		virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
 		virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
 		virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
+		virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
+		virtual void visit( TupleAssignExpr *tupleExpr ) { isConstExpr = false; }
 
 		bool isConstExpr;
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/Makefile.in	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -188,5 +188,6 @@
 	SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
-	Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT)
+	Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT) \
+	Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT)
 am_driver_cfa_cpp_OBJECTS = $(am__objects_1)
 driver_cfa_cpp_OBJECTS = $(am_driver_cfa_cpp_OBJECTS)
@@ -400,5 +401,6 @@
 	SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \
 	SynTree/AddStmtVisitor.cc SynTree/TypeSubstitution.cc \
-	SynTree/Attribute.cc Tuples/TupleAssignment.cc
+	SynTree/Attribute.cc Tuples/TupleAssignment.cc \
+	Tuples/TupleExpansion.cc
 MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
 	${cfa_cpplib_PROGRAMS}}
@@ -767,4 +769,6 @@
 Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT):  \
 	Tuples/$(am__dirstamp) Tuples/$(DEPDIR)/$(am__dirstamp)
+Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT):  \
+	Tuples/$(am__dirstamp) Tuples/$(DEPDIR)/$(am__dirstamp)
 driver/$(am__dirstamp):
 	@$(MKDIR_P) driver
@@ -874,4 +878,5 @@
 	-rm -f SynTree/driver_cfa_cpp-VoidType.$(OBJEXT)
 	-rm -f Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT)
+	-rm -f Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT)
 
 distclean-compile:
@@ -978,4 +983,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Po@am__quote@
 
 .cc.o:
@@ -2394,4 +2400,18 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-TupleAssignment.obj `if test -f 'Tuples/TupleAssignment.cc'; then $(CYGPATH_W) 'Tuples/TupleAssignment.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/TupleAssignment.cc'; fi`
+
+Tuples/driver_cfa_cpp-TupleExpansion.o: Tuples/TupleExpansion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Tuples/driver_cfa_cpp-TupleExpansion.o -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Tpo -c -o Tuples/driver_cfa_cpp-TupleExpansion.o `test -f 'Tuples/TupleExpansion.cc' || echo '$(srcdir)/'`Tuples/TupleExpansion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Tuples/TupleExpansion.cc' object='Tuples/driver_cfa_cpp-TupleExpansion.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-TupleExpansion.o `test -f 'Tuples/TupleExpansion.cc' || echo '$(srcdir)/'`Tuples/TupleExpansion.cc
+
+Tuples/driver_cfa_cpp-TupleExpansion.obj: Tuples/TupleExpansion.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT Tuples/driver_cfa_cpp-TupleExpansion.obj -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Tpo -c -o Tuples/driver_cfa_cpp-TupleExpansion.obj `if test -f 'Tuples/TupleExpansion.cc'; then $(CYGPATH_W) 'Tuples/TupleExpansion.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/TupleExpansion.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-TupleExpansion.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Tuples/TupleExpansion.cc' object='Tuples/driver_cfa_cpp-TupleExpansion.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o Tuples/driver_cfa_cpp-TupleExpansion.obj `if test -f 'Tuples/TupleExpansion.cc'; then $(CYGPATH_W) 'Tuples/TupleExpansion.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/TupleExpansion.cc'; fi`
 
 .ll.cc:
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -38,5 +38,5 @@
 #include "SynTree/TypeSubstitution.h"
 #include "SymTab/Validate.h"
-#include "Tuples/TupleAssignment.h"
+#include "Tuples/Tuples.h"
 #include "Common/utility.h"
 #include "InitTweak/InitTweak.h"
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SymTab/Indexer.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -452,7 +452,10 @@
 	}
 
-	void Indexer::visit( SolvedTupleExpr *tupleExpr ) {
+	void Indexer::visit( TupleAssignExpr *tupleExpr ) {
 		acceptAllNewScope( tupleExpr->get_results(), *this );
-		acceptAll( tupleExpr->get_exprs(), *this );
+		enterScope();
+		acceptAll( tupleExpr->get_tempDecls(), *this );
+		acceptAll( tupleExpr->get_assigns(), *this );
+		leaveScope();
 	}
 
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SymTab/Indexer.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -64,9 +64,9 @@
 		virtual void visit( ConditionalExpr *conditionalExpr );
 		virtual void visit( CommaExpr *commaExpr );
-		virtual void visit( TupleExpr *tupleExpr );
-		virtual void visit( SolvedTupleExpr *tupleExpr );
 		virtual void visit( TypeExpr *typeExpr );
 		virtual void visit( AsmExpr *asmExpr );
 		virtual void visit( UntypedValofExpr *valofExpr );
+		virtual void visit( TupleExpr *tupleExpr );
+		virtual void visit( TupleAssignExpr *tupleExpr );
 
 		virtual void visit( TraitInstType *contextInst );
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/Expression.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -375,6 +375,6 @@
 }
 
-
-UntypedExpr::UntypedExpr( Expression *_function, Expression *_aname ) : Expression( _aname ), function( _function ) {}
+UntypedExpr::UntypedExpr( Expression *_function, const std::list<Expression *> &_args, Expression *_aname ) :
+		Expression( _aname ), function(_function), args(_args) {}
 
 UntypedExpr::UntypedExpr( const UntypedExpr &other ) :
@@ -382,7 +382,4 @@
 	cloneAll( other.args, args );
 }
-
-UntypedExpr::UntypedExpr( Expression *_function, std::list<Expression *> &_args, Expression *_aname ) :
-		Expression( _aname ), function(_function), args(_args) {}
 
 UntypedExpr::~UntypedExpr() {
@@ -568,4 +565,22 @@
 }
 
+StmtExpr::StmtExpr( CompoundStmt *statements ) : statements( statements ) {
+	assert( statements );
+	std::list< Statement * > & body = statements->get_kids();
+	if ( ! body.empty() ) {
+		if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( body.back() ) ) {
+			cloneAll( exprStmt->get_expr()->get_results(), get_results() );
+		}
+	}
+}
+StmtExpr::StmtExpr( const StmtExpr &other ) : statements( other.statements->clone() ) {}
+StmtExpr::~StmtExpr() {
+	delete statements;
+}
+void StmtExpr::print( std::ostream &os, int indent ) const {
+	os << std::string( indent, ' ' ) << "Statement Expression: " << std::endl;
+	statements->print( os, indent+2 );
+}
+
 std::ostream & operator<<( std::ostream & out, const Expression * expr ) {
 	expr->print( out );
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/Expression.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -98,7 +98,6 @@
 class UntypedExpr : public Expression {
   public:
-	UntypedExpr( Expression *function, Expression *_aname = nullptr );
+	UntypedExpr( Expression *function, const std::list<Expression *> &args = std::list< Expression * >(), Expression *_aname = nullptr );
 	UntypedExpr( const UntypedExpr &other );
-	UntypedExpr( Expression *function, std::list<Expression *> &args, Expression *_aname = nullptr );
 	virtual ~UntypedExpr();
 
@@ -483,40 +482,4 @@
 };
 
-/// TupleExpr represents a tuple expression ( [a, b, c] )
-class TupleExpr : public Expression {
-  public:
-	TupleExpr( Expression *_aname = nullptr );
-	TupleExpr( const TupleExpr &other );
-	virtual ~TupleExpr();
-
-	void set_exprs( std::list<Expression*> newValue ) { exprs = newValue; }
-	std::list<Expression*>& get_exprs() { return exprs; }
-
-	virtual TupleExpr *clone() const { return new TupleExpr( *this ); }
-	virtual void accept( Visitor &v ) { v.visit( this ); }
-	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const;
-  private:
-	std::list<Expression*> exprs;
-};
-
-/// SolvedTupleExpr represents a TupleExpr whose components have been type-resolved. It is effectively a shell for the code generator to work on
-class SolvedTupleExpr : public Expression {
-  public:
-	SolvedTupleExpr( Expression *_aname = nullptr ) : Expression( _aname ) {}
-	SolvedTupleExpr( std::list<Expression *> &, Expression *_aname = nullptr );
-	SolvedTupleExpr( const SolvedTupleExpr &other );
-	virtual ~SolvedTupleExpr() {}
-
-	std::list<Expression*> &get_exprs() { return exprs; }
-
-	virtual SolvedTupleExpr *clone() const { return new SolvedTupleExpr( *this ); }
-	virtual void accept( Visitor &v ) { v.visit( this ); }
-	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const;
-  private:
-	std::list<Expression*> exprs;
-};
-
 /// TypeExpr represents a type used in an expression (e.g. as a type generator parameter)
 class TypeExpr : public Expression {
@@ -672,4 +635,22 @@
 };
 
+/// TupleExpr represents a tuple expression ( [a, b, c] )
+class TupleExpr : public Expression {
+  public:
+	TupleExpr( Expression *_aname = nullptr );
+	TupleExpr( const TupleExpr &other );
+	virtual ~TupleExpr();
+
+	void set_exprs( std::list<Expression*> newValue ) { exprs = newValue; }
+	std::list<Expression*>& get_exprs() { return exprs; }
+
+	virtual TupleExpr *clone() const { return new TupleExpr( *this ); }
+	virtual void accept( Visitor &v ) { v.visit( this ); }
+	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
+	virtual void print( std::ostream &os, int indent = 0 ) const;
+  private:
+	std::list<Expression*> exprs;
+};
+
 /// TupleIndexExpr represents an element selection operation on a tuple value, e.g. t.3 after processing by the expression analyzer
 class TupleIndexExpr : public Expression {
@@ -714,44 +695,39 @@
 };
 
-/// MultipleAssignExpr represents a multiple assignment operation, where both sides of the assignment have tuple type, e.g. [a, b, c] = [d, e, f];
-class MultipleAssignExpr : public Expression {
-  public:
-	MultipleAssignExpr( Expression * lhs, Expression * rhs );
-	MultipleAssignExpr( const MultipleAssignExpr &other );
-	virtual ~MultipleAssignExpr();
-
-	Expression * get_lhs() const { return lhs; }
-	Expression * get_rhs() const { return rhs; }
-	MultipleAssignExpr * set_lhs( Expression *newValue ) { lhs = newValue; return this; }
-	MultipleAssignExpr * set_rhs( Expression *newValue ) { rhs = newValue; return this; }
-
-	virtual MultipleAssignExpr *clone() const { return new MultipleAssignExpr( *this ); }
-	virtual void accept( Visitor &v ) { v.visit( this ); }
-	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const;
-  private:
-	Expression * lhs;
-	Expression * rhs;
-};
-
-/// MassAssignExpr represents a mass assignment operations, where the left hand side has tuple type and the right hand side does not, e.g. [a, b, c] = 5.0;
-class MassAssignExpr : public Expression {
-  public:
-	MassAssignExpr( Expression * tuple, int field );
-	MassAssignExpr( const MassAssignExpr &other );
-	virtual ~MassAssignExpr();
-
-	Expression * get_lhs() const { return lhs; }
-	Expression * get_rhs() const { return rhs; }
-	MassAssignExpr * set_lhs( Expression *newValue ) { lhs = newValue; return this; }
-	MassAssignExpr * set_rhs( Expression *newValue ) { rhs = newValue; return this; }
-
-	virtual MassAssignExpr *clone() const { return new MassAssignExpr( *this ); }
-	virtual void accept( Visitor &v ) { v.visit( this ); }
-	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
-	virtual void print( std::ostream &os, int indent = 0 ) const;
-  private:
-	Expression * lhs; // multiple exprs
-	Expression * rhs; // single expr
+/// TupleAssignExpr represents a multiple assignment operation, where both sides of the assignment have tuple type, e.g. [a, b, c] = [d, e, f];, or a mass assignment operation, where the left hand side has tuple type and the right hand side does not, e.g. [a, b, c] = 5.0;
+class TupleAssignExpr : public Expression {
+  public:
+	TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname = nullptr );
+	TupleAssignExpr( const TupleAssignExpr &other );
+	virtual ~TupleAssignExpr();
+
+	std::list< Expression * > & get_assigns() { return assigns; }
+	std::list< ObjectDecl * > & get_tempDecls() { return tempDecls; }
+
+	virtual TupleAssignExpr *clone() const { return new TupleAssignExpr( *this ); }
+	virtual void accept( Visitor &v ) { v.visit( this ); }
+	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
+	virtual void print( std::ostream &os, int indent = 0 ) const;
+  private:
+	std::list< Expression * > assigns; // assignment expressions that use tempDecls
+	std::list< ObjectDecl * > tempDecls; // temporaries for address of lhs exprs
+};
+
+/// StmtExpr represents a GCC 'statement expression', e.g. ({ int x = 5; x; })
+class StmtExpr : public Expression {
+public:
+	StmtExpr( CompoundStmt *statements );
+	StmtExpr( const StmtExpr & other );
+	virtual ~StmtExpr();
+
+	CompoundStmt * get_statements() const { return statements; }
+	StmtExpr * set_statements( CompoundStmt * newValue ) { statements = newValue; return this; }
+
+	virtual StmtExpr *clone() const { return new StmtExpr( *this ); }
+	virtual void accept( Visitor &v ) { v.visit( this ); }
+	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
+	virtual void print( std::ostream &os, int indent = 0 ) const;
+private:
+	CompoundStmt * statements;
 };
 
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/Mutator.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -308,16 +308,4 @@
 }
 
-Expression *Mutator::mutate( TupleExpr *tupleExpr ) {
-	mutateAll( tupleExpr->get_results(), *this );
-	mutateAll( tupleExpr->get_exprs(), *this );
-	return tupleExpr;
-}
-
-Expression *Mutator::mutate( SolvedTupleExpr *tupleExpr ) {
-	mutateAll( tupleExpr->get_results(), *this );
-	mutateAll( tupleExpr->get_exprs(), *this );
-	return tupleExpr;
-}
-
 Expression *Mutator::mutate( TypeExpr *typeExpr ) {
 	mutateAll( typeExpr->get_results(), *this );
@@ -364,4 +352,10 @@
 }
 
+Expression *Mutator::mutate( TupleExpr *tupleExpr ) {
+	mutateAll( tupleExpr->get_results(), *this );
+	mutateAll( tupleExpr->get_exprs(), *this );
+	return tupleExpr;
+}
+
 Expression *Mutator::mutate( TupleIndexExpr *tupleExpr ) {
 	mutateAll( tupleExpr->get_results(), *this );
@@ -377,16 +371,15 @@
 }
 
-Expression *Mutator::mutate( MultipleAssignExpr *assignExpr ) {
+Expression *Mutator::mutate( TupleAssignExpr *assignExpr ) {
 	mutateAll( assignExpr->get_results(), *this );
-	assignExpr->set_lhs( maybeMutate( assignExpr->get_lhs(), *this ) );
-	assignExpr->set_rhs( maybeMutate( assignExpr->get_rhs(), *this ) );
+	mutateAll( assignExpr->get_tempDecls(), *this );
+	mutateAll( assignExpr->get_assigns(), *this );
 	return assignExpr;
 }
 
-Expression *Mutator::mutate( MassAssignExpr *assignExpr ) {
-	mutateAll( assignExpr->get_results(), *this );
-	assignExpr->set_lhs( maybeMutate( assignExpr->get_lhs(), *this ) );
-	assignExpr->set_rhs( maybeMutate( assignExpr->get_rhs(), *this ) );
-	return assignExpr;
+Expression *Mutator::mutate( StmtExpr *stmtExpr ) {
+	mutateAll( stmtExpr->get_results(), *this );
+	stmtExpr->set_statements( maybeMutate( stmtExpr->get_statements(), *this ) );
+	return stmtExpr;
 }
 
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/Mutator.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -71,6 +71,4 @@
 	virtual Expression* mutate( ConditionalExpr *conditionalExpr );
 	virtual Expression* mutate( CommaExpr *commaExpr );
-	virtual Expression* mutate( TupleExpr *tupleExpr );
-	virtual Expression* mutate( SolvedTupleExpr *tupleExpr );
 	virtual Expression* mutate( TypeExpr *typeExpr );
 	virtual Expression* mutate( AsmExpr *asmExpr );
@@ -80,8 +78,9 @@
 	virtual Expression* mutate( UntypedValofExpr *valofExpr );
 	virtual Expression* mutate( RangeExpr *rangeExpr );
+	virtual Expression* mutate( TupleExpr *tupleExpr );
 	virtual Expression* mutate( TupleIndexExpr *tupleExpr );
 	virtual Expression* mutate( MemberTupleExpr *tupleExpr );
-	virtual Expression* mutate( MultipleAssignExpr *assignExpr );
-	virtual Expression* mutate( MassAssignExpr *assignExpr );
+	virtual Expression* mutate( TupleAssignExpr *assignExpr );
+	virtual Expression* mutate( StmtExpr * stmtExpr );
 
 	virtual Type* mutate( VoidType *basicType );
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/SynTree.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -76,6 +76,4 @@
 class ConditionalExpr;
 class CommaExpr;
-class TupleExpr;
-class SolvedTupleExpr;
 class TypeExpr;
 class AsmExpr;
@@ -85,8 +83,9 @@
 class UntypedValofExpr;
 class RangeExpr;
+class TupleExpr;
 class TupleIndexExpr;
 class MemberTupleExpr;
-class MultipleAssignExpr;
-class MassAssignExpr;
+class TupleAssignExpr;
+class StmtExpr;
 
 class Type;
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/TupleExpr.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -17,4 +17,5 @@
 #include "Common/utility.h"
 #include "Type.h"
+#include "Declaration.h"
 
 TupleExpr::TupleExpr( Expression *_aname ) : Expression( _aname ) {
@@ -31,18 +32,4 @@
 void TupleExpr::print( std::ostream &os, int indent ) const {
 	os << std::string( indent, ' ' ) << "Tuple:" << std::endl;
-	printAll( exprs, os, indent+2 );
-	Expression::print( os, indent );
-}
-
-SolvedTupleExpr::SolvedTupleExpr( std::list<Expression *> &_exprs, Expression *_aname ) : Expression( _aname ) {
-	std::copy(_exprs.begin(), _exprs.end(), back_inserter(exprs));
-}
-
-SolvedTupleExpr::SolvedTupleExpr( const SolvedTupleExpr &other ) : Expression( other ) {
-	cloneAll( other.exprs, exprs );
-}
-
-void SolvedTupleExpr::print( std::ostream &os, int indent ) const {
-	os << std::string( indent, ' ' ) << "Solved Tuple:" << std::endl;
 	printAll( exprs, os, indent+2 );
 	Expression::print( os, indent );
@@ -90,4 +77,30 @@
 
 
+TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname ) : Expression( _aname ), assigns( assigns ), tempDecls( tempDecls ) {
+	for ( Expression * expr : assigns ) {
+		cloneAll( expr->get_results(), get_results() );
+	}
+}
+
+TupleAssignExpr::TupleAssignExpr( const TupleAssignExpr &other ) : Expression( other ), tempDecls( other.tempDecls ) /* temporary */ {
+	cloneAll( other.assigns, assigns );
+	// xxx - clone needs to go into assigns and replace tempDecls
+}
+
+TupleAssignExpr::~TupleAssignExpr() {
+	deleteAll( assigns );
+	// deleteAll( tempDecls );
+}
+
+void TupleAssignExpr::print( std::ostream &os, int indent ) const {
+	os << std::string( indent, ' ' ) << "Tuple Assignment Expression, with temporaries:" << std::endl;
+	printAll( tempDecls, os, indent+4 );
+	os << std::string( indent+2, ' ' ) << "with assignments: " << std::endl;
+	printAll( assigns, os, indent+4 );
+	Expression::print( os, indent );
+}
+
+
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/SynTree/TupleType.cc
===================================================================
--- src/SynTree/TupleType.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/TupleType.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// TupleType.cc -- 
+// TupleType.cc --
 //
 // Author           : Richard C. Bilson
@@ -17,5 +17,5 @@
 #include "Common/utility.h"
 
-TupleType::TupleType( const Type::Qualifiers &tq ) : Type( tq ) {
+TupleType::TupleType( const Type::Qualifiers &tq, const std::list< Type * > & types ) : Type( tq ), types( types ) {
 }
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/Type.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -348,5 +348,5 @@
 class TupleType : public Type {
   public:
-	TupleType( const Type::Qualifiers &tq );
+	TupleType( const Type::Qualifiers &tq, const std::list< Type * > & types = std::list< Type * >() );
 	TupleType( const TupleType& );
 	virtual ~TupleType();
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/Visitor.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -261,14 +261,4 @@
 }
 
-void Visitor::visit( TupleExpr *tupleExpr ) {
-	acceptAll( tupleExpr->get_results(), *this );
-	acceptAll( tupleExpr->get_exprs(), *this );
-}
-
-void Visitor::visit( SolvedTupleExpr *tupleExpr ) {
-	acceptAll( tupleExpr->get_results(), *this );
-	acceptAll( tupleExpr->get_exprs(), *this );
-}
-
 void Visitor::visit( TypeExpr *typeExpr ) {
 	acceptAll( typeExpr->get_results(), *this );
@@ -309,4 +299,9 @@
 }
 
+void Visitor::visit( TupleExpr *tupleExpr ) {
+	acceptAll( tupleExpr->get_results(), *this );
+	acceptAll( tupleExpr->get_exprs(), *this );
+}
+
 void Visitor::visit( TupleIndexExpr *tupleExpr ) {
 	acceptAll( tupleExpr->get_results(), *this );
@@ -320,14 +315,13 @@
 }
 
-void Visitor::visit( MultipleAssignExpr *assignExpr ) {
+void Visitor::visit( TupleAssignExpr *assignExpr ) {
 	acceptAll( assignExpr->get_results(), *this );
-	maybeAccept( assignExpr->get_lhs(), *this );
-	maybeAccept( assignExpr->get_rhs(), *this );
-}
-
-void Visitor::visit( MassAssignExpr *assignExpr ) {
-	acceptAll( assignExpr->get_results(), *this );
-	maybeAccept( assignExpr->get_lhs(), *this );
-	maybeAccept( assignExpr->get_rhs(), *this );
+	acceptAll( assignExpr->get_tempDecls(), *this );
+	acceptAll( assignExpr->get_assigns(), *this );
+}
+
+void Visitor::visit( StmtExpr *stmtExpr ) {
+	acceptAll( stmtExpr->get_results(), *this );
+	maybeAccept( stmtExpr->get_statements(), *this );
 }
 
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/SynTree/Visitor.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -71,6 +71,4 @@
 	virtual void visit( ConditionalExpr *conditionalExpr );
 	virtual void visit( CommaExpr *commaExpr );
-	virtual void visit( TupleExpr *tupleExpr );
-	virtual void visit( SolvedTupleExpr *tupleExpr );
 	virtual void visit( TypeExpr *typeExpr );
 	virtual void visit( AsmExpr *asmExpr );
@@ -80,8 +78,9 @@
 	virtual void visit( UntypedValofExpr *valofExpr );
 	virtual void visit( RangeExpr *rangeExpr );
+	virtual void visit( TupleExpr *tupleExpr );
 	virtual void visit( TupleIndexExpr *tupleExpr );
 	virtual void visit( MemberTupleExpr *tupleExpr );
-	virtual void visit( MultipleAssignExpr *assignExpr );
-	virtual void visit( MassAssignExpr *assignExpr );
+	virtual void visit( TupleAssignExpr *assignExpr );
+	virtual void visit( StmtExpr * stmtExpr );
 
 	virtual void visit( VoidType *basicType );
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/Tuples/TupleAssignment.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -18,5 +18,6 @@
 #include "ResolvExpr/typeops.h"
 #include "SynTree/Expression.h"
-#include "TupleAssignment.h"
+#include "SynTree/Initializer.h"
+#include "Tuples.h"
 #include "Common/SemanticError.h"
 
@@ -40,5 +41,4 @@
 		// records for assignment generation
 		struct Options {
-			std::list< ResolvExpr::AltList > get_best();
 			void print( std::ostream & );
 			int size() const { return options.size(); }
@@ -51,17 +51,15 @@
 		};
 
-		class Matcher {
+		struct Matcher {
 		  public:
 			Matcher( TupleAssignSpotter &spotter, Expression *_lhs, Expression *_rhs );
 			virtual ~Matcher() {}
 			virtual void match( std::list< Expression * > &out ) = 0;
-			virtual void solve() = 0;
-			static UntypedExpr *createAssgn( Expression *left, Expression *right );
-		  protected:
 			std::list< Expression * > lhs, rhs;
 			TupleAssignSpotter &spotter;
-		};
-
-		class MassAssignMatcher : public Matcher {
+			std::list< ObjectDecl * > tmpDecls;
+		};
+
+		struct MassAssignMatcher : public Matcher {
 		  public:
 			MassAssignMatcher( TupleAssignSpotter &spotter, Expression *lhs, Expression *rhs ) : Matcher( spotter, lhs, rhs ) {
@@ -69,16 +67,14 @@
 			}
 			virtual void match( std::list< Expression * > &out );
-			virtual void solve();
-		};
-
-		class MultipleAssignMatcher : public Matcher {
+		};
+
+		struct MultipleAssignMatcher : public Matcher {
 		  public:
 			MultipleAssignMatcher( TupleAssignSpotter &spot, Expression *lhs, Expression *rhs );
 			virtual void match( std::list< Expression * > &out );
-			virtual void solve();
 		};
 
 		ResolvExpr::AlternativeFinder &currentFinder;
-		Expression *rhs, *lhs;
+		// Expression *rhs, *lhs;
 		Matcher *matcher = nullptr;
 		Options options;
@@ -149,5 +145,4 @@
 
 		if ( new_assigns.empty() ) return;
-		std::list< Expression * > solved_assigns;
 		ResolvExpr::AltList current;
 		// now resolve new assignments
@@ -161,7 +156,15 @@
 			current.push_back( alts.front() );
 		}
-		options.options.push_back( current );
-
-		matcher->solve();
+
+		// extract expressions from the assignment alternatives to produce a list of assignments that
+		// together form a single alternative
+		std::list< Expression *> solved_assigns;
+		for ( ResolvExpr::Alternative & alt : current ) {
+			solved_assigns.push_back( alt.expr->clone() );
+		}
+		// xxx - need to do this??
+		// TypeEnvironment compositeEnv;
+		// simpleCombineEnvironments( i->begin(), i->end(), compositeEnv );
+		currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), currentFinder.get_environ(), ResolvExpr::sumCost( current ) ) );
 	}
 
@@ -179,70 +182,56 @@
 	}
 
-	UntypedExpr *TupleAssignSpotter::Matcher::createAssgn( Expression *left, Expression *right ) {
+	UntypedExpr * createAssgn( ObjectDecl *left, ObjectDecl *right ) {
 		assert( left && right );
 		std::list< Expression * > args;
-		args.push_back( new AddressExpr( left->clone() ) );
-		args.push_back( right->clone() );
+		args.push_back( new AddressExpr( new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ new VariableExpr( left ) } ) ) );
+		args.push_back( new VariableExpr( right ) );
 		return new UntypedExpr( new NameExpr( "?=?" ), args );
 	}
 
+	ObjectDecl * newObject( UniqueName & namer, Expression * expr ) {
+		Type * type;
+		assert( expr->get_results().size() >= 1 );
+		if ( expr->get_results().size() > 1 ) {
+			TupleType * tt = new TupleType( Type::Qualifiers() );
+			cloneAll( expr->get_results(), tt->get_types() );
+			type = tt;
+		} else {
+			type = expr->get_results().front()->clone();
+		}
+		return new ObjectDecl( namer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, type, new SingleInit( expr->clone() ) );
+	}
+
 	void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
+		static UniqueName lhsNamer( "__massassign_L" );
+		static UniqueName rhsNamer( "__massassign_R" );
 		assert ( ! lhs.empty() && rhs.size() == 1);
 
+		ObjectDecl * rtmp = newObject( rhsNamer, rhs.front() );
 		for ( Expression * l : lhs ) {
-			out.push_back( createAssgn( l, rhs.front() ) );
-		}
-	}
-
-	void TupleAssignSpotter::MassAssignMatcher::solve() {
-		assert( ! spotter.options.empty() );
-		for ( std::list< ResolvExpr::AltList >::iterator i = spotter.options.begin(); i != spotter.options.end(); ++i ) {
-			// extract expressions from the alternatives to produce a list of assignments that
-			// together form a single alternative
-			std::list< Expression *> solved_assigns;
-			for ( ResolvExpr::Alternative & alt : *i ) {
-				solved_assigns.push_back( alt.expr );
-			}
-			spotter.currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns), spotter.currentFinder.get_environ(), ResolvExpr::sumCost( *i ) ) );
-		}
+			ObjectDecl * ltmp = newObject( lhsNamer, new AddressExpr( l ) );
+			out.push_back( createAssgn( ltmp, rtmp ) );
+			tmpDecls.push_back( ltmp );
+		}
+		tmpDecls.push_back( rtmp );
 	}
 
 	void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
+		static UniqueName lhsNamer( "__multassign_L" );
+		static UniqueName rhsNamer( "__multassign_R" );
 		// xxx - need more complicated matching?
 		if ( lhs.size() == rhs.size() ) {
-			zipWith( lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), back_inserter(out), TupleAssignSpotter::Matcher::createAssgn );
-		}
-	}
-
-	void TupleAssignSpotter::MultipleAssignMatcher::solve() {
-		// options.print( std::cerr );
-		std::list< ResolvExpr::AltList > best = spotter.options.get_best();
-		if ( best.size() == 1 ) {
-			std::list<Expression *> solved_assigns;
-			for ( ResolvExpr::AltList::iterator i = best.front().begin(); i != best.front().end(); ++i ) {
-				solved_assigns.push_back( i->expr );
-			}
-			/* assigning cost zero? */
-			spotter.currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns), spotter.currentFinder.get_environ(), ResolvExpr::Cost() ) );
-		}
-	}
-
-	std::list< ResolvExpr::AltList > TupleAssignSpotter::Options::get_best() {
-		std::list< ResolvExpr::AltList > ret;
-		std::list< ResolvExpr::AltList > solns;
-		for ( ResolvExpr::AltList & i : options ) {
-			ResolvExpr::AltList current;
-			findMinCost( i.begin(), i.end(), back_inserter(current) );
-			solns.push_back( ResolvExpr::AltList(current.begin(), current.end()) );
-		}
-		// need to combine -- previously "lift_intersection", which
-		// did some madness involving, effectively, the intersection of
-		// a bunch of AltLists
-		std::list<ResolvExpr::AltList> result = solns;
-		if ( result.size() != 1 ) {
-			throw SemanticError("Ambiguous tuple expression");
-		}
-		ret.push_back( *result.begin() );
-		return ret;
+			std::list< ObjectDecl * > ltmp;
+			std::list< ObjectDecl * > rtmp;
+			std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( Expression * expr ){
+				return newObject( lhsNamer, new AddressExpr( expr ) );
+			});
+			std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( Expression * expr ){
+				return newObject( rhsNamer, expr );
+			});
+			zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), createAssgn );
+			tmpDecls.splice( tmpDecls.end(), ltmp );
+			tmpDecls.splice( tmpDecls.end(), rtmp );
+		}
 	}
 
Index: src/Tuples/TupleAssignment.h
===================================================================
--- src/Tuples/TupleAssignment.h	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ 	(revision )
@@ -1,37 +1,0 @@
-//
-// 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.
-//
-// TupleAssignment.h --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon May 18 15:04:02 2015
-// Update Count     : 2
-//
-
-#ifndef _TUPLE_ASSIGNMENT_H_
-#define _TUPLE_ASSIGNMENT_H_
-
-#include <string>
-#include <vector>
-#include "ResolvExpr/AlternativeFinder.h"
-
-#include "SynTree/Expression.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Type.h"
-
-namespace Tuples {
-	void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, std::list<ResolvExpr::AltList> & possibilities );
-} // namespace Tuples
-
-#endif // _TUPLE_ASSIGNMENT_H_
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
+++ src/Tuples/TupleExpansion.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -0,0 +1,56 @@
+//
+// 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.
+//
+// TupleAssignment.cc --
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon May 18 15:02:53 2015
+// Update Count     : 2
+//
+
+#include <iterator>
+#include <iostream>
+#include <cassert>
+#include "Tuples.h"
+#include "GenPoly/PolyMutator.h"
+#include "SynTree/Statement.h"
+
+namespace Tuples {
+	class TupleAssignExpander : public GenPoly::PolyMutator {
+	public:
+		virtual Expression * mutate( TupleAssignExpr * tupleExpr );
+	};
+
+	void expandTuples( std::list< Declaration * > & translationUnit ) {
+		TupleAssignExpander expander;
+		mutateAll( translationUnit, expander );
+	}
+
+	Expression * TupleAssignExpander::mutate( TupleAssignExpr * tupleExpr ) {
+		CompoundStmt * compoundStmt = new CompoundStmt( noLabels );
+		std::list< Statement * > & stmts = compoundStmt->get_kids();
+		for ( ObjectDecl * obj : tupleExpr->get_tempDecls() ) {
+			stmts.push_back( new DeclStmt( noLabels, obj ) );
+		}
+		for ( Expression * assign : tupleExpr->get_assigns() ) {
+			stmts.push_back( new ExprStmt( noLabels, assign ) );
+		}
+		tupleExpr->get_tempDecls().clear();
+		tupleExpr->get_assigns().clear();
+		delete tupleExpr;
+		return new StmtExpr( compoundStmt );
+	}
+
+} // namespace Tuples
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
+
Index: src/Tuples/Tuples.h
===================================================================
--- src/Tuples/Tuples.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
+++ src/Tuples/Tuples.h	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -0,0 +1,41 @@
+//
+// 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.
+//
+// Tuples.h --
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon May 18 15:04:02 2015
+// Update Count     : 2
+//
+
+#ifndef _TUPLES_H_
+#define _TUPLE_H_
+
+#include <string>
+#include <vector>
+#include "ResolvExpr/AlternativeFinder.h"
+
+#include "SynTree/Expression.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+
+namespace Tuples {
+	// TupleAssignment.cc
+	void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, std::list<ResolvExpr::AltList> & possibilities );
+
+	// TupleExpansion.cc
+	void expandTuples( std::list< Declaration * > & translationUnit );
+} // namespace Tuples
+
+#endif // _TUPLE_ASSIGNMENT_H_
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/module.mk
===================================================================
--- src/Tuples/module.mk	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/Tuples/module.mk	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -15,3 +15,4 @@
 ###############################################################################
 
-SRC += 	Tuples/TupleAssignment.cc
+SRC += 	Tuples/TupleAssignment.cc \
+	Tuples/TupleExpansion.cc
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 8f7cea185385710ca47eaacdb8bc3a59fb752db5)
+++ src/main.cc	(revision 6eb89484ef2c58941d8905aad3ee756b10460cf9)
@@ -42,4 +42,5 @@
 #include "Common/UnimplementedError.h"
 #include "../config.h"
+#include "Tuples/Tuples.h"
 
 using namespace std;
@@ -265,4 +266,6 @@
 		OPTPRINT( "convertLvalue" )
 		GenPoly::convertLvalue( translationUnit );
+		OPTPRINT( "expandTuples" ); // xxx - is this the right place for this?
+		Tuples::expandTuples( translationUnit );
 
 		if ( bboxp ) {
