Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision aa8f9dfd89cb8d2df9f8a3892703dfc427bce64a)
@@ -38,6 +38,5 @@
 #include "SynTree/TypeSubstitution.h"
 #include "SymTab/Validate.h"
-#include "Tuples/TupleAssignment.h"
-#include "Tuples/NameMatcher.h"
+#include "Tuples/Tuples.h"
 #include "Common/utility.h"
 #include "InitTweak/InitTweak.h"
@@ -64,4 +63,12 @@
 	}
 
+	Cost sumCost( const AltList &in ) {
+		Cost total;
+		for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
+			total += i->cost;
+		}
+		return total;
+	}
+
 	namespace {
 		void printAlts( const AltList &list, std::ostream &os, int indent = 0 ) {
@@ -76,12 +83,4 @@
 				out.push_back( i->expr->clone() );
 			}
-		}
-
-		Cost sumCost( const AltList &in ) {
-			Cost total;
-			for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
-				total += i->cost;
-			}
-			return total;
 		}
 
@@ -139,24 +138,4 @@
 		}
 
-		template< typename InputIterator, typename OutputIterator >
-		void findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
-			AltList alternatives;
-
-			// select the alternatives that have the minimum parameter cost
-			Cost minCost = Cost::infinity;
-			for ( AltList::iterator i = begin; i != end; ++i ) {
-				if ( i->cost < minCost ) {
-					minCost = i->cost;
-					i->cost = i->cvtCost;
-					alternatives.clear();
-					alternatives.push_back( *i );
-				} else if ( i->cost == minCost ) {
-					i->cost = i->cvtCost;
-					alternatives.push_back( *i );
-				}
-			}
-			std::copy( alternatives.begin(), alternatives.end(), out );
-		}
-
 		template< typename InputIterator >
 		void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) {
@@ -236,5 +215,19 @@
 
 	template< typename StructOrUnionType >
-	void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string &name ) {
+	void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
+
+		// // member must be either a tuple expression or a name expr
+		// if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ) ) {
+		//  addAggMembers( structInst, agg->expr, agg->cost, nameExpr->get_name() );
+		// } else {
+		//  TupleExpr * tupleExpr = safe_dynamic_cast< TupleExpr * >( memberExpr->get_member() );
+		//  // xxx - ...
+		//  assert( false );
+		// }
+		// if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( memberExpr->get_member() ) ) {
+
+		// }
+		NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
+		const std::string & name = nameExpr->get_name();
 		std::list< Declaration* > members;
 		aggInst->lookup( name, members );
@@ -262,5 +255,10 @@
 		std::list< DeclarationWithType* >::iterator formal = formals.begin();
 		std::list< Expression* >& actuals = appExpr->get_args();
+
+		std::list< Type * > formalTypes;
+		std::list< Type * >::iterator formalType = formalTypes.end();
+
 		for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
+
 			PRINT(
 				std::cerr << "actual expression:" << std::endl;
@@ -271,23 +269,36 @@
 			std::list< DeclarationWithType* >::iterator startFormal = formal;
 			Cost actualCost;
-			// xxx - tuple type matching
 			std::list< Type * > flatActualTypes;
 			flatten( (*actualExpr)->get_result(), back_inserter( flatActualTypes ) );
-			for ( std::list< Type* >::iterator actual = flatActualTypes.begin(); actual != flatActualTypes.end(); ++actual ) {
-				if ( formal == formals.end() ) {
-					if ( function->get_isVarArgs() ) {
-						convCost += Cost( 1, 0, 0 );
-						break;
-					} else {
-						return Cost::infinity;
+			for ( std::list< Type* >::iterator actualType = flatActualTypes.begin(); actualType != flatActualTypes.end(); ++actualType ) {
+
+
+				// tuple handling code
+				if ( formalType == formalTypes.end() ) {
+					// the type of the formal parameter may be a tuple type. To make this easier to work with,
+					// flatten the tuple type and traverse the resulting list of types, incrementing the formal
+					// iterator once its types have been extracted. Once a particular formal parameter's type has
+					// been exhausted load the next formal parameter's type.
+					if ( formal == formals.end() ) {
+						if ( function->get_isVarArgs() ) {
+							convCost += Cost( 1, 0, 0 );
+							break;
+						} else {
+							return Cost::infinity;
+						}
 					}
+					formalTypes.clear();
+					flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
+					formalType = formalTypes.begin();
+					++formal;
 				}
+
 				PRINT(
 					std::cerr << std::endl << "converting ";
-					(*actual)->print( std::cerr, 8 );
+					(*actualType)->print( std::cerr, 8 );
 					std::cerr << std::endl << " to ";
 					(*formal)->get_type()->print( std::cerr, 8 );
 				)
-				Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
+				Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env );
 				PRINT(
 					std::cerr << std::endl << "cost is" << newCost << std::endl;
@@ -300,7 +311,7 @@
 				actualCost += newCost;
 
-				convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actual, alt.env, indexer ), 0 );
-
-				formal++;
+				convCost += Cost( 0, polyCost( *formalType, alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 );
+
+				formalType++;
 			}
 			if ( actualCost != Cost( 0, 0, 0 ) ) {
@@ -368,33 +379,43 @@
 		resultEnv.extractOpenVars( openVars );
 
-		/*
-		  Tuples::NameMatcher matcher( formals );
-		  try {
-		  matcher.match( actuals );
-		  } catch ( Tuples::NoMatch &e ) {
-		  std::cerr << "Alternative doesn't match: " << e.message << std::endl;
-		  }
-		*/
 		std::list< DeclarationWithType* >::iterator formal = formals.begin();
+
+		std::list< Type * > formalTypes;
+		std::list< Type * >::iterator formalType = formalTypes.end();
+
 		for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
 			std::list< Type * > flatActualTypes;
 			flatten( actualExpr->expr->get_result(), back_inserter( flatActualTypes ) );
-			for ( std::list< Type* >::iterator actual = flatActualTypes.begin(); actual != flatActualTypes.end(); ++actual ) {
-				if ( formal == formals.end() ) {
-					return isVarArgs;
+			for ( std::list< Type* >::iterator actualType = flatActualTypes.begin(); actualType != flatActualTypes.end(); ++actualType, ++formalType ) {
+				if ( formalType == formalTypes.end() ) {
+					// the type of the formal parameter may be a tuple type. To make this easier to work with,
+					// flatten the tuple type and traverse the resulting list of types, incrementing the formal
+					// iterator once its types have been extracted. Once a particular formal parameter's type has
+					// been exhausted load the next formal parameter's type.
+					if ( formal == formals.end() ) {
+						return isVarArgs;
+					}
+					formalTypes.clear();
+					flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
+					formalType = formalTypes.begin();
+					++formal;
 				}
 				PRINT(
 					std::cerr << "formal type is ";
-					(*formal)->get_type()->print( std::cerr );
+					(*formalType)->print( std::cerr );
 					std::cerr << std::endl << "actual type is ";
-					(*actual)->print( std::cerr );
+					(*actualType)->print( std::cerr );
 					std::cerr << std::endl;
 				)
-				if ( ! unify( (*formal)->get_type(), *actual, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
+				if ( ! unify( *formalType, *actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
 					return false;
 				}
-				formal++;
-			}
-		}
+			}
+		}
+
+		// xxx - a tuple type was not completely matched
+		// partially handle the tuple with default arguments??
+		if ( formalType != formalTypes.end() ) return false;
+
 		// Handling of default values
 		while ( formal != formals.end() ) {
@@ -583,9 +604,7 @@
 		combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
 
-		Tuples::TupleAssignSpotter tassign( this );
-		if ( tassign.isTupleAssignment( untypedExpr, possibilities ) ) {
-			// take care of possible tuple assignments, or discard expression
-			return;
-		} // else ...
+		// take care of possible tuple assignments
+		// if not tuple assignment, assignment is taken care of as a normal function call
+		Tuples::handleTupleAssignment( *this, untypedExpr, possibilities );
 
 		AltList candidates;
@@ -773,7 +792,9 @@
 			renameTypes( alternatives.back().expr );
 			if ( StructInstType *structInst = dynamic_cast< StructInstType* >( (*i)->get_type() ) ) {
-				addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
+				NameExpr nameExpr( "" );
+				addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), env, &nameExpr );
 			} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( (*i)->get_type() ) ) {
-				addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
+				NameExpr nameExpr( "" );
+				addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), env, &nameExpr );
 			} // if
 		} // for
@@ -973,7 +994,12 @@
 			TupleExpr *newExpr = new TupleExpr;
 			makeExprList( *i, newExpr->get_exprs() );
+			TupleType *tupleType = new TupleType( Type::Qualifiers(true, true, true, true, true, true) );
+			Type::Qualifiers &qualifiers = tupleType->get_qualifiers();
 			for ( Expression * resultExpr : newExpr->get_exprs() ) {
-				newExpr->set_result( resultExpr->get_result()->clone() );
+				Type * type = resultExpr->get_result()->clone();
+				tupleType->get_types().push_back( type );
+				qualifiers &= type->get_qualifiers();
 			} // for
+			newExpr->set_result( tupleType );
 
 			TypeEnvironment compositeEnv;
@@ -996,4 +1022,12 @@
 		}
 	}
+
+	void AlternativeFinder::visit( TupleIndexExpr *tupleExpr ) {
+		alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
+	}
+
+	void AlternativeFinder::visit( TupleAssignExpr *tupleAssignExpr ) {
+		alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
+	}
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
+++ src/ResolvExpr/AlternativeFinder.h	(revision aa8f9dfd89cb8d2df9f8a3892703dfc427bce64a)
@@ -67,11 +67,13 @@
 		virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
 		virtual void visit( ConstructorExpr * ctorExpr );
-	  public:  // xxx - temporary hack - should make Tuples::TupleAssignment a friend
+		virtual void visit( TupleIndexExpr *tupleExpr );
+		virtual void visit( TupleAssignExpr *tupleExpr );
+		/// Runs a new alternative finder on each element in [begin, end)
+		/// and writes each alternative finder to out.
 		template< typename InputIterator, typename OutputIterator >
 		void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
 
-	  private:
 		/// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
-		template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string &name );
+		template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
 		/// Adds alternatives for offsetof expressions, given the base type and name of the member
 		template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
@@ -89,4 +91,26 @@
 
 	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env );
+
+	template< typename InputIterator, typename OutputIterator >
+	void findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
+		AltList alternatives;
+
+		// select the alternatives that have the minimum parameter cost
+		Cost minCost = Cost::infinity;
+		for ( InputIterator i = begin; i != end; ++i ) {
+			if ( i->cost < minCost ) {
+				minCost = i->cost;
+				i->cost = i->cvtCost;
+				alternatives.clear();
+				alternatives.push_back( *i );
+			} else if ( i->cost == minCost ) {
+				i->cost = i->cvtCost;
+				alternatives.push_back( *i );
+			}
+		}
+		std::copy( alternatives.begin(), alternatives.end(), out );
+	}
+
+	Cost sumCost( const AltList &in );
 } // namespace ResolvExpr
 
