Index: src/Tuples/AssignExpand.cc
===================================================================
--- src/Tuples/AssignExpand.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/AssignExpand.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,146 @@
+//
+// 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.
+//
+// AssignExpand.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 11:24:47 2015
+// Update Count     : 2
+//
+
+#include <ctime>
+#include <cstdlib>
+
+#include <list>
+#include <cassert>
+#include <algorithm>
+
+#include "AssignExpand.h"
+
+#include "SynTree/Type.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Declaration.h"
+
+namespace Tuples {
+	AssignExpander::AssignExpander() : temporaryNamer("__tpl") {}
+
+	Statement *AssignExpander::mutate( ExprStmt *exprStmt ) {
+		replace.clear();
+		extra.clear();
+		extra2.clear();
+		exprStmt->set_expr( maybeMutate( exprStmt->get_expr(), *this ) );
+
+		CompoundStmt *newSt = 0;
+		if ( ! extra.empty() ) {
+			if ( ! newSt )
+				newSt= new CompoundStmt(std::list<Label>());
+
+			newSt->get_kids().splice(newSt->get_kids().end(), extra);
+		} // if
+
+		if ( ! extra2.empty() ) {
+			if ( ! newSt )
+				newSt= new CompoundStmt(std::list<Label>());
+
+			newSt->get_kids().splice(newSt->get_kids().end(), extra2);
+		}
+
+		if ( ! replace.empty() ) {
+			if ( ! newSt )
+				newSt= new CompoundStmt(std::list<Label>());
+
+			for ( std::list<Expression *>::iterator r = replace.begin(); r != replace.end(); r++ )
+				newSt->get_kids().push_back( new ExprStmt( std::list<Label>(), *r ));
+		}
+
+		if ( newSt ) return newSt; else return exprStmt;
+	}
+
+	Expression *AssignExpander::mutate( SolvedTupleExpr *tupleExpr ) {
+		/* 
+		   std::list<Expression *> &exprs = tupleExpr->get_exprs();
+
+		   if ( tupleExpr->get_type() == SolvedTupleExpr::MASS ) {
+		   // extract lhs of assignments, assert that rhs is the same, create temporaries
+		   assert ( ! exprs.empty());
+		   ApplicationExpr *ap1 = dynamic_cast< ApplicationExpr * >( exprs.front() );
+		   std::list<Expression *> &args = ap1->get_args();
+		   assert(args.size() == 2);
+		   std::list<Type *> &temp_types = args.back()->get_results();
+		   assert(temp_types.size() == 1);
+		   extra.push_back(new DeclStmt( std::list<Label>(), new ObjectDecl(temporaryNamer.newName(), Declaration::Auto, LinkageSpec::C, 0, temp_types.front(), 0 ) ));
+
+		   for ( std::list<Expression *>::iterator e = exprs.begin(); e != exprs.end(); e++ ) {
+		   ApplicationExpr *ap = dynamic_cast< ApplicationExpr * >( *e );
+		   assert( ap != 0 );
+		   replace.push_back(ap);
+		   }
+
+		   return tupleExpr;
+		   } else if ( tupleExpr->get_type() == SolvedTupleExpr::MULTIPLE ||
+		   tupleExpr->get_type() == SolvedTupleExpr::MASS ) */ {
+			std::list<Expression *> &comps = tupleExpr->get_exprs();
+			for ( std::list<Expression *>::iterator i = comps.begin(); i != comps.end(); ++i ) {
+				std::list<Statement *> decls;
+				std::list<Statement *> temps;
+				std::list<Statement *> assigns;
+				if ( ApplicationExpr *app = dynamic_cast< ApplicationExpr * >(*i) ) {
+					assert( app->get_args().size() == 2 );
+
+					Expression *lhsT = app->get_args().front();
+					Expression *rhsT = app->get_args().back();
+					// after the round of type analysis this should be true
+					assert( lhsT->get_results().size() == 1 );
+					assert( rhsT->get_results().size() == 1 );
+					// declare temporaries
+					ObjectDecl *lhs = new ObjectDecl( temporaryNamer.newName("_lhs_"), Declaration::NoStorageClass, LinkageSpec::Intrinsic, 0,
+													  lhsT->get_results().front(), 0 );
+					decls.push_back( new DeclStmt( std::list< Label >(), lhs ) );
+					ObjectDecl *rhs = new ObjectDecl( temporaryNamer.newName("_rhs_"), Declaration::NoStorageClass, LinkageSpec::Intrinsic, 0,
+													  rhsT->get_results().front(), 0);
+					decls.push_back( new DeclStmt( std::list< Label >(), rhs ));
+
+
+					// create temporary for lhs, assign address
+					UntypedExpr *assgnL = new UntypedExpr( new NameExpr( "?=?" ) );
+					assgnL->get_args().push_back( new VariableExpr( lhs ) );
+					assgnL->get_args().push_back( lhsT );
+					temps.push_back( new ExprStmt(std::list<Label>(), assgnL) );
+
+					// create temporary for rhs, assign value
+					UntypedExpr *assgnR = new UntypedExpr( new NameExpr( "?=?" ) );
+					assgnR->get_args().push_back( new VariableExpr( rhs ) );
+					assgnR->get_args().push_back( rhsT );
+					temps.push_back( new ExprStmt(std::list<Label>(), assgnR) );
+
+					// assign rhs to lhs
+					UntypedExpr *assgn = new UntypedExpr( new NameExpr( "?=?" ) );
+					UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
+					deref->get_args().push_back( new VariableExpr( lhs ) );
+					assgn->get_args().push_back( deref );
+					assgn->get_args().push_back( new VariableExpr( rhs ) );
+					assigns.push_back( new ExprStmt(std::list<Label>(), assgn) );
+				} else
+					throw CompilerError("Solved Tuple should contain only assignment statements");
+	  
+				extra.splice( extra.begin(), decls );
+				extra.splice( extra.end(), temps );
+				extra2.splice( extra2.end(), assigns );
+			} // for
+			return tupleExpr;
+		}
+		throw 0; // shouldn't be here
+	}
+} // namespace Tuples
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/AssignExpand.h
===================================================================
--- src/Tuples/AssignExpand.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/AssignExpand.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+// AssignExpand.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 11:25:53 2015
+// Update Count     : 3
+//
+
+#ifndef _ASSIGN_EXPAND_H_
+#define _ASSIGN_EXPAND_H_
+
+#include <cstdlib>
+
+#include "SynTree/Mutator.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Expression.h"
+
+#include "UniqueName.h"
+
+namespace Tuples {
+	class AssignExpander : public Mutator {
+		typedef Mutator Parent;
+	  public:
+		AssignExpander();
+		virtual Statement *mutate( ExprStmt *expr );
+		virtual Expression *mutate( SolvedTupleExpr *tupleExpr );
+	  private:
+		std::list<Statement *> extra, extra2;
+		std::list<Expression *> replace;
+		UniqueName temporaryNamer;
+	};
+} // namespace Tuples
+
+
+#endif // _ASSIGN_EXPAND_H_
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/FlattenTuple.cc
===================================================================
--- src/Tuples/FlattenTuple.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/FlattenTuple.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,65 @@
+//
+// 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.
+//
+// FlattenTuple.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 11:26:56 2015
+// Update Count     : 1
+//
+
+#include <list>
+#include <vector>
+#include <cassert>
+#include <algorithm>
+
+#include "FlattenTuple.h"
+
+namespace Tuples {
+	FlattenTuple::FlattenTuple() {
+	}
+
+	FlattenTuple::~FlattenTuple() {
+	}
+
+	Expression *FlattenTuple::mutate( TupleExpr *tupleExpr ) {
+		CollectArgs c;
+
+		acceptAll( tupleExpr->get_exprs(), c );
+		tupleExpr->set_exprs( c.get_args() );
+
+		return tupleExpr;
+	}
+
+	void FlattenTuple::CollectArgs::visit( UntypedExpr       *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( NameExpr          *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( CastExpr          *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( AddressExpr       *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( UntypedMemberExpr *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( MemberExpr        *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( VariableExpr      *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( ConstantExpr      *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( SizeofExpr        *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( AttrExpr          *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( LogicalExpr       *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( ConditionalExpr   *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( CommaExpr         *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( TypeExpr          *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+	void FlattenTuple::CollectArgs::visit( UntypedValofExpr  *expr )  {  currentArgs.insert( currentArgs.end(), expr );  }
+
+	void FlattenTuple::CollectArgs::visit( TupleExpr *tupleExpr) {
+		acceptAll( tupleExpr->get_exprs(), *this );
+		//currentArgs.splice( currentArgs.end(), c.get_args() );
+	}
+} // namespace Tuples
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/FlattenTuple.h
===================================================================
--- src/Tuples/FlattenTuple.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/FlattenTuple.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,67 @@
+//
+// 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.
+//
+// FlattenTuple.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 11:28:15 2015
+// Update Count     : 3
+//
+
+#ifndef _FLATTEN_TUPLE_H_
+#define _FLATTEN_TUPLE_H_
+
+#include "SynTree/Mutator.h"
+#include "SynTree/Visitor.h"
+
+#include "SynTree/Expression.h"
+
+namespace Tuples {
+	class FlattenTuple : public Mutator {
+		typedef Mutator Parent;
+	  public:
+		FlattenTuple();
+		~FlattenTuple();
+
+		virtual Expression *mutate( TupleExpr *tupleExpr );
+	  private:
+		class CollectArgs : public Visitor {
+		  public:
+			virtual void visit( UntypedExpr * );
+			virtual void visit( NameExpr * );
+			virtual void visit( CastExpr *);
+			virtual void visit( AddressExpr * );
+			virtual void visit( UntypedMemberExpr * );
+			virtual void visit( MemberExpr * );
+			virtual void visit( VariableExpr * );
+			virtual void visit( ConstantExpr * ); 
+			virtual void visit( SizeofExpr * );
+			virtual void visit( AttrExpr * );
+			virtual void visit( LogicalExpr * );
+			virtual void visit( ConditionalExpr * );
+			virtual void visit( CommaExpr * );
+			virtual void visit( TypeExpr * );
+			virtual void visit( UntypedValofExpr * );
+
+			virtual void visit( TupleExpr *tupleExpr );
+
+			std::list< Expression *> &get_args() { return currentArgs; }
+		  private:
+			std::list< Expression * > currentArgs;
+		};
+
+	};
+} // namespace Tuples
+
+#endif // _FLATTEN_TUPLE_H_
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/FunctionChecker.cc
===================================================================
--- src/Tuples/FunctionChecker.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/FunctionChecker.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,141 @@
+//
+// 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.
+//
+// FunctionChecker.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 11:59:55 2015
+// Update Count     : 3
+//
+
+#include "FunctionChecker.h"
+#include "FunctionFixer.h"
+#include "SemanticError.h"
+
+#include <algorithm>
+#include <iostream>
+#include <cassert>
+
+namespace Tuples {
+	using namespace std;
+
+	void checkFunctions( std::list< Declaration * > translationUnit ) {
+		FunctionChecker fchk( true );
+		TupleDistrib td;
+		FunctionFixer ff;
+
+		mutateAll( translationUnit , fchk );
+		mutateAll( translationUnit , ff );
+		mutateAll( translationUnit , td );
+		return;
+	}
+
+	FunctionChecker::FunctionChecker( bool _topLevel, UniqueName *_nameGen ) : topLevel( _topLevel ), nameGen( _nameGen ) {
+		if ( topLevel ) {
+			assert( ! nameGen );
+			nameGen = new UniqueName("_MVR_");
+		} else
+			assert( nameGen );
+	}
+
+	FunctionChecker::~FunctionChecker() {
+		if ( topLevel ) {
+			delete nameGen;
+			nameGen = 0;
+		}
+	}
+
+	Statement* FunctionChecker::mutate( ExprStmt *exprStmt ) {
+		exprStmt->set_expr( maybeMutate( exprStmt->get_expr(), *this ) );
+		if ( ! tempExpr.empty() ) {
+			assert ( ! temporaries.empty() );
+			CompoundStmt *newBlock = new CompoundStmt( std::list< Label >() );
+			// declarations
+			for ( std::list< ObjectDecl *>::iterator d = temporaries.begin(); d != temporaries.end(); ++d )
+				newBlock->get_kids().push_back( new DeclStmt( std::list<Label>(), *d ) );
+			// new expression statements
+			for ( std::list< Expression *>::iterator e = tempExpr.begin(); e != tempExpr.end(); ++e )
+				newBlock->get_kids().push_back( new ExprStmt( std::list<Label>(), *e ) );
+
+			newBlock->get_kids().push_back( exprStmt );
+			return newBlock;
+		} else
+			return exprStmt;
+	}
+
+	Expression* FunctionChecker::mutate( ApplicationExpr *applicationExpr ) {
+		if ( topLevel )
+			; // In top level of Functionchecker
+
+		if ( applicationExpr->get_results().size() > 1 ) {
+			for ( std::list< Type *>::iterator res = applicationExpr->get_results().begin(); res != applicationExpr->get_results().end(); res++ )
+				temporaries.push_back( new ObjectDecl( nameGen->newName(),Declaration::Auto,LinkageSpec::AutoGen, 0, (*res )->clone(), 0 ) );
+
+			assert( ! temporaries.empty() );
+		}
+
+		applicationExpr->set_function(  maybeMutate( applicationExpr->get_function(), *this ) );
+
+		std::list< Expression * > newArgs;
+		for ( std::list< Expression *>::iterator e = applicationExpr->get_args().begin(); e != applicationExpr->get_args().end(); ++e ) {
+			FunctionChecker rec( false, nameGen );
+			(*e )->acceptMutator( rec );
+
+			if ( ! rec.temporaries.empty() ) {
+				TupleExpr *lhs = new TupleExpr;
+				std::list< Expression * > &tmem = lhs->get_exprs();
+				for ( std::list<ObjectDecl *>::iterator d = rec.temporaries.begin();  d != rec.temporaries.end(); ++d ) {
+					tmem.push_back( new VariableExpr( *d ) );
+					newArgs.push_back( new VariableExpr( *d ) );
+				}
+
+				// construct tuple assignment
+				std::list<Expression *> args;
+				args.push_back( new AddressExpr( lhs ) );
+				args.push_back( *e );
+				tempExpr.push_back( new UntypedExpr( new NameExpr("?=?"), args ) );
+
+				temporaries.splice( temporaries.end(), rec.temporaries );
+			} else
+				newArgs.push_back( *e );
+			// percolate to recursive calls
+		}
+
+		applicationExpr->get_args().clear();
+		std::copy( newArgs.begin(), newArgs.end(), back_inserter( applicationExpr->get_args()) );
+
+		return applicationExpr;
+	}
+
+	Expression* TupleDistrib::mutate( UntypedExpr *expr ) {
+		if (  NameExpr *assgnop = dynamic_cast< NameExpr * >( expr->get_function()) ) {
+			if ( assgnop->get_name() == std::string("?=?") ) {
+				std::list<Expression *> &args = expr->get_args();
+				assert( args.size() == 2 );
+				//if args.front() points to a tuple and if args.back() is already resolved
+				if ( AddressExpr *addr = dynamic_cast<AddressExpr *>( args.front()) )
+					if ( TupleExpr *lhs = dynamic_cast<TupleExpr *>( addr->get_arg()) )
+						if ( ApplicationExpr *rhs = dynamic_cast<ApplicationExpr *>( args.back() ) ) {
+							for ( std::list<Expression *>::iterator tc = lhs->get_exprs().begin(); tc != lhs->get_exprs().end(); ++tc )
+								rhs->get_args().push_back( new AddressExpr( *tc ) );
+							return rhs; // XXX
+						} // if
+			} else
+				assert( false ); // It's not an assignment, shouldn't be here
+		} // if
+		return expr;
+	}
+
+}
+
+// namespace Tuples
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/FunctionChecker.h
===================================================================
--- src/Tuples/FunctionChecker.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/FunctionChecker.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,64 @@
+//
+// 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.
+//
+// FunctionChecker.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 12:00:57 2015
+// Update Count     : 2
+//
+
+#ifndef _TUPLE_FUNCHK_H_
+#define _TUPLE_FUNCHK_H_
+
+#include <string>
+#include <list>
+#include <iostream>
+
+#include "UniqueName.h"
+
+#include "SynTree/SynTree.h"
+#include "SynTree/Mutator.h"
+
+#include "SynTree/Type.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Statement.h"
+
+namespace Tuples {
+	class FunctionChecker : public Mutator {
+		typedef Mutator Parent;
+	  public:
+		FunctionChecker( bool _topLevel = false, UniqueName *_nameGen = 0 );
+		~FunctionChecker();
+
+		virtual Expression* mutate(ApplicationExpr *applicationExpr);
+		virtual Statement* mutate(ExprStmt *exprStmt);
+	  private:
+		bool topLevel;
+		UniqueName *nameGen;
+		std::list< ObjectDecl * > temporaries;
+		std::list< Expression * > tempExpr;
+	};
+
+	class TupleDistrib : public Mutator {
+	  public:
+		virtual Expression* mutate(UntypedExpr *utExpr);
+	  private:
+	};
+
+	void checkFunctions( std::list< Declaration * > translationUnit );
+} // namespace Tuples
+
+#endif // _TUPLE_FUNCHK_H_
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/FunctionFixer.cc
===================================================================
--- src/Tuples/FunctionFixer.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/FunctionFixer.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,127 @@
+//
+// 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.
+//
+// FunctionFixer.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 12:02:22 2015
+// Update Count     : 1
+//
+
+#include <list>
+#include <vector>
+#include <cassert>
+#include <algorithm>
+
+#include "FunctionFixer.h"
+
+namespace Tuples {
+	DeclarationWithType *FunctionFixer::mutate( FunctionDecl *functionDecl ) {
+		functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
+		mutateAll( functionDecl->get_oldDecls(), *this );
+		functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
+		index.visit( functionDecl );
+		rets.clear();
+		return functionDecl;
+	}
+
+	Type *FunctionFixer::mutate( FunctionType *functionType ) {
+		typedef std::list< DeclarationWithType * >  Decls;
+
+		if ( functionType->get_returnVals().size() <= 1 )  return functionType;
+		std::copy( functionType->get_returnVals().begin(), functionType->get_returnVals().end(), back_inserter(rets) );
+
+		Type::Qualifiers qual;
+		for ( Decls::iterator i = rets.begin(); i != rets.end(); i++ ) {
+			(*i)->set_type( new PointerType( qual, (*i)->get_type() ) );
+			functionType->get_parameters().push_back( *i );
+		} // for
+
+		functionType->get_returnVals() = *(new std::list< DeclarationWithType * >());
+
+		functionType->set_isVarArgs( false );
+		return functionType;
+	}
+
+	Statement *FunctionFixer::mutate( ReturnStmt *retStmt ) {
+		bool tupleReturn = false;
+		Expression *rhs = 0;
+		// also check if returning multiple values
+		if ( CastExpr *cst = dynamic_cast<CastExpr *>( retStmt->get_expr() ) ) {
+			if ( ApplicationExpr *app = dynamic_cast<ApplicationExpr *>( cst->get_arg() ) ) {
+				if ( app->get_results().size() > 1 ) { // doesn't need to be ApplicationExpr
+					tupleReturn = true;
+					rhs = app;
+				}
+			} else if ( TupleExpr *t = dynamic_cast<TupleExpr *>( cst->get_arg() ) ) {
+				tupleReturn = true;
+				assert( rets.size() == t->get_exprs().size() ); // stupid check, resolve expression
+				rhs = t;
+			} // if
+
+			if ( tupleReturn ) {
+				assert ( rhs != 0 );
+				std::list< Expression * > lhs;
+				for ( std::list< DeclarationWithType * >::iterator d = rets.begin(); d != rets.end(); ++d ) {
+					std::list<Expression *> largs;
+					largs.push_back(new VariableExpr( *d ));
+					Expression *exp = ResolvExpr::resolveInVoidContext( new CastExpr( new UntypedExpr(new NameExpr("*?"), largs), (*d)->get_type()),
+																		index );
+					lhs.push_back(exp);
+				} // for
+				std::list< Expression * > args;
+				TupleExpr *tlhs = new TupleExpr; tlhs->set_exprs( lhs );
+				args.push_back( new AddressExpr(tlhs) );
+				args.push_back(rhs);
+
+				return new ExprStmt( std::list< Label>(), new UntypedExpr( new NameExpr("?=?"), args ) );
+			} // if
+		} // if
+		/*
+		  else
+		  std::cerr << "Empty return statement" << std::endl;
+		*/
+
+		return retStmt;
+	}
+
+	Expression* FunctionFixer::mutate( VariableExpr *variableExpr ) {
+		if ( rets.empty() ) return variableExpr;
+		mutateAll( variableExpr->get_results(), *this );
+		if ( std::find( rets.begin(), rets.end(), variableExpr->get_var() ) != rets.end() )
+//      if ( PointerType *ptr = dynamic_cast<PointerType *>(variableExpr->get_var()->get_type()) ) {
+			if ( dynamic_cast<PointerType *>(variableExpr->get_var()->get_type()) != 0 ) {
+				std::list<Expression *> largs;
+				largs.push_back( new AddressExpr(variableExpr) );
+				Expression *expr = ResolvExpr::resolveInVoidContext( /*new CastExpr(*/new UntypedExpr( new NameExpr( "*?" ), largs )/*,
+																																	  ptr->get_base()),*/, index);
+				if ( ApplicationExpr *app = dynamic_cast< ApplicationExpr * >( expr ) ) {
+					assert( app->get_args().size() == 1 );
+					app->get_args().pop_front();
+					app->get_args().push_back( variableExpr );
+					return app;
+				}
+			}
+		return variableExpr;
+	}
+
+	/*
+	  Expression* FunctionFixer::mutate(ApplicationExpr *applicationExpr) {
+	  std::cerr << "In Application Expression" << std::endl;
+	  mutateAll( applicationExpr->get_results(), *this );
+	  applicationExpr->set_function(  maybeMutate( applicationExpr->get_function(), *this ) );
+	  mutateAll( applicationExpr->get_args(), *this );
+	  return applicationExpr;
+	  }
+	*/
+} // namespace Tuples
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/FunctionFixer.h
===================================================================
--- src/Tuples/FunctionFixer.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/FunctionFixer.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,71 @@
+//
+// 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.
+//
+// FunctionFixer.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 14:58:45 2015
+// Update Count     : 3
+//
+
+#ifndef _FUNCTIONFIXER_H_
+#define _FUNCTIONFIXER_H_
+
+#include "SynTree/Mutator.h"
+
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Type.h"
+
+#include "SymTab/Indexer.h"
+#include "ResolvExpr/Resolver.h"
+#include "ResolvExpr/AlternativeFinder.h"
+
+namespace Tuples {
+	class FunctionFixer : public Mutator {
+		typedef Mutator Parent;
+	  public:
+		FunctionFixer() {}
+		virtual ~FunctionFixer() {}
+		virtual Type       *mutate( FunctionType *functionType );
+		virtual Statement  *mutate( ReturnStmt   *retStmt  );
+		virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
+		virtual Expression *mutate( VariableExpr *variableExpr);
+
+		// indexer runs
+		virtual ObjectDecl     *mutate( ObjectDecl *objectDecl )
+			{ index.visit( objectDecl ); return objectDecl; }
+		virtual TypeDecl       *mutate( TypeDecl *typeDecl )
+			{ index.visit( typeDecl ); return typeDecl; }
+		virtual TypedefDecl    *mutate( TypedefDecl *typeDecl )
+			{ index.visit( typeDecl ); return typeDecl; }
+		virtual StructDecl     *mutate( StructDecl *aggregateDecl )
+			{ index.visit( aggregateDecl ); return aggregateDecl; }
+		virtual UnionDecl      *mutate( UnionDecl *aggregateDecl )
+			{ index.visit( aggregateDecl ); return aggregateDecl; }
+		virtual EnumDecl       *mutate( EnumDecl *aggregateDecl )
+			{ index.visit( aggregateDecl ); return aggregateDecl; }
+
+		virtual Type           *mutate( StructInstType *aggrInst )
+			{ index.visit( aggrInst ); return aggrInst; }
+		virtual Type           *mutate( UnionInstType *aggrInst )
+			{ index.visit( aggrInst ); return aggrInst; }
+	  private:
+		std::list< DeclarationWithType * > rets;
+		SymTab::Indexer index;
+	};
+} // namespace Tuples
+
+#endif // _FUNCTIONFIXER_H_
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/MultRet.cc
===================================================================
--- src/Tuples/MultRet.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/MultRet.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,170 @@
+//
+// 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.
+//
+// MultRet.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 12:37:57 2015
+// Update Count     : 1
+//
+
+#include <list>
+#include <vector>
+#include <cassert>
+#include <algorithm>
+
+#include "MultRet.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+
+namespace Tuples {
+	MVRMutator::MVRMutator() : newVars( 0 ), newCode( 0 ) {
+	}
+
+	MVRMutator::~MVRMutator() {
+	}
+
+	int MVRMutator::curVal = 0;
+
+	Statement *MVRMutator::mutate( ExprStmt *exprStmt ) {
+		MVRMutator toplevel;
+		exprStmt->set_expr( maybeMutate( exprStmt->get_expr(), toplevel ) );
+
+		if ( toplevel.hasCode() ) {
+			assert ( toplevel.getVars() != 0 );
+
+			typedef std::list<Statement *> Statements;
+
+			CompoundStmt *code = new CompoundStmt( std::list< Label >() );
+
+			// copy variables
+			Statements &vars = toplevel.getVars()->get_kids();
+			for ( Statements::iterator i = vars.begin(); i != vars.end(); i++ )
+				code->get_kids().push_back( *i );
+
+			// copy statements
+			Statements &block = toplevel.getCode()->get_kids();
+			for ( Statements::iterator i = block.begin(); i != block.end(); i++ )
+				code->get_kids().push_back( *i );
+
+			return code;
+		} else
+			return exprStmt;
+	}
+
+	Expression *MVRMutator::mutate( ApplicationExpr *appExpr ) {
+		// appExpr->set_function(  maybeMutate( appExpr->get_function(), *this ) );
+		bool mulretp = false;
+		VariableExpr *funname;
+		if ( (funname = dynamic_cast<VariableExpr *>(appExpr->get_function())) == 0 ) goto DoArgs;
+
+		FunctionDecl *fundecl;
+		if ((fundecl = dynamic_cast<FunctionDecl *>(funname->get_var())) == 0) goto DoArgs;
+		{
+			typedef std::list<DeclarationWithType*> RetType;
+
+			RetType &rets = fundecl->get_functionType()->get_returnVals();
+			if ( rets.size() <= 1 ) goto DoArgs;
+			mulretp = true;
+
+			if ( newVars == 0 )
+				newVars = new CompoundStmt( std::list<Label>(0) );
+
+			for (RetType::iterator i = rets.begin() ; i != rets.end(); i++) {
+				DeclStmt *arg = newVar( *i );
+				newVars->get_kids().push_back( arg );
+				add_pending( arg->get_decl() );
+			} // for
+		}
+
+	  DoArgs:
+		// mutate the argument list
+		typedef std::list< Expression *> Exprs;
+		Exprs &args = appExpr->get_args();
+		std::list< Expression * > newArgs;
+		for ( Exprs::iterator i = args.begin(); i != args.end(); i++ ) {
+			MVRMutator next;
+			Expression *mutated = (*i)->acceptMutator( next );
+
+			if ( next.hasCode() ) {
+				// merge new vars and bodies
+				typedef std::list< Statement * > Stmts;
+				Stmts &vars = next.getVars()->get_kids();
+				Stmts &block = next.getCode()->get_kids();
+
+				if (newVars == 0)
+					newVars = new CompoundStmt( std::list< Label >() );
+				for ( Stmts::iterator i = vars.begin(); i != vars.end(); i++ )  // std::splice? -- need to append lists
+					newVars->get_kids().push_back( *i );
+
+				if (newCode == 0)
+					newCode = new CompoundStmt( std::list< Label >() );
+				for ( Stmts::iterator i = block.begin(); i != block.end(); i++ )
+					newCode->get_kids().push_back( *i );
+			} // if
+
+			if ( next.hasResults() ) {
+				Exprs &res = next.get_results();
+				for ( Exprs::iterator i = res.begin(); i != res.end(); i++ )
+					newArgs.push_back( *i );
+			} else
+				newArgs.push_back( mutated );
+		}
+
+		appExpr->get_args() = newArgs;  // new argument list
+
+		if ( mulretp ) {
+			// add 'out' parameters
+			if ( ! argsToAdd.empty() )
+				for (std::list< Expression *>::iterator i = argsToAdd.begin(); i != argsToAdd.end(); i++)
+					(appExpr->get_args()).push_back( *i );
+			// clear 'out' parameters ( so that the list can be reused -- substitute by auto_ptr later? )
+
+			if (newCode == 0)
+				newCode = new CompoundStmt( std::list<Label>(0) );
+		} // if
+
+		// add to block of code
+		if ( newCode != 0 )
+			newCode->get_kids().push_back( new ExprStmt( std::list<Label>(), appExpr ) );
+
+		return appExpr;
+	}
+
+	// Auxiliary function to generate new names for the `output' parameters
+	DeclStmt *MVRMutator::newVar( DeclarationWithType *reqDecl ) {
+		// std::ostrstream os;
+		// os << "__" << curVal++ << "__";// << std::ends;
+		// os.freeze( false );
+
+		ObjectDecl *decl;
+		if ((decl = dynamic_cast<ObjectDecl *>( reqDecl )) != 0)
+			// return new DeclStmt( new ObjectDecl( std::string (os.str(), os.pcount()), );
+			return new DeclStmt( std::list<Label>(), decl );
+		else
+			return 0;
+	}
+
+	void MVRMutator::add_pending( Declaration *decl ) {
+		ObjectDecl *obj;
+		if ( (obj = dynamic_cast< ObjectDecl * >( decl )) == 0 ) return;
+
+		VariableExpr *var = new VariableExpr(obj, 0 );
+		results.push_back( var ); // probably change this name to newResults or something
+		argsToAdd.push_back( new AddressExpr( var ) );
+		return;
+	}
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/MultRet.h
===================================================================
--- src/Tuples/MultRet.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/MultRet.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,59 @@
+//
+// 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.
+//
+// MultRet.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 12:39:20 2015
+// Update Count     : 3
+//
+
+#ifndef _MULTRET_H_
+#define _MULTRET_H_
+
+#include "SynTree/Mutator.h"
+#include "SynTree/Visitor.h"
+
+#include "SynTree/Expression.h"
+#include "SynTree/Statement.h"
+
+namespace Tuples {
+	class MVRMutator : public Mutator {
+		typedef Mutator Parent;
+	  public:
+		MVRMutator();
+		~MVRMutator();
+
+		virtual Statement  *mutate( ExprStmt        *exprStmt );
+		virtual Expression *mutate( ApplicationExpr *appExpr  );
+
+		bool hasCode() const { return ( newCode != 0 ); }
+		CompoundStmt *getCode() const { return newCode; }
+		CompoundStmt *getVars() const { return newVars; }
+
+		bool hasResults() const { return ( ! results.empty()); }
+		std::list<Expression *> &get_results() { return results; }
+	  private:
+		CompoundStmt *newVars;
+		CompoundStmt *newCode;
+		std::list<Expression *> argsToAdd;
+		std::list<Expression *> results;
+
+		static int curVal;
+		DeclStmt *newVar( DeclarationWithType * );
+		void add_pending( Declaration * );
+	};
+} // namespace Tuples
+
+#endif // _MULTRET_H_
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/Mutate.cc
===================================================================
--- src/Tuples/Mutate.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/Mutate.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -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.
+//
+// Mutate.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 14:57:10 2015
+// Update Count     : 2
+//
+
+#include "SynTree/Mutator.h"
+
+#include "Mutate.h"
+//#include "TupleFixer.h"
+//#include "FlattenTuple.h"
+//#include "MultRet.h"
+#include "FunctionFixer.h"
+#include "AssignExpand.h"
+//#include "FixReturn.h"
+//#include "MassAssignment.h"
+
+namespace Tuples {
+	void mutate( std::list< Declaration * > translationUnit ) {
+		//FunctionFixer fst;
+		AssignExpander snd;
+
+		//mutateAll( translationUnit, fst );
+		mutateAll( translationUnit, snd );
+	}
+} // namespace Tuples
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/Mutate.h
===================================================================
--- src/Tuples/Mutate.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/Mutate.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,35 @@
+//
+// 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.
+//
+// Mutate.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 14:58:05 2015
+// Update Count     : 2
+//
+
+#ifndef MUTATE_H
+#define MUTATE_H
+
+#include <list>
+#include <iostream>
+
+#include "SynTree/Declaration.h"
+
+namespace Tuples {
+	void mutate( std::list< Declaration* > translationUnit );
+	void mulReturn( std::list< Declaration * > translationUnit );
+} // namespace Tuples
+
+#endif // MUTATE_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/NameMatcher.cc
===================================================================
--- src/Tuples/NameMatcher.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/NameMatcher.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,67 @@
+//
+// 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.
+//
+// NameMatcher.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:00:06 2015
+// Update Count     : 1
+//
+
+#include "NameMatcher.h"
+#include "NameMatcher.h"
+
+namespace Tuples {
+	NameMatcher::NameMatcher( std::list< DeclarationWithType* > &formals ) : current( 0 ) {
+		int cnt = 0;
+		for ( std::list< DeclarationWithType *>::const_iterator f = formals.begin(); f != formals.end(); ++f ) {
+			table.insert( std::pair< std::string, int >( (*f)->get_name(), cnt++ ) );
+			index.push_back(*f);
+		} // for
+		exprs.reserve( index.size() );
+	}
+
+	NameMatcher::~NameMatcher() {}
+
+	void NameMatcher::match( ResolvExpr::AltList &alternatives ) throw (NoMatch) {
+		if ( alternatives.size() != index.size() )
+			throw NoMatch("Length of actuals and formals differ");
+
+		for ( ResolvExpr::AltList::const_iterator a = alternatives.begin(); a != alternatives.end(); ++a ) {
+			if ( a->expr->get_argName() != 0 )
+				if ( NameExpr *name = dynamic_cast<NameExpr *>( a->expr->get_argName() ) ) {
+					if ( table.find( name->get_name() ) != table.end() ) {
+						std::cerr << "Rearranging to " << table[ name->get_name() ] << "position in the list." << std::endl;
+						exprs[ table[ name->get_name() ] ] = &(*a);
+					} else
+						throw NoMatch( name->get_name() + "no such  designation" );
+				} /*else if ( TupleExpr *tup = dynamic_cast<TupleExpr *>( a->expr->get_argName() ) )
+					std::cerr << "Designated expression" << std::endl; */
+			exprs.push_back( &(*a) );
+		} // for
+
+		/*std::cerr << "In matcher/match: ";
+		  if ( exprs.size() != index.size() )
+		  std::cerr << "exprs and index differ in length" << std::endl;
+		  else
+		  std::cerr << "is all good." << std::endl;
+		*/
+	}
+
+	ResolvExpr::Alternative &NameMatcher::get_next() throw (NoMoreElements) {
+		if ( current++ >= (int)(index.size()) )
+			throw NoMoreElements();
+		return *(new ResolvExpr::Alternative());
+	}
+} // namespace Tuples
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/NameMatcher.h
===================================================================
--- src/Tuples/NameMatcher.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/NameMatcher.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,62 @@
+//
+// 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.
+//
+// NameMatcher.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:01:37 2015
+// Update Count     : 3
+//
+
+#ifndef _NAMEMATCHER_H_
+#define _NAMEMATCHER_H_
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "SynTree/SynTree.h"
+#include "SynTree/Mutator.h"
+
+#include "SynTree/Type.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Statement.h"
+
+#include "ResolvExpr/Alternative.h"
+
+namespace Tuples {
+	struct NoMoreElements {};
+	struct NoMatch {
+		NoMatch( std::string msg ) : message( msg ) {}
+		std::string message;
+	};
+
+	class NameMatcher {
+	  public:
+		NameMatcher( std::list< DeclarationWithType* >& );
+		~NameMatcher();
+
+		void match( ResolvExpr::AltList &alternatives ) throw (NoMatch) ;
+		ResolvExpr::Alternative &get_next() throw (NoMoreElements);
+
+	  private:
+		int current;
+		std::vector< DeclarationWithType* > index;
+		std::vector< const ResolvExpr::Alternative * > exprs;
+		std::map< std::string, int> table;
+	};
+} // namespace Tuples
+
+#endif // _NAMEMATCHER_H_
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/TupleAssignment.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,415 @@
+//
+// 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 "ResolvExpr/AlternativeFinder.h"
+#include "ResolvExpr/Alternative.h"
+#include "ResolvExpr/typeops.h"
+#include "SynTree/Expression.h"
+#include "TupleAssignment.h"
+#include "SemanticError.h"
+
+#include <functional>
+#include <algorithm>
+#include <iterator>
+#include <iostream>
+#include <cassert>
+#include <set>
+
+namespace Tuples {
+	TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder *f = 0 )
+		: currentFinder(f), matcher(0), hasMatched( false ) {}
+
+	bool TupleAssignSpotter::pointsToTuple( Expression *expr ) {
+		// also check for function returning tuple of reference types
+		if (AddressExpr *addr = dynamic_cast<AddressExpr *>(expr) )
+			if ( isTuple(addr->get_arg() ) )
+				return true;
+		return false;
+	}
+
+	bool TupleAssignSpotter::isTupleVar( DeclarationWithType *decl ) {
+		if ( dynamic_cast<TupleType *>(decl->get_type()) )
+			return true;
+		return false;
+	}
+
+	bool TupleAssignSpotter::isTuple( Expression *expr, bool isRight ) {
+		// true if `expr' is an expression returning a tuple: tuple, tuple variable or MRV function
+		if ( ! expr ) return false;
+
+		if ( dynamic_cast<TupleExpr *>(expr) )
+			return true;
+		else if ( VariableExpr *var = dynamic_cast<VariableExpr *>(expr) ) {
+			if ( isTupleVar(var->get_var()) )
+				return true;
+		}
+
+		return false;
+	}
+
+	bool TupleAssignSpotter::match() {
+		assert ( matcher != 0 );
+
+		std::list< Expression * > new_assigns;
+		if ( ! matcher->match(new_assigns) )
+			return false;
+
+		if ( new_assigns.empty() ) return false;
+		/*return */matcher->solve( new_assigns );
+		if ( dynamic_cast<TupleAssignSpotter::MultipleAssignMatcher *>( matcher ) ) {
+			// now resolve new assignments
+			std::list< Expression * > solved_assigns;
+			ResolvExpr::AltList solved_alts;
+			assert( currentFinder != 0 );
+
+			ResolvExpr::AltList current;
+			for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
+				//try {
+				ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
+				finder.findWithAdjustment(*i);
+				// prune expressions that don't coincide with
+				ResolvExpr::AltList alts = finder.get_alternatives();
+				assert( alts.size() == 1 );
+				assert(alts.front().expr != 0 );
+				current.push_back( finder.get_alternatives().front() );
+				solved_assigns.push_back( alts.front().expr->clone() );
+				//solved_assigns.back()->print(std::cerr);
+				/*} catch( ... ) {
+				  continue; // no reasonable alternative found
+				  }*/
+			}
+			options.add_option( current );
+
+			return true;
+		} else { // mass assignment
+			//if ( new_assigns.empty() ) return false;
+			std::list< Expression * > solved_assigns;
+			ResolvExpr::AltList solved_alts;
+			assert( currentFinder != 0 );
+
+			ResolvExpr::AltList current;
+			if ( optMass.empty() ) {
+				for ( std::list< Expression * >::size_type i = 0; i != new_assigns.size(); ++i )
+					optMass.push_back( ResolvExpr::AltList() );
+			}
+			int cnt = 0;
+			for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i, cnt++ ) {
+
+				ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
+				finder.findWithAdjustment(*i);
+				ResolvExpr::AltList alts = finder.get_alternatives();
+				assert( alts.size() == 1 );
+				assert(alts.front().expr != 0 );
+				current.push_back( finder.get_alternatives().front() );
+				optMass[cnt].push_back( finder.get_alternatives().front() );
+				solved_assigns.push_back( alts.front().expr->clone() );
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+
+	bool TupleAssignSpotter::isMVR( Expression *expr ) {
+		if ( expr->get_results().size() > 1 ) {
+			// MVR processing
+			return true;
+		}
+		return false;
+	}
+
+	bool TupleAssignSpotter::isTupleAssignment( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
+		if (  NameExpr *assgnop = dynamic_cast< NameExpr * >(expr->get_function()) ) {
+
+			if ( assgnop->get_name() == std::string("?=?") ) {
+
+				for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
+					assert( ali->size() == 2 );
+					ResolvExpr::AltList::iterator opit = ali->begin();
+					ResolvExpr::Alternative op1 = *opit, op2 = *(++opit);
+
+					if ( pointsToTuple(op1.expr) ) { // also handles tuple vars
+						if ( isTuple( op2.expr, true ) )
+							matcher = new MultipleAssignMatcher(op1.expr, op2.expr);
+						else if ( isMVR( op2.expr ) ) {
+							// handle MVR differently
+						} else
+							// mass assignment
+							matcher = new MassAssignMatcher(op1.expr, op2.expr);
+
+						std::list< ResolvExpr::AltList > options;
+						if ( match() )
+							/*
+							  if ( hasMatched ) {
+							  // throw SemanticError("Ambiguous tuple assignment");
+							  } else {*/
+							// Matched for the first time
+							hasMatched = true;
+						/*} */
+					} /* else if ( isTuple( op2 ) )
+						 throw SemanticError("Inapplicable tuple assignment.");
+					  */
+				}
+
+				if ( hasMatched ) {
+					if ( dynamic_cast<TupleAssignSpotter::MultipleAssignMatcher *>( matcher ) ) {
+						//options.print( std::cerr );
+						std::list< ResolvExpr::AltList >best = 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? */
+							currentFinder->get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns/*, SolvedTupleExpr::MULTIPLE*/), currentFinder->get_environ(), ResolvExpr::Cost() ) );
+						}
+					} else {
+						assert( ! optMass.empty() );
+						ResolvExpr::AltList winners;
+						for ( std::vector< ResolvExpr::AltList >::iterator i = optMass.begin(); i != optMass.end(); ++i )
+							findMinCostAlt( i->begin(), i->end(), back_inserter(winners) );
+
+						std::list< Expression *> solved_assigns;
+						for ( ResolvExpr::AltList::iterator i = winners.begin(); i != winners.end(); ++i )
+							solved_assigns.push_back( i->expr );
+						currentFinder->get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns/*, SolvedTupleExpr::MASS*/), currentFinder->get_environ(), ResolvExpr::Cost() ) );
+					}
+				}
+			}
+		}
+		return hasMatched;
+	}
+
+	void TupleAssignSpotter::Matcher::init( Expression *_lhs, Expression *_rhs ) {
+		lhs.clear();
+		if (AddressExpr *addr = dynamic_cast<AddressExpr *>(_lhs) )
+			if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(addr->get_arg()) )
+				std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(lhs) );
+
+		rhs.clear();
+	}
+
+	TupleAssignSpotter::Matcher::Matcher( /*TupleAssignSpotter &spot,*/ Expression *_lhs, Expression *_rhs ) /*: own_spotter(spot) */{
+		init(_lhs,_rhs);
+	}
+
+	TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( Expression *_lhs, Expression *_rhs )/* : own_spotter(spot) */{
+		init(_lhs,_rhs);
+
+		if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(_rhs) )
+			std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(rhs) );
+	}
+
+	UntypedExpr *TupleAssignSpotter::Matcher::createAssgn( Expression *left, Expression *right ) {
+		if ( left && right ) {
+			std::list< Expression * > args;
+			args.push_back(new AddressExpr(left->clone()));  args.push_back(right->clone());
+			return new UntypedExpr(new NameExpr("?=?"), args);
+		} else
+			throw 0; // xxx - diagnose the problem
+	}
+
+	bool TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
+		if ( lhs.empty() || (rhs.size() != 1) ) return false;
+
+		for ( std::list< Expression * >::iterator l = lhs.begin(); l != lhs.end(); l++ ) {
+			std::list< Expression * > args;
+			args.push_back( new AddressExpr(*l) );
+			args.push_back( rhs.front() );
+			out.push_back( new UntypedExpr(new NameExpr("?=?"), args) );
+		}
+
+		return true;
+	}
+
+	bool TupleAssignSpotter::MassAssignMatcher::solve( std::list< Expression * > &assigns ) {
+		/*
+		  std::list< Expression * > solved_assigns;
+		  ResolvExpr::AltList solved_alts;
+		  assert( currentFinder != 0 );
+
+		  ResolvExpr::AltList current;
+		  if ( optMass.empty() ) {
+		  for ( std::list< Expression * >::size_type i = 0; i != new_assigns.size(); ++i )
+		  optMass.push_back( ResolvExpr::AltList() );
+		  }
+		  int cnt = 0;
+		  for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i, cnt++ ) {
+
+		  ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
+		  finder.findWithAdjustment(*i);
+		  ResolvExpr::AltList alts = finder.get_alternatives();
+		  assert( alts.size() == 1 );
+		  assert(alts.front().expr != 0 );
+		  current.push_back( finder.get_alternatives().front() );
+		  optMass[cnt].push_back( finder.get_alternatives().front() );
+		  solved_assigns.push_back( alts.front().expr->clone() );
+		  }
+		*/
+		return true;
+	}
+
+	bool TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
+		// need more complicated matching
+		if ( lhs.size() == rhs.size() ) {
+			zipWith( lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), back_inserter(out), TupleAssignSpotter::Matcher::createAssgn );
+			return true;
+		} //else
+		//std::cerr << "The length of (left, right) is: (" << lhs.size() << "," << rhs.size() << ")" << std::endl;*/
+		return false;
+	}
+
+	bool TupleAssignSpotter::MultipleAssignMatcher::solve( std::list< Expression * > &assigns ) {
+		/*
+		  std::list< Expression * > solved_assigns;
+		  ResolvExpr::AltList solved_alts;
+		  assert( currentFinder != 0 );
+
+		  ResolvExpr::AltList current;
+		  for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
+		  //try {
+		  ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
+		  finder.findWithAdjustment(*i);
+		  // prune expressions that don't coincide with
+		  ResolvExpr::AltList alts = finder.get_alternatives();
+		  assert( alts.size() == 1 );
+		  assert(alts.front().expr != 0 );
+		  current.push_back( finder.get_alternatives().front() );
+		  solved_assigns.push_back( alts.front().expr->clone() );
+		  //solved_assigns.back()->print(std::cerr);
+		  //} catch( ... ) {
+		  //continue; // no reasonable alternative found
+		  //}
+		  }
+		  options.add_option( current );
+		*/
+
+		return true;
+	}
+
+	void TupleAssignSpotter::Options::add_option( ResolvExpr::AltList &opt ) {
+		using namespace std;
+
+		options.push_back( opt );
+		/*
+		  vector< Cost > costs;
+		  costs.reserve( opt.size() );
+		  transform( opt.begin(), opt.end(), back_inserter(costs), ptr_fun(extract_cost) );
+		*/
+		// transpose matrix
+		if ( costMatrix.empty() )
+			for ( unsigned int i = 0; i< opt.size(); ++i)
+				costMatrix.push_back( vector<ResolvExpr::Cost>() );
+
+		int cnt = 0;
+		for ( ResolvExpr::AltList::iterator i = opt.begin(); i != opt.end(); ++i, cnt++ )
+			costMatrix[cnt].push_back( i->cost );
+
+		return;
+	}
+
+	std::list< ResolvExpr::AltList > TupleAssignSpotter::Options::get_best() {
+		using namespace std;
+		using namespace ResolvExpr;
+		list< ResolvExpr::AltList > ret;
+		list< multiset<int> > solns;
+		for ( vector< vector<Cost> >::iterator i = costMatrix.begin(); i != costMatrix.end(); ++i ) {
+			list<int> current;
+			findMinCost( i->begin(), i->end(), back_inserter(current) );
+			solns.push_back( multiset<int>(current.begin(), current.end()) );
+		}
+		// need to combine
+		multiset<int> result;
+		lift_intersection( solns.begin(), solns.end(), inserter( result, result.begin() ) );
+		if ( result.size() != 1 )
+			throw SemanticError("Ambiguous tuple expression");
+		ret.push_back(get_option( *(result.begin() )));
+		return ret;
+	}
+
+	void TupleAssignSpotter::Options::print( std::ostream &ostr ) {
+		using namespace std;
+
+		for ( vector< vector < ResolvExpr::Cost > >::iterator i = costMatrix.begin(); i != costMatrix.end(); ++i ) {
+			for ( vector < ResolvExpr::Cost >::iterator j = i->begin(); j != i->end(); ++j )
+				ostr << *j << " " ;
+			ostr << std::endl;
+		} // for
+		return;
+	}
+
+	ResolvExpr::Cost extract_cost( ResolvExpr::Alternative &alt ) {
+		return alt.cost;
+	}
+
+	template< typename InputIterator, typename OutputIterator >
+	void TupleAssignSpotter::Options::findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
+		using namespace ResolvExpr;
+		std::list<int> alternatives;
+
+		// select the alternatives that have the minimum parameter cost
+		Cost minCost = Cost::infinity;
+		unsigned int index = 0;
+		for ( InputIterator i = begin; i != end; ++i, index++ ) {
+			if ( *i < minCost ) {
+				minCost = *i;
+				alternatives.clear();
+				alternatives.push_back( index );
+			} else if ( *i == minCost ) {
+				alternatives.push_back( index );
+			}
+		}
+		std::copy( alternatives.begin(), alternatives.end(), out );
+	}
+
+	template< class InputIterator, class OutputIterator >
+	void TupleAssignSpotter::Options::lift_intersection( InputIterator begin, InputIterator end, OutputIterator out ) {
+		if ( begin == end ) return;
+		InputIterator test = begin;
+
+		if (++test == end)
+			{ copy(begin->begin(), begin->end(), out); return; }
+
+
+		std::multiset<int> cur; // InputIterator::value_type::value_type
+		copy( begin->begin(), begin->end(), inserter( cur, cur.begin() ) );
+
+		while ( test != end ) {
+			std::multiset<int> temp;
+			set_intersection( cur.begin(), cur.end(), test->begin(), test->end(), inserter(temp,temp.begin()) );
+			cur.clear();
+			copy( temp.begin(), temp.end(), inserter(cur,cur.begin()));
+			++test;
+		}
+
+		copy( cur.begin(), cur.end(), out );
+		return;
+	}
+
+	ResolvExpr::AltList TupleAssignSpotter::Options::get_option( std::list< ResolvExpr::AltList >::size_type index ) {
+		if ( index >= options.size() )
+			throw 0; // XXX
+		std::list< ResolvExpr::AltList >::iterator it = options.begin();
+		for ( std::list< ResolvExpr::AltList >::size_type i = 0; i < index; ++i, ++it );
+		return *it;
+	}
+} // namespace Tuples
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/TupleAssignment.h
===================================================================
--- src/Tuples/TupleAssignment.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/TupleAssignment.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,136 @@
+//
+// 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 {
+	class TupleAssignSpotter {
+	  public:
+		// dispatcher for Tuple (multiple and mass) assignment operations
+		TupleAssignSpotter( ResolvExpr::AlternativeFinder * );
+		~TupleAssignSpotter() { delete matcher; matcher = 0; }
+
+		bool pointsToTuple( Expression * );
+		static bool isTupleVar( DeclarationWithType * );
+		bool isTuple( Expression *, bool isRight = false );
+		bool isMVR( Expression * );
+		bool isTupleAssignment( UntypedExpr *, std::list<ResolvExpr::AltList> & );
+		bool match();
+	  private:
+		// records for assignment generation
+		class Options {
+		  public:
+			void add_option( ResolvExpr::AltList &opt );
+			std::list< ResolvExpr::AltList > get_best();
+			void print( std::ostream & );
+			int size() const { return options.size(); }
+			ResolvExpr::AltList get_option( std::list< ResolvExpr::AltList >::size_type index );
+
+			// should really use the one in ResolvExpr/AlternativeFinder, but it's too coupled with the object
+			template< typename InputIterator, typename OutputIterator >
+			void findMinCost( InputIterator begin, InputIterator end, OutputIterator out );
+
+			template< typename InputIterator, typename OutputIterator >
+			void lift_intersection( InputIterator begin, InputIterator end, OutputIterator out );
+		  private:
+			std::list< ResolvExpr::AltList > options;
+			std::vector< std::vector< ResolvExpr::Cost > > costMatrix;
+		};
+
+		class Matcher {
+		  public:
+			Matcher( /*TupleAssignSpotter &spot, */Expression *_lhs, Expression *_rhs );
+			virtual ~Matcher() {}
+			virtual bool match( std::list< Expression * > &out ) = 0;
+			virtual bool solve( std::list< Expression * > &assigns ) = 0;
+			static UntypedExpr *createAssgn( Expression *left, Expression *right );
+		  protected:
+			Matcher() /*: own_spotter( TupleAssignSpotter(0) ) */{}
+			void init(/* TupleAssignSpotter &, */Expression *_lhs, Expression *_rhs );
+			std::list< Expression * > lhs, rhs;
+			//TupleAssignSpotter &own_spotter;
+		};
+
+		class MassAssignMatcher : public Matcher {
+		  public:
+			MassAssignMatcher( Expression *_lhs, Expression *_rhs ) : Matcher( _lhs, _rhs ) {
+				rhs.push_back( _rhs );
+			}
+			virtual bool match( std::list< Expression * > &out );
+			virtual bool solve( std::list< Expression * > &assigns );
+		  private:
+			//std::vector< ResolvExpr::AltList > optMass;
+		};
+
+		class MultipleAssignMatcher : public Matcher {
+		  public:
+			MultipleAssignMatcher( Expression *_lhs, Expression *_rhs );
+			virtual bool match( std::list< Expression * > &out );
+			virtual bool solve( std::list< Expression * > &assigns );
+		  private:
+			//Options options;
+		};
+
+		friend class Matcher;
+
+		ResolvExpr::AlternativeFinder *currentFinder;
+		//std::list<Expression *> rhs, lhs;
+		Expression *rhs, *lhs;
+		Matcher *matcher;
+		bool hasMatched;
+		Options options;
+		std::vector< ResolvExpr::AltList > optMass;
+	};
+
+	ResolvExpr::Cost extract_cost( ResolvExpr::Alternative & );
+
+	template< typename InputIterator, typename OutputIterator >
+	void findMinCostAlt( InputIterator begin, InputIterator end, OutputIterator out ) {
+		using namespace ResolvExpr;
+		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 );
+	}
+} // 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 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/Tuples/module.mk	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,14 @@
+SRC += 	Tuples/Mutate.cc \
+	Tuples/AssignExpand.cc \
+	Tuples/FunctionFixer.cc \
+	Tuples/TupleAssignment.cc \
+	Tuples/FunctionChecker.cc \
+	Tuples/NameMatcher.cc \
+#	Tuples/MultipleAssign.cc \
+#	Tuples/FlattenTuple.cc \
+#	Tuples/MultRet.cc \
+#	Tuples/FixReturn.cc \
+#	Tuples/MassAssignment.cc \
+#	Tuples/TupleFixer.cc \
+	$(NULL)
+
