Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/CodeGen/CodeGenerator.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -307,10 +307,12 @@
 						} else {
 							// no address-of operator, so must be a pointer - add dereference
+							// NOTE: if the assertion starts to trigger, check that the application expr isn't being shared.
+							// Since its arguments are modified here, this assertion most commonly triggers when the application
+							// is visited multiple times.
 							UntypedExpr * newExpr = new UntypedExpr( new NameExpr( "*?" ) );
 							newExpr->get_args().push_back( *arg );
-							assert( (*arg)->get_results().size() == 1 );
-							Type * type = InitTweak::getPointerBase( (*arg)->get_results().front() );
-							assert( type );
-							newExpr->get_results().push_back( type->clone() );
+							Type * type = InitTweak::getPointerBase( (*arg)->get_result() );
+							assertf( type, "First argument to a derefence must be a pointer. Ensure that expressions are not being shared." );
+							newExpr->set_result( type->clone() );
 							*arg = newExpr;
 						} // if
@@ -527,10 +529,10 @@
 		extension( castExpr );
 		output << "(";
-		if ( castExpr->get_results().empty() ) {
+		if ( castExpr->get_result()->isVoid() ) {
 			output << "(void)" ;
-		} else if ( ! castExpr->get_results().front()->get_isLvalue() ) {
+		} else if ( ! castExpr->get_result()->get_isLvalue() ) {
 			// at least one result type of cast, but not an lvalue
 			output << "(";
-			output << genType( castExpr->get_results().front(), "" );
+			output << genType( castExpr->get_result(), "" );
 			output << ")";
 		} else {
@@ -640,5 +642,5 @@
 	}
 
-	void CodeGenerator::visit( TupleExpr * tupleExpr ) {}
+	void CodeGenerator::visit( TupleExpr * tupleExpr ) { assert( false ); }
 
 	void CodeGenerator::visit( TypeExpr * typeExpr ) {}
@@ -654,4 +656,39 @@
 		asmExpr->get_operand()->accept( *this );
 		output << " )";
+	}
+
+	void CodeGenerator::visit( CompoundLiteralExpr *compLitExpr ) {
+		assert( compLitExpr->get_type() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
+		output << "(" << genType( compLitExpr->get_type(), "" ) << ")";
+		compLitExpr->get_initializer()->accept( *this );
+	}
+
+	void CodeGenerator::visit( StmtExpr * stmtExpr ) {
+		std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
+		output << "({" << std::endl;
+		cur_indent += CodeGenerator::tabsize;
+		unsigned int numStmts = stmts.size();
+		unsigned int i = 0;
+		for ( Statement * stmt : stmts ) {
+			output << indent << printLabels( stmt->get_labels() );
+			if ( i+1 == numStmts ) {
+				// last statement in a statement expression needs to be handled specially -
+				// cannot cast to void, otherwise the expression statement has no value
+				if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
+					exprStmt->get_expr()->accept( *this );
+					output << ";" << endl;
+					++i;
+					break;
+				}
+			}
+			stmt->accept( *this );
+			output << endl;
+			if ( wantSpacing( stmt ) ) {
+				output << endl;
+			} // if
+			++i;
+		}
+		cur_indent -= CodeGenerator::tabsize;
+		output << indent << "})";
 	}
 
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/CodeGen/CodeGenerator.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -70,7 +70,9 @@
 		virtual void visit( ConditionalExpr *conditionalExpr );
 		virtual void visit( CommaExpr *commaExpr );
+		virtual void visit( CompoundLiteralExpr *compLitExpr );
 		virtual void visit( TupleExpr *tupleExpr );
 		virtual void visit( TypeExpr *typeExpr );
 		virtual void visit( AsmExpr * );
+		virtual void visit( StmtExpr * );
 
 		//*** Statements
Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/CodeGen/GenType.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -227,7 +227,4 @@
 			typeString = "_Atomic " + typeString;
 		} // if
-		if ( type->get_isAttribute() ) {
-			typeString = "__attribute(( )) " + typeString;
-		} // if
 	}
 } // namespace CodeGen
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Common/utility.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -148,4 +148,5 @@
 }
 
+// replace element of list with all elements of another list
 template< typename T >
 void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) {
@@ -158,4 +159,11 @@
 
 	return;
+}
+
+// replace range of a list with a single element
+template< typename T >
+void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) {
+	org.insert( begin, with );
+	org.erase( begin, end );
 }
 
Index: src/ControlStruct/LabelTypeChecker.cc
===================================================================
--- src/ControlStruct/LabelTypeChecker.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ 	(revision )
@@ -1,86 +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.
-//
-// LabelTypeChecker.cc --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Wed Jun 24 16:24:48 2015
-// Update Count     : 3
-//
-
-#include <list>
-#include <cassert>
-
-#include "SynTree/Type.h"
-#include "SynTree/Statement.h"
-#include "SynTree/Expression.h"
-#include "SynTree/Declaration.h"
-
-#include "LabelTypeChecker.h"
-
-namespace ControlStruct {
-	void LabelTypeChecker::visit(UntypedExpr *untypedExpr) {
-		assert( untypedExpr != 0 );
-		NameExpr *fname;
-		if ( ((fname = dynamic_cast<NameExpr *>(untypedExpr->get_function())) != 0)
-			 && fname->get_name() == std::string("&&") )
-			std::cerr << "Taking the label of an address." << std::endl;
-		else {
-			acceptAll( untypedExpr->get_results(), *this );
-			acceptAll( untypedExpr->get_args(), *this );
-		} // if
-		return;
-	}
-
-	void LabelTypeChecker::visit(CompoundStmt *compoundStmt) {
-		index.enterScope();
-		acceptAll( compoundStmt->get_kids(), *this );
-		index.leaveScope();
-	}
-
-	void LabelTypeChecker::visit(DeclStmt *declStmt) {
-		declStmt->accept( index );
-
-		//ObjectDecl *odecl = 0;
-		// if ( ( odecl = dynamic_cast<ObjectDecl *>(declStmt->get_decl()) ) != 0 ) {
-		return;
-	}
-
-	void LabelTypeChecker::visit(BranchStmt *branchStmt) {
-		if ( branchStmt->get_type() != BranchStmt::Goto ) return;
-		Expression *target;
-		if ( (target = branchStmt->get_computedTarget()) == 0 ) return;
-
-		NameExpr *name;
-		if ( (name = dynamic_cast<NameExpr *>(target)) == 0 )
-			return; // Not a name expression
-
-		std::list< DeclarationWithType * > interps;
-		index.lookupId(name->get_name(), interps);
-		if ( interps.size() != 1)
-			// in case of multiple declarations
-			throw SemanticError("Illegal label expression: " + name->get_name() );
-
-		PointerType *ptr;
-		if ( (ptr = dynamic_cast<PointerType *>(interps.front()->get_type())) != 0 )
-			if ( dynamic_cast<VoidType *>(ptr->get_base()) != 0 )
-				return;
-			else
-				throw SemanticError("Wrong type of parameter for computed goto");
-		else
-			throw SemanticError("Wrong type of parameter for computed goto");
-
-		return;
-	}
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ControlStruct/LabelTypeChecker.h
===================================================================
--- src/ControlStruct/LabelTypeChecker.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ 	(revision )
@@ -1,45 +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.
-//
-// LabelTypeChecker.h -- 
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jan 25 21:22:30 2016
-// Update Count     : 4
-//
-
-#ifndef LABEL_TYPE_H
-#define LABEL_TYPE_H
-
-#include "SynTree/Visitor.h"
-#include "SymTab/Indexer.h"
-#include "SynTree/Statement.h"
-
-#include "Common/utility.h"
-
-namespace ControlStruct {
-	class LabelTypeChecker : public Visitor {
-	  public:
-		//LabelTypeChecker() {
-
-		virtual void visit( CompoundStmt *compoundStmt );
-		virtual void visit( DeclStmt *declStmt );
-		virtual void visit( BranchStmt *branchStmt );
-		virtual void visit( UntypedExpr *untypedExpr );
-	  private:
-		SymTab::Indexer index;
-	};
-} // namespace ControlStruct
-
-#endif // LABEL_TYPE_H
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ControlStruct/Mutate.cc
===================================================================
--- src/ControlStruct/Mutate.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ControlStruct/Mutate.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -23,5 +23,4 @@
 #include "MLEMutator.h"
 #include "ForExprMutator.h"
-#include "LabelTypeChecker.h"
 //#include "ExceptMutator.h"
 
@@ -41,10 +40,8 @@
 
 		//ExceptMutator exc;
-		// LabelTypeChecker lbl;
 
 		mutateAll( translationUnit, formut );
 		acceptAll( translationUnit, lfix );
 		//mutateAll( translationUnit, exc );
-		//acceptAll( translationUnit, lbl );
 	}
 } // namespace CodeGen
Index: src/ControlStruct/module.mk
===================================================================
--- src/ControlStruct/module.mk	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ControlStruct/module.mk	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -6,5 +6,5 @@
 ## file "LICENCE" distributed with Cforall.
 ##
-## module.mk -- 
+## module.mk --
 ##
 ## Author           : Richard C. Bilson
@@ -19,5 +19,4 @@
         ControlStruct/MLEMutator.cc \
 	ControlStruct/Mutate.cc \
-	ControlStruct/ForExprMutator.cc \
-	ControlStruct/LabelTypeChecker.cc
+	ControlStruct/ForExprMutator.cc
 
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/GenPoly/Box.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -113,5 +113,5 @@
 			void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
 			/// Stores assignment operators from assertion list in local map of assignment operations
-			void findTypeOps( const std::list< TypeDecl *> &forall );
+			void findTypeOps( const Type::ForallList &forall );
 			void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
 			FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
@@ -619,8 +619,8 @@
 		}
 
-		void Pass1::findTypeOps( const std::list< TypeDecl *> &forall ) {
+		void Pass1::findTypeOps( const Type::ForallList &forall ) {
 			// what if a nested function uses an assignment operator?
 			// assignOps.clear();
-			for ( std::list< TypeDecl *>::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
+			for ( Type::ForallList::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
 				for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
 					std::string typeName;
@@ -687,5 +687,5 @@
 				std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
 				std::list< FunctionType *> functions;
-				for ( std::list< TypeDecl *>::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
+				for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
 					for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
 						findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter );
@@ -789,6 +789,6 @@
 
 			// add size/align for generic types to parameter list
-			if ( appExpr->get_function()->get_results().empty() ) return;
-			FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() );
+			if ( ! appExpr->get_function()->has_result() ) return;
+			FunctionType *funcType = getFunctionType( appExpr->get_function()->get_result() );
 			assert( funcType );
 
@@ -806,6 +806,6 @@
 			for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
 				VariableExpr *fnArgBase = getBaseVar( *fnArg );
-				if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue;
-				passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes );
+				if ( ! fnArgBase ) continue; // xxx - previously had check for non-empty fnArgBase results
+				passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_result(), arg, exprTyVars, seenTypes );
 			}
 		}
@@ -897,5 +897,5 @@
 			Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
 			appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) );
-			appExpr->set_function( new NameExpr( adapterName ) );
+			appExpr->set_function( new NameExpr( adapterName ) ); // xxx - result is never set on NameExpr
 
 			return ret;
@@ -903,10 +903,10 @@
 
 		void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
-			assert( ! arg->get_results().empty() );
+			assert( arg->has_result() );
 			if ( isPolyType( param, exprTyVars ) ) {
-				if ( isPolyType( arg->get_results().front() ) ) {
+				if ( isPolyType( arg->get_result() ) ) {
 					// if the argument's type is polymorphic, we don't need to box again!
 					return;
-				} else if ( arg->get_results().front()->get_isLvalue() ) {
+				} else if ( arg->get_result()->get_isLvalue() ) {
 					// VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue)
 					// xxx - need to test that this code is still reachable
@@ -953,5 +953,5 @@
 		void Pass1::addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
 			std::list< Expression *>::iterator cur = arg;
-			for ( std::list< TypeDecl *>::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
+			for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
 				for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
 					InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
@@ -994,5 +994,5 @@
 					UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
 					deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
-					deref->get_results().push_back( arg->get_type()->clone() );
+					deref->set_result( arg->get_type()->clone() );
 					return deref;
 				} // if
@@ -1020,7 +1020,7 @@
 			Statement *bodyStmt;
 
-			std::list< TypeDecl *>::iterator tyArg = realType->get_forall().begin();
-			std::list< TypeDecl *>::iterator tyParam = adapterType->get_forall().begin();
-			std::list< TypeDecl *>::iterator realTyParam = adaptee->get_forall().begin();
+			Type::ForallList::iterator tyArg = realType->get_forall().begin();
+			Type::ForallList::iterator tyParam = adapterType->get_forall().begin();
+			Type::ForallList::iterator realTyParam = adaptee->get_forall().begin();
 			for ( ; tyParam != adapterType->get_forall().end(); ++tyArg, ++tyParam, ++realTyParam ) {
 				assert( tyArg != realType->get_forall().end() );
@@ -1071,5 +1071,5 @@
 			std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
 			std::list< FunctionType *> functions;
-			for ( std::list< TypeDecl *>::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
+			for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
 				for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
 					findFunction( (*assert)->get_type(), functions, exprTyVars, needsAdapter );
@@ -1131,5 +1131,5 @@
 			} // if
 			addAssign->get_args().push_back( new NameExpr( sizeofName( mangleType( polyType ) ) ) );
-			addAssign->get_results().front() = appExpr->get_results().front()->clone();
+			addAssign->set_result( appExpr->get_result()->clone() );
 			if ( appExpr->get_env() ) {
 				addAssign->set_env( appExpr->get_env() );
@@ -1145,8 +1145,8 @@
 				if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
 					if ( varExpr->get_var()->get_name() == "?[?]" ) {
-						assert( ! appExpr->get_results().empty() );
+						assert( appExpr->has_result() );
 						assert( appExpr->get_args().size() == 2 );
-						Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), scopeTyVars, env );
-						Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), scopeTyVars, env );
+						Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
+						Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
 						assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers
 						UntypedExpr *ret = 0;
@@ -1168,5 +1168,5 @@
 						} // if
 						if ( baseType1 || baseType2 ) {
-							ret->get_results().push_front( appExpr->get_results().front()->clone() );
+							ret->set_result( appExpr->get_result()->clone() );
 							if ( appExpr->get_env() ) {
 								ret->set_env( appExpr->get_env() );
@@ -1178,10 +1178,10 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "*?" ) {
-						assert( ! appExpr->get_results().empty() );
+						assert( appExpr->has_result() );
 						assert( ! appExpr->get_args().empty() );
-						if ( isPolyType( appExpr->get_results().front(), scopeTyVars, env ) ) {
+						if ( isPolyType( appExpr->get_result(), scopeTyVars, env ) ) {
 							Expression *ret = appExpr->get_args().front();
-							delete ret->get_results().front();
-							ret->get_results().front() = appExpr->get_results().front()->clone();
+							delete ret->get_result();
+							ret->set_result( appExpr->get_result()->clone() );
 							if ( appExpr->get_env() ) {
 								ret->set_env( appExpr->get_env() );
@@ -1193,8 +1193,8 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "?++" || varExpr->get_var()->get_name() == "?--" ) {
-						assert( ! appExpr->get_results().empty() );
+						assert( appExpr->has_result() );
 						assert( appExpr->get_args().size() == 1 );
-						if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) {
-							Type *tempType = appExpr->get_results().front()->clone();
+						if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
+							Type *tempType = appExpr->get_result()->clone();
 							if ( env ) {
 								env->apply( tempType );
@@ -1213,19 +1213,19 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "++?" || varExpr->get_var()->get_name() == "--?" ) {
-						assert( ! appExpr->get_results().empty() );
+						assert( appExpr->has_result() );
 						assert( appExpr->get_args().size() == 1 );
-						if ( Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env ) ) {
+						if ( Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env ) ) {
 							return makeIncrDecrExpr( appExpr, baseType, varExpr->get_var()->get_name() == "++?" );
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "?+?" || varExpr->get_var()->get_name() == "?-?" ) {
-						assert( ! appExpr->get_results().empty() );
+						assert( appExpr->has_result() );
 						assert( appExpr->get_args().size() == 2 );
-						Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_results().front(), scopeTyVars, env );
-						Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_results().front(), scopeTyVars, env );
+						Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
+						Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
 						if ( baseType1 && baseType2 ) {
 							UntypedExpr *divide = new UntypedExpr( new NameExpr( "?/?" ) );
 							divide->get_args().push_back( appExpr );
 							divide->get_args().push_back( new SizeofExpr( baseType1->clone() ) );
-							divide->get_results().push_front( appExpr->get_results().front()->clone() );
+							divide->set_result( appExpr->get_result()->clone() );
 							if ( appExpr->get_env() ) {
 								divide->set_env( appExpr->get_env() );
@@ -1245,7 +1245,7 @@
 						} // if
 					} else if ( varExpr->get_var()->get_name() == "?+=?" || varExpr->get_var()->get_name() == "?-=?" ) {
-						assert( ! appExpr->get_results().empty() );
+						assert( appExpr->has_result() );
 						assert( appExpr->get_args().size() == 2 );
-						Type *baseType = isPolyPtr( appExpr->get_results().front(), scopeTyVars, env );
+						Type *baseType = isPolyPtr( appExpr->get_result(), scopeTyVars, env );
 						if ( baseType ) {
 							UntypedExpr *multiply = new UntypedExpr( new NameExpr( "?*?" ) );
@@ -1273,9 +1273,7 @@
 			useRetval = oldUseRetval;
 
-			assert( ! appExpr->get_function()->get_results().empty() );
-			PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() );
-			assert( pointer );
-			FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() );
-			assert( function );
+			assert( appExpr->get_function()->has_result() );
+			PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
+			FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
 
 			if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
@@ -1315,5 +1313,5 @@
 
 		Expression *Pass1::mutate( UntypedExpr *expr ) {
-			if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) {
+			if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
 				if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
 					if ( name->get_name() == "*?" ) {
@@ -1329,17 +1327,15 @@
 
 		Expression *Pass1::mutate( AddressExpr *addrExpr ) {
-			assert( ! addrExpr->get_arg()->get_results().empty() );
+			assert( addrExpr->get_arg()->has_result() && ! addrExpr->get_arg()->get_result()->isVoid() );
 
 			bool needs = false;
 			if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->get_arg() ) ) {
-				if ( ! expr->get_results().empty() && isPolyType( expr->get_results().front(), scopeTyVars, env ) ) {
+				if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
 					if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
 						if ( name->get_name() == "*?" ) {
 							if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->get_args().front() ) ) {
-								assert( ! appExpr->get_function()->get_results().empty() );
-								PointerType *pointer = dynamic_cast< PointerType *>( appExpr->get_function()->get_results().front() );
-								assert( pointer );
-								FunctionType *function = dynamic_cast< FunctionType *>( pointer->get_base() );
-								assert( function );
+								assert( appExpr->get_function()->has_result() );
+								PointerType *pointer = safe_dynamic_cast< PointerType *>( appExpr->get_function()->get_result() );
+								FunctionType *function = safe_dynamic_cast< FunctionType *>( pointer->get_base() );
 								needs = needsAdapter( function, scopeTyVars );
 							} // if
@@ -1350,10 +1346,10 @@
 			// isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
 			// out of the if condition.
-			bool polytype = isPolyType( addrExpr->get_arg()->get_results().front(), scopeTyVars, env );
+			bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
 			addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
 			if ( polytype || needs ) {
 				Expression *ret = addrExpr->get_arg();
-				delete ret->get_results().front();
-				ret->get_results().front() = addrExpr->get_results().front()->clone();
+				delete ret->get_result();
+				ret->set_result( addrExpr->get_result()->clone() );
 				addrExpr->set_arg( 0 );
 				delete addrExpr;
@@ -1393,5 +1389,5 @@
 		Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
 			if ( retval && returnStmt->get_expr() ) {
-				assert( ! returnStmt->get_expr()->get_results().empty() );
+				assert( returnStmt->get_expr()->has_result() && ! returnStmt->get_expr()->get_result()->isVoid() );
 				// ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous.
 				// if ( returnStmt->get_expr()->get_results().front()->get_isLvalue() ) {
@@ -1427,7 +1423,7 @@
 					// find each of its needed secondary assignment operators
 					std::list< Expression* > &tyParams = refType->get_parameters();
-					std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall();
+					Type::ForallList &forallParams = functionDecl->get_type()->get_forall();
 					std::list< Expression* >::const_iterator tyIt = tyParams.begin();
-					std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
+					Type::ForallList::const_iterator forallIt = forallParams.begin();
 					for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
 						// Add appropriate mapping to assignment expression environment
@@ -1473,5 +1469,5 @@
 				// replace return statement with appropriate assignment to out parameter
 				Expression *retParm = new NameExpr( retval->get_name() );
-				retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
+				retParm->set_result( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
 				assignExpr->get_args().push_back( retParm );
 				assignExpr->get_args().push_back( returnStmt->get_expr() );
@@ -1603,5 +1599,5 @@
 			ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0,
 			                   new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
-			for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
+			for ( Type::ForallList::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
 				ObjectDecl *sizeParm, *alignParm;
 				// add all size and alignment parameters to parameter list
Index: src/GenPoly/CopyParams.cc
===================================================================
--- src/GenPoly/CopyParams.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/GenPoly/CopyParams.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -54,5 +54,5 @@
 				std::map< std::string, DeclarationWithType* > assignOps;
 				// assume the assignment operator is the first assert param after any "type" parameter
-				for ( std::list< TypeDecl* >::const_iterator tyVar = funcDecl->get_functionType()->get_forall().begin(); tyVar != funcDecl->get_functionType()->get_forall().end(); ++tyVar ) {
+				for ( Type::ForallList::const_iterator tyVar = funcDecl->get_functionType()->get_forall().begin(); tyVar != funcDecl->get_functionType()->get_forall().end(); ++tyVar ) {
 					if ( (*tyVar)->get_kind() == TypeDecl::Any ) {
 						assert( !(*tyVar)->get_assertions().empty() );
Index: src/GenPoly/FindFunction.cc
===================================================================
--- src/GenPoly/FindFunction.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/GenPoly/FindFunction.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -29,5 +29,5 @@
 		virtual Type *mutate( PointerType *pointerType );
 	  private:
-		void handleForall( const std::list< TypeDecl* > &forall );
+		void handleForall( const Type::ForallList &forall );
 
 		std::list< FunctionType* > &functions;
@@ -51,6 +51,6 @@
 	}
 
-	void FindFunction::handleForall( const std::list< TypeDecl* > &forall ) {
-		for ( std::list< TypeDecl* >::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
+	void FindFunction::handleForall( const Type::ForallList &forall ) {
+		for ( Type::ForallList::const_iterator i = forall.begin(); i != forall.end(); ++i ) {
 			TyVarMap::iterator var = tyVars.find( (*i)->get_name() );
 			if ( var != tyVars.end() ) {
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/GenPoly/GenPoly.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -110,5 +110,5 @@
 	ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &forallTypes ) {
 		if ( function->get_returnVals().empty() ) return 0;
-		
+
 		return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
 	}
@@ -127,5 +127,5 @@
 // 		} // if
 		if ( isDynRet( adaptee, tyVars ) ) return true;
-		
+
 		for ( std::list< DeclarationWithType* >::const_iterator innerArg = adaptee->get_parameters().begin(); innerArg != adaptee->get_parameters().end(); ++innerArg ) {
 // 			if ( isPolyType( (*innerArg)->get_type(), tyVars ) ) {
@@ -228,5 +228,5 @@
 
 	void makeTyVarMap( Type *type, TyVarMap &tyVarMap ) {
-		for ( std::list< TypeDecl* >::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {
+		for ( Type::ForallList::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {
 			assert( *tyVar );
 			tyVarMap[ (*tyVar)->get_name() ] = (*tyVar)->get_kind();
Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/GenPoly/Lvalue.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Lvalue.cc -- 
+// Lvalue.cc --
 //
 // Author           : Richard C. Bilson
@@ -41,5 +41,5 @@
 		  public:
 			Pass1();
-  
+
 			virtual Expression *mutate( ApplicationExpr *appExpr );
 			virtual Statement *mutate( ReturnStmt *appExpr );
@@ -55,4 +55,13 @@
 		  private:
 		};
+
+		/// GCC-like Generalized Lvalues (which have since been removed from GCC)
+		/// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
+		/// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
+		class GeneralizedLvalue : public Mutator {
+			typedef Mutator Parent;
+
+			virtual Expression * mutate( AddressExpr * addressExpr );
+		};
 	} // namespace
 
@@ -60,6 +69,8 @@
 		Pass1 p1;
 		Pass2 p2;
+		GeneralizedLvalue genLval;
 		mutateAll( translationUnit, p1 );
 		acceptAll( translationUnit, p2 );
+		mutateAll( translationUnit, genLval );
 	}
 
@@ -99,16 +110,12 @@
 			appExpr->get_function()->acceptMutator( *this );
 			mutateAll( appExpr->get_args(), *this );
-  
-			assert( ! appExpr->get_function()->get_results().empty() );
 
-			PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
-			assert( pointer );
-			FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
-			assert( function );
+			PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
+			FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
 
 			Type *funType = isLvalueRet( function );
 			if ( funType && ! isIntrinsicApp( appExpr ) ) {
 				Expression *expr = appExpr;
-				Type *appType = appExpr->get_results().front();
+				Type *appType = appExpr->get_result();
 				if ( isPolyType( funType ) && ! isPolyType( appType ) ) {
 					// make sure cast for polymorphic type is inside dereference
@@ -116,6 +123,6 @@
 				}
 				UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
-				deref->get_results().push_back( appType->clone() );
-				appExpr->get_results().front() = new PointerType( Type::Qualifiers(), appType );
+				deref->set_result( appType->clone() );
+				appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) );
 				deref->get_args().push_back( expr );
 				return deref;
@@ -127,6 +134,5 @@
 		Statement * Pass1::mutate(ReturnStmt *retStmt) {
 			if ( retval && retStmt->get_expr() ) {
-				assert( ! retStmt->get_expr()->get_results().empty() );
-				if ( retStmt->get_expr()->get_results().front()->get_isLvalue() ) {
+				if ( retStmt->get_expr()->get_result()->get_isLvalue() ) {
 					// ***** Code Removal ***** because casts may be stripped already
 
@@ -155,6 +161,23 @@
 				retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
 			} // if
-  
+
 			Visitor::visit( funType );
+		}
+
+		Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) {
+			addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) );
+			if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( addrExpr->get_arg() ) ) {
+				Expression * arg1 = commaExpr->get_arg1()->clone();
+				Expression * arg2 = commaExpr->get_arg2()->clone();
+				delete addrExpr;
+				return new CommaExpr( arg1, new AddressExpr( arg2 ) );
+			} else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( addrExpr->get_arg() ) ) {
+				Expression * arg1 = condExpr->get_arg1()->clone();
+				Expression * arg2 = condExpr->get_arg2()->clone();
+				Expression * arg3 = condExpr->get_arg3()->clone();
+				delete addrExpr;
+				return new ConditionalExpr( arg1, new AddressExpr( arg2 ), new AddressExpr( arg3 ) );
+			}
+			return addrExpr;
 		}
 	} // namespace
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/GenPoly/Specialize.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -148,6 +148,6 @@
 
 	Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
-		assert( ! actual->get_results().empty() ); // using front, should have this assert
-		if ( needsSpecialization( formalType, actual->get_results().front(), env ) ) {
+		assertf( actual->has_result(), "attempting to specialize an untyped expression" );
+		if ( needsSpecialization( formalType, actual->get_result(), env ) ) {
 			FunctionType *funType;
 			if ( ( funType = getFunctionType( formalType ) ) ) {
@@ -172,6 +172,6 @@
 	void Specialize::handleExplicitParams( ApplicationExpr *appExpr ) {
 		// create thunks for the explicit parameters
-		assert( ! appExpr->get_function()->get_results().empty() );
-		FunctionType *function = getFunctionType( appExpr->get_function()->get_results().front() );
+		assert( appExpr->get_function()->has_result() );
+		FunctionType *function = getFunctionType( appExpr->get_function()->get_result() );
 		assert( function );
 		std::list< DeclarationWithType* >::iterator formal;
@@ -201,6 +201,6 @@
 	Expression * Specialize::mutate( AddressExpr *addrExpr ) {
 		addrExpr->get_arg()->acceptMutator( *this );
-		assert( ! addrExpr->get_results().empty() );
-		addrExpr->set_arg( doSpecialization( addrExpr->get_results().front(), addrExpr->get_arg() ) );
+		assert( addrExpr->has_result() );
+		addrExpr->set_arg( doSpecialization( addrExpr->get_result(), addrExpr->get_arg() ) );
 		return addrExpr;
 	}
@@ -208,9 +208,9 @@
 	Expression * Specialize::mutate( CastExpr *castExpr ) {
 		castExpr->get_arg()->acceptMutator( *this );
-		if ( castExpr->get_results().empty() ) {
+		if ( castExpr->get_result()->isVoid() ) {
 			// can't specialize if we don't have a return value
 			return castExpr;
 		}
-		Expression *specialized = doSpecialization( castExpr->get_results().front(), castExpr->get_arg() );
+		Expression *specialized = doSpecialization( castExpr->get_result(), castExpr->get_arg() );
 		if ( specialized != castExpr->get_arg() ) {
 			// assume here that the specialization incorporates the cast
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/InitTweak/FixInit.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -18,4 +18,6 @@
 #include <iterator>
 #include <algorithm>
+#include <unordered_map>
+#include <unordered_set>
 #include "InitTweak.h"
 #include "FixInit.h"
@@ -35,10 +37,10 @@
 #include "GenPoly/DeclMutator.h"
 #include "SynTree/AddStmtVisitor.h"
-#include "CodeGen/GenType.h"  // for warnings
-
-bool ctordtorp = false;
-bool ctorp = false;
-bool cpctorp = false;
-bool dtorp = false;
+#include "CodeGen/GenType.h"  // for warning/error messages
+
+bool ctordtorp = false; // print all debug
+bool ctorp = false; // print ctor debug
+bool cpctorp = false; // print copy ctor debug
+bool dtorp = false; // print dtor debug
 #define PRINT( text ) if ( ctordtorp ) { text }
 #define CP_CTOR_PRINT( text ) if ( ctordtorp || cpctorp ) { text }
@@ -47,7 +49,4 @@
 namespace InitTweak {
 	namespace {
-		const std::list<Label> noLabels;
-		const std::list<Expression*> noDesignators;
-
 		class InsertImplicitCalls final : public GenPoly::PolyMutator {
 		public:
@@ -67,11 +66,17 @@
 			static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
 
-			using SymTab::Indexer::visit;
+			typedef SymTab::Indexer Parent;
+			using Parent::visit;
+
 			virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
+			virtual void visit( UniqueExpr * unqExpr );
 
 			/// create and resolve ctor/dtor expression: fname(var, [cpArg])
-			ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
+			Expression * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
+			Expression * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL );
 			/// true if type does not need to be copy constructed to ensure correctness
-			bool skipCopyConstruct( Type * );
+			bool skipCopyConstruct( Type * type );
+			void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
+			void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
 		private:
 			TypeSubstitution * env;
@@ -183,4 +188,5 @@
 			using GenPoly::PolyMutator::mutate;
 			virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
+			virtual Expression * mutate( UniqueExpr * unqExpr ) override;
 		};
 
@@ -368,8 +374,13 @@
 		}
 
-		ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
+		Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
 			assert( var );
+			return makeCtorDtor( fname, new AddressExpr( new VariableExpr( var ) ), cpArg );
+		}
+
+		Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg ) {
+			assert( thisArg );
 			UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) );
-			untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) );
+			untyped->get_args().push_back( thisArg );
 			if (cpArg) untyped->get_args().push_back( cpArg->clone() );
 
@@ -378,20 +389,52 @@
 			// (VariableExpr and already resolved expression)
 			CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
-			ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) );
+			Expression * resolved = ResolvExpr::findVoidExpression( untyped, *this );
+			assert( resolved );
 			if ( resolved->get_env() ) {
 				env->add( *resolved->get_env() );
 			} // if
 
-			assert( resolved );
 			delete untyped;
 			return resolved;
 		}
 
+		void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
+			static UniqueName tempNamer("_tmp_cp");
+			CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
+			assert( arg->has_result() );
+			Type * result = arg->get_result();
+			if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
+
+			// type may involve type variables, so apply type substitution to get temporary variable's actual type
+			result = result->clone();
+			impCpCtorExpr->get_env()->apply( result );
+			ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
+			tmp->get_type()->set_isConst( false );
+
+			// create and resolve copy constructor
+			CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
+			Expression * cpCtor = makeCtorDtor( "?{}", tmp, arg );
+
+			if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( cpCtor ) ) {
+				// if the chosen constructor is intrinsic, the copy is unnecessary, so
+				// don't create the temporary and don't call the copy constructor
+				VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
+				assert( function );
+				if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
+			}
+
+			// replace argument to function call with temporary
+			arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
+			impCpCtorExpr->get_tempDecls().push_back( tmp );
+			impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
+		}
+
+		void ResolveCopyCtors::destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) {
+			impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", new AddressExpr( ret ) ) );
+		}
+
 		void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
-			static UniqueName tempNamer("_tmp_cp");
-			static UniqueName retNamer("_tmp_cp_ret");
-
 			CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
-			Visitor::visit( impCpCtorExpr );
+			Parent::visit( impCpCtorExpr );
 			env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer...
 
@@ -400,29 +443,5 @@
 			// take each argument and attempt to copy construct it.
 			for ( Expression * & arg : appExpr->get_args() ) {
-				CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
-				// xxx - need to handle tuple arguments
-				assert( ! arg->get_results().empty() );
-				Type * result = arg->get_results().front();
-				if ( skipCopyConstruct( result ) ) continue; // skip certain non-copyable types
-				// type may involve type variables, so apply type substitution to get temporary variable's actual type
-				result = result->clone();
-				impCpCtorExpr->get_env()->apply( result );
-				ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
-				tmp->get_type()->set_isConst( false );
-
-				// create and resolve copy constructor
-				CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
-				ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg );
-
-				// if the chosen constructor is intrinsic, the copy is unnecessary, so
-				// don't create the temporary and don't call the copy constructor
-				VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() );
-				assert( function );
-				if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) {
-					// replace argument to function call with temporary
-					arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
-					impCpCtorExpr->get_tempDecls().push_back( tmp );
-					impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
-				} // if
+				copyConstructArg( arg, impCpCtorExpr );
 			} // for
 
@@ -434,5 +453,7 @@
 			// level. Trying to pass that environment along.
 			callExpr->set_env( impCpCtorExpr->get_env()->clone() );
-			for ( Type * result : appExpr->get_results() ) {
+			Type * result = appExpr->get_result();
+			if ( ! result->isVoid() ) {
+				static UniqueName retNamer("_tmp_cp_ret");
 				result = result->clone();
 				impCpCtorExpr->get_env()->apply( result );
@@ -441,7 +462,32 @@
 				impCpCtorExpr->get_returnDecls().push_back( ret );
 				CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
-				impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
+				if ( ! result->get_isLvalue() ) {
+					// destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
+					destructRet( new VariableExpr( ret ), impCpCtorExpr );
+				}
 			} // for
 			CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
+		}
+
+		void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) {
+			static std::unordered_set< int > vars;
+			if ( vars.count( unqExpr->get_id() ) ) {
+				// xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
+				return;
+			}
+
+			Parent::visit( unqExpr );
+			// it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
+			assert( unqExpr->get_result() );
+			if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->get_expr() ) ) {
+				// note the variable used as the result from the call
+				assert( impCpCtorExpr->get_result() && impCpCtorExpr->get_returnDecls().size() == 1 );
+				unqExpr->set_var( new VariableExpr( impCpCtorExpr->get_returnDecls().front() ) );
+			} else {
+				// expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
+				unqExpr->set_object( new ObjectDecl( toString("_unq_expr_", unqExpr->get_id()), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
+				unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
+			}
+			vars.insert( unqExpr->get_id() );
 		}
 
@@ -490,8 +536,8 @@
 				// know the result type of the assignment is the type of the LHS (minus the pointer), so
 				// add that onto the assignment expression so that later steps have the necessary information
-				assign->add_result( returnDecl->get_type()->clone() );
+				assign->set_result( returnDecl->get_type()->clone() );
 
 				Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
-				if ( callExpr->get_results().front()->get_isLvalue() ) {
+				if ( callExpr->get_result()->get_isLvalue() ) {
 					// lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
 					// non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
@@ -500,17 +546,15 @@
 					// an AddressExpr.  Effectively, this turns
 					//   lvalue T f();
-					//   &*f()
+					//   &*f();
 					// into
+					//   T * f();
 					//   T * tmp_cp_retN;
-					//   tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret);
+					//   &*(tmp_cp_retN = &*f(), tmp_cp_retN);		// the first * and second & are generated here
 					// which work out in terms of types, but is pretty messy. It would be nice to find a better way.
 					assign->get_args().back() = new AddressExpr( assign->get_args().back() );
 
-					Type * resultType = returnDecl->get_type()->clone();
 					returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );
-					UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
-					deref->get_args().push_back( retExpr );
-					deref->add_result( resultType );
-					retExpr = deref;
+					retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );
+					retExpr = UntypedExpr::createDeref( retExpr );
 				} // if
 				retExpr->set_env( env->clone() );
@@ -519,4 +563,35 @@
 				return callExpr;
 			} // if
+		}
+
+		Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
+			static std::unordered_map< int, UniqueExpr * > unqMap;
+			static std::unordered_set< int > addDeref;
+			// has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
+			unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) );
+			if ( unqMap.count( unqExpr->get_id() ) ) {
+				// take data from other UniqueExpr to ensure consistency
+				delete unqExpr->get_expr();
+				unqExpr->set_expr( unqMap[unqExpr->get_id()]->get_expr()->clone() );
+				delete unqExpr->get_result();
+				unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) );
+				if ( addDeref.count( unqExpr->get_id() ) ) {
+					// other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too
+					return UntypedExpr::createDeref( unqExpr );
+				}
+				return unqExpr;
+			}
+			unqMap[unqExpr->get_id()] = unqExpr;
+			if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
+				// unique expression is now a dereference, because the inner expression is an lvalue returning function call.
+				// Normalize the expression by dereferencing the unique expression, rather than the inner expression
+				// (i.e. move the dereference out a level)
+				assert( getFunctionName( deref ) == "*?" );
+				unqExpr->set_expr( getCallArg( deref, 0 ) );
+				getCallArg( deref, 0 ) = unqExpr;
+				addDeref.insert( unqExpr->get_id() );
+				return deref;
+			}
+			return unqExpr;
 		}
 
@@ -950,6 +1025,7 @@
 		Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
 			static UniqueName tempNamer( "_tmp_ctor_expr" );
-			assert( ctorExpr->get_results().size() == 1 );
-			ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_results().front()->clone(), nullptr );
+			// xxx - is the size check necessary?
+			assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 );
+			ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
 			addDeclaration( tmp );
 
@@ -963,5 +1039,5 @@
 			assign->get_args().push_back( new VariableExpr( tmp ) );
 			assign->get_args().push_back( firstArg );
-			cloneAll( ctorExpr->get_results(), assign->get_results() );
+			assign->set_result( ctorExpr->get_result()->clone() );
 			firstArg = assign;
 
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/InitTweak/GenInit.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -29,4 +29,5 @@
 #include "GenPoly/DeclMutator.h"
 #include "GenPoly/ScopedSet.h"
+#include "ResolvExpr/typeops.h"
 
 namespace InitTweak {
@@ -50,5 +51,5 @@
 
 	  protected:
-		std::list<DeclarationWithType*> returnVals;
+		FunctionType * ftype;
 		UniqueName tempNamer;
 		std::string funcName;
@@ -86,4 +87,5 @@
 
 		bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
+		bool isManaged( Type * type ) const; // determine if type is managed
 		void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
 		GenPoly::ScopedSet< std::string > managedTypes;
@@ -136,5 +138,5 @@
 
 	Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) {
-		// update for multiple return values
+		std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
 		assert( returnVals.size() == 0 || returnVals.size() == 1 );
 		// hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
@@ -158,9 +160,24 @@
 
 	DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
-		ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals );
+		// xxx - need to handle named return values - this pass may need to happen
+		// after resolution? the ordering is tricky because return statements must be
+		// constructed - the simplest way to do that (while also handling multiple
+		// returns) is to structure the returnVals into a tuple, as done here.
+		// however, if the tuple return value is structured before resolution,
+		// it's difficult to resolve named return values, since the name is lost
+		// in conversion to a tuple. this might be easiest to deal with
+		// after reference types are added, as it may then be possible to
+		// uniformly move named return values to the parameter list directly
+		ValueGuard< FunctionType * > oldFtype( ftype );
 		ValueGuard< std::string > oldFuncName( funcName );
 
-		FunctionType * type = functionDecl->get_functionType();
-		returnVals = type->get_returnVals();
+		ftype = functionDecl->get_functionType();
+		std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
+		if ( retVals.size() > 1 ) {
+			TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
+			ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
+			retVals.clear();
+			retVals.push_back( newRet );
+		}
 		funcName = functionDecl->get_name();
 		DeclarationWithType * decl = Mutator::mutate( functionDecl );
@@ -222,4 +239,14 @@
 	}
 
+	bool CtorDtor::isManaged( Type * type ) const {
+		if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
+			// tuple is also managed if any of its components are managed
+			if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
+				return true;
+			}
+		}
+		return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
+	}
+
 	bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
 		Type * type = objDecl->get_type();
@@ -227,5 +254,5 @@
 			type = at->get_base();
 		}
-		return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
+		return isManaged( type );
 	}
 
@@ -238,4 +265,36 @@
 			managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
 		}
+	}
+
+	ConstructorInit * genCtorInit( ObjectDecl * objDecl ) {
+		// call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
+		// for each constructable object
+		std::list< Statement * > ctor;
+		std::list< Statement * > dtor;
+
+		InitExpander srcParam( objDecl->get_init() );
+		InitExpander nullParam( (Initializer *)NULL );
+		SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
+		SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
+
+		// Currently genImplicitCall produces a single Statement - a CompoundStmt
+		// which  wraps everything that needs to happen. As such, it's technically
+		// possible to use a Statement ** in the above calls, but this is inherently
+		// unsafe, so instead we take the slightly less efficient route, but will be
+		// immediately informed if somehow the above assumption is broken. In this case,
+		// we could always wrap the list of statements at this point with a CompoundStmt,
+		// but it seems reasonable at the moment for this to be done by genImplicitCall
+		// itself. It is possible that genImplicitCall produces no statements (e.g. if
+		// an array type does not have a dimension). In this case, it's fine to ignore
+		// the object for the purposes of construction.
+		assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
+		if ( ctor.size() == 1 ) {
+			// need to remember init expression, in case no ctors exist
+			// if ctor does exist, want to use ctor expression instead of init
+			// push this decision to the resolver
+			assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
+			return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() );
+		}
+		return nullptr;
 	}
 
@@ -250,32 +309,5 @@
 			if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
 
-			// call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
-			// for each constructable object
-			std::list< Statement * > ctor;
-			std::list< Statement * > dtor;
-
-			InitExpander srcParam( objDecl->get_init() );
-			InitExpander nullParam( (Initializer *)NULL );
-			SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
-			SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
-
-			// Currently genImplicitCall produces a single Statement - a CompoundStmt
-			// which  wraps everything that needs to happen. As such, it's technically
-			// possible to use a Statement ** in the above calls, but this is inherently
-			// unsafe, so instead we take the slightly less efficient route, but will be
-			// immediately informed if somehow the above assumption is broken. In this case,
-			// we could always wrap the list of statements at this point with a CompoundStmt,
-			// but it seems reasonable at the moment for this to be done by genImplicitCall
-			// itself. It is possible that genImplicitCall produces no statements (e.g. if
-			// an array type does not have a dimension). In this case, it's fine to ignore
-			// the object for the purposes of construction.
-			assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
-			if ( ctor.size() == 1 ) {
-				// need to remember init expression, in case no ctors exist
-				// if ctor does exist, want to use ctor expression instead of init
-				// push this decision to the resolver
-				assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
-				objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
-			}
+			objDecl->set_init( genCtorInit( objDecl ) );
 		}
 		return Parent::mutate( objDecl );
@@ -290,5 +322,5 @@
 		managedTypes.beginScope();
 		// go through assertions and recursively add seen ctor/dtors
-		for ( TypeDecl * tyDecl : functionDecl->get_functionType()->get_forall() ) {
+		for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
 			for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
 				assertion = assertion->acceptMutator( *this );
Index: src/InitTweak/GenInit.h
===================================================================
--- src/InitTweak/GenInit.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/InitTweak/GenInit.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// RemoveInit.h --
+// GenInit.h --
 //
 // Author           : Rodolfo G. Esteves
@@ -27,4 +27,7 @@
 	/// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
 	void genInit( std::list< Declaration * > & translationUnit );
+
+	/// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
+	ConstructorInit * genCtorInit( ObjectDecl * objDecl );
 } // namespace
 
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/InitTweak/InitTweak.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -340,6 +340,5 @@
 		return allofCtorDtor( stmt, []( Expression * callExpr ){
 			if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
-				assert( ! appExpr->get_function()->get_results().empty() );
-				FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
+				FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_result() );
 				assert( funcType );
 				return funcType->get_parameters().size() == 1;
@@ -388,5 +387,5 @@
 				return memberExpr->get_member()->get_name();
 			} else if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * > ( func ) ) {
-				return memberExpr->get_member();
+				return funcName( memberExpr->get_member() );
 			} else {
 				assertf( false, "Unexpected expression type being called as a function in call expression" );
@@ -451,10 +450,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 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Makefile.in	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -105,5 +105,4 @@
 	ControlStruct/driver_cfa_cpp-Mutate.$(OBJEXT) \
 	ControlStruct/driver_cfa_cpp-ForExprMutator.$(OBJEXT) \
-	ControlStruct/driver_cfa_cpp-LabelTypeChecker.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-Box.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT) \
@@ -190,6 +189,8 @@
 	SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
+	SynTree/driver_cfa_cpp-VarExprReplacer.$(OBJEXT) \
 	Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT) \
-	Tuples/driver_cfa_cpp-NameMatcher.$(OBJEXT)
+	Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT) \
+	Tuples/driver_cfa_cpp-Explode.$(OBJEXT)
 am_driver_cfa_cpp_OBJECTS = $(am__objects_1)
 driver_cfa_cpp_OBJECTS = $(am_driver_cfa_cpp_OBJECTS)
@@ -364,6 +365,5 @@
 	ControlStruct/LabelGenerator.cc ControlStruct/LabelFixer.cc \
 	ControlStruct/MLEMutator.cc ControlStruct/Mutate.cc \
-	ControlStruct/ForExprMutator.cc \
-	ControlStruct/LabelTypeChecker.cc GenPoly/Box.cc \
+	ControlStruct/ForExprMutator.cc GenPoly/Box.cc \
 	GenPoly/GenPoly.cc GenPoly/PolyMutator.cc \
 	GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc GenPoly/Specialize.cc \
@@ -404,6 +404,7 @@
 	SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \
 	SynTree/AddStmtVisitor.cc SynTree/TypeSubstitution.cc \
-	SynTree/Attribute.cc Tuples/TupleAssignment.cc \
-	Tuples/NameMatcher.cc
+	SynTree/Attribute.cc SynTree/VarExprReplacer.cc \
+	Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
+	Tuples/Explode.cc
 MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
 	${cfa_cpplib_PROGRAMS}}
@@ -541,7 +542,4 @@
 	ControlStruct/$(DEPDIR)/$(am__dirstamp)
 ControlStruct/driver_cfa_cpp-ForExprMutator.$(OBJEXT):  \
-	ControlStruct/$(am__dirstamp) \
-	ControlStruct/$(DEPDIR)/$(am__dirstamp)
-ControlStruct/driver_cfa_cpp-LabelTypeChecker.$(OBJEXT):  \
 	ControlStruct/$(am__dirstamp) \
 	ControlStruct/$(DEPDIR)/$(am__dirstamp)
@@ -769,4 +767,6 @@
 SynTree/driver_cfa_cpp-Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \
 	SynTree/$(DEPDIR)/$(am__dirstamp)
+SynTree/driver_cfa_cpp-VarExprReplacer.$(OBJEXT):  \
+	SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
 Tuples/$(am__dirstamp):
 	@$(MKDIR_P) Tuples
@@ -777,5 +777,7 @@
 Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT):  \
 	Tuples/$(am__dirstamp) Tuples/$(DEPDIR)/$(am__dirstamp)
-Tuples/driver_cfa_cpp-NameMatcher.$(OBJEXT): Tuples/$(am__dirstamp) \
+Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT):  \
+	Tuples/$(am__dirstamp) Tuples/$(DEPDIR)/$(am__dirstamp)
+Tuples/driver_cfa_cpp-Explode.$(OBJEXT): Tuples/$(am__dirstamp) \
 	Tuples/$(DEPDIR)/$(am__dirstamp)
 driver/$(am__dirstamp):
@@ -800,5 +802,4 @@
 	-rm -f ControlStruct/driver_cfa_cpp-LabelFixer.$(OBJEXT)
 	-rm -f ControlStruct/driver_cfa_cpp-LabelGenerator.$(OBJEXT)
-	-rm -f ControlStruct/driver_cfa_cpp-LabelTypeChecker.$(OBJEXT)
 	-rm -f ControlStruct/driver_cfa_cpp-MLEMutator.$(OBJEXT)
 	-rm -f ControlStruct/driver_cfa_cpp-Mutate.$(OBJEXT)
@@ -884,9 +885,11 @@
 	-rm -f SynTree/driver_cfa_cpp-TypeofType.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-VarArgsType.$(OBJEXT)
+	-rm -f SynTree/driver_cfa_cpp-VarExprReplacer.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-Visitor.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-VoidType.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-ZeroOneType.$(OBJEXT)
-	-rm -f Tuples/driver_cfa_cpp-NameMatcher.$(OBJEXT)
+	-rm -f Tuples/driver_cfa_cpp-Explode.$(OBJEXT)
 	-rm -f Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT)
+	-rm -f Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT)
 
 distclean-compile:
@@ -907,5 +910,4 @@
 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelFixer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelGenerator.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelTypeChecker.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-MLEMutator.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ControlStruct/$(DEPDIR)/driver_cfa_cpp-Mutate.Po@am__quote@
@@ -991,9 +993,11 @@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/driver_cfa_cpp-NameMatcher.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.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:
@@ -1237,18 +1241,4 @@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ControlStruct/driver_cfa_cpp-ForExprMutator.obj `if test -f 'ControlStruct/ForExprMutator.cc'; then $(CYGPATH_W) 'ControlStruct/ForExprMutator.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/ForExprMutator.cc'; fi`
 
-ControlStruct/driver_cfa_cpp-LabelTypeChecker.o: ControlStruct/LabelTypeChecker.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-LabelTypeChecker.o -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelTypeChecker.Tpo -c -o ControlStruct/driver_cfa_cpp-LabelTypeChecker.o `test -f 'ControlStruct/LabelTypeChecker.cc' || echo '$(srcdir)/'`ControlStruct/LabelTypeChecker.cc
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelTypeChecker.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelTypeChecker.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='ControlStruct/LabelTypeChecker.cc' object='ControlStruct/driver_cfa_cpp-LabelTypeChecker.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 ControlStruct/driver_cfa_cpp-LabelTypeChecker.o `test -f 'ControlStruct/LabelTypeChecker.cc' || echo '$(srcdir)/'`ControlStruct/LabelTypeChecker.cc
-
-ControlStruct/driver_cfa_cpp-LabelTypeChecker.obj: ControlStruct/LabelTypeChecker.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ControlStruct/driver_cfa_cpp-LabelTypeChecker.obj -MD -MP -MF ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelTypeChecker.Tpo -c -o ControlStruct/driver_cfa_cpp-LabelTypeChecker.obj `if test -f 'ControlStruct/LabelTypeChecker.cc'; then $(CYGPATH_W) 'ControlStruct/LabelTypeChecker.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/LabelTypeChecker.cc'; fi`
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelTypeChecker.Tpo ControlStruct/$(DEPDIR)/driver_cfa_cpp-LabelTypeChecker.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='ControlStruct/LabelTypeChecker.cc' object='ControlStruct/driver_cfa_cpp-LabelTypeChecker.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 ControlStruct/driver_cfa_cpp-LabelTypeChecker.obj `if test -f 'ControlStruct/LabelTypeChecker.cc'; then $(CYGPATH_W) 'ControlStruct/LabelTypeChecker.cc'; else $(CYGPATH_W) '$(srcdir)/ControlStruct/LabelTypeChecker.cc'; fi`
-
 GenPoly/driver_cfa_cpp-Box.o: GenPoly/Box.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-Box.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Tpo -c -o GenPoly/driver_cfa_cpp-Box.o `test -f 'GenPoly/Box.cc' || echo '$(srcdir)/'`GenPoly/Box.cc
@@ -2427,4 +2417,18 @@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Attribute.obj `if test -f 'SynTree/Attribute.cc'; then $(CYGPATH_W) 'SynTree/Attribute.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Attribute.cc'; fi`
 
+SynTree/driver_cfa_cpp-VarExprReplacer.o: SynTree/VarExprReplacer.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-VarExprReplacer.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Tpo -c -o SynTree/driver_cfa_cpp-VarExprReplacer.o `test -f 'SynTree/VarExprReplacer.cc' || echo '$(srcdir)/'`SynTree/VarExprReplacer.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SynTree/VarExprReplacer.cc' object='SynTree/driver_cfa_cpp-VarExprReplacer.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 SynTree/driver_cfa_cpp-VarExprReplacer.o `test -f 'SynTree/VarExprReplacer.cc' || echo '$(srcdir)/'`SynTree/VarExprReplacer.cc
+
+SynTree/driver_cfa_cpp-VarExprReplacer.obj: SynTree/VarExprReplacer.cc
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-VarExprReplacer.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Tpo -c -o SynTree/driver_cfa_cpp-VarExprReplacer.obj `if test -f 'SynTree/VarExprReplacer.cc'; then $(CYGPATH_W) 'SynTree/VarExprReplacer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/VarExprReplacer.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SynTree/VarExprReplacer.cc' object='SynTree/driver_cfa_cpp-VarExprReplacer.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 SynTree/driver_cfa_cpp-VarExprReplacer.obj `if test -f 'SynTree/VarExprReplacer.cc'; then $(CYGPATH_W) 'SynTree/VarExprReplacer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/VarExprReplacer.cc'; fi`
+
 Tuples/driver_cfa_cpp-TupleAssignment.o: Tuples/TupleAssignment.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-TupleAssignment.o -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-TupleAssignment.Tpo -c -o Tuples/driver_cfa_cpp-TupleAssignment.o `test -f 'Tuples/TupleAssignment.cc' || echo '$(srcdir)/'`Tuples/TupleAssignment.cc
@@ -2441,17 +2445,31 @@
 @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-NameMatcher.o: Tuples/NameMatcher.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-NameMatcher.o -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-NameMatcher.Tpo -c -o Tuples/driver_cfa_cpp-NameMatcher.o `test -f 'Tuples/NameMatcher.cc' || echo '$(srcdir)/'`Tuples/NameMatcher.cc
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-NameMatcher.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-NameMatcher.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Tuples/NameMatcher.cc' object='Tuples/driver_cfa_cpp-NameMatcher.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-NameMatcher.o `test -f 'Tuples/NameMatcher.cc' || echo '$(srcdir)/'`Tuples/NameMatcher.cc
-
-Tuples/driver_cfa_cpp-NameMatcher.obj: Tuples/NameMatcher.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-NameMatcher.obj -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-NameMatcher.Tpo -c -o Tuples/driver_cfa_cpp-NameMatcher.obj `if test -f 'Tuples/NameMatcher.cc'; then $(CYGPATH_W) 'Tuples/NameMatcher.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/NameMatcher.cc'; fi`
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-NameMatcher.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-NameMatcher.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Tuples/NameMatcher.cc' object='Tuples/driver_cfa_cpp-NameMatcher.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-NameMatcher.obj `if test -f 'Tuples/NameMatcher.cc'; then $(CYGPATH_W) 'Tuples/NameMatcher.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/NameMatcher.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`
+
+Tuples/driver_cfa_cpp-Explode.o: Tuples/Explode.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-Explode.o -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Tpo -c -o Tuples/driver_cfa_cpp-Explode.o `test -f 'Tuples/Explode.cc' || echo '$(srcdir)/'`Tuples/Explode.cc
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Tuples/Explode.cc' object='Tuples/driver_cfa_cpp-Explode.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-Explode.o `test -f 'Tuples/Explode.cc' || echo '$(srcdir)/'`Tuples/Explode.cc
+
+Tuples/driver_cfa_cpp-Explode.obj: Tuples/Explode.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-Explode.obj -MD -MP -MF Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Tpo -c -o Tuples/driver_cfa_cpp-Explode.obj `if test -f 'Tuples/Explode.cc'; then $(CYGPATH_W) 'Tuples/Explode.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/Explode.cc'; fi`
+@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Tpo Tuples/$(DEPDIR)/driver_cfa_cpp-Explode.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='Tuples/Explode.cc' object='Tuples/driver_cfa_cpp-Explode.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-Explode.obj `if test -f 'Tuples/Explode.cc'; then $(CYGPATH_W) 'Tuples/Explode.cc'; else $(CYGPATH_W) '$(srcdir)/Tuples/Explode.cc'; fi`
 
 .ll.cc:
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Parser/ExpressionNode.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -172,4 +172,47 @@
 } // build_constantStr
 
+Expression * build_field_name_FLOATINGconstant( const std::string & str ) {
+	// str is of the form A.B -> separate at the . and return member expression
+	int a, b;
+	char dot;
+	std::stringstream ss( str );
+	ss >> a >> dot >> b;
+	UntypedMemberExpr * ret = new UntypedMemberExpr(
+		new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::SignedInt ), toString( b ) ) ),
+		new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::SignedInt ), toString( a ) ) ) );
+	delete &str;
+	return ret;
+} // build_field_name_FLOATINGconstant
+
+Expression * make_field_name_fraction_constants( Expression * fieldName, Expression * fracts ) {
+	if ( fracts ) {
+		if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( fracts ) ) {
+			memberExpr->set_member( make_field_name_fraction_constants( fieldName, memberExpr->get_aggregate() ) );
+			return memberExpr;
+		} else {
+			return new UntypedMemberExpr( fracts, fieldName );
+		}
+	}
+	return fieldName;
+} // make_field_name_fraction_constants
+
+Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) {
+	return make_field_name_fraction_constants( fieldName, maybeMoveBuild< Expression >( fracts ) );
+} // build_field_name_fraction_constants
+
+Expression * build_field_name_REALFRACTIONconstant( const std::string & str ) {
+	assert( str[0] == '.' );
+	Expression * ret = build_constantInteger( *new std::string( str.substr(1) ) );
+	delete &str;
+	return ret;
+} // build_field_name_REALFRACTIONconstant
+
+Expression * build_field_name_REALDECIMALconstant( const std::string & str ) {
+	assert( str[str.size()-1] == '.' );
+	Expression * ret = build_constantInteger( *new std::string( str.substr( 0, str.size()-1 ) ) );
+	delete &str;
+	return ret;
+} // build_field_name_REALDECIMALconstant
+
 NameExpr * build_varref( const string *name, bool labelp ) {
 	NameExpr *expr = new NameExpr( *name, nullptr );
@@ -198,15 +241,13 @@
 }
 
-Expression *build_fieldSel( ExpressionNode *expr_node, NameExpr *member ) {
-	UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), maybeMoveBuild< Expression >(expr_node) );
-	delete member;
-	return ret;
-}
-
-Expression *build_pfieldSel( ExpressionNode *expr_node, NameExpr *member ) {
+Expression *build_fieldSel( ExpressionNode *expr_node, Expression *member ) {
+	UntypedMemberExpr *ret = new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) );
+	return ret;
+}
+
+Expression *build_pfieldSel( ExpressionNode *expr_node, Expression *member ) {
 	UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
 	deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) );
-	UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), deref );
-	delete member;
+	UntypedMemberExpr *ret = new UntypedMemberExpr( member, deref );
 	return ret;
 }
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Parser/ParseNode.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -155,4 +155,8 @@
 Expression * build_constantChar( const std::string &str );
 ConstantExpr * build_constantStr( const std::string &str );
+Expression * build_field_name_FLOATINGconstant( const std::string & str );
+Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts );
+Expression * build_field_name_REALFRACTIONconstant( const std::string & str );
+Expression * build_field_name_REALDECIMALconstant( const std::string & str );
 
 NameExpr * build_varref( const std::string * name, bool labelp = false );
@@ -160,6 +164,6 @@
 
 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );
-Expression * build_fieldSel( ExpressionNode * expr_node, NameExpr * member );
-Expression * build_pfieldSel( ExpressionNode * expr_node, NameExpr * member );
+Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member );
+Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member );
 Expression * build_addressOf( ExpressionNode * expr_node );
 Expression * build_sizeOfexpr( ExpressionNode * expr_node );
@@ -383,8 +387,8 @@
 //##############################################################################
 
-template< typename SynTreeType, typename NodeType >
-void buildList( const NodeType * firstNode, std::list< SynTreeType * > &outputList ) {
+template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >
+void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > &outputList ) {
 	SemanticError errors;
-	std::back_insert_iterator< std::list< SynTreeType * > > out( outputList );
+	std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );
 	const NodeType * cur = firstNode;
 
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Parser/TypeData.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -385,31 +385,33 @@
 } // TypeData::print
 
-void buildForall( const DeclarationNode * firstNode, list< TypeDecl* > &outputList ) {
+template< typename ForallList >
+void buildForall( const DeclarationNode * firstNode, ForallList &outputList ) {
 	buildList( firstNode, outputList );
-	for ( list< TypeDecl* >::iterator i = outputList.begin(); i != outputList.end(); ++i ) {
-		if ( (*i)->get_kind() == TypeDecl::Any ) {
+	for ( typename ForallList::iterator i = outputList.begin(); i != outputList.end(); ++i ) {
+		TypeDecl * td = static_cast<TypeDecl*>(*i);
+		if ( td->get_kind() == TypeDecl::Any ) {
 			// add assertion parameters to `type' tyvars in reverse order
 			// add dtor:  void ^?{}(T *)
 			FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false );
-			dtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), nullptr ) );
-			(*i)->get_assertions().push_front( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, dtorType, nullptr, false, false ) );
+			dtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
+			td->get_assertions().push_front( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, dtorType, nullptr, false, false ) );
 
 			// add copy ctor:  void ?{}(T *, T)
 			FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false );
-			copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), nullptr ) );
-			copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), nullptr ) );
-			(*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, copyCtorType, nullptr, false, false ) );
+			copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
+			copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
+			td->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, copyCtorType, nullptr, false, false ) );
 
 			// add default ctor:  void ?{}(T *)
 			FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false );
-			ctorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), nullptr ) );
-			(*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, ctorType, nullptr, false, false ) );
+			ctorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
+			td->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, ctorType, nullptr, false, false ) );
 
 			// add assignment operator:  T * ?=?(T *, T)
 			FunctionType * assignType = new FunctionType( Type::Qualifiers(), false );
-			assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), nullptr ) );
-			assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), nullptr ) );
-			assignType->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), nullptr ) );
-			(*i)->get_assertions().push_front( new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignType, nullptr, false, false ) );
+			assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
+			assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
+			assignType->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
+			td->get_assertions().push_front( new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignType, nullptr, false, false ) );
 		} // if
 	} // for
@@ -515,5 +517,5 @@
 		// character types. The implementation shall define char to have the same range, representation, and behavior as
 		// either signed char or unsigned char.
-		static BasicType::Kind chartype[] = { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::Char }; 
+		static BasicType::Kind chartype[] = { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::Char };
 
 		if ( td->length != DeclarationNode::NoLength ) {
Index: src/Parser/parser.cc
===================================================================
--- src/Parser/parser.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Parser/parser.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -1030,80 +1030,80 @@
 static const yytype_uint16 yyrline[] =
 {
-       0,   306,   306,   310,   317,   318,   319,   320,   321,   325,
-     326,   327,   331,   332,   336,   337,   341,   342,   346,   350,
-     351,   362,   364,   366,   367,   369,   374,   375,   381,   383,
-     385,   386,   387,   389,   390,   392,   394,   396,   405,   406,
-     412,   413,   417,   418,   422,   424,   426,   428,   430,   432,
-     434,   439,   441,   443,   447,   449,   453,   456,   458,   460,
-     465,   478,   480,   482,   484,   486,   488,   490,   492,   494,
-     496,   498,   505,   506,   512,   513,   514,   515,   519,   520,
-     527,   528,   530,   532,   537,   538,   540,   545,   546,   548,
-     553,   554,   556,   558,   560,   565,   566,   568,   573,   574,
-     579,   580,   585,   586,   591,   592,   597,   598,   603,   604,
-     607,   614,   619,   620,   628,   629,   633,   634,   635,   636,
-     637,   638,   639,   640,   641,   642,   643,   644,   654,   656,
-     661,   662,   667,   668,   674,   675,   681,   682,   683,   684,
-     685,   686,   687,   688,   689,   699,   706,   708,   718,   719,
-     724,   726,   732,   734,   738,   739,   744,   749,   752,   754,
-     756,   766,   768,   779,   780,   782,   786,   788,   792,   793,
-     798,   799,   803,   808,   809,   813,   815,   821,   822,   826,
-     828,   830,   832,   838,   839,   843,   845,   850,   852,   854,
-     859,   861,   866,   868,   872,   875,   879,   882,   886,   888,
-     890,   892,   897,   899,   901,   906,   908,   910,   912,   914,
-     919,   921,   923,   925,   930,   942,   943,   948,   950,   955,
-     959,   961,   963,   965,   967,   973,   974,   980,   981,   985,
-     986,   991,   993,   999,  1000,  1002,  1007,  1012,  1022,  1024,
-    1028,  1029,  1034,  1036,  1040,  1041,  1045,  1047,  1051,  1052,
-    1056,  1057,  1061,  1062,  1077,  1078,  1079,  1080,  1081,  1085,
-    1090,  1097,  1107,  1112,  1117,  1125,  1130,  1135,  1140,  1145,
-    1175,  1180,  1187,  1189,  1196,  1201,  1206,  1217,  1222,  1227,
-    1232,  1237,  1246,  1251,  1259,  1260,  1261,  1262,  1268,  1273,
-    1281,  1282,  1283,  1284,  1288,  1289,  1290,  1291,  1296,  1297,
-    1306,  1307,  1312,  1313,  1318,  1320,  1322,  1324,  1326,  1329,
-    1328,  1340,  1341,  1343,  1353,  1354,  1359,  1361,  1363,  1365,
-    1367,  1370,  1372,  1375,  1380,  1382,  1384,  1386,  1388,  1390,
-    1392,  1394,  1396,  1398,  1400,  1402,  1404,  1406,  1408,  1414,
-    1415,  1417,  1419,  1421,  1426,  1427,  1433,  1434,  1436,  1438,
-    1443,  1445,  1447,  1449,  1454,  1455,  1457,  1459,  1464,  1465,
-    1467,  1472,  1473,  1475,  1477,  1482,  1484,  1486,  1491,  1492,
-    1496,  1498,  1504,  1503,  1507,  1509,  1514,  1516,  1522,  1523,
-    1528,  1529,  1531,  1532,  1541,  1542,  1544,  1546,  1551,  1553,
-    1559,  1560,  1562,  1565,  1568,  1573,  1574,  1579,  1584,  1588,
-    1590,  1596,  1595,  1602,  1604,  1610,  1611,  1619,  1620,  1624,
-    1625,  1626,  1628,  1630,  1637,  1638,  1640,  1642,  1647,  1648,
-    1654,  1655,  1659,  1660,  1665,  1666,  1667,  1669,  1677,  1678,
-    1680,  1683,  1685,  1689,  1690,  1691,  1693,  1695,  1699,  1704,
-    1712,  1713,  1722,  1724,  1729,  1730,  1731,  1735,  1736,  1737,
-    1741,  1742,  1743,  1747,  1748,  1749,  1754,  1755,  1756,  1757,
-    1763,  1764,  1766,  1771,  1772,  1777,  1778,  1779,  1780,  1781,
-    1796,  1797,  1802,  1803,  1809,  1811,  1814,  1816,  1818,  1841,
-    1842,  1844,  1846,  1851,  1852,  1854,  1859,  1864,  1865,  1871,
-    1870,  1874,  1878,  1880,  1882,  1888,  1889,  1894,  1899,  1901,
-    1906,  1908,  1909,  1911,  1916,  1918,  1920,  1925,  1927,  1932,
-    1937,  1945,  1951,  1950,  1964,  1965,  1970,  1971,  1975,  1980,
-    1985,  1993,  1998,  2009,  2010,  2015,  2016,  2022,  2023,  2027,
-    2028,  2029,  2032,  2031,  2042,  2051,  2057,  2063,  2072,  2078,
-    2084,  2090,  2096,  2104,  2110,  2118,  2124,  2133,  2134,  2135,
-    2139,  2143,  2145,  2150,  2151,  2155,  2156,  2161,  2167,  2168,
-    2171,  2173,  2174,  2178,  2179,  2180,  2181,  2215,  2217,  2218,
-    2220,  2225,  2230,  2235,  2237,  2239,  2244,  2246,  2248,  2250,
-    2255,  2257,  2266,  2268,  2269,  2274,  2276,  2278,  2283,  2285,
-    2287,  2292,  2294,  2296,  2305,  2306,  2307,  2311,  2313,  2315,
-    2320,  2322,  2324,  2329,  2331,  2333,  2348,  2350,  2351,  2353,
-    2358,  2359,  2364,  2366,  2368,  2373,  2375,  2377,  2379,  2384,
-    2386,  2388,  2398,  2400,  2401,  2403,  2408,  2410,  2412,  2417,
-    2419,  2421,  2423,  2428,  2430,  2432,  2463,  2465,  2466,  2468,
-    2473,  2478,  2486,  2488,  2490,  2495,  2497,  2502,  2504,  2518,
-    2519,  2521,  2526,  2528,  2530,  2532,  2534,  2539,  2540,  2542,
-    2544,  2549,  2551,  2553,  2559,  2561,  2563,  2567,  2569,  2571,
-    2573,  2587,  2588,  2590,  2595,  2597,  2599,  2601,  2603,  2608,
-    2609,  2611,  2613,  2618,  2620,  2622,  2628,  2629,  2631,  2640,
-    2643,  2645,  2648,  2650,  2652,  2665,  2666,  2668,  2673,  2675,
-    2677,  2679,  2681,  2686,  2687,  2689,  2691,  2696,  2698,  2706,
-    2707,  2708,  2713,  2714,  2718,  2720,  2722,  2724,  2726,  2728,
-    2735,  2737,  2739,  2741,  2743,  2746,  2748,  2750,  2752,  2754,
-    2759,  2761,  2763,  2768,  2794,  2795,  2797,  2801,  2802,  2806,
-    2808,  2810,  2812,  2814,  2816,  2823,  2825,  2827,  2829,  2831,
-    2833,  2838,  2845,  2847,  2865,  2867,  2872,  2873
+       0,   305,   305,   309,   316,   317,   318,   319,   320,   324,
+     325,   326,   330,   331,   335,   336,   340,   341,   345,   349,
+     350,   361,   363,   365,   366,   368,   373,   374,   380,   382,
+     384,   386,   388,   390,   392,   394,   396,   398,   407,   408,
+     414,   415,   419,   420,   424,   425,   427,   429,   431,   433,
+     435,   440,   442,   444,   450,   451,   459,   462,   464,   466,
+     471,   484,   486,   488,   490,   492,   494,   496,   498,   500,
+     502,   504,   511,   512,   518,   519,   520,   521,   525,   526,
+     533,   534,   536,   538,   543,   544,   546,   551,   552,   554,
+     559,   560,   562,   564,   566,   571,   572,   574,   579,   580,
+     585,   586,   591,   592,   597,   598,   603,   604,   609,   610,
+     613,   620,   625,   626,   634,   635,   639,   640,   641,   642,
+     643,   644,   645,   646,   647,   648,   649,   650,   660,   662,
+     667,   668,   673,   674,   680,   681,   687,   688,   689,   690,
+     691,   692,   693,   694,   695,   705,   712,   714,   724,   725,
+     730,   732,   738,   740,   744,   745,   750,   755,   758,   760,
+     762,   772,   774,   785,   786,   788,   792,   794,   798,   799,
+     804,   805,   809,   814,   815,   819,   821,   827,   828,   832,
+     834,   836,   838,   844,   845,   849,   851,   856,   858,   860,
+     865,   867,   872,   874,   878,   881,   885,   888,   892,   894,
+     896,   898,   903,   905,   907,   912,   914,   916,   918,   920,
+     925,   927,   929,   931,   936,   948,   949,   954,   956,   961,
+     965,   967,   969,   971,   973,   979,   980,   986,   987,   991,
+     992,   997,   999,  1005,  1006,  1008,  1013,  1018,  1028,  1030,
+    1034,  1035,  1040,  1042,  1046,  1047,  1051,  1053,  1057,  1058,
+    1062,  1063,  1067,  1068,  1083,  1084,  1085,  1086,  1087,  1091,
+    1096,  1103,  1113,  1118,  1123,  1131,  1136,  1141,  1146,  1151,
+    1181,  1186,  1193,  1195,  1202,  1207,  1212,  1223,  1228,  1233,
+    1238,  1243,  1252,  1257,  1265,  1266,  1267,  1268,  1274,  1279,
+    1287,  1288,  1289,  1290,  1294,  1295,  1296,  1297,  1302,  1303,
+    1312,  1313,  1318,  1319,  1324,  1326,  1328,  1330,  1332,  1335,
+    1334,  1346,  1347,  1349,  1359,  1360,  1365,  1367,  1369,  1371,
+    1373,  1376,  1378,  1381,  1386,  1388,  1390,  1392,  1394,  1396,
+    1398,  1400,  1402,  1404,  1406,  1408,  1410,  1412,  1414,  1420,
+    1421,  1423,  1425,  1427,  1432,  1433,  1439,  1440,  1442,  1444,
+    1449,  1451,  1453,  1455,  1460,  1461,  1463,  1465,  1470,  1471,
+    1473,  1478,  1479,  1481,  1483,  1488,  1490,  1492,  1497,  1498,
+    1502,  1504,  1510,  1509,  1513,  1515,  1520,  1522,  1528,  1529,
+    1534,  1535,  1537,  1538,  1547,  1548,  1550,  1552,  1557,  1559,
+    1565,  1566,  1568,  1571,  1574,  1579,  1580,  1585,  1590,  1594,
+    1596,  1602,  1601,  1608,  1610,  1616,  1617,  1625,  1626,  1630,
+    1631,  1632,  1634,  1636,  1643,  1644,  1646,  1648,  1653,  1654,
+    1660,  1661,  1665,  1666,  1671,  1672,  1673,  1675,  1683,  1684,
+    1686,  1689,  1691,  1695,  1696,  1697,  1699,  1701,  1705,  1710,
+    1718,  1719,  1728,  1730,  1735,  1736,  1737,  1741,  1742,  1743,
+    1747,  1748,  1749,  1753,  1754,  1755,  1760,  1761,  1762,  1763,
+    1769,  1770,  1772,  1777,  1778,  1783,  1784,  1785,  1786,  1787,
+    1802,  1803,  1808,  1809,  1815,  1817,  1820,  1822,  1824,  1847,
+    1848,  1850,  1852,  1857,  1858,  1860,  1865,  1870,  1871,  1877,
+    1876,  1880,  1884,  1886,  1888,  1894,  1895,  1900,  1905,  1907,
+    1912,  1914,  1915,  1917,  1922,  1924,  1926,  1931,  1933,  1938,
+    1943,  1951,  1957,  1956,  1970,  1971,  1976,  1977,  1981,  1986,
+    1991,  1999,  2004,  2015,  2016,  2021,  2022,  2028,  2029,  2033,
+    2034,  2035,  2038,  2037,  2048,  2057,  2063,  2069,  2078,  2084,
+    2090,  2096,  2102,  2110,  2116,  2124,  2130,  2139,  2140,  2141,
+    2145,  2149,  2151,  2156,  2157,  2161,  2162,  2167,  2173,  2174,
+    2177,  2179,  2180,  2184,  2185,  2186,  2187,  2221,  2223,  2224,
+    2226,  2231,  2236,  2241,  2243,  2245,  2250,  2252,  2254,  2256,
+    2261,  2263,  2272,  2274,  2275,  2280,  2282,  2284,  2289,  2291,
+    2293,  2298,  2300,  2302,  2311,  2312,  2313,  2317,  2319,  2321,
+    2326,  2328,  2330,  2335,  2337,  2339,  2354,  2356,  2357,  2359,
+    2364,  2365,  2370,  2372,  2374,  2379,  2381,  2383,  2385,  2390,
+    2392,  2394,  2404,  2406,  2407,  2409,  2414,  2416,  2418,  2423,
+    2425,  2427,  2429,  2434,  2436,  2438,  2469,  2471,  2472,  2474,
+    2479,  2484,  2492,  2494,  2496,  2501,  2503,  2508,  2510,  2524,
+    2525,  2527,  2532,  2534,  2536,  2538,  2540,  2545,  2546,  2548,
+    2550,  2555,  2557,  2559,  2565,  2567,  2569,  2573,  2575,  2577,
+    2579,  2593,  2594,  2596,  2601,  2603,  2605,  2607,  2609,  2614,
+    2615,  2617,  2619,  2624,  2626,  2628,  2634,  2635,  2637,  2646,
+    2649,  2651,  2654,  2656,  2658,  2671,  2672,  2674,  2679,  2681,
+    2683,  2685,  2687,  2692,  2693,  2695,  2697,  2702,  2704,  2712,
+    2713,  2714,  2719,  2720,  2724,  2726,  2728,  2730,  2732,  2734,
+    2741,  2743,  2745,  2747,  2749,  2752,  2754,  2756,  2758,  2760,
+    2765,  2767,  2769,  2774,  2800,  2801,  2803,  2807,  2808,  2812,
+    2814,  2816,  2818,  2820,  2822,  2829,  2831,  2833,  2835,  2837,
+    2839,  2844,  2851,  2853,  2871,  2873,  2878,  2879
 };
 #endif
@@ -4928,5 +4928,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 306 "parser.yy"
+#line 305 "parser.yy"
     { typedefTable.enterScope(); }
     break;
@@ -4935,5 +4935,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 310 "parser.yy"
+#line 309 "parser.yy"
     { typedefTable.leaveScope(); }
     break;
@@ -4942,9 +4942,16 @@
 
 /* Line 1806 of yacc.c  */
+#line 316 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_constantInteger( *(yyvsp[(1) - (1)].tok) ) ); }
+    break;
+
+  case 5:
+
+/* Line 1806 of yacc.c  */
 #line 317 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_constantInteger( *(yyvsp[(1) - (1)].tok) ) ); }
-    break;
-
-  case 5:
+    { (yyval.en) = new ExpressionNode( build_constantFloat( *(yyvsp[(1) - (1)].tok) ) ); }
+    break;
+
+  case 6:
 
 /* Line 1806 of yacc.c  */
@@ -4953,5 +4960,5 @@
     break;
 
-  case 6:
+  case 7:
 
 /* Line 1806 of yacc.c  */
@@ -4960,15 +4967,8 @@
     break;
 
-  case 7:
+  case 8:
 
 /* Line 1806 of yacc.c  */
 #line 320 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_constantFloat( *(yyvsp[(1) - (1)].tok) ) ); }
-    break;
-
-  case 8:
-
-/* Line 1806 of yacc.c  */
-#line 321 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_constantChar( *(yyvsp[(1) - (1)].tok) ) ); }
     break;
@@ -4977,5 +4977,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 346 "parser.yy"
+#line 345 "parser.yy"
     { (yyval.constant) = build_constantStr( *(yyvsp[(1) - (1)].str) ); }
     break;
@@ -4984,5 +4984,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 350 "parser.yy"
+#line 349 "parser.yy"
     { (yyval.str) = (yyvsp[(1) - (1)].tok); }
     break;
@@ -4991,5 +4991,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 352 "parser.yy"
+#line 351 "parser.yy"
     {
 			appendStr( (yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].tok) );						// append 2nd juxtaposed string to 1st
@@ -5002,5 +5002,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 363 "parser.yy"
+#line 362 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_varref( (yyvsp[(1) - (1)].tok) ) ); }
     break;
@@ -5009,5 +5009,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 365 "parser.yy"
+#line 364 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_varref( (yyvsp[(1) - (1)].tok) ) ); }
     break;
@@ -5016,5 +5016,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 368 "parser.yy"
+#line 367 "parser.yy"
     { (yyval.en) = (yyvsp[(2) - (3)].en); }
     break;
@@ -5023,5 +5023,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 370 "parser.yy"
+#line 369 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_valexpr( (yyvsp[(2) - (3)].sn) ) ); }
     break;
@@ -5030,5 +5030,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 380 "parser.yy"
+#line 379 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Index, (yyvsp[(1) - (6)].en), (yyvsp[(4) - (6)].en) ) ); }
     break;
@@ -5037,5 +5037,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 382 "parser.yy"
+#line 381 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_func( (yyvsp[(1) - (4)].en), (yyvsp[(3) - (4)].en) ) ); }
     break;
@@ -5044,19 +5044,40 @@
 
 /* Line 1806 of yacc.c  */
-#line 384 "parser.yy"
+#line 383 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(1) - (3)].en), build_varref( (yyvsp[(3) - (3)].tok) ) ) ); }
     break;
 
+  case 30:
+
+/* Line 1806 of yacc.c  */
+#line 385 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(1) - (7)].en), build_tuple( (yyvsp[(5) - (7)].en) ) ) ); }
+    break;
+
+  case 31:
+
+/* Line 1806 of yacc.c  */
+#line 387 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(1) - (2)].en), build_field_name_REALFRACTIONconstant( *(yyvsp[(2) - (2)].tok) ) ) ); }
+    break;
+
   case 32:
 
 /* Line 1806 of yacc.c  */
-#line 388 "parser.yy"
+#line 389 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_pfieldSel( (yyvsp[(1) - (3)].en), build_varref( (yyvsp[(3) - (3)].tok) ) ) ); }
     break;
 
+  case 33:
+
+/* Line 1806 of yacc.c  */
+#line 391 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_pfieldSel( (yyvsp[(1) - (7)].en), build_tuple( (yyvsp[(5) - (7)].en) ) ) ); }
+    break;
+
   case 34:
 
 /* Line 1806 of yacc.c  */
-#line 391 "parser.yy"
+#line 393 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, (yyvsp[(1) - (2)].en) ) ); }
     break;
@@ -5065,5 +5086,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 393 "parser.yy"
+#line 395 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_unary_ptr( OperKinds::DecrPost, (yyvsp[(1) - (2)].en) ) ); }
     break;
@@ -5072,5 +5093,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 395 "parser.yy"
+#line 397 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_compoundLiteral( (yyvsp[(2) - (7)].decl), new InitializerNode( (yyvsp[(5) - (7)].in), true ) ) ); }
     break;
@@ -5079,5 +5100,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 397 "parser.yy"
+#line 399 "parser.yy"
     {
 			Token fn;
@@ -5090,5 +5111,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 407 "parser.yy"
+#line 409 "parser.yy"
     { (yyval.en) = (ExpressionNode *)( (yyvsp[(1) - (3)].en)->set_last( (yyvsp[(3) - (3)].en) )); }
     break;
@@ -5097,5 +5118,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 412 "parser.yy"
+#line 414 "parser.yy"
     { (yyval.en) = 0; }
     break;
@@ -5104,20 +5125,13 @@
 
 /* Line 1806 of yacc.c  */
-#line 418 "parser.yy"
+#line 420 "parser.yy"
     { (yyval.en) = (ExpressionNode *)(yyvsp[(1) - (3)].en)->set_last( (yyvsp[(3) - (3)].en) ); }
     break;
 
-  case 44:
-
-/* Line 1806 of yacc.c  */
-#line 423 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_varref( (yyvsp[(1) - (1)].tok) ) ); }
-    break;
-
   case 45:
 
 /* Line 1806 of yacc.c  */
-#line 425 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(2) - (2)].en), build_varref( (yyvsp[(1) - (2)].tok) ) ) ); }
+#line 426 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_REALDECIMALconstant( *(yyvsp[(1) - (2)].tok) ) ), maybeMoveBuild<Expression>( (yyvsp[(2) - (2)].en) ) ) ); }
     break;
 
@@ -5125,6 +5139,6 @@
 
 /* Line 1806 of yacc.c  */
-#line 427 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(4) - (6)].en), build_varref( (yyvsp[(1) - (6)].tok) ) ) ); }
+#line 428 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_REALDECIMALconstant( *(yyvsp[(1) - (6)].tok) ) ), build_tuple( (yyvsp[(4) - (6)].en) ) ) ); }
     break;
 
@@ -5132,6 +5146,6 @@
 
 /* Line 1806 of yacc.c  */
-#line 429 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(3) - (3)].en), build_varref( (yyvsp[(1) - (3)].tok) ) ) ); }
+#line 430 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(1) - (3)].en), maybeMoveBuild<Expression>( (yyvsp[(3) - (3)].en) ) ) ); }
     break;
 
@@ -5139,6 +5153,6 @@
 
 /* Line 1806 of yacc.c  */
-#line 431 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(5) - (7)].en), build_varref( (yyvsp[(1) - (7)].tok) ) ) ); }
+#line 432 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_fieldSel( (yyvsp[(1) - (7)].en), build_tuple( (yyvsp[(5) - (7)].en) ) ) ); }
     break;
 
@@ -5146,6 +5160,6 @@
 
 /* Line 1806 of yacc.c  */
-#line 433 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_pfieldSel( (yyvsp[(3) - (3)].en), build_varref( (yyvsp[(1) - (3)].tok) ) ) ); }
+#line 434 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_pfieldSel( (yyvsp[(1) - (3)].en), maybeMoveBuild<Expression>( (yyvsp[(3) - (3)].en) ) ) ); }
     break;
 
@@ -5153,6 +5167,6 @@
 
 /* Line 1806 of yacc.c  */
-#line 435 "parser.yy"
-    { (yyval.en) = new ExpressionNode( build_pfieldSel( (yyvsp[(5) - (7)].en), build_varref( (yyvsp[(1) - (7)].tok) ) ) ); }
+#line 436 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_pfieldSel( (yyvsp[(1) - (7)].en), build_tuple( (yyvsp[(5) - (7)].en) ) ) ); }
     break;
 
@@ -5160,6 +5174,6 @@
 
 /* Line 1806 of yacc.c  */
-#line 440 "parser.yy"
-    { (yyval.tok) = (yyvsp[(1) - (2)].tok); }
+#line 441 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *(yyvsp[(1) - (2)].tok) ), (yyvsp[(2) - (2)].en) ) ); }
     break;
 
@@ -5167,6 +5181,6 @@
 
 /* Line 1806 of yacc.c  */
-#line 442 "parser.yy"
-    { (yyval.tok) = (yyvsp[(1) - (2)].tok); }
+#line 443 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *(yyvsp[(1) - (2)].tok) ), (yyvsp[(2) - (2)].en) ) ); }
     break;
 
@@ -5174,6 +5188,23 @@
 
 /* Line 1806 of yacc.c  */
-#line 444 "parser.yy"
-    { (yyval.tok) = (yyvsp[(1) - (2)].tok); }
+#line 445 "parser.yy"
+    { (yyval.en) = new ExpressionNode( build_field_name_fraction_constants( build_varref( (yyvsp[(1) - (2)].tok) ), (yyvsp[(2) - (2)].en) ) ); }
+    break;
+
+  case 54:
+
+/* Line 1806 of yacc.c  */
+#line 450 "parser.yy"
+    { (yyval.en) = nullptr; }
+    break;
+
+  case 55:
+
+/* Line 1806 of yacc.c  */
+#line 452 "parser.yy"
+    {
+			Expression * constant = build_field_name_REALFRACTIONconstant( *(yyvsp[(2) - (2)].tok) );
+			(yyval.en) = (yyvsp[(1) - (2)].en) != nullptr ? new ExpressionNode( build_fieldSel( (yyvsp[(1) - (2)].en),  constant ) ) : new ExpressionNode( constant );
+		}
     break;
 
@@ -5181,5 +5212,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 457 "parser.yy"
+#line 463 "parser.yy"
     { (yyval.en) = (yyvsp[(1) - (1)].en); }
     break;
@@ -5188,5 +5219,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 459 "parser.yy"
+#line 465 "parser.yy"
     { (yyval.en) = new ExpressionNode( (yyvsp[(1) - (1)].constant) ); }
     break;
@@ -5195,5 +5226,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 461 "parser.yy"
+#line 467 "parser.yy"
     { (yyval.en) = (yyvsp[(2) - (2)].en)->set_extension( true ); }
     break;
@@ -5202,5 +5233,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 466 "parser.yy"
+#line 472 "parser.yy"
     {
 			switch ( (yyvsp[(1) - (2)].op) ) {
@@ -5220,5 +5251,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 479 "parser.yy"
+#line 485 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_unary_val( (yyvsp[(1) - (2)].op), (yyvsp[(2) - (2)].en) ) ); }
     break;
@@ -5227,5 +5258,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 481 "parser.yy"
+#line 487 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_unary_ptr( OperKinds::Incr, (yyvsp[(2) - (2)].en) ) ); }
     break;
@@ -5234,5 +5265,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 483 "parser.yy"
+#line 489 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_unary_ptr( OperKinds::Decr, (yyvsp[(2) - (2)].en) ) ); }
     break;
@@ -5241,5 +5272,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 485 "parser.yy"
+#line 491 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_sizeOfexpr( (yyvsp[(2) - (2)].en) ) ); }
     break;
@@ -5248,5 +5279,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 487 "parser.yy"
+#line 493 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_sizeOftype( (yyvsp[(3) - (4)].decl) ) ); }
     break;
@@ -5255,5 +5286,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 489 "parser.yy"
+#line 495 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_alignOfexpr( (yyvsp[(2) - (2)].en) ) ); }
     break;
@@ -5262,5 +5293,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 491 "parser.yy"
+#line 497 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_alignOftype( (yyvsp[(3) - (4)].decl) ) ); }
     break;
@@ -5269,5 +5300,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 493 "parser.yy"
+#line 499 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_offsetOf( (yyvsp[(3) - (6)].decl), build_varref( (yyvsp[(5) - (6)].tok) ) ) ); }
     break;
@@ -5276,5 +5307,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 495 "parser.yy"
+#line 501 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_attrexpr( build_varref( (yyvsp[(1) - (1)].tok) ), nullptr ) ); }
     break;
@@ -5283,5 +5314,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 497 "parser.yy"
+#line 503 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_attrexpr( build_varref( (yyvsp[(1) - (4)].tok) ), (yyvsp[(3) - (4)].en) ) ); }
     break;
@@ -5290,5 +5321,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 499 "parser.yy"
+#line 505 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_attrtype( build_varref( (yyvsp[(1) - (4)].tok) ), (yyvsp[(3) - (4)].decl) ) ); }
     break;
@@ -5297,5 +5328,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 505 "parser.yy"
+#line 511 "parser.yy"
     { (yyval.op) = OperKinds::PointTo; }
     break;
@@ -5304,5 +5335,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 506 "parser.yy"
+#line 512 "parser.yy"
     { (yyval.op) = OperKinds::AddressOf; }
     break;
@@ -5311,5 +5342,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 512 "parser.yy"
+#line 518 "parser.yy"
     { (yyval.op) = OperKinds::UnPlus; }
     break;
@@ -5318,5 +5349,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 513 "parser.yy"
+#line 519 "parser.yy"
     { (yyval.op) = OperKinds::UnMinus; }
     break;
@@ -5325,5 +5356,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 514 "parser.yy"
+#line 520 "parser.yy"
     { (yyval.op) = OperKinds::Neg; }
     break;
@@ -5332,5 +5363,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 515 "parser.yy"
+#line 521 "parser.yy"
     { (yyval.op) = OperKinds::BitNeg; }
     break;
@@ -5339,5 +5370,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 521 "parser.yy"
+#line 527 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_cast( (yyvsp[(2) - (4)].decl), (yyvsp[(4) - (4)].en) ) ); }
     break;
@@ -5346,5 +5377,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 529 "parser.yy"
+#line 535 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Mul, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5353,5 +5384,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 531 "parser.yy"
+#line 537 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Div, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5360,5 +5391,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 533 "parser.yy"
+#line 539 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Mod, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5367,5 +5398,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 539 "parser.yy"
+#line 545 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Plus, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5374,5 +5405,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 541 "parser.yy"
+#line 547 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Minus, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5381,5 +5412,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 547 "parser.yy"
+#line 553 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::LShift, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5388,5 +5419,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 549 "parser.yy"
+#line 555 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::RShift, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5395,5 +5426,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 555 "parser.yy"
+#line 561 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::LThan, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5402,5 +5433,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 557 "parser.yy"
+#line 563 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::GThan, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5409,5 +5440,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 559 "parser.yy"
+#line 565 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::LEThan, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5416,5 +5447,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 561 "parser.yy"
+#line 567 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::GEThan, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5423,5 +5454,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 567 "parser.yy"
+#line 573 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Eq, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5430,5 +5461,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 569 "parser.yy"
+#line 575 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Neq, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5437,5 +5468,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 575 "parser.yy"
+#line 581 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::BitAnd, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5444,5 +5475,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 581 "parser.yy"
+#line 587 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::Xor, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5451,5 +5482,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 587 "parser.yy"
+#line 593 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_val( OperKinds::BitOr, (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5458,5 +5489,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 593 "parser.yy"
+#line 599 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_and_or( (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en), true ) ); }
     break;
@@ -5465,5 +5496,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 599 "parser.yy"
+#line 605 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_and_or( (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en), false ) ); }
     break;
@@ -5472,5 +5503,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 605 "parser.yy"
+#line 611 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_cond( (yyvsp[(1) - (5)].en), (yyvsp[(3) - (5)].en), (yyvsp[(5) - (5)].en) ) ); }
     break;
@@ -5479,5 +5510,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 608 "parser.yy"
+#line 614 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_cond( (yyvsp[(1) - (4)].en), (yyvsp[(1) - (4)].en), (yyvsp[(4) - (4)].en) ) ); }
     break;
@@ -5486,5 +5517,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 621 "parser.yy"
+#line 627 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_binary_ptr( (yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5493,5 +5524,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 628 "parser.yy"
+#line 634 "parser.yy"
     { (yyval.en) = nullptr; }
     break;
@@ -5500,5 +5531,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 633 "parser.yy"
+#line 639 "parser.yy"
     { (yyval.op) = OperKinds::Assign; }
     break;
@@ -5507,5 +5538,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 634 "parser.yy"
+#line 640 "parser.yy"
     { (yyval.op) = OperKinds::AtAssn; }
     break;
@@ -5514,5 +5545,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 635 "parser.yy"
+#line 641 "parser.yy"
     { (yyval.op) = OperKinds::MulAssn; }
     break;
@@ -5521,5 +5552,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 636 "parser.yy"
+#line 642 "parser.yy"
     { (yyval.op) = OperKinds::DivAssn; }
     break;
@@ -5528,5 +5559,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 637 "parser.yy"
+#line 643 "parser.yy"
     { (yyval.op) = OperKinds::ModAssn; }
     break;
@@ -5535,5 +5566,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 638 "parser.yy"
+#line 644 "parser.yy"
     { (yyval.op) = OperKinds::PlusAssn; }
     break;
@@ -5542,5 +5573,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 639 "parser.yy"
+#line 645 "parser.yy"
     { (yyval.op) = OperKinds::MinusAssn; }
     break;
@@ -5549,5 +5580,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 640 "parser.yy"
+#line 646 "parser.yy"
     { (yyval.op) = OperKinds::LSAssn; }
     break;
@@ -5556,5 +5587,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 641 "parser.yy"
+#line 647 "parser.yy"
     { (yyval.op) = OperKinds::RSAssn; }
     break;
@@ -5563,5 +5594,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 642 "parser.yy"
+#line 648 "parser.yy"
     { (yyval.op) = OperKinds::AndAssn; }
     break;
@@ -5570,5 +5601,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 643 "parser.yy"
+#line 649 "parser.yy"
     { (yyval.op) = OperKinds::ERAssn; }
     break;
@@ -5577,5 +5608,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 644 "parser.yy"
+#line 650 "parser.yy"
     { (yyval.op) = OperKinds::OrAssn; }
     break;
@@ -5584,5 +5615,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 655 "parser.yy"
+#line 661 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( (yyvsp[(4) - (6)].en) ) ) ); }
     break;
@@ -5591,5 +5622,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 657 "parser.yy"
+#line 663 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_tuple( (ExpressionNode *)(yyvsp[(3) - (7)].en)->set_last( (yyvsp[(5) - (7)].en) ) ) ); }
     break;
@@ -5598,5 +5629,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 663 "parser.yy"
+#line 669 "parser.yy"
     { (yyval.en) = (ExpressionNode *)(yyvsp[(1) - (3)].en)->set_last( (yyvsp[(3) - (3)].en) ); }
     break;
@@ -5605,5 +5636,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 669 "parser.yy"
+#line 675 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_comma( (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5612,5 +5643,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 674 "parser.yy"
+#line 680 "parser.yy"
     { (yyval.en) = 0; }
     break;
@@ -5619,5 +5650,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 683 "parser.yy"
+#line 689 "parser.yy"
     { (yyval.sn) = (yyvsp[(1) - (1)].sn); }
     break;
@@ -5626,5 +5657,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 690 "parser.yy"
+#line 696 "parser.yy"
     {
 			Token fn;
@@ -5637,5 +5668,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 700 "parser.yy"
+#line 706 "parser.yy"
     {
 			(yyval.sn) = (yyvsp[(4) - (4)].sn)->add_label( (yyvsp[(1) - (4)].tok) );
@@ -5646,5 +5677,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 707 "parser.yy"
+#line 713 "parser.yy"
     { (yyval.sn) = new StatementNode( build_compound( (StatementNode *)0 ) ); }
     break;
@@ -5653,5 +5684,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 714 "parser.yy"
+#line 720 "parser.yy"
     { (yyval.sn) = new StatementNode( build_compound( (yyvsp[(5) - (7)].sn) ) ); }
     break;
@@ -5660,5 +5691,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 720 "parser.yy"
+#line 726 "parser.yy"
     { if ( (yyvsp[(1) - (3)].sn) != 0 ) { (yyvsp[(1) - (3)].sn)->set_last( (yyvsp[(3) - (3)].sn) ); (yyval.sn) = (yyvsp[(1) - (3)].sn); } }
     break;
@@ -5667,5 +5698,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 725 "parser.yy"
+#line 731 "parser.yy"
     { (yyval.sn) = new StatementNode( (yyvsp[(1) - (1)].decl) ); }
     break;
@@ -5674,5 +5705,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 727 "parser.yy"
+#line 733 "parser.yy"
     {	// mark all fields in list
 			for ( DeclarationNode *iter = (yyvsp[(2) - (2)].decl); iter != nullptr; iter = (DeclarationNode *)iter->get_next() )
@@ -5685,5 +5716,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 733 "parser.yy"
+#line 739 "parser.yy"
     { (yyval.sn) = new StatementNode( (yyvsp[(1) - (1)].decl) ); }
     break;
@@ -5692,5 +5723,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 740 "parser.yy"
+#line 746 "parser.yy"
     { if ( (yyvsp[(1) - (2)].sn) != 0 ) { (yyvsp[(1) - (2)].sn)->set_last( (yyvsp[(2) - (2)].sn) ); (yyval.sn) = (yyvsp[(1) - (2)].sn); } }
     break;
@@ -5699,5 +5730,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 745 "parser.yy"
+#line 751 "parser.yy"
     { (yyval.sn) = new StatementNode( build_expr( (yyvsp[(1) - (2)].en) ) ); }
     break;
@@ -5706,5 +5737,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 751 "parser.yy"
+#line 757 "parser.yy"
     { (yyval.sn) = new StatementNode( build_if( (yyvsp[(3) - (5)].en), (yyvsp[(5) - (5)].sn), nullptr ) ); }
     break;
@@ -5713,5 +5744,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 753 "parser.yy"
+#line 759 "parser.yy"
     { (yyval.sn) = new StatementNode( build_if( (yyvsp[(3) - (7)].en), (yyvsp[(5) - (7)].sn), (yyvsp[(7) - (7)].sn) ) ); }
     break;
@@ -5720,5 +5751,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 755 "parser.yy"
+#line 761 "parser.yy"
     { (yyval.sn) = new StatementNode( build_switch( (yyvsp[(3) - (5)].en), (yyvsp[(5) - (5)].sn) ) ); }
     break;
@@ -5727,5 +5758,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 757 "parser.yy"
+#line 763 "parser.yy"
     {
 			StatementNode *sw = new StatementNode( build_switch( (yyvsp[(3) - (9)].en), (yyvsp[(8) - (9)].sn) ) );
@@ -5742,5 +5773,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 767 "parser.yy"
+#line 773 "parser.yy"
     { (yyval.sn) = new StatementNode( build_switch( (yyvsp[(3) - (5)].en), (yyvsp[(5) - (5)].sn) ) ); }
     break;
@@ -5749,5 +5780,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 769 "parser.yy"
+#line 775 "parser.yy"
     {
 			StatementNode *sw = new StatementNode( build_switch( (yyvsp[(3) - (9)].en), (yyvsp[(8) - (9)].sn) ) );
@@ -5759,5 +5790,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 779 "parser.yy"
+#line 785 "parser.yy"
     { (yyval.en) = (yyvsp[(1) - (1)].en); }
     break;
@@ -5766,5 +5797,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 781 "parser.yy"
+#line 787 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_range( (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -5773,5 +5804,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 786 "parser.yy"
+#line 792 "parser.yy"
     { (yyval.sn) = new StatementNode( build_case( (yyvsp[(1) - (1)].en) ) ); }
     break;
@@ -5780,5 +5811,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 788 "parser.yy"
+#line 794 "parser.yy"
     { (yyval.sn) = (StatementNode *)((yyvsp[(1) - (3)].sn)->set_last( new StatementNode( build_case( (yyvsp[(3) - (3)].en) ) ) ) ); }
     break;
@@ -5787,5 +5818,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 792 "parser.yy"
+#line 798 "parser.yy"
     { (yyval.sn) = (yyvsp[(2) - (3)].sn); }
     break;
@@ -5794,5 +5825,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 793 "parser.yy"
+#line 799 "parser.yy"
     { (yyval.sn) = new StatementNode( build_default() ); }
     break;
@@ -5801,5 +5832,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 799 "parser.yy"
+#line 805 "parser.yy"
     { (yyval.sn) = (StatementNode *)( (yyvsp[(1) - (2)].sn)->set_last( (yyvsp[(2) - (2)].sn) )); }
     break;
@@ -5808,5 +5839,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 803 "parser.yy"
+#line 809 "parser.yy"
     { (yyval.sn) = (yyvsp[(1) - (2)].sn)->append_last_case( new StatementNode( build_compound( (yyvsp[(2) - (2)].sn) ) ) ); }
     break;
@@ -5815,5 +5846,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 808 "parser.yy"
+#line 814 "parser.yy"
     { (yyval.sn) = 0; }
     break;
@@ -5822,5 +5853,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 814 "parser.yy"
+#line 820 "parser.yy"
     { (yyval.sn) = (yyvsp[(1) - (2)].sn)->append_last_case( new StatementNode( build_compound( (yyvsp[(2) - (2)].sn) ) ) ); }
     break;
@@ -5829,5 +5860,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 816 "parser.yy"
+#line 822 "parser.yy"
     { (yyval.sn) = (StatementNode *)( (yyvsp[(1) - (3)].sn)->set_last( (yyvsp[(2) - (3)].sn)->append_last_case( new StatementNode( build_compound( (yyvsp[(3) - (3)].sn) ) ) ) ) ); }
     break;
@@ -5836,5 +5867,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 821 "parser.yy"
+#line 827 "parser.yy"
     { (yyval.sn) = 0; }
     break;
@@ -5843,5 +5874,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 827 "parser.yy"
+#line 833 "parser.yy"
     { (yyval.sn) = (yyvsp[(1) - (2)].sn)->append_last_case( (yyvsp[(2) - (2)].sn) ); }
     break;
@@ -5850,5 +5881,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 829 "parser.yy"
+#line 835 "parser.yy"
     { (yyval.sn) = (yyvsp[(1) - (3)].sn)->append_last_case( new StatementNode( build_compound( (StatementNode *)(yyvsp[(2) - (3)].sn)->set_last( (yyvsp[(3) - (3)].sn) ) ) ) ); }
     break;
@@ -5857,5 +5888,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 831 "parser.yy"
+#line 837 "parser.yy"
     { (yyval.sn) = (StatementNode *)( (yyvsp[(1) - (3)].sn)->set_last( (yyvsp[(2) - (3)].sn)->append_last_case( (yyvsp[(3) - (3)].sn) ))); }
     break;
@@ -5864,5 +5895,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 833 "parser.yy"
+#line 839 "parser.yy"
     { (yyval.sn) = (StatementNode *)( (yyvsp[(1) - (4)].sn)->set_last( (yyvsp[(2) - (4)].sn)->append_last_case( new StatementNode( build_compound( (StatementNode *)(yyvsp[(3) - (4)].sn)->set_last( (yyvsp[(4) - (4)].sn) ) ) ) ) ) ); }
     break;
@@ -5871,5 +5902,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 838 "parser.yy"
+#line 844 "parser.yy"
     { (yyval.sn) = new StatementNode( build_branch( BranchStmt::Break ) ); }
     break;
@@ -5878,5 +5909,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 844 "parser.yy"
+#line 850 "parser.yy"
     { (yyval.sn) = 0; }
     break;
@@ -5885,5 +5916,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 846 "parser.yy"
+#line 852 "parser.yy"
     { (yyval.sn) = 0; }
     break;
@@ -5892,5 +5923,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 851 "parser.yy"
+#line 857 "parser.yy"
     { (yyval.sn) = new StatementNode( build_while( (yyvsp[(3) - (5)].en), (yyvsp[(5) - (5)].sn) ) ); }
     break;
@@ -5899,5 +5930,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 853 "parser.yy"
+#line 859 "parser.yy"
     { (yyval.sn) = new StatementNode( build_while( (yyvsp[(5) - (7)].en), (yyvsp[(2) - (7)].sn), true ) ); }
     break;
@@ -5906,5 +5937,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 855 "parser.yy"
+#line 861 "parser.yy"
     { (yyval.sn) = new StatementNode( build_for( (yyvsp[(4) - (6)].fctl), (yyvsp[(6) - (6)].sn) ) ); }
     break;
@@ -5913,5 +5944,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 860 "parser.yy"
+#line 866 "parser.yy"
     { (yyval.fctl) = new ForCtl( (yyvsp[(1) - (6)].en), (yyvsp[(4) - (6)].en), (yyvsp[(6) - (6)].en) ); }
     break;
@@ -5920,5 +5951,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 862 "parser.yy"
+#line 868 "parser.yy"
     { (yyval.fctl) = new ForCtl( (yyvsp[(1) - (4)].decl), (yyvsp[(2) - (4)].en), (yyvsp[(4) - (4)].en) ); }
     break;
@@ -5927,5 +5958,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 867 "parser.yy"
+#line 873 "parser.yy"
     { (yyval.sn) = new StatementNode( build_branch( (yyvsp[(2) - (3)].tok), BranchStmt::Goto ) ); }
     break;
@@ -5934,5 +5965,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 871 "parser.yy"
+#line 877 "parser.yy"
     { (yyval.sn) = new StatementNode( build_computedgoto( (yyvsp[(3) - (4)].en) ) ); }
     break;
@@ -5941,5 +5972,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 874 "parser.yy"
+#line 880 "parser.yy"
     { (yyval.sn) = new StatementNode( build_branch( BranchStmt::Continue ) ); }
     break;
@@ -5948,5 +5979,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 878 "parser.yy"
+#line 884 "parser.yy"
     { (yyval.sn) = new StatementNode( build_branch( (yyvsp[(2) - (3)].tok), BranchStmt::Continue ) ); }
     break;
@@ -5955,5 +5986,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 881 "parser.yy"
+#line 887 "parser.yy"
     { (yyval.sn) = new StatementNode( build_branch( BranchStmt::Break ) ); }
     break;
@@ -5962,5 +5993,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 885 "parser.yy"
+#line 891 "parser.yy"
     { (yyval.sn) = new StatementNode( build_branch( (yyvsp[(2) - (3)].tok), BranchStmt::Break ) ); }
     break;
@@ -5969,5 +6000,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 887 "parser.yy"
+#line 893 "parser.yy"
     { (yyval.sn) = new StatementNode( build_return( (yyvsp[(2) - (3)].en) ) ); }
     break;
@@ -5976,5 +6007,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 889 "parser.yy"
+#line 895 "parser.yy"
     { (yyval.sn) = new StatementNode( build_throw( (yyvsp[(2) - (3)].en) ) ); }
     break;
@@ -5983,5 +6014,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 891 "parser.yy"
+#line 897 "parser.yy"
     { (yyval.sn) = new StatementNode( build_throw( (yyvsp[(2) - (3)].en) ) ); }
     break;
@@ -5990,5 +6021,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 893 "parser.yy"
+#line 899 "parser.yy"
     { (yyval.sn) = new StatementNode( build_throw( (yyvsp[(2) - (5)].en) ) ); }
     break;
@@ -5997,5 +6028,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 898 "parser.yy"
+#line 904 "parser.yy"
     { (yyval.sn) = new StatementNode( build_try( (yyvsp[(2) - (3)].sn), (yyvsp[(3) - (3)].sn), 0 ) ); }
     break;
@@ -6004,5 +6035,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 900 "parser.yy"
+#line 906 "parser.yy"
     { (yyval.sn) = new StatementNode( build_try( (yyvsp[(2) - (3)].sn), 0, (yyvsp[(3) - (3)].sn) ) ); }
     break;
@@ -6011,5 +6042,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 902 "parser.yy"
+#line 908 "parser.yy"
     { (yyval.sn) = new StatementNode( build_try( (yyvsp[(2) - (4)].sn), (yyvsp[(3) - (4)].sn), (yyvsp[(4) - (4)].sn) ) ); }
     break;
@@ -6018,5 +6049,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 909 "parser.yy"
+#line 915 "parser.yy"
     { (yyval.sn) = new StatementNode( build_catch( 0, (yyvsp[(5) - (5)].sn), true ) ); }
     break;
@@ -6025,5 +6056,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 911 "parser.yy"
+#line 917 "parser.yy"
     { (yyval.sn) = (StatementNode *)(yyvsp[(1) - (6)].sn)->set_last( new StatementNode( build_catch( 0, (yyvsp[(6) - (6)].sn), true ) ) ); }
     break;
@@ -6032,5 +6063,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 913 "parser.yy"
+#line 919 "parser.yy"
     { (yyval.sn) = new StatementNode( build_catch( 0, (yyvsp[(5) - (5)].sn), true ) ); }
     break;
@@ -6039,5 +6070,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 915 "parser.yy"
+#line 921 "parser.yy"
     { (yyval.sn) = (StatementNode *)(yyvsp[(1) - (6)].sn)->set_last( new StatementNode( build_catch( 0, (yyvsp[(6) - (6)].sn), true ) ) ); }
     break;
@@ -6046,5 +6077,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 920 "parser.yy"
+#line 926 "parser.yy"
     { (yyval.sn) = new StatementNode( build_catch( (yyvsp[(5) - (9)].decl), (yyvsp[(8) - (9)].sn) ) ); }
     break;
@@ -6053,5 +6084,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 922 "parser.yy"
+#line 928 "parser.yy"
     { (yyval.sn) = (StatementNode *)(yyvsp[(1) - (10)].sn)->set_last( new StatementNode( build_catch( (yyvsp[(6) - (10)].decl), (yyvsp[(9) - (10)].sn) ) ) ); }
     break;
@@ -6060,5 +6091,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 924 "parser.yy"
+#line 930 "parser.yy"
     { (yyval.sn) = new StatementNode( build_catch( (yyvsp[(5) - (9)].decl), (yyvsp[(8) - (9)].sn) ) ); }
     break;
@@ -6067,5 +6098,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 926 "parser.yy"
+#line 932 "parser.yy"
     { (yyval.sn) = (StatementNode *)(yyvsp[(1) - (10)].sn)->set_last( new StatementNode( build_catch( (yyvsp[(6) - (10)].decl), (yyvsp[(9) - (10)].sn) ) ) ); }
     break;
@@ -6074,5 +6105,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 931 "parser.yy"
+#line 937 "parser.yy"
     {
 			(yyval.sn) = new StatementNode( build_finally( (yyvsp[(2) - (2)].sn) ) );
@@ -6083,5 +6114,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 944 "parser.yy"
+#line 950 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6093,5 +6124,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 949 "parser.yy"
+#line 955 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addType( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -6100,5 +6131,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 951 "parser.yy"
+#line 957 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6110,5 +6141,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 960 "parser.yy"
+#line 966 "parser.yy"
     { (yyval.sn) = new StatementNode( build_asmstmt( (yyvsp[(2) - (6)].flag), (yyvsp[(4) - (6)].constant), 0 ) ); }
     break;
@@ -6117,5 +6148,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 962 "parser.yy"
+#line 968 "parser.yy"
     { (yyval.sn) = new StatementNode( build_asmstmt( (yyvsp[(2) - (8)].flag), (yyvsp[(4) - (8)].constant), (yyvsp[(6) - (8)].en) ) ); }
     break;
@@ -6124,5 +6155,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 964 "parser.yy"
+#line 970 "parser.yy"
     { (yyval.sn) = new StatementNode( build_asmstmt( (yyvsp[(2) - (10)].flag), (yyvsp[(4) - (10)].constant), (yyvsp[(6) - (10)].en), (yyvsp[(8) - (10)].en) ) ); }
     break;
@@ -6131,5 +6162,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 966 "parser.yy"
+#line 972 "parser.yy"
     { (yyval.sn) = new StatementNode( build_asmstmt( (yyvsp[(2) - (12)].flag), (yyvsp[(4) - (12)].constant), (yyvsp[(6) - (12)].en), (yyvsp[(8) - (12)].en), (yyvsp[(10) - (12)].en) ) ); }
     break;
@@ -6138,5 +6169,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 968 "parser.yy"
+#line 974 "parser.yy"
     { (yyval.sn) = new StatementNode( build_asmstmt( (yyvsp[(2) - (14)].flag), (yyvsp[(5) - (14)].constant), 0, (yyvsp[(8) - (14)].en), (yyvsp[(10) - (14)].en), (yyvsp[(12) - (14)].label) ) ); }
     break;
@@ -6145,5 +6176,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 973 "parser.yy"
+#line 979 "parser.yy"
     { (yyval.flag) = false; }
     break;
@@ -6152,5 +6183,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 975 "parser.yy"
+#line 981 "parser.yy"
     { (yyval.flag) = true; }
     break;
@@ -6159,5 +6190,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 980 "parser.yy"
+#line 986 "parser.yy"
     { (yyval.en) = 0; }
     break;
@@ -6166,5 +6197,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 987 "parser.yy"
+#line 993 "parser.yy"
     { (yyval.en) = (ExpressionNode *)(yyvsp[(1) - (3)].en)->set_last( (yyvsp[(3) - (3)].en) ); }
     break;
@@ -6173,5 +6204,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 992 "parser.yy"
+#line 998 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_asmexpr( 0, (yyvsp[(1) - (4)].constant), (yyvsp[(3) - (4)].en) ) ); }
     break;
@@ -6180,5 +6211,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 994 "parser.yy"
+#line 1000 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_asmexpr( (yyvsp[(2) - (7)].en), (yyvsp[(4) - (7)].constant), (yyvsp[(6) - (7)].en) ) ); }
     break;
@@ -6187,5 +6218,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 999 "parser.yy"
+#line 1005 "parser.yy"
     { (yyval.en) = 0; }
     break;
@@ -6194,5 +6225,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1001 "parser.yy"
+#line 1007 "parser.yy"
     { (yyval.en) = new ExpressionNode( (yyvsp[(1) - (1)].constant) ); }
     break;
@@ -6201,5 +6232,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1003 "parser.yy"
+#line 1009 "parser.yy"
     { (yyval.en) = (ExpressionNode *)(yyvsp[(1) - (3)].en)->set_last( new ExpressionNode( (yyvsp[(3) - (3)].constant) ) ); }
     break;
@@ -6208,5 +6239,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1008 "parser.yy"
+#line 1014 "parser.yy"
     {
 			(yyval.label) = new LabelNode(); (yyval.label)->labels.push_back( *(yyvsp[(1) - (1)].tok) );
@@ -6218,5 +6249,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1013 "parser.yy"
+#line 1019 "parser.yy"
     {
 			(yyval.label) = (yyvsp[(1) - (3)].label); (yyvsp[(1) - (3)].label)->labels.push_back( *(yyvsp[(3) - (3)].tok) );
@@ -6228,5 +6259,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1023 "parser.yy"
+#line 1029 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -6235,5 +6266,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1030 "parser.yy"
+#line 1036 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->appendList( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -6242,5 +6273,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1035 "parser.yy"
+#line 1041 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -6249,5 +6280,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1042 "parser.yy"
+#line 1048 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->appendList( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -6256,5 +6287,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1056 "parser.yy"
+#line 1062 "parser.yy"
     {}
     break;
@@ -6263,5 +6294,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1057 "parser.yy"
+#line 1063 "parser.yy"
     {}
     break;
@@ -6270,5 +6301,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1086 "parser.yy"
+#line 1092 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6280,5 +6311,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1093 "parser.yy"
+#line 1099 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6290,5 +6321,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1098 "parser.yy"
+#line 1104 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( *(yyvsp[(5) - (6)].tok), TypedefTable::ID );
@@ -6300,5 +6331,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1108 "parser.yy"
+#line 1114 "parser.yy"
     {
 			typedefTable.setNextIdentifier( *(yyvsp[(2) - (3)].tok) );
@@ -6310,5 +6341,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1113 "parser.yy"
+#line 1119 "parser.yy"
     {
 			typedefTable.setNextIdentifier( *(yyvsp[(2) - (3)].tok) );
@@ -6320,5 +6351,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1118 "parser.yy"
+#line 1124 "parser.yy"
     {
 			typedefTable.setNextIdentifier( *(yyvsp[(3) - (4)].tok) );
@@ -6330,5 +6361,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1126 "parser.yy"
+#line 1132 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6340,5 +6371,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1131 "parser.yy"
+#line 1137 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6350,5 +6381,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1136 "parser.yy"
+#line 1142 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6360,5 +6391,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1141 "parser.yy"
+#line 1147 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6370,5 +6401,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1146 "parser.yy"
+#line 1152 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( *(yyvsp[(5) - (5)].tok), TypedefTable::ID );
@@ -6380,5 +6411,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1177 "parser.yy"
+#line 1183 "parser.yy"
     {
 			(yyval.decl) = DeclarationNode::newFunction( (yyvsp[(2) - (7)].tok), (yyvsp[(1) - (7)].decl), (yyvsp[(5) - (7)].decl), 0, true );
@@ -6389,5 +6420,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1181 "parser.yy"
+#line 1187 "parser.yy"
     {
 			(yyval.decl) = DeclarationNode::newFunction( (yyvsp[(2) - (7)].tok), (yyvsp[(1) - (7)].decl), (yyvsp[(5) - (7)].decl), 0, true );
@@ -6398,5 +6429,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1188 "parser.yy"
+#line 1194 "parser.yy"
     { (yyval.decl) = DeclarationNode::newTuple( (yyvsp[(3) - (5)].decl) ); }
     break;
@@ -6405,5 +6436,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1192 "parser.yy"
+#line 1198 "parser.yy"
     { (yyval.decl) = DeclarationNode::newTuple( (yyvsp[(3) - (9)].decl)->appendList( (yyvsp[(7) - (9)].decl) ) ); }
     break;
@@ -6412,5 +6443,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1197 "parser.yy"
+#line 1203 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::TD );
@@ -6422,5 +6453,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1202 "parser.yy"
+#line 1208 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::TD );
@@ -6432,5 +6463,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1207 "parser.yy"
+#line 1213 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( *(yyvsp[(5) - (5)].tok), TypedefTable::TD );
@@ -6442,5 +6473,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1218 "parser.yy"
+#line 1224 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::TD );
@@ -6452,5 +6483,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1223 "parser.yy"
+#line 1229 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::TD );
@@ -6462,5 +6493,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1228 "parser.yy"
+#line 1234 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::TD );
@@ -6472,5 +6503,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1233 "parser.yy"
+#line 1239 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::TD );
@@ -6482,5 +6513,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1238 "parser.yy"
+#line 1244 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::TD );
@@ -6492,5 +6523,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1247 "parser.yy"
+#line 1253 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( *(yyvsp[(2) - (4)].tok), TypedefTable::TD );
@@ -6502,5 +6533,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1252 "parser.yy"
+#line 1258 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( *(yyvsp[(5) - (7)].tok), TypedefTable::TD );
@@ -6512,5 +6543,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1269 "parser.yy"
+#line 1275 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6522,5 +6553,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1274 "parser.yy"
+#line 1280 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -6532,5 +6563,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1296 "parser.yy"
+#line 1302 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -6539,5 +6570,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1308 "parser.yy"
+#line 1314 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6546,5 +6577,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1319 "parser.yy"
+#line 1325 "parser.yy"
     { (yyval.decl) = DeclarationNode::newQualifier( DeclarationNode::Const ); }
     break;
@@ -6553,5 +6584,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1321 "parser.yy"
+#line 1327 "parser.yy"
     { (yyval.decl) = DeclarationNode::newQualifier( DeclarationNode::Restrict ); }
     break;
@@ -6560,5 +6591,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1323 "parser.yy"
+#line 1329 "parser.yy"
     { (yyval.decl) = DeclarationNode::newQualifier( DeclarationNode::Volatile ); }
     break;
@@ -6567,5 +6598,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1325 "parser.yy"
+#line 1331 "parser.yy"
     { (yyval.decl) = DeclarationNode::newQualifier( DeclarationNode::Lvalue ); }
     break;
@@ -6574,5 +6605,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1327 "parser.yy"
+#line 1333 "parser.yy"
     { (yyval.decl) = DeclarationNode::newQualifier( DeclarationNode::Atomic ); }
     break;
@@ -6581,5 +6612,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1329 "parser.yy"
+#line 1335 "parser.yy"
     {
 			typedefTable.enterScope();
@@ -6590,5 +6621,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1333 "parser.yy"
+#line 1339 "parser.yy"
     {
 			typedefTable.leaveScope();
@@ -6600,5 +6631,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1342 "parser.yy"
+#line 1348 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6607,5 +6638,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1344 "parser.yy"
+#line 1350 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->addQualifiers( (yyvsp[(2) - (3)].decl) )->addQualifiers( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -6614,5 +6645,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1355 "parser.yy"
+#line 1361 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6621,5 +6652,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1360 "parser.yy"
+#line 1366 "parser.yy"
     { (yyval.decl) = DeclarationNode::newStorageClass( DeclarationNode::Extern ); }
     break;
@@ -6628,5 +6659,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1362 "parser.yy"
+#line 1368 "parser.yy"
     { (yyval.decl) = DeclarationNode::newStorageClass( DeclarationNode::Static ); }
     break;
@@ -6635,5 +6666,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1364 "parser.yy"
+#line 1370 "parser.yy"
     { (yyval.decl) = DeclarationNode::newStorageClass( DeclarationNode::Auto ); }
     break;
@@ -6642,5 +6673,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1366 "parser.yy"
+#line 1372 "parser.yy"
     { (yyval.decl) = DeclarationNode::newStorageClass( DeclarationNode::Register ); }
     break;
@@ -6649,5 +6680,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1369 "parser.yy"
+#line 1375 "parser.yy"
     { (yyval.decl) = new DeclarationNode; (yyval.decl)->isInline = true; }
     break;
@@ -6656,5 +6687,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1371 "parser.yy"
+#line 1377 "parser.yy"
     { (yyval.decl) = DeclarationNode::newStorageClass( DeclarationNode::Fortran ); }
     break;
@@ -6663,5 +6694,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1374 "parser.yy"
+#line 1380 "parser.yy"
     { (yyval.decl) = new DeclarationNode; (yyval.decl)->isNoreturn = true; }
     break;
@@ -6670,5 +6701,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1376 "parser.yy"
+#line 1382 "parser.yy"
     { (yyval.decl) = DeclarationNode::newStorageClass( DeclarationNode::Threadlocal ); }
     break;
@@ -6677,5 +6708,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1381 "parser.yy"
+#line 1387 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBasicType( DeclarationNode::Char ); }
     break;
@@ -6684,5 +6715,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1383 "parser.yy"
+#line 1389 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBasicType( DeclarationNode::Double ); }
     break;
@@ -6691,5 +6722,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1385 "parser.yy"
+#line 1391 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBasicType( DeclarationNode::Float ); }
     break;
@@ -6698,5 +6729,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1387 "parser.yy"
+#line 1393 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBasicType( DeclarationNode::Int ); }
     break;
@@ -6705,5 +6736,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1389 "parser.yy"
+#line 1395 "parser.yy"
     { (yyval.decl) = DeclarationNode::newLength( DeclarationNode::Long ); }
     break;
@@ -6712,5 +6743,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1391 "parser.yy"
+#line 1397 "parser.yy"
     { (yyval.decl) = DeclarationNode::newLength( DeclarationNode::Short ); }
     break;
@@ -6719,5 +6750,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1393 "parser.yy"
+#line 1399 "parser.yy"
     { (yyval.decl) = DeclarationNode::newSignedNess( DeclarationNode::Signed ); }
     break;
@@ -6726,5 +6757,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1395 "parser.yy"
+#line 1401 "parser.yy"
     { (yyval.decl) = DeclarationNode::newSignedNess( DeclarationNode::Unsigned ); }
     break;
@@ -6733,5 +6764,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1397 "parser.yy"
+#line 1403 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBasicType( DeclarationNode::Void ); }
     break;
@@ -6740,5 +6771,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1399 "parser.yy"
+#line 1405 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
     break;
@@ -6747,5 +6778,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1401 "parser.yy"
+#line 1407 "parser.yy"
     { (yyval.decl) = DeclarationNode::newComplexType( DeclarationNode::Complex ); }
     break;
@@ -6754,5 +6785,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1403 "parser.yy"
+#line 1409 "parser.yy"
     { (yyval.decl) = DeclarationNode::newComplexType( DeclarationNode::Imaginary ); }
     break;
@@ -6761,5 +6792,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1405 "parser.yy"
+#line 1411 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBuiltinType( DeclarationNode::Valist ); }
     break;
@@ -6768,5 +6799,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1407 "parser.yy"
+#line 1413 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBasicType( DeclarationNode::Char ); }
     break;
@@ -6775,5 +6806,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1409 "parser.yy"
+#line 1415 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBasicType( DeclarationNode::Char ); }
     break;
@@ -6782,5 +6813,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1416 "parser.yy"
+#line 1422 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -6789,5 +6820,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1418 "parser.yy"
+#line 1424 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6796,5 +6827,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1420 "parser.yy"
+#line 1426 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->addQualifiers( (yyvsp[(2) - (3)].decl) )->addQualifiers( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -6803,5 +6834,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1422 "parser.yy"
+#line 1428 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addQualifiers( (yyvsp[(2) - (3)].decl) )->addType( (yyvsp[(1) - (3)].decl) ); }
     break;
@@ -6810,5 +6841,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1428 "parser.yy"
+#line 1434 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl)->addQualifiers( (yyvsp[(1) - (3)].decl) )->addQualifiers( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -6817,5 +6848,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1435 "parser.yy"
+#line 1441 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -6824,5 +6855,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1437 "parser.yy"
+#line 1443 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6831,5 +6862,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1439 "parser.yy"
+#line 1445 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addType( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6838,5 +6869,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1444 "parser.yy"
+#line 1450 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (4)].decl); }
     break;
@@ -6845,5 +6876,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1446 "parser.yy"
+#line 1452 "parser.yy"
     { (yyval.decl) = DeclarationNode::newTypeof( (yyvsp[(3) - (4)].en) ); }
     break;
@@ -6852,5 +6883,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1448 "parser.yy"
+#line 1454 "parser.yy"
     { (yyval.decl) = DeclarationNode::newAttr( (yyvsp[(1) - (4)].tok), (yyvsp[(3) - (4)].decl) ); }
     break;
@@ -6859,5 +6890,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1450 "parser.yy"
+#line 1456 "parser.yy"
     { (yyval.decl) = DeclarationNode::newAttr( (yyvsp[(1) - (4)].tok), (yyvsp[(3) - (4)].en) ); }
     break;
@@ -6866,5 +6897,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1456 "parser.yy"
+#line 1462 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -6873,5 +6904,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1458 "parser.yy"
+#line 1464 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6880,5 +6911,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1460 "parser.yy"
+#line 1466 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->addQualifiers( (yyvsp[(2) - (3)].decl) )->addQualifiers( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -6887,5 +6918,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1466 "parser.yy"
+#line 1472 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -6894,5 +6925,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1468 "parser.yy"
+#line 1474 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6901,5 +6932,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1474 "parser.yy"
+#line 1480 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -6908,5 +6939,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1476 "parser.yy"
+#line 1482 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6915,5 +6946,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1478 "parser.yy"
+#line 1484 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->addQualifiers( (yyvsp[(2) - (3)].decl) )->addQualifiers( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -6922,5 +6953,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1483 "parser.yy"
+#line 1489 "parser.yy"
     { (yyval.decl) = DeclarationNode::newFromTypedef( (yyvsp[(1) - (1)].tok) ); }
     break;
@@ -6929,5 +6960,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1485 "parser.yy"
+#line 1491 "parser.yy"
     { (yyval.decl) = DeclarationNode::newFromTypedef( (yyvsp[(2) - (2)].tok) )->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -6936,5 +6967,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1487 "parser.yy"
+#line 1493 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -6943,5 +6974,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1497 "parser.yy"
+#line 1503 "parser.yy"
     { (yyval.decl) = DeclarationNode::newAggregate( (yyvsp[(1) - (4)].aggKey), nullptr, nullptr, (yyvsp[(3) - (4)].decl), true ); }
     break;
@@ -6950,5 +6981,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1499 "parser.yy"
+#line 1505 "parser.yy"
     {
 			typedefTable.makeTypedef( *(yyvsp[(2) - (2)].tok) );
@@ -6960,5 +6991,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1504 "parser.yy"
+#line 1510 "parser.yy"
     { typedefTable.makeTypedef( *(yyvsp[(2) - (2)].tok) ); }
     break;
@@ -6967,5 +6998,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1506 "parser.yy"
+#line 1512 "parser.yy"
     { (yyval.decl) = DeclarationNode::newAggregate( (yyvsp[(1) - (6)].aggKey), (yyvsp[(2) - (6)].tok), nullptr, (yyvsp[(5) - (6)].decl), true ); }
     break;
@@ -6974,5 +7005,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1508 "parser.yy"
+#line 1514 "parser.yy"
     { (yyval.decl) = DeclarationNode::newAggregate( (yyvsp[(1) - (7)].aggKey), nullptr, (yyvsp[(3) - (7)].en), (yyvsp[(6) - (7)].decl), false ); }
     break;
@@ -6981,5 +7012,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1510 "parser.yy"
+#line 1516 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl); }
     break;
@@ -6988,5 +7019,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1515 "parser.yy"
+#line 1521 "parser.yy"
     { (yyval.aggKey) = DeclarationNode::Struct; }
     break;
@@ -6995,5 +7026,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1517 "parser.yy"
+#line 1523 "parser.yy"
     { (yyval.aggKey) = DeclarationNode::Union; }
     break;
@@ -7002,5 +7033,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1522 "parser.yy"
+#line 1528 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -7009,5 +7040,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1524 "parser.yy"
+#line 1530 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl) != 0 ? (yyvsp[(1) - (2)].decl)->appendList( (yyvsp[(2) - (2)].decl) ) : (yyvsp[(2) - (2)].decl); }
     break;
@@ -7016,5 +7047,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1530 "parser.yy"
+#line 1536 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl)->set_extension( true ); }
     break;
@@ -7023,5 +7054,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1533 "parser.yy"
+#line 1539 "parser.yy"
     {	// mark all fields in list
 			for ( DeclarationNode *iter = (yyvsp[(2) - (3)].decl); iter != nullptr; iter = (DeclarationNode *)iter->get_next() )
@@ -7034,5 +7065,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1543 "parser.yy"
+#line 1549 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addName( (yyvsp[(2) - (2)].tok) ); }
     break;
@@ -7041,5 +7072,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1545 "parser.yy"
+#line 1551 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->appendList( (yyvsp[(1) - (3)].decl)->cloneType( (yyvsp[(3) - (3)].tok) ) ); }
     break;
@@ -7048,5 +7079,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1547 "parser.yy"
+#line 1553 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->appendList( (yyvsp[(1) - (2)].decl)->cloneType( 0 ) ); }
     break;
@@ -7055,5 +7086,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1552 "parser.yy"
+#line 1558 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addType( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -7062,5 +7093,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1554 "parser.yy"
+#line 1560 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (4)].decl)->appendList( (yyvsp[(1) - (4)].decl)->cloneBaseType( (yyvsp[(4) - (4)].decl) ) ); }
     break;
@@ -7069,5 +7100,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1559 "parser.yy"
+#line 1565 "parser.yy"
     { (yyval.decl) = DeclarationNode::newName( 0 ); /* XXX */ }
     break;
@@ -7076,5 +7107,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1561 "parser.yy"
+#line 1567 "parser.yy"
     { (yyval.decl) = DeclarationNode::newBitfield( (yyvsp[(1) - (1)].en) ); }
     break;
@@ -7083,5 +7114,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1564 "parser.yy"
+#line 1570 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addBitfield( (yyvsp[(2) - (2)].en) ); }
     break;
@@ -7090,5 +7121,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1567 "parser.yy"
+#line 1573 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addBitfield( (yyvsp[(2) - (2)].en) ); }
     break;
@@ -7097,5 +7128,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1573 "parser.yy"
+#line 1579 "parser.yy"
     { (yyval.en) = 0; }
     break;
@@ -7104,5 +7135,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1575 "parser.yy"
+#line 1581 "parser.yy"
     { (yyval.en) = (yyvsp[(1) - (1)].en); }
     break;
@@ -7111,5 +7142,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1580 "parser.yy"
+#line 1586 "parser.yy"
     { (yyval.en) = (yyvsp[(2) - (2)].en); }
     break;
@@ -7118,5 +7149,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1589 "parser.yy"
+#line 1595 "parser.yy"
     { (yyval.decl) = DeclarationNode::newEnum( nullptr, (yyvsp[(3) - (5)].decl) ); }
     break;
@@ -7125,5 +7156,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1591 "parser.yy"
+#line 1597 "parser.yy"
     {
 			typedefTable.makeTypedef( *(yyvsp[(2) - (2)].tok) );
@@ -7135,5 +7166,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1596 "parser.yy"
+#line 1602 "parser.yy"
     { typedefTable.makeTypedef( *(yyvsp[(2) - (2)].tok) ); }
     break;
@@ -7142,5 +7173,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1598 "parser.yy"
+#line 1604 "parser.yy"
     { (yyval.decl) = DeclarationNode::newEnum( (yyvsp[(2) - (7)].tok), (yyvsp[(5) - (7)].decl) ); }
     break;
@@ -7149,5 +7180,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1603 "parser.yy"
+#line 1609 "parser.yy"
     { (yyval.decl) = DeclarationNode::newEnumConstant( (yyvsp[(1) - (2)].tok), (yyvsp[(2) - (2)].en) ); }
     break;
@@ -7156,5 +7187,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1605 "parser.yy"
+#line 1611 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (4)].decl)->appendList( DeclarationNode::newEnumConstant( (yyvsp[(3) - (4)].tok), (yyvsp[(4) - (4)].en) ) ); }
     break;
@@ -7163,5 +7194,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1610 "parser.yy"
+#line 1616 "parser.yy"
     { (yyval.en) = 0; }
     break;
@@ -7170,5 +7201,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1612 "parser.yy"
+#line 1618 "parser.yy"
     { (yyval.en) = (yyvsp[(2) - (2)].en); }
     break;
@@ -7177,5 +7208,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1619 "parser.yy"
+#line 1625 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -7184,5 +7215,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1627 "parser.yy"
+#line 1633 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->appendList( (yyvsp[(5) - (5)].decl) ); }
     break;
@@ -7191,5 +7222,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1629 "parser.yy"
+#line 1635 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->addVarArgs(); }
     break;
@@ -7198,5 +7229,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1631 "parser.yy"
+#line 1637 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->addVarArgs(); }
     break;
@@ -7205,5 +7236,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1639 "parser.yy"
+#line 1645 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->appendList( (yyvsp[(5) - (5)].decl) ); }
     break;
@@ -7212,5 +7243,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1641 "parser.yy"
+#line 1647 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->appendList( (yyvsp[(5) - (5)].decl) ); }
     break;
@@ -7219,5 +7250,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1643 "parser.yy"
+#line 1649 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (9)].decl)->appendList( (yyvsp[(5) - (9)].decl) )->appendList( (yyvsp[(9) - (9)].decl) ); }
     break;
@@ -7226,5 +7257,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1649 "parser.yy"
+#line 1655 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->appendList( (yyvsp[(5) - (5)].decl) ); }
     break;
@@ -7233,5 +7264,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1654 "parser.yy"
+#line 1660 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -7240,5 +7271,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1661 "parser.yy"
+#line 1667 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->addVarArgs(); }
     break;
@@ -7247,5 +7278,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1668 "parser.yy"
+#line 1674 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->appendList( (yyvsp[(5) - (5)].decl) ); }
     break;
@@ -7254,5 +7285,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1670 "parser.yy"
+#line 1676 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (5)].decl)->appendList( (yyvsp[(5) - (5)].decl) ); }
     break;
@@ -7261,5 +7292,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1679 "parser.yy"
+#line 1685 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->addName( (yyvsp[(2) - (3)].tok) ); }
     break;
@@ -7268,5 +7299,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1682 "parser.yy"
+#line 1688 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->addName( (yyvsp[(2) - (3)].tok) ); }
     break;
@@ -7275,5 +7306,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1684 "parser.yy"
+#line 1690 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addName( (yyvsp[(3) - (4)].tok) )->addQualifiers( (yyvsp[(1) - (4)].decl) ); }
     break;
@@ -7282,5 +7313,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1694 "parser.yy"
+#line 1700 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -7289,5 +7320,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1700 "parser.yy"
+#line 1706 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7299,5 +7330,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1705 "parser.yy"
+#line 1711 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7309,5 +7340,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1714 "parser.yy"
+#line 1720 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addType( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -7316,5 +7347,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1723 "parser.yy"
+#line 1729 "parser.yy"
     { (yyval.decl) = DeclarationNode::newName( (yyvsp[(1) - (1)].tok) ); }
     break;
@@ -7323,5 +7354,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1725 "parser.yy"
+#line 1731 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->appendList( DeclarationNode::newName( (yyvsp[(3) - (3)].tok) ) ); }
     break;
@@ -7330,5 +7361,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1750 "parser.yy"
+#line 1756 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addType( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -7337,5 +7368,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1758 "parser.yy"
+#line 1764 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addType( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -7344,5 +7375,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1763 "parser.yy"
+#line 1769 "parser.yy"
     { (yyval.in) = 0; }
     break;
@@ -7351,5 +7382,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1765 "parser.yy"
+#line 1771 "parser.yy"
     { (yyval.in) = (yyvsp[(2) - (2)].in); }
     break;
@@ -7358,5 +7389,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1767 "parser.yy"
+#line 1773 "parser.yy"
     { (yyval.in) = (yyvsp[(2) - (2)].in)->set_maybeConstructed( false ); }
     break;
@@ -7365,5 +7396,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1771 "parser.yy"
+#line 1777 "parser.yy"
     { (yyval.in) = new InitializerNode( (yyvsp[(1) - (1)].en) ); }
     break;
@@ -7372,5 +7403,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1772 "parser.yy"
+#line 1778 "parser.yy"
     { (yyval.in) = new InitializerNode( (yyvsp[(2) - (4)].in), true ); }
     break;
@@ -7379,5 +7410,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1777 "parser.yy"
+#line 1783 "parser.yy"
     { (yyval.in) = 0; }
     break;
@@ -7386,5 +7417,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1779 "parser.yy"
+#line 1785 "parser.yy"
     { (yyval.in) = (yyvsp[(2) - (2)].in)->set_designators( (yyvsp[(1) - (2)].en) ); }
     break;
@@ -7393,5 +7424,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1780 "parser.yy"
+#line 1786 "parser.yy"
     { (yyval.in) = (InitializerNode *)( (yyvsp[(1) - (3)].in)->set_last( (yyvsp[(3) - (3)].in) ) ); }
     break;
@@ -7400,5 +7431,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1782 "parser.yy"
+#line 1788 "parser.yy"
     { (yyval.in) = (InitializerNode *)( (yyvsp[(1) - (4)].in)->set_last( (yyvsp[(4) - (4)].in)->set_designators( (yyvsp[(3) - (4)].en) ) ) ); }
     break;
@@ -7407,5 +7438,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1798 "parser.yy"
+#line 1804 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_varref( (yyvsp[(1) - (2)].tok) ) ); }
     break;
@@ -7414,5 +7445,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1804 "parser.yy"
+#line 1810 "parser.yy"
     { (yyval.en) = (ExpressionNode *)( (yyvsp[(1) - (2)].en)->set_last( (yyvsp[(2) - (2)].en) ) ); }
     break;
@@ -7421,5 +7452,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1810 "parser.yy"
+#line 1816 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_varref( (yyvsp[(2) - (2)].tok) ) ); }
     break;
@@ -7428,5 +7459,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1813 "parser.yy"
+#line 1819 "parser.yy"
     { (yyval.en) = (yyvsp[(3) - (5)].en); }
     break;
@@ -7435,5 +7466,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1815 "parser.yy"
+#line 1821 "parser.yy"
     { (yyval.en) = (yyvsp[(3) - (5)].en); }
     break;
@@ -7442,5 +7473,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1817 "parser.yy"
+#line 1823 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_range( (yyvsp[(3) - (7)].en), (yyvsp[(5) - (7)].en) ) ); }
     break;
@@ -7449,5 +7480,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1819 "parser.yy"
+#line 1825 "parser.yy"
     { (yyval.en) = (yyvsp[(4) - (6)].en); }
     break;
@@ -7456,5 +7487,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1843 "parser.yy"
+#line 1849 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -7463,5 +7494,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1845 "parser.yy"
+#line 1851 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -7470,5 +7501,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1847 "parser.yy"
+#line 1853 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->addQualifiers( (yyvsp[(2) - (3)].decl) )->addQualifiers( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -7477,5 +7508,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1853 "parser.yy"
+#line 1859 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -7484,5 +7515,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1855 "parser.yy"
+#line 1861 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -7491,5 +7522,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1860 "parser.yy"
+#line 1866 "parser.yy"
     { (yyval.decl) = DeclarationNode::newFromTypeGen( (yyvsp[(1) - (4)].tok), (yyvsp[(3) - (4)].en) ); }
     break;
@@ -7498,5 +7529,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1866 "parser.yy"
+#line 1872 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (4)].decl)->appendList( (yyvsp[(3) - (4)].decl) ); }
     break;
@@ -7505,5 +7536,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1871 "parser.yy"
+#line 1877 "parser.yy"
     { typedefTable.addToEnclosingScope( *(yyvsp[(2) - (2)].tok), TypedefTable::TD ); }
     break;
@@ -7512,5 +7543,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1873 "parser.yy"
+#line 1879 "parser.yy"
     { (yyval.decl) = DeclarationNode::newTypeParam( (yyvsp[(1) - (4)].tclass), (yyvsp[(2) - (4)].tok) )->addAssertions( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -7519,5 +7550,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1879 "parser.yy"
+#line 1885 "parser.yy"
     { (yyval.tclass) = DeclarationNode::Otype; }
     break;
@@ -7526,5 +7557,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1881 "parser.yy"
+#line 1887 "parser.yy"
     { (yyval.tclass) = DeclarationNode::Ftype; }
     break;
@@ -7533,5 +7564,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1883 "parser.yy"
+#line 1889 "parser.yy"
     { (yyval.tclass) = DeclarationNode::Dtype; }
     break;
@@ -7540,5 +7571,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1888 "parser.yy"
+#line 1894 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -7547,5 +7578,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1890 "parser.yy"
+#line 1896 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl) != 0 ? (yyvsp[(1) - (2)].decl)->appendList( (yyvsp[(2) - (2)].decl) ) : (yyvsp[(2) - (2)].decl); }
     break;
@@ -7554,5 +7585,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1895 "parser.yy"
+#line 1901 "parser.yy"
     {
 			typedefTable.openTrait( *(yyvsp[(2) - (5)].tok) );
@@ -7564,5 +7595,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1900 "parser.yy"
+#line 1906 "parser.yy"
     { (yyval.decl) = (yyvsp[(4) - (5)].decl); }
     break;
@@ -7571,5 +7602,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1902 "parser.yy"
+#line 1908 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -7578,5 +7609,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1907 "parser.yy"
+#line 1913 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_typevalue( (yyvsp[(1) - (1)].decl) ) ); }
     break;
@@ -7585,5 +7616,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1910 "parser.yy"
+#line 1916 "parser.yy"
     { (yyval.en) = (ExpressionNode *)( (yyvsp[(1) - (3)].en)->set_last( new ExpressionNode( build_typevalue( (yyvsp[(3) - (3)].decl) ) ) ) ); }
     break;
@@ -7592,5 +7623,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1912 "parser.yy"
+#line 1918 "parser.yy"
     { (yyval.en) = (ExpressionNode *)( (yyvsp[(1) - (3)].en)->set_last( (yyvsp[(3) - (3)].en) )); }
     break;
@@ -7599,5 +7630,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1917 "parser.yy"
+#line 1923 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl); }
     break;
@@ -7606,5 +7637,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1919 "parser.yy"
+#line 1925 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addQualifiers( (yyvsp[(1) - (3)].decl) ); }
     break;
@@ -7613,5 +7644,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1921 "parser.yy"
+#line 1927 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->appendList( (yyvsp[(3) - (3)].decl)->copyStorageClasses( (yyvsp[(1) - (3)].decl) ) ); }
     break;
@@ -7620,5 +7651,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1926 "parser.yy"
+#line 1932 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addAssertions( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -7627,5 +7658,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1928 "parser.yy"
+#line 1934 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (4)].decl)->addAssertions( (yyvsp[(2) - (4)].decl) )->addType( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -7634,5 +7665,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1933 "parser.yy"
+#line 1939 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( *(yyvsp[(1) - (1)].tok), TypedefTable::TD );
@@ -7644,5 +7675,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1938 "parser.yy"
+#line 1944 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( *(yyvsp[(1) - (6)].tok), TypedefTable::TG );
@@ -7654,5 +7685,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1946 "parser.yy"
+#line 1952 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( *(yyvsp[(2) - (9)].tok), TypedefTable::ID );
@@ -7664,5 +7695,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1951 "parser.yy"
+#line 1957 "parser.yy"
     {
 			typedefTable.enterTrait( *(yyvsp[(2) - (8)].tok) );
@@ -7674,5 +7705,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1956 "parser.yy"
+#line 1962 "parser.yy"
     {
 			typedefTable.leaveTrait();
@@ -7685,5 +7716,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1966 "parser.yy"
+#line 1972 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl)->appendList( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -7692,5 +7723,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1976 "parser.yy"
+#line 1982 "parser.yy"
     {
 			typedefTable.addToEnclosingScope2( TypedefTable::ID );
@@ -7702,5 +7733,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1981 "parser.yy"
+#line 1987 "parser.yy"
     {
 			typedefTable.addToEnclosingScope2( TypedefTable::ID );
@@ -7712,5 +7743,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1986 "parser.yy"
+#line 1992 "parser.yy"
     {
 			typedefTable.addToEnclosingScope2( *(yyvsp[(5) - (5)].tok), TypedefTable::ID );
@@ -7722,5 +7753,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1994 "parser.yy"
+#line 2000 "parser.yy"
     {
 			typedefTable.addToEnclosingScope2( TypedefTable::ID );
@@ -7732,5 +7763,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 1999 "parser.yy"
+#line 2005 "parser.yy"
     {
 			typedefTable.addToEnclosingScope2( TypedefTable::ID );
@@ -7742,5 +7773,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2009 "parser.yy"
+#line 2015 "parser.yy"
     {}
     break;
@@ -7749,5 +7780,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2011 "parser.yy"
+#line 2017 "parser.yy"
     { parseTree = parseTree != nullptr ? parseTree->appendList( (yyvsp[(1) - (1)].decl) ) : (yyvsp[(1) - (1)].decl);	}
     break;
@@ -7756,5 +7787,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2017 "parser.yy"
+#line 2023 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (3)].decl) != nullptr ? (yyvsp[(1) - (3)].decl)->appendList( (yyvsp[(3) - (3)].decl) ) : (yyvsp[(3) - (3)].decl); }
     break;
@@ -7763,5 +7794,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2022 "parser.yy"
+#line 2028 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -7770,5 +7801,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2030 "parser.yy"
+#line 2036 "parser.yy"
     {}
     break;
@@ -7777,5 +7808,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2032 "parser.yy"
+#line 2038 "parser.yy"
     {
 			linkageStack.push( linkage );				// handle nested extern "C"/"Cforall"
@@ -7787,5 +7818,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2037 "parser.yy"
+#line 2043 "parser.yy"
     {
 			linkage = linkageStack.top();
@@ -7798,5 +7829,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2043 "parser.yy"
+#line 2049 "parser.yy"
     {	// mark all fields in list
 			for ( DeclarationNode *iter = (yyvsp[(2) - (2)].decl); iter != nullptr; iter = (DeclarationNode *)iter->get_next() )
@@ -7809,5 +7840,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2058 "parser.yy"
+#line 2064 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7820,5 +7851,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2064 "parser.yy"
+#line 2070 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7831,5 +7862,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2073 "parser.yy"
+#line 2079 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7842,5 +7873,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2079 "parser.yy"
+#line 2085 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7851,15 +7882,4 @@
 
   case 540:
-
-/* Line 1806 of yacc.c  */
-#line 2085 "parser.yy"
-    {
-			typedefTable.addToEnclosingScope( TypedefTable::ID );
-			typedefTable.leaveScope();
-			(yyval.decl) = (yyvsp[(2) - (3)].decl)->addFunctionBody( (yyvsp[(3) - (3)].sn) )->addQualifiers( (yyvsp[(1) - (3)].decl) );
-		}
-    break;
-
-  case 541:
 
 /* Line 1806 of yacc.c  */
@@ -7872,8 +7892,19 @@
     break;
 
+  case 541:
+
+/* Line 1806 of yacc.c  */
+#line 2097 "parser.yy"
+    {
+			typedefTable.addToEnclosingScope( TypedefTable::ID );
+			typedefTable.leaveScope();
+			(yyval.decl) = (yyvsp[(2) - (3)].decl)->addFunctionBody( (yyvsp[(3) - (3)].sn) )->addQualifiers( (yyvsp[(1) - (3)].decl) );
+		}
+    break;
+
   case 542:
 
 /* Line 1806 of yacc.c  */
-#line 2097 "parser.yy"
+#line 2103 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7886,5 +7917,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2105 "parser.yy"
+#line 2111 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7897,5 +7928,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2111 "parser.yy"
+#line 2117 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7908,5 +7939,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2119 "parser.yy"
+#line 2125 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7919,5 +7950,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2125 "parser.yy"
+#line 2131 "parser.yy"
     {
 			typedefTable.addToEnclosingScope( TypedefTable::ID );
@@ -7930,5 +7961,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2140 "parser.yy"
+#line 2146 "parser.yy"
     { (yyval.en) = new ExpressionNode( build_range( (yyvsp[(1) - (3)].en), (yyvsp[(3) - (3)].en) ) ); }
     break;
@@ -7937,5 +7968,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2145 "parser.yy"
+#line 2151 "parser.yy"
     { delete (yyvsp[(3) - (5)].str); }
     break;
@@ -7944,5 +7975,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2150 "parser.yy"
+#line 2156 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -7951,5 +7982,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2157 "parser.yy"
+#line 2163 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -7958,5 +7989,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2163 "parser.yy"
+#line 2169 "parser.yy"
     { (yyval.decl) = 0; }
     break;
@@ -7965,5 +7996,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2174 "parser.yy"
+#line 2180 "parser.yy"
     { delete (yyvsp[(3) - (4)].en); }
     break;
@@ -7972,5 +8003,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2178 "parser.yy"
+#line 2184 "parser.yy"
     { delete (yyvsp[(1) - (1)].tok); }
     break;
@@ -7979,5 +8010,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2179 "parser.yy"
+#line 2185 "parser.yy"
     { delete (yyvsp[(1) - (1)].decl); }
     break;
@@ -7986,5 +8017,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2180 "parser.yy"
+#line 2186 "parser.yy"
     { delete (yyvsp[(1) - (1)].decl); }
     break;
@@ -7993,5 +8024,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2181 "parser.yy"
+#line 2187 "parser.yy"
     { delete (yyvsp[(1) - (1)].decl); }
     break;
@@ -8000,5 +8031,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2216 "parser.yy"
+#line 2222 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8007,5 +8038,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2219 "parser.yy"
+#line 2225 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8014,5 +8045,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2221 "parser.yy"
+#line 2227 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8021,5 +8052,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2226 "parser.yy"
+#line 2232 "parser.yy"
     {
 			typedefTable.setNextIdentifier( *(yyvsp[(1) - (1)].tok) );
@@ -8031,5 +8062,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2231 "parser.yy"
+#line 2237 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8038,5 +8069,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2236 "parser.yy"
+#line 2242 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8045,5 +8076,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2238 "parser.yy"
+#line 2244 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8052,5 +8083,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2240 "parser.yy"
+#line 2246 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8059,5 +8090,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2245 "parser.yy"
+#line 2251 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addArray( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8066,5 +8097,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2247 "parser.yy"
+#line 2253 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8073,5 +8104,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2249 "parser.yy"
+#line 2255 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8080,5 +8111,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2251 "parser.yy"
+#line 2257 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8087,5 +8118,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2256 "parser.yy"
+#line 2262 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (8)].decl)->addParamList( (yyvsp[(6) - (8)].decl) ); }
     break;
@@ -8094,5 +8125,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2258 "parser.yy"
+#line 2264 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8101,5 +8132,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2267 "parser.yy"
+#line 2273 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8108,5 +8139,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2270 "parser.yy"
+#line 2276 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8115,5 +8146,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2275 "parser.yy"
+#line 2281 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (6)].decl)->addParamList( (yyvsp[(4) - (6)].decl) ); }
     break;
@@ -8122,5 +8153,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2277 "parser.yy"
+#line 2283 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (8)].decl)->addParamList( (yyvsp[(6) - (8)].decl) ); }
     break;
@@ -8129,5 +8160,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2279 "parser.yy"
+#line 2285 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8136,5 +8167,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2284 "parser.yy"
+#line 2290 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8143,5 +8174,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2286 "parser.yy"
+#line 2292 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8150,5 +8181,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2288 "parser.yy"
+#line 2294 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8157,5 +8188,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2293 "parser.yy"
+#line 2299 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8164,5 +8195,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2295 "parser.yy"
+#line 2301 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8171,5 +8202,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2297 "parser.yy"
+#line 2303 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8178,5 +8209,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2312 "parser.yy"
+#line 2318 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (4)].decl)->addIdList( (yyvsp[(3) - (4)].decl) ); }
     break;
@@ -8185,5 +8216,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2314 "parser.yy"
+#line 2320 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (6)].decl)->addIdList( (yyvsp[(5) - (6)].decl) ); }
     break;
@@ -8192,5 +8223,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2316 "parser.yy"
+#line 2322 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8199,5 +8230,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2321 "parser.yy"
+#line 2327 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8206,5 +8237,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2323 "parser.yy"
+#line 2329 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8213,5 +8244,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2325 "parser.yy"
+#line 2331 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8220,5 +8251,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2330 "parser.yy"
+#line 2336 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8227,5 +8258,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2332 "parser.yy"
+#line 2338 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8234,5 +8265,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2334 "parser.yy"
+#line 2340 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8241,5 +8272,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2349 "parser.yy"
+#line 2355 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8248,5 +8279,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2352 "parser.yy"
+#line 2358 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8255,5 +8286,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2354 "parser.yy"
+#line 2360 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8262,5 +8293,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2360 "parser.yy"
+#line 2366 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8269,5 +8300,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2365 "parser.yy"
+#line 2371 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8276,5 +8307,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2367 "parser.yy"
+#line 2373 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8283,5 +8314,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2369 "parser.yy"
+#line 2375 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8290,5 +8321,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2374 "parser.yy"
+#line 2380 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addArray( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8297,5 +8328,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2376 "parser.yy"
+#line 2382 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8304,5 +8335,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2378 "parser.yy"
+#line 2384 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8311,5 +8342,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2380 "parser.yy"
+#line 2386 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8318,5 +8349,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2385 "parser.yy"
+#line 2391 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (6)].decl)->addParamList( (yyvsp[(4) - (6)].decl) ); }
     break;
@@ -8325,5 +8356,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2387 "parser.yy"
+#line 2393 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (8)].decl)->addParamList( (yyvsp[(6) - (8)].decl) ); }
     break;
@@ -8332,5 +8363,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2389 "parser.yy"
+#line 2395 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8339,5 +8370,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2399 "parser.yy"
+#line 2405 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8346,5 +8377,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2402 "parser.yy"
+#line 2408 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8353,5 +8384,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2404 "parser.yy"
+#line 2410 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8360,5 +8391,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2409 "parser.yy"
+#line 2415 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8367,5 +8398,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2411 "parser.yy"
+#line 2417 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8374,5 +8405,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2413 "parser.yy"
+#line 2419 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8381,5 +8412,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2418 "parser.yy"
+#line 2424 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addArray( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8388,5 +8419,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2420 "parser.yy"
+#line 2426 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8395,5 +8426,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2422 "parser.yy"
+#line 2428 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8402,5 +8433,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2424 "parser.yy"
+#line 2430 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8409,5 +8440,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2429 "parser.yy"
+#line 2435 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (6)].decl)->addParamList( (yyvsp[(4) - (6)].decl) ); }
     break;
@@ -8416,5 +8447,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2431 "parser.yy"
+#line 2437 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (8)].decl)->addParamList( (yyvsp[(6) - (8)].decl) ); }
     break;
@@ -8423,5 +8454,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2433 "parser.yy"
+#line 2439 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8430,5 +8461,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2464 "parser.yy"
+#line 2470 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8437,5 +8468,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2467 "parser.yy"
+#line 2473 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8444,5 +8475,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2469 "parser.yy"
+#line 2475 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8451,5 +8482,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2474 "parser.yy"
+#line 2480 "parser.yy"
     {
 			typedefTable.setNextIdentifier( *(yyvsp[(1) - (1)].tok) );
@@ -8461,5 +8492,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2479 "parser.yy"
+#line 2485 "parser.yy"
     {
 			typedefTable.setNextIdentifier( *(yyvsp[(1) - (1)].tok) );
@@ -8471,5 +8502,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2487 "parser.yy"
+#line 2493 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8478,5 +8509,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2489 "parser.yy"
+#line 2495 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8485,5 +8516,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2491 "parser.yy"
+#line 2497 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8492,5 +8523,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2496 "parser.yy"
+#line 2502 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addArray( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8499,5 +8530,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2498 "parser.yy"
+#line 2504 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8506,5 +8537,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2503 "parser.yy"
+#line 2509 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (6)].decl)->addParamList( (yyvsp[(4) - (6)].decl) ); }
     break;
@@ -8513,5 +8544,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2505 "parser.yy"
+#line 2511 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (8)].decl)->addParamList( (yyvsp[(6) - (8)].decl) ); }
     break;
@@ -8520,5 +8551,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2520 "parser.yy"
+#line 2526 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8527,5 +8558,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2522 "parser.yy"
+#line 2528 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8534,5 +8565,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2527 "parser.yy"
+#line 2533 "parser.yy"
     { (yyval.decl) = DeclarationNode::newPointer( 0 ); }
     break;
@@ -8541,5 +8572,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2529 "parser.yy"
+#line 2535 "parser.yy"
     { (yyval.decl) = DeclarationNode::newPointer( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8548,5 +8579,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2531 "parser.yy"
+#line 2537 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8555,5 +8586,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2533 "parser.yy"
+#line 2539 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8562,5 +8593,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2535 "parser.yy"
+#line 2541 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8569,5 +8600,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2541 "parser.yy"
+#line 2547 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8576,5 +8607,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2543 "parser.yy"
+#line 2549 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8583,5 +8614,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2545 "parser.yy"
+#line 2551 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8590,5 +8621,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2550 "parser.yy"
+#line 2556 "parser.yy"
     { (yyval.decl) = DeclarationNode::newFunction( nullptr, nullptr, (yyvsp[(3) - (5)].decl), nullptr ); }
     break;
@@ -8597,5 +8628,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2552 "parser.yy"
+#line 2558 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (8)].decl)->addParamList( (yyvsp[(6) - (8)].decl) ); }
     break;
@@ -8604,5 +8635,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2554 "parser.yy"
+#line 2560 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8611,5 +8642,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2560 "parser.yy"
+#line 2566 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( 0, 0, false ); }
     break;
@@ -8618,5 +8649,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2562 "parser.yy"
+#line 2568 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( 0, 0, false )->addArray( (yyvsp[(3) - (3)].decl) ); }
     break;
@@ -8625,5 +8656,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2568 "parser.yy"
+#line 2574 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( (yyvsp[(3) - (5)].en), 0, false ); }
     break;
@@ -8632,5 +8663,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2570 "parser.yy"
+#line 2576 "parser.yy"
     { (yyval.decl) = DeclarationNode::newVarArray( 0 ); }
     break;
@@ -8639,5 +8670,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2572 "parser.yy"
+#line 2578 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (6)].decl)->addArray( DeclarationNode::newArray( (yyvsp[(4) - (6)].en), 0, false ) ); }
     break;
@@ -8646,5 +8677,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2574 "parser.yy"
+#line 2580 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (6)].decl)->addArray( DeclarationNode::newVarArray( 0 ) ); }
     break;
@@ -8653,5 +8684,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2589 "parser.yy"
+#line 2595 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8660,5 +8691,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2591 "parser.yy"
+#line 2597 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8667,5 +8698,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2596 "parser.yy"
+#line 2602 "parser.yy"
     { (yyval.decl) = DeclarationNode::newPointer( 0 ); }
     break;
@@ -8674,5 +8705,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2598 "parser.yy"
+#line 2604 "parser.yy"
     { (yyval.decl) = DeclarationNode::newPointer( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8681,5 +8712,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2600 "parser.yy"
+#line 2606 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8688,5 +8719,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2602 "parser.yy"
+#line 2608 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8695,5 +8726,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2604 "parser.yy"
+#line 2610 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8702,5 +8733,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2610 "parser.yy"
+#line 2616 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8709,5 +8740,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2612 "parser.yy"
+#line 2618 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8716,5 +8747,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2614 "parser.yy"
+#line 2620 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8723,5 +8754,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2619 "parser.yy"
+#line 2625 "parser.yy"
     { (yyval.decl) = DeclarationNode::newFunction( nullptr, nullptr, (yyvsp[(3) - (5)].decl), nullptr ); }
     break;
@@ -8730,5 +8761,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2621 "parser.yy"
+#line 2627 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (8)].decl)->addParamList( (yyvsp[(6) - (8)].decl) ); }
     break;
@@ -8737,5 +8768,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2623 "parser.yy"
+#line 2629 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8744,5 +8775,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2630 "parser.yy"
+#line 2636 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addArray( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8751,5 +8782,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2641 "parser.yy"
+#line 2647 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( 0, 0, false ); }
     break;
@@ -8758,5 +8789,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2644 "parser.yy"
+#line 2650 "parser.yy"
     { (yyval.decl) = DeclarationNode::newVarArray( (yyvsp[(3) - (6)].decl) ); }
     break;
@@ -8765,5 +8796,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2646 "parser.yy"
+#line 2652 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( 0, (yyvsp[(3) - (5)].decl), false ); }
     break;
@@ -8772,5 +8803,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2649 "parser.yy"
+#line 2655 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( (yyvsp[(4) - (6)].en), (yyvsp[(3) - (6)].decl), false ); }
     break;
@@ -8779,5 +8810,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2651 "parser.yy"
+#line 2657 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( (yyvsp[(5) - (7)].en), (yyvsp[(4) - (7)].decl), true ); }
     break;
@@ -8786,5 +8817,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2653 "parser.yy"
+#line 2659 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( (yyvsp[(5) - (7)].en), (yyvsp[(3) - (7)].decl), true ); }
     break;
@@ -8793,5 +8824,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2667 "parser.yy"
+#line 2673 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8800,5 +8831,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2669 "parser.yy"
+#line 2675 "parser.yy"
     { (yyval.decl) = (yyvsp[(1) - (2)].decl)->addQualifiers( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8807,5 +8838,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2674 "parser.yy"
+#line 2680 "parser.yy"
     { (yyval.decl) = DeclarationNode::newPointer( 0 ); }
     break;
@@ -8814,5 +8845,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2676 "parser.yy"
+#line 2682 "parser.yy"
     { (yyval.decl) = DeclarationNode::newPointer( (yyvsp[(2) - (2)].decl) ); }
     break;
@@ -8821,5 +8852,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2678 "parser.yy"
+#line 2684 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8828,5 +8859,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2680 "parser.yy"
+#line 2686 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addPointer( DeclarationNode::newPointer( (yyvsp[(2) - (3)].decl) ) ); }
     break;
@@ -8835,5 +8866,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2682 "parser.yy"
+#line 2688 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8842,5 +8873,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2688 "parser.yy"
+#line 2694 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8849,5 +8880,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2690 "parser.yy"
+#line 2696 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (4)].decl)->addArray( (yyvsp[(4) - (4)].decl) ); }
     break;
@@ -8856,5 +8887,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2692 "parser.yy"
+#line 2698 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8863,5 +8894,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2697 "parser.yy"
+#line 2703 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (8)].decl)->addParamList( (yyvsp[(6) - (8)].decl) ); }
     break;
@@ -8870,5 +8901,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2699 "parser.yy"
+#line 2705 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (3)].decl); }
     break;
@@ -8877,5 +8908,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2709 "parser.yy"
+#line 2715 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -8884,5 +8915,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2719 "parser.yy"
+#line 2725 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8891,5 +8922,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2721 "parser.yy"
+#line 2727 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewPointer( DeclarationNode::newPointer( (yyvsp[(1) - (3)].decl) ) ); }
     break;
@@ -8898,5 +8929,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2723 "parser.yy"
+#line 2729 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8905,5 +8936,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2725 "parser.yy"
+#line 2731 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewPointer( DeclarationNode::newPointer( (yyvsp[(1) - (3)].decl) ) ); }
     break;
@@ -8912,5 +8943,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2727 "parser.yy"
+#line 2733 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -8919,5 +8950,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2729 "parser.yy"
+#line 2735 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewPointer( DeclarationNode::newPointer( (yyvsp[(1) - (3)].decl) ) ); }
     break;
@@ -8926,30 +8957,9 @@
 
 /* Line 1806 of yacc.c  */
-#line 2736 "parser.yy"
+#line 2742 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     break;
 
   case 721:
-
-/* Line 1806 of yacc.c  */
-#line 2738 "parser.yy"
-    { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewArray( (yyvsp[(1) - (2)].decl) ); }
-    break;
-
-  case 722:
-
-/* Line 1806 of yacc.c  */
-#line 2740 "parser.yy"
-    { (yyval.decl) = (yyvsp[(4) - (4)].decl)->addNewArray( (yyvsp[(3) - (4)].decl) )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
-    break;
-
-  case 723:
-
-/* Line 1806 of yacc.c  */
-#line 2742 "parser.yy"
-    { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewArray( (yyvsp[(2) - (3)].decl) )->addNewArray( (yyvsp[(1) - (3)].decl) ); }
-    break;
-
-  case 724:
 
 /* Line 1806 of yacc.c  */
@@ -8958,33 +8968,33 @@
     break;
 
+  case 722:
+
+/* Line 1806 of yacc.c  */
+#line 2746 "parser.yy"
+    { (yyval.decl) = (yyvsp[(4) - (4)].decl)->addNewArray( (yyvsp[(3) - (4)].decl) )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+    break;
+
+  case 723:
+
+/* Line 1806 of yacc.c  */
+#line 2748 "parser.yy"
+    { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewArray( (yyvsp[(2) - (3)].decl) )->addNewArray( (yyvsp[(1) - (3)].decl) ); }
+    break;
+
+  case 724:
+
+/* Line 1806 of yacc.c  */
+#line 2750 "parser.yy"
+    { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewArray( (yyvsp[(1) - (2)].decl) ); }
+    break;
+
   case 725:
 
 /* Line 1806 of yacc.c  */
-#line 2747 "parser.yy"
+#line 2753 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     break;
 
   case 726:
-
-/* Line 1806 of yacc.c  */
-#line 2749 "parser.yy"
-    { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewArray( (yyvsp[(1) - (2)].decl) ); }
-    break;
-
-  case 727:
-
-/* Line 1806 of yacc.c  */
-#line 2751 "parser.yy"
-    { (yyval.decl) = (yyvsp[(4) - (4)].decl)->addNewArray( (yyvsp[(3) - (4)].decl) )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
-    break;
-
-  case 728:
-
-/* Line 1806 of yacc.c  */
-#line 2753 "parser.yy"
-    { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewArray( (yyvsp[(2) - (3)].decl) )->addNewArray( (yyvsp[(1) - (3)].decl) ); }
-    break;
-
-  case 729:
 
 /* Line 1806 of yacc.c  */
@@ -8993,8 +9003,29 @@
     break;
 
+  case 727:
+
+/* Line 1806 of yacc.c  */
+#line 2757 "parser.yy"
+    { (yyval.decl) = (yyvsp[(4) - (4)].decl)->addNewArray( (yyvsp[(3) - (4)].decl) )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
+    break;
+
+  case 728:
+
+/* Line 1806 of yacc.c  */
+#line 2759 "parser.yy"
+    { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewArray( (yyvsp[(2) - (3)].decl) )->addNewArray( (yyvsp[(1) - (3)].decl) ); }
+    break;
+
+  case 729:
+
+/* Line 1806 of yacc.c  */
+#line 2761 "parser.yy"
+    { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewArray( (yyvsp[(1) - (2)].decl) ); }
+    break;
+
   case 730:
 
 /* Line 1806 of yacc.c  */
-#line 2760 "parser.yy"
+#line 2766 "parser.yy"
     { (yyval.decl) = DeclarationNode::newVarArray( (yyvsp[(3) - (6)].decl) ); }
     break;
@@ -9003,5 +9034,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2762 "parser.yy"
+#line 2768 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( (yyvsp[(4) - (6)].en), (yyvsp[(3) - (6)].decl), false ); }
     break;
@@ -9010,5 +9041,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2767 "parser.yy"
+#line 2773 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( (yyvsp[(4) - (6)].en), (yyvsp[(3) - (6)].decl), true ); }
     break;
@@ -9017,5 +9048,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2769 "parser.yy"
+#line 2775 "parser.yy"
     { (yyval.decl) = DeclarationNode::newArray( (yyvsp[(5) - (7)].en), (yyvsp[(4) - (7)].decl)->addQualifiers( (yyvsp[(3) - (7)].decl) ), true ); }
     break;
@@ -9024,5 +9055,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2796 "parser.yy"
+#line 2802 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addQualifiers( (yyvsp[(1) - (2)].decl) ); }
     break;
@@ -9031,5 +9062,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2807 "parser.yy"
+#line 2813 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -9038,5 +9069,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2809 "parser.yy"
+#line 2815 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewPointer( DeclarationNode::newPointer( (yyvsp[(1) - (3)].decl) ) ); }
     break;
@@ -9045,5 +9076,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2811 "parser.yy"
+#line 2817 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -9052,5 +9083,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2813 "parser.yy"
+#line 2819 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewPointer( DeclarationNode::newPointer( (yyvsp[(1) - (3)].decl) ) ); }
     break;
@@ -9059,5 +9090,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2815 "parser.yy"
+#line 2821 "parser.yy"
     { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
     break;
@@ -9066,30 +9097,9 @@
 
 /* Line 1806 of yacc.c  */
-#line 2817 "parser.yy"
+#line 2823 "parser.yy"
     { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewPointer( DeclarationNode::newPointer( (yyvsp[(1) - (3)].decl) ) ); }
     break;
 
   case 745:
-
-/* Line 1806 of yacc.c  */
-#line 2824 "parser.yy"
-    { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
-    break;
-
-  case 746:
-
-/* Line 1806 of yacc.c  */
-#line 2826 "parser.yy"
-    { (yyval.decl) = (yyvsp[(4) - (4)].decl)->addNewArray( (yyvsp[(3) - (4)].decl) )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
-    break;
-
-  case 747:
-
-/* Line 1806 of yacc.c  */
-#line 2828 "parser.yy"
-    { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewArray( (yyvsp[(1) - (2)].decl) ); }
-    break;
-
-  case 748:
 
 /* Line 1806 of yacc.c  */
@@ -9098,5 +9108,5 @@
     break;
 
-  case 749:
+  case 746:
 
 /* Line 1806 of yacc.c  */
@@ -9105,5 +9115,5 @@
     break;
 
-  case 750:
+  case 747:
 
 /* Line 1806 of yacc.c  */
@@ -9112,8 +9122,29 @@
     break;
 
+  case 748:
+
+/* Line 1806 of yacc.c  */
+#line 2836 "parser.yy"
+    { (yyval.decl) = (yyvsp[(3) - (3)].decl)->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
+    break;
+
+  case 749:
+
+/* Line 1806 of yacc.c  */
+#line 2838 "parser.yy"
+    { (yyval.decl) = (yyvsp[(4) - (4)].decl)->addNewArray( (yyvsp[(3) - (4)].decl) )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
+    break;
+
+  case 750:
+
+/* Line 1806 of yacc.c  */
+#line 2840 "parser.yy"
+    { (yyval.decl) = (yyvsp[(2) - (2)].decl)->addNewArray( (yyvsp[(1) - (2)].decl) ); }
+    break;
+
   case 751:
 
 /* Line 1806 of yacc.c  */
-#line 2839 "parser.yy"
+#line 2845 "parser.yy"
     { (yyval.decl) = DeclarationNode::newTuple( (yyvsp[(3) - (5)].decl) ); }
     break;
@@ -9122,5 +9153,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2846 "parser.yy"
+#line 2852 "parser.yy"
     { (yyval.decl) = DeclarationNode::newFunction( nullptr, (yyvsp[(1) - (6)].decl), (yyvsp[(4) - (6)].decl), nullptr ); }
     break;
@@ -9129,5 +9160,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2848 "parser.yy"
+#line 2854 "parser.yy"
     { (yyval.decl) = DeclarationNode::newFunction( nullptr, (yyvsp[(1) - (6)].decl), (yyvsp[(4) - (6)].decl), nullptr ); }
     break;
@@ -9136,5 +9167,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2872 "parser.yy"
+#line 2878 "parser.yy"
     { (yyval.en) = 0; }
     break;
@@ -9143,5 +9174,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 2874 "parser.yy"
+#line 2880 "parser.yy"
     { (yyval.en) = (yyvsp[(2) - (2)].en); }
     break;
@@ -9150,5 +9181,5 @@
 
 /* Line 1806 of yacc.c  */
-#line 9153 "Parser/parser.cc"
+#line 9184 "Parser/parser.cc"
       default: break;
     }
@@ -9381,5 +9412,5 @@
 
 /* Line 2067 of yacc.c  */
-#line 2877 "parser.yy"
+#line 2883 "parser.yy"
 
 // ----end of grammar----
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Parser/parser.yy	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -199,6 +199,5 @@
 
 %type<decl> field_declaration field_declaration_list field_declarator field_declaring_list
-%type<en> field field_list
-%type<tok> field_name
+%type<en> field field_list field_name fraction_constants
 
 %type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr
@@ -384,8 +383,11 @@
 		{ $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
 	| postfix_expression '.' '[' push field_list pop ']' // CFA, tuple field selector
+		{ $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $5 ) ) ); }
 	| postfix_expression REALFRACTIONconstant			// CFA, tuple index
+		{ $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_REALFRACTIONconstant( *$2 ) ) ); }
 	| postfix_expression ARROW no_attr_identifier
 		{ $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
 	| postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
+			{ $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); }
 	| postfix_expression ICR
 	  	{ $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); }
@@ -421,31 +423,35 @@
 field:													// CFA, tuple field selector
 	field_name
-		{ $$ = new ExpressionNode( build_varref( $1 ) ); }
 	| REALDECIMALconstant field
-		{ $$ = new ExpressionNode( build_fieldSel( $2, build_varref( $1 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_REALDECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); }
 	| REALDECIMALconstant '[' push field_list pop ']'
-		{ $$ = new ExpressionNode( build_fieldSel( $4, build_varref( $1 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_REALDECIMALconstant( *$1 ) ), build_tuple( $4 ) ) ); }
 	| field_name '.' field
-		{ $$ = new ExpressionNode( build_fieldSel( $3, build_varref( $1 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
 	| field_name '.' '[' push field_list pop ']'
-		{ $$ = new ExpressionNode( build_fieldSel( $5, build_varref( $1 ) ) ); }
+		{ $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $5 ) ) ); }
 	| field_name ARROW field
-		{ $$ = new ExpressionNode( build_pfieldSel( $3, build_varref( $1 ) ) ); }
+		{ $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
 	| field_name ARROW '[' push field_list pop ']'
-		{ $$ = new ExpressionNode( build_pfieldSel( $5, build_varref( $1 ) ) ); }
+		{ $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); }
 	;
 
 field_name:
 	INTEGERconstant	fraction_constants
-		{ $$ = $1; }
+		{ $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *$1 ), $2 ) ); }
 	| FLOATINGconstant fraction_constants
-		{ $$ = $1; }
+		{ $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
 	| no_attr_identifier fraction_constants
-		{ $$ = $1; }
+		{ $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) ); }
 	;
 
 fraction_constants:
 	// empty
+		{ $$ = nullptr; }
 	| fraction_constants REALFRACTIONconstant
+		{
+			Expression * constant = build_field_name_REALFRACTIONconstant( *$2 );
+			$$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( $1,  constant ) ) : new ExpressionNode( constant );
+		}
 	;
 
Index: src/ResolvExpr/Alternative.cc
===================================================================
--- src/ResolvExpr/Alternative.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/Alternative.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Alternative.cc -- 
+// Alternative.cc --
 //
 // Author           : Richard C. Bilson
@@ -12,5 +12,5 @@
 // Last Modified On : Sat May 16 23:54:23 2015
 // Update Count     : 2
-// 
+//
 
 #include "Alternative.h"
@@ -20,5 +20,5 @@
 
 namespace ResolvExpr {
-	Alternative::Alternative() : expr( 0 ) {}
+	Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( 0 ) {}
 
 	Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
@@ -35,4 +35,19 @@
 		if ( &other == this ) return *this;
 		initialize( other, *this );
+		return *this;
+	}
+
+	Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( other.env ) {
+		other.expr = nullptr;
+	}
+
+	Alternative & Alternative::operator=( Alternative && other ) {
+		if ( &other == this )  return *this;
+		delete expr;
+		cost = other.cost;
+		cvtCost = other.cvtCost;
+		expr = other.expr;
+		env = other.env;
+		other.expr = nullptr;
 		return *this;
 	}
@@ -54,6 +69,7 @@
 			expr->print( os, indent );
 			os << "(types:" << std::endl;
-			printAll( expr->get_results(), os, indent + 4 );
-			os << ")" << std::endl;
+			os << std::string( indent+4, ' ' );
+			expr->get_result()->print( os, indent + 4 );
+			os << std::endl << ")" << std::endl;
 		} else {
 			os << "Null expression!" << std::endl;
Index: src/ResolvExpr/Alternative.h
===================================================================
--- src/ResolvExpr/Alternative.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/Alternative.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Alternative.h -- 
+// Alternative.h --
 //
 // Author           : Richard C. Bilson
@@ -12,5 +12,5 @@
 // Last Modified On : Sat May 16 23:54:39 2015
 // Update Count     : 2
-// 
+//
 
 #ifndef ALTERNATIVE_H
@@ -32,10 +32,12 @@
 		Alternative( const Alternative &other );
 		Alternative &operator=( const Alternative &other );
+		Alternative( Alternative && other );
+		Alternative &operator=( Alternative && other );
 		~Alternative();
-  
+
 		void initialize( const Alternative &src, Alternative &dest );
-  
+
 		void print( std::ostream &os, int indent = 0 ) const;
-  
+
 		Cost cost;
 		Cost cvtCost;
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -38,8 +38,9 @@
 #include "SynTree/TypeSubstitution.h"
 #include "SymTab/Validate.h"
-#include "Tuples/TupleAssignment.h"
-#include "Tuples/NameMatcher.h"
+#include "Tuples/Tuples.h"
+#include "Tuples/Explode.h"
 #include "Common/utility.h"
 #include "InitTweak/InitTweak.h"
+#include "InitTweak/GenInit.h"
 #include "ResolveTypeof.h"
 
@@ -64,4 +65,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 +85,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;
 		}
 
@@ -101,8 +102,8 @@
 				PruneStruct current( candidate );
 				std::string mangleName;
-				for ( std::list< Type* >::const_iterator retType = candidate->expr->get_results().begin(); retType != candidate->expr->get_results().end(); ++retType ) {
-					Type *newType = (*retType)->clone();
+				{
+					Type * newType = candidate->expr->get_result()->clone();
 					candidate->env.apply( newType );
-					mangleName += SymTab::Mangler::mangle( newType );
+					mangleName = SymTab::Mangler::mangle( newType );
 					delete newType;
 				}
@@ -133,44 +134,12 @@
 				if ( ! target->second.isAmbiguous ) {
 					Alternative &alt = *target->second.candidate;
-					for ( std::list< Type* >::iterator result = alt.expr->get_results().begin(); result != alt.expr->get_results().end(); ++result ) {
-						alt.env.applyFree( *result );
-					}
+					alt.env.applyFree( alt.expr->get_result() );
 					*out++ = alt;
 				}
 			}
-
-		}
-
-		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 ) {
-			while ( begin != end ) {
-				result.simpleCombine( (*begin++).env );
-			}
 		}
 
 		void renameTypes( Expression *expr ) {
-			for ( std::list< Type* >::iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
-				(*i)->accept( global_renamer );
-			}
+			expr->get_result()->accept( global_renamer );
 		}
 	}
@@ -204,5 +173,5 @@
 		for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
 			if ( adjust ) {
-				adjustExprTypeList( i->expr->get_results().begin(), i->expr->get_results().end(), i->env, indexer );
+				adjustExprType( i->expr->get_result(), i->env, indexer );
 			}
 		}
@@ -240,6 +209,11 @@
 	}
 
+	// std::unordered_map< Expression *, UniqueExpr * > ;
+
 	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 ) {
+		// by this point, member must be a name expr
+		NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
+		const std::string & name = nameExpr->get_name();
 		std::list< Declaration* > members;
 		aggInst->lookup( name, members );
@@ -254,4 +228,28 @@
 	}
 
+	void AlternativeFinder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
+		if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
+			// get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
+			// xxx - this should be improved by memoizing the value of constant exprs
+			// during parsing and reusing that information here.
+			std::stringstream ss( constantExpr->get_constant()->get_value() );
+			int val;
+			std::string tmp;
+			if ( ss >> val && ! (ss >> tmp) ) {
+				if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
+					alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
+				} // if
+			} // if
+		} else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
+			// xxx - temporary hack until 0/1 are int constants
+			if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
+				std::stringstream ss( nameExpr->get_name() );
+				int val;
+				ss >> val;
+				alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
+			}
+		} // if
+	}
+
 	void AlternativeFinder::visit( ApplicationExpr *applicationExpr ) {
 		alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
@@ -259,10 +257,7 @@
 
 	Cost computeConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
-		ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( alt.expr );
-		assert( appExpr );
-		PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
-		assert( pointer );
-		FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
-		assert( function );
+		ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( alt.expr );
+		PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
+		FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
 
 		Cost convCost( 0, 0, 0 );
@@ -270,29 +265,50 @@
 		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;
 				(*actualExpr)->print( std::cerr, 8 );
 				std::cerr << "--- results are" << std::endl;
-				printAll( (*actualExpr)->get_results(), std::cerr, 8 );
+				(*actualExpr)->get_result()->print( std::cerr, 8 );
 			)
 			std::list< DeclarationWithType* >::iterator startFormal = formal;
 			Cost actualCost;
-			for ( std::list< Type* >::iterator actual = (*actualExpr)->get_results().begin(); actual != (*actualExpr)->get_results().end(); ++actual ) {
-				if ( formal == formals.end() ) {
-					if ( function->get_isVarArgs() ) {
-						convCost += Cost( 1, 0, 0 );
-						break;
-					} else {
-						return Cost::infinity;
+			std::list< Type * > flatActualTypes;
+			flatten( (*actualExpr)->get_result(), back_inserter( flatActualTypes ) );
+			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;
@@ -305,7 +321,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 ) ) {
@@ -356,5 +372,5 @@
 	/// Adds type variables to the open variable set and marks their assertions
 	void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) {
-		for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
+		for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
 			unifiableVars[ (*tyvar)->get_name() ] = (*tyvar)->get_kind();
 			for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
@@ -365,5 +381,59 @@
 	}
 
-	bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave ) {
+	/// instantiate a single argument by matching actuals from [actualIt, actualEnd) against formalType,
+	/// producing expression(s) in out and their total cost in cost.
+	template< typename AltIterator, typename OutputIterator >
+	bool instantiateArgument( Type * formalType, Initializer * defaultValue, AltIterator & actualIt, AltIterator actualEnd, OpenVarSet & openVars, TypeEnvironment & resultEnv, AssertionSet & resultNeed, AssertionSet & resultHave, const SymTab::Indexer & indexer, Cost & cost, OutputIterator out ) {
+		if ( TupleType * tupleType = dynamic_cast< TupleType * >( formalType ) ) {
+			// formalType is a TupleType - group actuals into a TupleExpr whose type unifies with the TupleType
+			TupleExpr * tupleExpr = new TupleExpr();
+			for ( Type * type : *tupleType ) {
+				if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( tupleExpr->get_exprs() ) ) ) {
+					delete tupleExpr;
+					return false;
+				}
+			}
+			tupleExpr->set_result( Tuples::makeTupleType( tupleExpr->get_exprs() ) );
+			*out++ = tupleExpr;
+		} else if ( actualIt != actualEnd ) {
+			// both actualType and formalType are atomic (non-tuple) types - if they unify
+			// then accept actual as an argument, otherwise return false (fail to instantiate argument)
+			Expression * actual = actualIt->expr;
+			Type * actualType = actual->get_result();
+			PRINT(
+				std::cerr << "formal type is ";
+				formalType->print( std::cerr );
+				std::cerr << std::endl << "actual type is ";
+				actualType->print( std::cerr );
+				std::cerr << std::endl;
+			)
+			if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
+				return false;
+			}
+			// move the expression from the alternative to the output iterator
+			*out++ = actual;
+			actualIt->expr = nullptr;
+			cost += actualIt->cost;
+			++actualIt;
+		} else {
+			// End of actuals - Handle default values
+			if ( SingleInit *si = dynamic_cast<SingleInit *>( defaultValue )) {
+				// so far, only constant expressions are accepted as default values
+				if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( si->get_value()) ) {
+					if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) ) {
+						if ( unify( formalType, cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
+							// xxx - Don't know if this is right
+							*out++ = cnstexpr->clone();
+							return true;
+						} // if
+					} // if
+				} // if
+			} // if
+			return false;
+		} // if
+		return true;
+	}
+
+	bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out ) {
 		simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );
 		// make sure we don't widen any existing bindings
@@ -373,45 +443,31 @@
 		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();
-		for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
-			for ( std::list< Type* >::iterator actual = actualExpr->expr->get_results().begin(); actual != actualExpr->expr->get_results().end(); ++actual ) {
-				if ( formal == formals.end() ) {
-					return isVarArgs;
-				}
-				PRINT(
-					std::cerr << "formal type is ";
-					(*formal)->get_type()->print( std::cerr );
-					std::cerr << std::endl << "actual type is ";
-					(*actual)->print( std::cerr );
-					std::cerr << std::endl;
-				)
-				if ( ! unify( (*formal)->get_type(), *actual, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
-					return false;
-				}
-				formal++;
-			}
-		}
-		// Handling of default values
-		while ( formal != formals.end() ) {
-			if ( ObjectDecl *od = dynamic_cast<ObjectDecl *>( *formal ) )
-				if ( SingleInit *si = dynamic_cast<SingleInit *>( od->get_init() ))
-					// so far, only constant expressions are accepted as default values
-					if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( si->get_value()) )
-						if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) )
-							if ( unify( (*formal)->get_type(), cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
-								// XXX Don't know if this is right
-								actuals.push_back( Alternative( cnstexpr->clone(), env, Cost::zero ) );
-								formal++;
-								if ( formal == formals.end()) break;
-							}
-			return false;
+		// flatten actuals so that each actual has an atomic (non-tuple) type
+		AltList exploded;
+		Tuples::explode( actuals, indexer, back_inserter( exploded ) );
+
+		AltList::iterator actualExpr = exploded.begin();
+		AltList::iterator actualEnd = exploded.end();
+		for ( DeclarationWithType * formal : formals ) {
+			// match flattened actuals with formal parameters - actuals will be grouped to match
+			// with formals as appropriate
+			Cost cost;
+			std::list< Expression * > newExprs;
+			ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
+			if ( ! instantiateArgument( obj->get_type(), obj->get_init(), actualExpr, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( newExprs ) ) ) {
+				deleteAll( newExprs );
+				return false;
+			}
+			// success - produce argument as a new alternative
+			assert( newExprs.size() == 1 );
+			out.push_back( Alternative( newExprs.front(), resultEnv, cost ) );
+		}
+		if ( actualExpr != actualEnd ) {
+			// there are still actuals remaining, but we've run out of formal parameters to match against
+			// this is okay only if the function is variadic
+			if ( ! isVarArgs ) {
+				return false;
+			}
+			out.splice( out.end(), exploded, actualExpr, actualEnd );
 		}
 		return true;
@@ -500,7 +556,6 @@
 				//if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
 				Expression *varExpr = new VariableExpr( candDecl );
-				deleteAll( varExpr->get_results() );
-				varExpr->get_results().clear();
-				varExpr->get_results().push_front( adjType->clone() );
+				delete varExpr->get_result();
+				varExpr->set_result( adjType->clone() );
 				PRINT(
 					std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
@@ -545,13 +600,14 @@
 
 	template< typename OutputIterator >
-	void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out ) {
+	void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out ) {
 		OpenVarSet openVars;
 		AssertionSet resultNeed, resultHave;
 		TypeEnvironment resultEnv;
 		makeUnifiableVars( funcType, openVars, resultNeed );
-		if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave ) ) {
+		AltList instantiatedActuals; // filled by instantiate function
+		if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) {
 			ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
-			Alternative newAlt( appExpr, resultEnv, sumCost( actualAlt ) );
-			makeExprList( actualAlt, appExpr->get_args() );
+			Alternative newAlt( appExpr, resultEnv, sumCost( instantiatedActuals ) );
+			makeExprList( instantiatedActuals, appExpr->get_args() );
 			PRINT(
 				std::cerr << "need assertions:" << std::endl;
@@ -574,5 +630,5 @@
 				PointerType pt( Type::Qualifiers(), v.clone() );
 				UntypedExpr *vexpr = untypedExpr->clone();
-				vexpr->get_results().push_front( pt.clone() );
+				vexpr->set_result( pt.clone() );
 				alternatives.push_back( Alternative( vexpr, env, Cost()) );
 				return;
@@ -587,9 +643,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;
@@ -604,5 +658,5 @@
 				// check if the type is pointer to function
 				PointerType *pointer;
-				if ( func->expr->get_results().size() == 1 && ( pointer = dynamic_cast< PointerType* >( func->expr->get_results().front() ) ) ) {
+				if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) {
 					if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
 						for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
@@ -640,6 +694,5 @@
 						// check if the type is pointer to function
 						PointerType *pointer;
-						if ( funcOp->expr->get_results().size() == 1
-							&& ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_results().front() ) ) ) {
+						if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) {
 							if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
 								for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
@@ -665,10 +718,7 @@
 
 			PRINT(
-				ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( withFunc->expr );
-				assert( appExpr );
-				PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
-				assert( pointer );
-				FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
-				assert( function );
+				ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( withFunc->expr );
+				PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
+				FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
 				std::cerr << "Case +++++++++++++" << std::endl;
 				std::cerr << "formals are:" << std::endl;
@@ -692,8 +742,6 @@
 
 	bool isLvalue( Expression *expr ) {
-		for ( std::list< Type* >::const_iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
-			if ( !(*i)->get_isLvalue() ) return false;
-		} // for
-		return true;
+		// xxx - recurse into tuples?
+		return expr->has_result() && expr->get_result()->get_isLvalue();
 	}
 
@@ -709,9 +757,8 @@
 
 	void AlternativeFinder::visit( CastExpr *castExpr ) {
-		for ( std::list< Type* >::iterator i = castExpr->get_results().begin(); i != castExpr->get_results().end(); ++i ) {
-			*i = resolveTypeof( *i, indexer );
-			SymTab::validateType( *i, &indexer );
-			adjustExprType( *i, env, indexer );
-		} // for
+		Type *& toType = castExpr->get_result();
+		toType = resolveTypeof( toType, indexer );
+		SymTab::validateType( toType, &indexer );
+		adjustExprType( toType, env, indexer );
 
 		AlternativeFinder finder( indexer, env );
@@ -727,15 +774,10 @@
 			// that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
 			// to.
-			int discardedValues = (*i).expr->get_results().size() - castExpr->get_results().size();
+			int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
 			if ( discardedValues < 0 ) continue;
-			std::list< Type* >::iterator candidate_end = (*i).expr->get_results().begin();
-			std::advance( candidate_end, castExpr->get_results().size() );
+			// xxx - may need to go into tuple types and extract relavent types and use unifyList
 			// unification run for side-effects
-			unifyList( castExpr->get_results().begin(), castExpr->get_results().end(),
-					   (*i).expr->get_results().begin(), candidate_end,
-			           i->env, needAssertions, haveAssertions, openVars, indexer );
-			Cost thisCost = castCostList( (*i).expr->get_results().begin(), candidate_end,
-										  castExpr->get_results().begin(), castExpr->get_results().end(),
-										  indexer, i->env );
+			unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
+			Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );
 			if ( thisCost != Cost::infinity ) {
 				// count one safe conversion for each value that is thrown away
@@ -760,10 +802,10 @@
 
 		for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
-			if ( agg->expr->get_results().size() == 1 ) {
-				if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_results().front() ) ) {
-					addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
-				} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_results().front() ) ) {
-					addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
-				} // if
+			if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) {
+				addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
+			} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) {
+				addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
+			} else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) {
+				addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
 			} // if
 		} // for
@@ -791,7 +833,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
@@ -894,5 +938,5 @@
 			alternatives.push_back( Alternative( new AttrExpr( new VariableExpr( funcDecl ), argType->clone() ), env, Cost::zero ) );
 			for ( std::list< DeclarationWithType* >::iterator i = function->get_returnVals().begin(); i != function->get_returnVals().end(); ++i ) {
-				alternatives.back().expr->get_results().push_back( (*i)->get_type()->clone() );
+				alternatives.back().expr->set_result( (*i)->get_type()->clone() );
 			} // for
 		} // if
@@ -917,6 +961,6 @@
 							finder.find( attrExpr->get_expr() );
 							for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
-								if ( choice->expr->get_results().size() == 1 ) {
-									resolveAttr(*i, function, choice->expr->get_results().front(), choice->env );
+								if ( choice->expr->get_result()->size() == 1 ) {
+									resolveAttr(*i, function, choice->expr->get_result(), choice->env );
 								} // fi
 							} // for
@@ -960,16 +1004,8 @@
 					AssertionSet needAssertions, haveAssertions;
 					Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );
-					std::list< Type* > commonTypes;
-					if ( unifyList( second->expr->get_results().begin(), second->expr->get_results().end(), third->expr->get_results().begin(), third->expr->get_results().end(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
+					Type* commonType = nullptr;
+					if ( unify( second->expr->get_result(), third->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
 						ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
-						std::list< Type* >::const_iterator original = second->expr->get_results().begin();
-						std::list< Type* >::const_iterator commonType = commonTypes.begin();
-						for ( ; original != second->expr->get_results().end() && commonType != commonTypes.end(); ++original, ++commonType ) {
-							if ( *commonType ) {
-								newExpr->get_results().push_back( *commonType );
-							} else {
-								newExpr->get_results().push_back( (*original)->clone() );
-							} // if
-						} // for
+						newExpr->set_result( commonType ? commonType : second->expr->get_result()->clone() );
 						newAlt.expr = newExpr;
 						inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
@@ -999,9 +1035,5 @@
 			TupleExpr *newExpr = new TupleExpr;
 			makeExprList( *i, newExpr->get_exprs() );
-			for ( std::list< Expression* >::const_iterator resultExpr = newExpr->get_exprs().begin(); resultExpr != newExpr->get_exprs().end(); ++resultExpr ) {
-				for ( std::list< Type* >::const_iterator resultType = (*resultExpr)->get_results().begin(); resultType != (*resultExpr)->get_results().end(); ++resultType ) {
-					newExpr->get_results().push_back( (*resultType)->clone() );
-				} // for
-			} // for
+			newExpr->set_result( Tuples::makeTupleType( newExpr->get_exprs() ) );
 
 			TypeEnvironment compositeEnv;
@@ -1024,4 +1056,23 @@
 		}
 	}
+
+	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 ) );
+	}
+
+	void AlternativeFinder::visit( UniqueExpr *unqExpr ) {
+		AlternativeFinder finder( indexer, env );
+		finder.findWithAdjustment( unqExpr->get_expr() );
+		for ( Alternative & alt : finder.alternatives ) {
+			// ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
+			UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
+			alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
+		}
+	}
+
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/AlternativeFinder.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -67,16 +67,21 @@
 		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 );
+		virtual void visit( UniqueExpr *unqExpr );
+		/// 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 member expressions where the left side has tuple type
+		void addTupleMembers( TupleType * tupleType, 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 );
-		bool instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave );
+		bool instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out );
 		template< typename OutputIterator >
-		void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out );
+		void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out );
 		template< typename OutputIterator >
 		void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
@@ -89,4 +94,33 @@
 
 	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 );
+
+	template< typename InputIterator >
+	void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) {
+		while ( begin != end ) {
+			result.simpleCombine( (*begin++).env );
+		}
+	}
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/AlternativePrinter.cc
===================================================================
--- src/ResolvExpr/AlternativePrinter.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/AlternativePrinter.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// AlternativePrinter.cc -- 
+// AlternativePrinter.cc --
 //
 // Author           : Richard C. Bilson
@@ -33,5 +33,5 @@
 		for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
 			os << "Alternative " << count++ << " ==============" << std::endl;
-			printAll( i->expr->get_results(), os );
+			i->expr->get_result()->print( os );
 			//    i->print( os );
 			os << std::endl;
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/ConversionCost.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -240,5 +240,5 @@
 			std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
 			std::list< Type* >::const_iterator destIt = destAsTuple->get_types().begin();
-			while ( srcIt != tupleType->get_types().end() ) {
+			while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) {
 				Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env );
 				if ( newCost == Cost::infinity ) {
Index: src/ResolvExpr/FindOpenVars.cc
===================================================================
--- src/ResolvExpr/FindOpenVars.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/FindOpenVars.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// FindOpenVars.cc -- 
+// FindOpenVars.cc --
 //
 // Author           : Richard C. Bilson
@@ -47,5 +47,5 @@
 	void FindOpenVars::common_action( Type *type ) {
 		if ( nextIsOpen ) {
-			for ( std::list< TypeDecl* >::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
+			for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
 				openVars[ (*i)->get_name() ] = (*i)->get_kind();
 				for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
@@ -56,5 +56,5 @@
 			}
 		} else {
-			for ( std::list< TypeDecl* >::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
+			for ( Type::ForallList::const_iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
 				closedVars[ (*i)->get_name() ] = (*i)->get_kind();
 				for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
Index: src/ResolvExpr/RenameVars.cc
===================================================================
--- src/ResolvExpr/RenameVars.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/RenameVars.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// RenameVars.cc -- 
+// RenameVars.cc --
 //
 // Author           : Richard C. Bilson
@@ -125,5 +125,5 @@
 			mapStack.push_front( mapStack.front() );
 			// renames all "forall" type names to `_${level}_${name}'
-			for ( std::list< TypeDecl* >::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
+			for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
 				std::ostringstream output;
 				output << "_" << level << "_" << (*i)->get_name();
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// ResolveTypeof.cc -- 
+// ResolveTypeof.cc --
 //
 // Author           : Richard C. Bilson
@@ -58,13 +58,6 @@
 		if ( typeofType->get_expr() ) {
 			Expression *newExpr = resolveInVoidContext( typeofType->get_expr(), indexer );
-			assert( newExpr->get_results().size() > 0 );
-			Type *newType;
-			if ( newExpr->get_results().size() > 1 ) {
-				TupleType *tupleType = new TupleType( Type::Qualifiers() );
-				cloneAll( newExpr->get_results(), tupleType->get_types() );
-				newType = tupleType;
-			} else {
-				newType = newExpr->get_results().front()->clone();
-			} // if
+			assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() );
+			Type *newType = newExpr->get_result();
 			delete typeofType;
 			return newType;
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/Resolver.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -19,4 +19,5 @@
 #include "RenameVars.h"
 #include "ResolveTypeof.h"
+#include "typeops.h"
 #include "SynTree/Statement.h"
 #include "SynTree/Type.h"
@@ -68,6 +69,7 @@
 	  void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator & );
 	  void fallbackInit( ConstructorInit * ctorInit );
-		std::list< Type * > functionReturn;
-		Type *initContext;
+
+		Type * functionReturn = nullptr;
+		Type *initContext = nullptr;
 		bool inEnumDecl = false;
 	};
@@ -157,5 +159,5 @@
 			const TypeEnvironment *newEnv = 0;
 			for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
-				if ( i->expr->get_results().size() == 1 && isIntegralType( i->expr->get_results().front() ) ) {
+				if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) {
 					if ( newExpr ) {
 						throw SemanticError( "Too many interpretations for case control expression", untyped );
@@ -234,11 +236,7 @@
 		Type *new_type = resolveTypeof( functionDecl->get_type(), *this );
 		functionDecl->set_type( new_type );
-		std::list< Type * > oldFunctionReturn = functionReturn;
-		functionReturn.clear();
-		for ( std::list< DeclarationWithType * >::const_iterator i = functionDecl->get_functionType()->get_returnVals().begin(); i != functionDecl->get_functionType()->get_returnVals().end(); ++i ) {
-			functionReturn.push_back( (*i)->get_type() );
-		} // for
+		ValueGuard< Type * > oldFunctionReturn( functionReturn );
+		functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
 		SymTab::Indexer::visit( functionDecl );
-		functionReturn = oldFunctionReturn;
 	}
 
@@ -338,6 +336,5 @@
 	void Resolver::visit( ReturnStmt *returnStmt ) {
 		if ( returnStmt->get_expr() ) {
-			CastExpr *castExpr = new CastExpr( returnStmt->get_expr() );
-			cloneAll( functionReturn, castExpr->get_results() );
+			CastExpr *castExpr = new CastExpr( returnStmt->get_expr(), functionReturn->clone() );
 			Expression *newExpr = findSingleExpression( castExpr, *this );
 			delete castExpr;
@@ -384,5 +381,5 @@
 				if ( isCharType( at->get_base() ) ) {
 					// check if the resolved type is char *
-					if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_results().front() ) ) {
+					if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
 						if ( isCharType( pt->get_base() ) ) {
 							// strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
@@ -446,4 +443,10 @@
 				(*iter)->accept( *this );
 			} // for
+		} else if ( TupleType * tt = dynamic_cast< TupleType * > ( initContext ) ) {
+			for ( Type * t : *tt ) {
+				if ( iter == end ) break;
+				initContext = t;
+				(*iter++)->accept( *this );
+			}
 		} else if ( StructInstType * st = dynamic_cast< StructInstType * >( initContext ) ) {
 			resolveAggrInit( st->get_baseStruct(), iter, end );
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -158,6 +158,6 @@
 	}
 
-	void TypeEnvironment::add( const std::list< TypeDecl* > &tyDecls ) {
-		for ( std::list< TypeDecl* >::const_iterator i = tyDecls.begin(); i != tyDecls.end(); ++i ) {
+	void TypeEnvironment::add( const Type::ForallList &tyDecls ) {
+		for ( Type::ForallList::const_iterator i = tyDecls.begin(); i != tyDecls.end(); ++i ) {
 			EqvClass newClass;
 			newClass.vars.insert( (*i)->get_name() );
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/TypeEnvironment.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -55,5 +55,5 @@
 		bool lookup( const std::string &var, EqvClass &eqvClass ) const;
 		void add( const EqvClass &eqvClass );
-		void add( const std::list< TypeDecl* > &tyDecls );
+		void add( const Type::ForallList &tyDecls );
 		template< typename SynTreeClass > int apply( SynTreeClass *&type ) const;
 		template< typename SynTreeClass > int applyFree( SynTreeClass *&type ) const;
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/Unify.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -597,4 +597,18 @@
 	}
 
+	// xxx - compute once and store in the FunctionType?
+	Type * extractResultType( FunctionType * function ) {
+		if ( function->get_returnVals().size() == 0 ) {
+			return new VoidType( Type::Qualifiers() );
+		} else if ( function->get_returnVals().size() == 1 ) {
+			return function->get_returnVals().front()->get_type()->clone();
+		} else {
+			TupleType * tupleType = new TupleType( Type::Qualifiers() );
+			for ( DeclarationWithType * decl : function->get_returnVals() ) {
+				tupleType->get_types().push_back( decl->get_type()->clone() );
+			} // for
+			return tupleType;
+		}
+	}
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/ResolvExpr/typeops.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// typeops.h -- 
+// typeops.h --
 //
 // Author           : Richard C. Bilson
@@ -30,10 +30,10 @@
 		typedef typename InputIterator::value_type SetType;
 		typedef typename std::list< typename SetType::value_type > ListType;
-  
+
 		if ( begin == end )	{
 			*out++ = ListType();
 			return;
 		} // if
-  
+
 		InputIterator current = begin;
 		begin++;
@@ -41,5 +41,5 @@
 		std::list< ListType > recursiveResult;
 		combos( begin, end, back_inserter( recursiveResult ) );
-  
+
 		for ( typename std::list< ListType >::const_iterator i = recursiveResult.begin(); i != recursiveResult.end(); ++i ) {
 			for ( typename ListType::const_iterator j = current->begin(); j != current->end(); ++j ) {
@@ -52,5 +52,5 @@
 		} // for
 	}
-  
+
 	// in AdjustExprType.cc
 	/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
@@ -144,4 +144,7 @@
 	}
 
+	/// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
+	Type * extractResultType( FunctionType * functionType );
+
 	// in CommonType.cc
 	Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
@@ -152,4 +155,16 @@
 	// in Occurs.cc
 	bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
+
+	// flatten tuple type into list of types
+	template< typename OutputIterator >
+	void flatten( Type * type, OutputIterator out ) {
+		if ( TupleType * tupleType = dynamic_cast< TupleType * >( type ) ) {
+			for ( Type * t : tupleType->get_types() ) {
+				flatten( t, out );
+			}
+		} else {
+			*out++ = type;
+		}
+	}
 } // namespace ResolvExpr
 
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SymTab/Autogen.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -116,6 +116,7 @@
 		// This happens before function pointer type conversion, so need to do it manually here
 		VariableExpr * assignVarExpr = new VariableExpr( assignDecl );
-		Type *& assignVarExprType = assignVarExpr->get_results().front();
+		Type * assignVarExprType = assignVarExpr->get_result();
 		assignVarExprType = new PointerType( Type::Qualifiers(), assignVarExprType );
+		assignVarExpr->set_result( assignVarExprType );
 		ApplicationExpr * assignExpr = new ApplicationExpr( assignVarExpr );
 		assignExpr->get_args().push_back( new VariableExpr( dstParam ) );
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SymTab/Indexer.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -40,8 +40,8 @@
 
 namespace SymTab {
-	template< typename Container, typename VisitorType >
-	inline void acceptAllNewScope( Container &container, VisitorType &visitor ) {
+	template< typename TreeType, typename VisitorType >
+	inline void acceptNewScope( TreeType *tree, VisitorType &visitor ) {
 		visitor.enterScope();
-		acceptAll( container, visitor );
+		maybeAccept( tree, visitor );
 		visitor.leaveScope();
 	}
@@ -143,5 +143,5 @@
 		for ( DeclarationWithType * decl : copy ) {
 			if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl ) ) {
-				std::list< DeclarationWithType * > params = function->get_functionType()->get_parameters();
+				std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
 				assert( ! params.empty() );
 				// use base type of pointer, so that qualifiers on the pointer type aren't considered.
@@ -337,5 +337,5 @@
 
 	void Indexer::visit( ApplicationExpr *applicationExpr ) {
-		acceptAllNewScope( applicationExpr->get_results(), *this );
+		acceptNewScope( applicationExpr->get_result(), *this );
 		maybeAccept( applicationExpr->get_function(), *this );
 		acceptAll( applicationExpr->get_args(), *this );
@@ -343,48 +343,48 @@
 
 	void Indexer::visit( UntypedExpr *untypedExpr ) {
-		acceptAllNewScope( untypedExpr->get_results(), *this );
+		acceptNewScope( untypedExpr->get_result(), *this );
 		acceptAll( untypedExpr->get_args(), *this );
 	}
 
 	void Indexer::visit( NameExpr *nameExpr ) {
-		acceptAllNewScope( nameExpr->get_results(), *this );
+		acceptNewScope( nameExpr->get_result(), *this );
 	}
 
 	void Indexer::visit( AddressExpr *addressExpr ) {
-		acceptAllNewScope( addressExpr->get_results(), *this );
+		acceptNewScope( addressExpr->get_result(), *this );
 		maybeAccept( addressExpr->get_arg(), *this );
 	}
 
 	void Indexer::visit( LabelAddressExpr *labAddressExpr ) {
-		acceptAllNewScope( labAddressExpr->get_results(), *this );
+		acceptNewScope( labAddressExpr->get_result(), *this );
 		maybeAccept( labAddressExpr->get_arg(), *this );
 	}
 
 	void Indexer::visit( CastExpr *castExpr ) {
-		acceptAllNewScope( castExpr->get_results(), *this );
+		acceptNewScope( castExpr->get_result(), *this );
 		maybeAccept( castExpr->get_arg(), *this );
 	}
 
 	void Indexer::visit( UntypedMemberExpr *memberExpr ) {
-		acceptAllNewScope( memberExpr->get_results(), *this );
+		acceptNewScope( memberExpr->get_result(), *this );
 		maybeAccept( memberExpr->get_aggregate(), *this );
 	}
 
 	void Indexer::visit( MemberExpr *memberExpr ) {
-		acceptAllNewScope( memberExpr->get_results(), *this );
+		acceptNewScope( memberExpr->get_result(), *this );
 		maybeAccept( memberExpr->get_aggregate(), *this );
 	}
 
 	void Indexer::visit( VariableExpr *variableExpr ) {
-		acceptAllNewScope( variableExpr->get_results(), *this );
+		acceptNewScope( variableExpr->get_result(), *this );
 	}
 
 	void Indexer::visit( ConstantExpr *constantExpr ) {
-		acceptAllNewScope( constantExpr->get_results(), *this );
+		acceptNewScope( constantExpr->get_result(), *this );
 		maybeAccept( constantExpr->get_constant(), *this );
 	}
 
 	void Indexer::visit( SizeofExpr *sizeofExpr ) {
-		acceptAllNewScope( sizeofExpr->get_results(), *this );
+		acceptNewScope( sizeofExpr->get_result(), *this );
 		if ( sizeofExpr->get_isType() ) {
 			maybeAccept( sizeofExpr->get_type(), *this );
@@ -395,5 +395,5 @@
 
 	void Indexer::visit( AlignofExpr *alignofExpr ) {
-		acceptAllNewScope( alignofExpr->get_results(), *this );
+		acceptNewScope( alignofExpr->get_result(), *this );
 		if ( alignofExpr->get_isType() ) {
 			maybeAccept( alignofExpr->get_type(), *this );
@@ -404,10 +404,10 @@
 
 	void Indexer::visit( UntypedOffsetofExpr *offsetofExpr ) {
-		acceptAllNewScope( offsetofExpr->get_results(), *this );
+		acceptNewScope( offsetofExpr->get_result(), *this );
 		maybeAccept( offsetofExpr->get_type(), *this );
 	}
 
 	void Indexer::visit( OffsetofExpr *offsetofExpr ) {
-		acceptAllNewScope( offsetofExpr->get_results(), *this );
+		acceptNewScope( offsetofExpr->get_result(), *this );
 		maybeAccept( offsetofExpr->get_type(), *this );
 		maybeAccept( offsetofExpr->get_member(), *this );
@@ -415,10 +415,10 @@
 
 	void Indexer::visit( OffsetPackExpr *offsetPackExpr ) {
-		acceptAllNewScope( offsetPackExpr->get_results(), *this );
+		acceptNewScope( offsetPackExpr->get_result(), *this );
 		maybeAccept( offsetPackExpr->get_type(), *this );
 	}
 
 	void Indexer::visit( AttrExpr *attrExpr ) {
-		acceptAllNewScope( attrExpr->get_results(), *this );
+		acceptNewScope( attrExpr->get_result(), *this );
 		if ( attrExpr->get_isType() ) {
 			maybeAccept( attrExpr->get_type(), *this );
@@ -429,5 +429,5 @@
 
 	void Indexer::visit( LogicalExpr *logicalExpr ) {
-		acceptAllNewScope( logicalExpr->get_results(), *this );
+		acceptNewScope( logicalExpr->get_result(), *this );
 		maybeAccept( logicalExpr->get_arg1(), *this );
 		maybeAccept( logicalExpr->get_arg2(), *this );
@@ -435,5 +435,5 @@
 
 	void Indexer::visit( ConditionalExpr *conditionalExpr ) {
-		acceptAllNewScope( conditionalExpr->get_results(), *this );
+		acceptNewScope( conditionalExpr->get_result(), *this );
 		maybeAccept( conditionalExpr->get_arg1(), *this );
 		maybeAccept( conditionalExpr->get_arg2(), *this );
@@ -442,5 +442,5 @@
 
 	void Indexer::visit( CommaExpr *commaExpr ) {
-		acceptAllNewScope( commaExpr->get_results(), *this );
+		acceptNewScope( commaExpr->get_result(), *this );
 		maybeAccept( commaExpr->get_arg1(), *this );
 		maybeAccept( commaExpr->get_arg2(), *this );
@@ -448,15 +448,18 @@
 
 	void Indexer::visit( TupleExpr *tupleExpr ) {
-		acceptAllNewScope( tupleExpr->get_results(), *this );
+		acceptNewScope( tupleExpr->get_result(), *this );
 		acceptAll( tupleExpr->get_exprs(), *this );
 	}
 
-	void Indexer::visit( SolvedTupleExpr *tupleExpr ) {
-		acceptAllNewScope( tupleExpr->get_results(), *this );
-		acceptAll( tupleExpr->get_exprs(), *this );
+	void Indexer::visit( TupleAssignExpr *tupleExpr ) {
+		acceptNewScope( tupleExpr->get_result(), *this );
+		enterScope();
+		acceptAll( tupleExpr->get_tempDecls(), *this );
+		acceptAll( tupleExpr->get_assigns(), *this );
+		leaveScope();
 	}
 
 	void Indexer::visit( TypeExpr *typeExpr ) {
-		acceptAllNewScope( typeExpr->get_results(), *this );
+		acceptNewScope( typeExpr->get_result(), *this );
 		maybeAccept( typeExpr->get_type(), *this );
 	}
@@ -469,5 +472,5 @@
 
 	void Indexer::visit( UntypedValofExpr *valofExpr ) {
-		acceptAllNewScope( valofExpr->get_results(), *this );
+		acceptNewScope( valofExpr->get_result(), *this );
 		maybeAccept( valofExpr->get_body(), *this );
 	}
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SymTab/Indexer.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -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/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SymTab/Mangler.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Mangler.cc -- 
+// Mangler.cc --
 //
 // Author           : Richard C. Bilson
@@ -35,8 +35,8 @@
 		return mangler.get_mangleName();
 	}
-	
+
 	Mangler::Mangler( bool mangleOverridable, bool typeMode )
 		: nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ) {}
-		
+
 	Mangler::Mangler( const Mangler &rhs ) : mangleName() {
 		varNums = rhs.varNums;
@@ -115,5 +115,5 @@
 			"Ir",	// LongDoubleImaginary
 		};
-  
+
 		printQualifiers( basicType );
 		mangleName << btLetter[ basicType->get_kind() ];
@@ -253,10 +253,10 @@
 		// skip if not including qualifiers
 		if ( typeMode ) return;
-		
+
 		if ( ! type->get_forall().empty() ) {
 			std::list< std::string > assertionNames;
 			int tcount = 0, dcount = 0, fcount = 0;
 			mangleName << "A";
-			for ( std::list< TypeDecl* >::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
+			for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
 				switch ( (*i)->get_kind() ) {
 				  case TypeDecl::Any:
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SymTab/Validate.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -23,6 +23,6 @@
 // - All enumeration constants have type EnumInstType.
 //
-// - The type "void" never occurs in lists of function parameter or return types; neither do tuple types.  A function
-//   taking no arguments has no argument types, and tuples are flattened.
+// - The type "void" never occurs in lists of function parameter or return types.  A function
+//   taking no arguments has no argument types.
 //
 // - No context instances exist; they are all replaced by the set of declarations signified by the context, instantiated
@@ -243,5 +243,5 @@
 		return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl );
 	}
-
+	// xxx - shouldn't this be declsToAddBefore?
 	template< typename AggDecl >
 	void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
@@ -431,5 +431,5 @@
 	/// Fix up assertions
 	void forallFixer( Type *func ) {
-		for ( std::list< TypeDecl * >::iterator type = func->get_forall().begin(); type != func->get_forall().end(); ++type ) {
+		for ( Type::ForallList::iterator type = func->get_forall().begin(); type != func->get_forall().end(); ++type ) {
 			std::list< DeclarationWithType * > toBeDone, nextRound;
 			toBeDone.splice( toBeDone.end(), (*type )->get_assertions() );
Index: src/SynTree/AddressExpr.cc
===================================================================
--- src/SynTree/AddressExpr.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/AddressExpr.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -19,7 +19,7 @@
 
 AddressExpr::AddressExpr( Expression *arg, Expression *_aname ) : Expression( _aname ), arg( arg ) {
-	for ( std::list< Type* >::const_iterator i = arg->get_results().begin(); i != arg->get_results().end(); ++i ) {
-		get_results().push_back( new PointerType( Type::Qualifiers(), (*i)->clone() ) );
-	} // for
+	if ( arg->has_result() ) {
+		set_result( new PointerType( Type::Qualifiers(), arg->get_result()->clone() ) );
+	}
 }
 
@@ -35,5 +35,5 @@
 	if ( arg ) {
 		os << std::string( indent+2, ' ' );
-    arg->print( os, indent+2 );
+		arg->print( os, indent+2 );
 	} // if
 }
Index: src/SynTree/ApplicationExpr.cc
===================================================================
--- src/SynTree/ApplicationExpr.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/ApplicationExpr.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -21,5 +21,5 @@
 #include "TypeSubstitution.h"
 #include "Common/utility.h"
-
+#include "ResolvExpr/typeops.h"
 
 ParamEntry::ParamEntry( const ParamEntry &other ) :
@@ -43,12 +43,10 @@
 
 ApplicationExpr::ApplicationExpr( Expression *funcExpr ) : function( funcExpr ) {
-	PointerType *pointer = dynamic_cast< PointerType* >( funcExpr->get_results().front() );
-	assert( pointer );
-	FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
-	assert( function );
+	PointerType *pointer = safe_dynamic_cast< PointerType* >( funcExpr->get_result() );
+	FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
 
-	for ( std::list< DeclarationWithType* >::const_iterator i = function->get_returnVals().begin(); i != function->get_returnVals().end(); ++i ) {
-		get_results().push_back( (*i)->get_type()->clone() );
-	} // for
+	set_result( ResolvExpr::extractResultType( function ) );
+
+	assert( has_result() );
 }
 
Index: src/SynTree/CommaExpr.cc
===================================================================
--- src/SynTree/CommaExpr.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/CommaExpr.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -23,8 +23,6 @@
 	// to false on all result types. Actually doing this causes some strange things
 	// to happen in later passes (particularly, Specialize, Lvalue, and Box). This needs to be looked into.
-	cloneAll( arg2->get_results(), get_results() );
-	// for ( Type *& type : get_results() ) {
-	// 	type->set_isLvalue( false );
-	// }
+	set_result( maybeClone( arg2->get_result() ) );
+	// get_type->set_isLvalue( false );
 }
 
Index: src/SynTree/CompoundStmt.cc
===================================================================
--- src/SynTree/CompoundStmt.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/CompoundStmt.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -20,24 +20,8 @@
 #include "Expression.h"
 #include "Declaration.h"
+#include "SynTree/VarExprReplacer.h"
 
 using std::string;
 using std::endl;
-
-class VarExprReplacer : public Visitor {
-public:
-  typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
-private:
-  const DeclMap & declMap;
-public:
-  VarExprReplacer( const DeclMap & declMap ) : declMap( declMap ) {}
-
-  // replace variable with new node from decl map
-  virtual void visit( VariableExpr * varExpr ) {
-    if ( declMap.count( varExpr->get_var() ) ) {
-      varExpr->set_var( declMap.at( varExpr->get_var() ) );
-    }
-  }
-};
-
 
 CompoundStmt::CompoundStmt( std::list<Label> labels ) : Statement( labels ) {
@@ -47,34 +31,36 @@
 	cloneAll( other.kids, kids );
 
-  // when cloning a compound statement, we may end up cloning declarations which
-  // are referred to by VariableExprs throughout the block. Cloning a VariableExpr
-  // does a shallow copy, so the VariableExpr will end up pointing to the original
-  // declaration. If the original declaration is deleted, e.g. because the original
-  // CompoundStmt is deleted, then we have a dangling pointer. To avoid this case,
-  // find all DeclarationWithType nodes (since a VariableExpr must point to a
-  // DeclarationWithType) in the original CompoundStmt and map them to the cloned
-  // node in the new CompoundStmt ('this'), then replace the Declarations referred to
-  // by each VariableExpr according to the constructed map. Note that only the declarations
-  // in the current level are collected into the map, because child CompoundStmts will
-  // recursively execute this routine. There may be more efficient ways of doing
-  // this.
-  VarExprReplacer::DeclMap declMap;
-  std::list< Statement * >::const_iterator origit = other.kids.begin();
-  for ( Statement * s : kids ) {
-    assert( origit != other.kids.end() );
-    if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( s ) ) {
-      DeclStmt * origDeclStmt = dynamic_cast< DeclStmt * >( *origit );
-      assert( origDeclStmt );
-      if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * > ( declStmt->get_decl() ) ) {
-        DeclarationWithType * origdwt = dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );
-        assert( origdwt );
-        declMap[ origdwt ] = dwt;
-      }
-    }
-  }
-  if ( ! declMap.empty() ) {
-    VarExprReplacer replacer( declMap );
-    accept( replacer );
-  }
+	// when cloning a compound statement, we may end up cloning declarations which
+	// are referred to by VariableExprs throughout the block. Cloning a VariableExpr
+	// does a shallow copy, so the VariableExpr will end up pointing to the original
+	// declaration. If the original declaration is deleted, e.g. because the original
+	// CompoundStmt is deleted, then we have a dangling pointer. To avoid this case,
+	// find all DeclarationWithType nodes (since a VariableExpr must point to a
+	// DeclarationWithType) in the original CompoundStmt and map them to the cloned
+	// node in the new CompoundStmt ('this'), then replace the Declarations referred to
+	// by each VariableExpr according to the constructed map. Note that only the declarations
+	// in the current level are collected into the map, because child CompoundStmts will
+	// recursively execute this routine. There may be more efficient ways of doing
+	// this.
+	VarExprReplacer::DeclMap declMap;
+	std::list< Statement * >::const_iterator origit = other.kids.begin();
+	for ( Statement * s : kids ) {
+		assert( origit != other.kids.end() );
+		Statement * origStmt = *origit++;
+		if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( s ) ) {
+			DeclStmt * origDeclStmt = dynamic_cast< DeclStmt * >( origStmt );
+			assert( origDeclStmt );
+			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * > ( declStmt->get_decl() ) ) {
+				DeclarationWithType * origdwt = dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );
+				assert( origdwt );
+				assert( dwt->get_name() == origdwt->get_name() );
+				declMap[ origdwt ] = dwt;
+			}
+		}
+	}
+	if ( ! declMap.empty() ) {
+		VarExprReplacer replacer( declMap );
+		accept( replacer );
+	}
 }
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/Expression.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -31,8 +31,7 @@
 
 
-Expression::Expression( Expression *_aname ) : env( 0 ), argName( _aname ) {}
-
-Expression::Expression( const Expression &other ) : env( maybeClone( other.env ) ), argName( maybeClone( other.get_argName() ) ), extension( other.extension ) {
-	cloneAll( other.results, results );
+Expression::Expression( Expression *_aname ) : result( 0 ), env( 0 ), argName( _aname ) {}
+
+Expression::Expression( const Expression &other ) : result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), argName( maybeClone( other.get_argName() ) ), extension( other.extension ) {
 }
 
@@ -40,13 +39,5 @@
 	delete env;
 	delete argName;	// xxx -- there's a problem in cloning ConstantExpr I still don't know how to fix
-	deleteAll( results );
-}
-
-void Expression::add_result( Type *t ) {
-	if ( TupleType *tuple = dynamic_cast< TupleType* >( t ) ) {
-		std::copy( tuple->get_types().begin(), tuple->get_types().end(), back_inserter( results ) );
-	} else {
-		results.push_back(t);
-	} // if
+	delete result;
 }
 
@@ -68,5 +59,5 @@
 
 ConstantExpr::ConstantExpr( Constant _c, Expression *_aname ) : Expression( _aname ), constant( _c ) {
-	add_result( constant.get_type()->clone() );
+	set_result( constant.get_type()->clone() );
 }
 
@@ -85,8 +76,7 @@
 	assert( var );
 	assert( var->get_type() );
-	add_result( var->get_type()->clone() );
-	for ( std::list< Type* >::iterator i = get_results().begin(); i != get_results().end(); ++i ) {
-		(*i)->set_isLvalue( true );
-	} // for
+	Type * type = var->get_type()->clone();
+	type->set_isLvalue( true );
+	set_result( type );
 }
 
@@ -110,10 +100,10 @@
 SizeofExpr::SizeofExpr( Expression *expr_, Expression *_aname ) :
 		Expression( _aname ), expr(expr_), type(0), isType(false) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
+	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
 SizeofExpr::SizeofExpr( Type *type_, Expression *_aname ) :
 		Expression( _aname ), expr(0), type(type_), isType(true) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
+	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
@@ -141,10 +131,10 @@
 AlignofExpr::AlignofExpr( Expression *expr_, Expression *_aname ) :
 		Expression( _aname ), expr(expr_), type(0), isType(false) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
+	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
 AlignofExpr::AlignofExpr( Type *type_, Expression *_aname ) :
 		Expression( _aname ), expr(0), type(type_), isType(true) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
+	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
@@ -172,5 +162,5 @@
 UntypedOffsetofExpr::UntypedOffsetofExpr( Type *type_, const std::string &member_, Expression *_aname ) :
 		Expression( _aname ), type(type_), member(member_) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
+	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
@@ -197,5 +187,5 @@
 OffsetofExpr::OffsetofExpr( Type *type_, DeclarationWithType *member_, Expression *_aname ) :
 		Expression( _aname ), type(type_), member(member_) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
+	set_result( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) );
 }
 
@@ -229,5 +219,5 @@
 
 OffsetPackExpr::OffsetPackExpr( StructInstType *type_, Expression *aname_ ) : Expression( aname_ ), type( type_ ) {
-	add_result( new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, false, false ) );
+	set_result( new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0, false, false ) );
 }
 
@@ -284,8 +274,9 @@
 
 CastExpr::CastExpr( Expression *arg_, Type *toType, Expression *_aname ) : Expression( _aname ), arg(arg_) {
-	add_result(toType);
+	set_result(toType);
 }
 
 CastExpr::CastExpr( Expression *arg_, Expression *_aname ) : Expression( _aname ), arg(arg_) {
+	set_result( new VoidType( Type::Qualifiers() ) );
 }
 
@@ -303,31 +294,37 @@
 	arg->print(os, indent+2);
 	os << std::endl << std::string( indent, ' ' ) << "to:" << std::endl;
-	if ( results.empty() ) {
-		os << std::string( indent+2, ' ' ) << "nothing" << std::endl;
+	os << std::string( indent+2, ' ' );
+	if ( result->isVoid() ) {
+		os << "nothing";
 	} else {
-		printAll(results, os, indent+2);
+		result->print( os, indent+2 );
 	} // if
-	Expression::print( os, indent );
-}
-
-UntypedMemberExpr::UntypedMemberExpr( std::string _member, Expression *_aggregate, Expression *_aname ) :
+	os << std::endl;
+	Expression::print( os, indent );
+}
+
+UntypedMemberExpr::UntypedMemberExpr( Expression * _member, Expression *_aggregate, Expression *_aname ) :
 		Expression( _aname ), member(_member), aggregate(_aggregate) {}
 
 UntypedMemberExpr::UntypedMemberExpr( const UntypedMemberExpr &other ) :
-		Expression( other ), member( other.member ), aggregate( maybeClone( other.aggregate ) ) {
+		Expression( other ), member( maybeClone( other.member ) ), aggregate( maybeClone( other.aggregate ) ) {
 }
 
 UntypedMemberExpr::~UntypedMemberExpr() {
 	delete aggregate;
+	delete member;
 }
 
 void UntypedMemberExpr::print( std::ostream &os, int indent ) const {
-	os << "Untyped Member Expression, with field: " << get_member();
+	os << "Untyped Member Expression, with field: " << std::endl;
+	os << std::string( indent+2, ' ' );
+	get_member()->print(os, indent+4);
+	os << std::string( indent+2, ' ' );
 
 	Expression *agg = get_aggregate();
-	os << ", from aggregate: ";
+	os << "from aggregate: " << std::endl;
 	if (agg != 0) {
-		os << std::string( indent + 2, ' ' );
-		agg->print(os, indent + 2);
+		os << std::string( indent + 4, ' ' );
+		agg->print(os, indent + 4);
 	}
 	os << std::string( indent+2, ' ' );
@@ -338,8 +335,6 @@
 MemberExpr::MemberExpr( DeclarationWithType *_member, Expression *_aggregate, Expression *_aname ) :
 		Expression( _aname ), member(_member), aggregate(_aggregate) {
-	add_result( member->get_type()->clone() );
-	for ( std::list< Type* >::iterator i = get_results().begin(); i != get_results().end(); ++i ) {
-		(*i)->set_isLvalue( true );
-	} // for
+	set_result( member->get_type()->clone() );
+	get_result()->set_isLvalue( true );
 }
 
@@ -372,6 +367,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 ) :
@@ -380,11 +375,33 @@
 }
 
-UntypedExpr::UntypedExpr( Expression *_function, std::list<Expression *> &_args, Expression *_aname ) :
-		Expression( _aname ), function(_function), args(_args) {}
-
 UntypedExpr::~UntypedExpr() {
 	delete function;
 	deleteAll( args );
 }
+
+UntypedExpr * UntypedExpr::createDeref( Expression * expr ) {
+	UntypedExpr * ret = new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ expr } );
+	if ( Type * type = expr->get_result() ) {
+		Type * base = InitTweak::getPointerBase( type );
+		if ( ! base ) {
+			std::cerr << type << std::endl;
+		}
+		assertf( base, "expected pointer type in dereference\n" );
+		ret->set_result( maybeClone( base ) );
+	}
+	return ret;
+}
+
+UntypedExpr * UntypedExpr::createAssign( Expression * arg1, Expression * arg2 ) {
+	assert( arg1 && arg2 );
+	UntypedExpr * ret = new UntypedExpr( new NameExpr( "?=?" ), std::list< Expression * >{ arg1, arg2 } );
+	if ( arg1->get_result() && arg2->get_result() ) {
+		// if both expressions are typed, assumes that this assignment is a C bitwise assignment,
+		// so the result is the type of the RHS
+		ret->set_result( arg2->get_result()->clone() );
+	}
+	return ret;
+}
+
 
 void UntypedExpr::print( std::ostream &os, int indent ) const {
@@ -419,5 +436,5 @@
 LogicalExpr::LogicalExpr( Expression *arg1_, Expression *arg2_, bool andp, Expression *_aname ) :
 		Expression( _aname ), arg1(arg1_), arg2(arg2_), isAnd(andp) {
-	add_result( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
+	set_result( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
 }
 
@@ -454,9 +471,12 @@
 
 void ConditionalExpr::print( std::ostream &os, int indent ) const {
-	os << std::string( indent, ' ' ) << "Conditional expression on: " << std::endl;
+	os << "Conditional expression on: " << std::endl;
+	os << std::string( indent+2, ' ' );
 	arg1->print( os, indent+2 );
 	os << std::string( indent, ' ' ) << "First alternative:" << std::endl;
+	os << std::string( indent+2, ' ' );
 	arg2->print( os, indent+2 );
 	os << std::string( indent, ' ' ) << "Second alternative:" << std::endl;
+	os << std::string( indent+2, ' ' );
 	arg3->print( os, indent+2 );
 	os << std::endl;
@@ -477,5 +497,6 @@
 ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( ApplicationExpr * callExpr ) : callExpr( callExpr ) {
 	assert( callExpr );
-	cloneAll( callExpr->get_results(), results );
+	assert( callExpr->has_result() );
+	set_result( callExpr->get_result()->clone() );
 }
 
@@ -510,5 +531,5 @@
 	Expression * arg = InitTweak::getCallArg( callExpr, 0 );
 	assert( arg );
-	cloneAll( arg->get_results(), results );
+	set_result( maybeClone( arg->get_result() ) );
 }
 
@@ -530,8 +551,9 @@
 
 CompoundLiteralExpr::CompoundLiteralExpr( Type * type, Initializer * initializer ) : type( type ), initializer( initializer ) {
-	add_result( type->clone() );
-}
-
-CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr &other ) : Expression( other ), type( maybeClone( other.type ) ), initializer( maybeClone( other.initializer ) ) {}
+	assert( type && initializer );
+	set_result( type->clone() );
+}
+
+CompoundLiteralExpr::CompoundLiteralExpr( const CompoundLiteralExpr &other ) : Expression( other ), type( other.type->clone() ), initializer( other.initializer->clone() ) {}
 
 CompoundLiteralExpr::~CompoundLiteralExpr() {
@@ -542,6 +564,8 @@
 void CompoundLiteralExpr::print( std::ostream &os, int indent ) const {
 	os << "Compound Literal Expression: " << std::endl;
-	if ( type ) type->print( os, indent + 2 );
-	if ( initializer ) initializer->print( os, indent + 2 );
+	os << std::string( indent+2, ' ' );
+	type->print( os, indent + 2 );
+	os << std::string( indent+2, ' ' );
+	initializer->print( os, indent + 2 );
 }
 
@@ -557,10 +581,54 @@
 
 RangeExpr::RangeExpr( Expression *low, Expression *high ) : low( low ), high( high ) {}
-RangeExpr::RangeExpr( const RangeExpr &other ) : low( other.low->clone() ), high( other.high->clone() ) {}
+RangeExpr::RangeExpr( const RangeExpr &other ) : Expression( other ), low( other.low->clone() ), high( other.high->clone() ) {}
 void RangeExpr::print( std::ostream &os, int indent ) const {
-	os << std::string( indent, ' ' ) << "Range Expression: ";
+	os << "Range Expression: ";
 	low->print( os, indent );
 	os << " ... ";
 	high->print( os, indent );
+}
+
+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() ) ) {
+			set_result( maybeClone( exprStmt->get_expr()->get_result() ) );
+		}
+	}
+}
+StmtExpr::StmtExpr( const StmtExpr &other ) : Expression( other ), statements( other.statements->clone() ) {}
+StmtExpr::~StmtExpr() {
+	delete statements;
+}
+void StmtExpr::print( std::ostream &os, int indent ) const {
+	os << "Statement Expression: " << std::endl << std::string( indent, ' ' );
+	statements->print( os, indent+2 );
+}
+
+
+long long UniqueExpr::count = 0;
+UniqueExpr::UniqueExpr( Expression *expr, long long idVal ) : expr( expr ), object( nullptr ), var( nullptr ), id( idVal ) {
+	assert( expr );
+	assert( count != -1 );
+	if ( id == -1 ) id = count++;
+	if ( expr->get_result() ) {
+		set_result( expr->get_result()->clone() );
+	}
+}
+UniqueExpr::UniqueExpr( const UniqueExpr &other ) : Expression( other ), expr( maybeClone( other.expr ) ), object( maybeClone( other.object ) ), var( maybeClone( other.var ) ), id( other.id ) {
+}
+UniqueExpr::~UniqueExpr() {
+	delete expr;
+	delete object;
+	delete var;
+}
+void UniqueExpr::print( std::ostream &os, int indent ) const {
+	os << "Unique Expression with id:" << id << std::endl << std::string( indent+2, ' ' );
+	get_expr()->print( os, indent+2 );
+	if ( get_object() ) {
+		os << " with decl: ";
+		get_object()->printShort( os, indent+2 );
+	}
 }
 
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/Expression.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -32,6 +32,7 @@
 	virtual ~Expression();
 
-	std::list<Type *>& get_results() { return results; }
-	void add_result( Type *t );
+	Type *& get_result() { return result; }
+	void set_result( Type *newValue ) { result = newValue; }
+	bool has_result() const { return result != nullptr; }
 
 	TypeSubstitution *get_env() const { return env; }
@@ -47,5 +48,5 @@
 	virtual void print( std::ostream &os, int indent = 0 ) const;
   protected:
-	std::list<Type *> results;
+	Type * result;
 	TypeSubstitution *env;
 	Expression* argName; // if expression is used as an argument, it can be "designated" by this name
@@ -98,7 +99,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();
 
@@ -111,4 +111,7 @@
 	std::list<Expression*>& get_args() { return args; }
 
+	static UntypedExpr * createDeref( Expression * arg );
+	static UntypedExpr * createAssign( Expression * arg1, Expression * arg2 );
+
 	virtual UntypedExpr *clone() const { return new UntypedExpr( *this ); }
 	virtual void accept( Visitor &v ) { v.visit( this ); }
@@ -200,10 +203,10 @@
 class UntypedMemberExpr : public Expression {
   public:
-	UntypedMemberExpr( std::string member, Expression *aggregate, Expression *_aname = nullptr );
+	UntypedMemberExpr( Expression *member, Expression *aggregate, Expression *_aname = nullptr );
 	UntypedMemberExpr( const UntypedMemberExpr &other );
 	virtual ~UntypedMemberExpr();
 
-	std::string get_member() const { return member; }
-	void set_member( const std::string &newValue ) { member = newValue; }
+	Expression * get_member() const { return member; }
+	void set_member( Expression * newValue ) { member = newValue; }
 	Expression *get_aggregate() const { return aggregate; }
 	void set_aggregate( Expression *newValue ) { aggregate = newValue; }
@@ -214,5 +217,5 @@
 	virtual void print( std::ostream &os, int indent = 0 ) const;
   private:
-	std::string member;
+	Expression *member;
 	Expression *aggregate;
 };
@@ -483,40 +486,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 {
@@ -618,5 +585,5 @@
 	CompoundLiteralExpr( Type * type, Initializer * initializer );
 	CompoundLiteralExpr( const CompoundLiteralExpr &other );
-	~CompoundLiteralExpr();
+	virtual ~CompoundLiteralExpr();
 
 	Type * get_type() const { return type; }
@@ -670,4 +637,130 @@
   private:
 	Expression *low, *high;
+};
+
+/// TupleExpr represents a tuple expression ( [a, b, c] )
+class TupleExpr : public Expression {
+  public:
+	TupleExpr( const std::list< Expression * > & exprs = std::list< Expression * >(), 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 {
+  public:
+	TupleIndexExpr( Expression * tuple, unsigned int index );
+	TupleIndexExpr( const TupleIndexExpr &other );
+	virtual ~TupleIndexExpr();
+
+	Expression * get_tuple() const { return tuple; }
+	int get_index() const { return index; }
+	TupleIndexExpr * set_tuple( Expression *newValue ) { tuple = newValue; return this; }
+	TupleIndexExpr * set_index( unsigned int newValue ) { index = newValue; return this; }
+
+	virtual TupleIndexExpr *clone() const { return new TupleIndexExpr( *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 * tuple;
+	unsigned int index;
+};
+
+/// MemberTupleExpr represents a tuple member selection operation on a struct type, e.g. s.[a, b, c] after processing by the expression analyzer
+class MemberTupleExpr : public Expression {
+  public:
+	MemberTupleExpr( Expression * member, Expression * aggregate, Expression * _aname = nullptr );
+	MemberTupleExpr( const MemberTupleExpr &other );
+	virtual ~MemberTupleExpr();
+
+	Expression * get_member() const { return member; }
+	Expression * get_aggregate() const { return aggregate; }
+	MemberTupleExpr * set_member( Expression *newValue ) { member = newValue; return this; }
+	MemberTupleExpr * set_aggregate( Expression *newValue ) { aggregate = newValue; return this; }
+
+	virtual MemberTupleExpr *clone() const { return new MemberTupleExpr( *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 * member;
+	Expression * aggregate;
+};
+
+/// TupleAssignExpr represents a multiple assignment operation, where both sides of the assignment have tuple type, e.g. [a, b, c] = [d, e, f];, 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;, or a tuple ctor/dtor expression
+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;
+};
+
+class UniqueExpr : public Expression {
+public:
+	UniqueExpr( Expression * expr, long long idVal = -1 );
+	UniqueExpr( const UniqueExpr & other );
+	~UniqueExpr();
+
+	Expression * get_expr() const { return expr; }
+	UniqueExpr * set_expr( Expression * newValue ) { expr = newValue; return this; }
+
+	ObjectDecl * get_object() const { return object; }
+	UniqueExpr * set_object( ObjectDecl * newValue ) { object = newValue; return this; }
+
+	VariableExpr * get_var() const { return var; }
+	UniqueExpr * set_var( VariableExpr * newValue ) { var = newValue; return this; }
+
+	int get_id() const { return id; }
+
+	virtual UniqueExpr *clone() const { return new UniqueExpr( *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 * expr;
+	ObjectDecl * object;
+	VariableExpr * var;
+	int id;
+	static long long count;
 };
 
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/Initializer.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -23,4 +23,6 @@
 
 #include <cassert>
+
+const std::list<Expression*> noDesignators;
 
 // Initializer: base class for object initializers (provide default values)
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/Mutator.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -178,5 +178,5 @@
 
 Expression *Mutator::mutate( ApplicationExpr *applicationExpr ) {
-	mutateAll( applicationExpr->get_results(), *this );
+	applicationExpr->set_result( maybeMutate( applicationExpr->get_result(), *this ) );
 	applicationExpr->set_function( maybeMutate( applicationExpr->get_function(), *this ) );
 	mutateAll( applicationExpr->get_args(), *this );
@@ -185,5 +185,5 @@
 
 Expression *Mutator::mutate( UntypedExpr *untypedExpr ) {
-	mutateAll( untypedExpr->get_results(), *this );
+	untypedExpr->set_result( maybeMutate( untypedExpr->get_result(), *this ) );
 	mutateAll( untypedExpr->get_args(), *this );
 	return untypedExpr;
@@ -191,10 +191,10 @@
 
 Expression *Mutator::mutate( NameExpr *nameExpr ) {
-	mutateAll( nameExpr->get_results(), *this );
+	nameExpr->set_result( maybeMutate( nameExpr->get_result(), *this ) );
 	return nameExpr;
 }
 
 Expression *Mutator::mutate( AddressExpr *addressExpr ) {
-	mutateAll( addressExpr->get_results(), *this );
+	addressExpr->set_result( maybeMutate( addressExpr->get_result(), *this ) );
 	addressExpr->set_arg( maybeMutate( addressExpr->get_arg(), *this ) );
 	return addressExpr;
@@ -202,5 +202,5 @@
 
 Expression *Mutator::mutate( LabelAddressExpr *labelAddressExpr ) {
-	mutateAll( labelAddressExpr->get_results(), *this );
+	labelAddressExpr->set_result( maybeMutate( labelAddressExpr->get_result(), *this ) );
 	labelAddressExpr->set_arg( maybeMutate( labelAddressExpr->get_arg(), *this ) );
 	return labelAddressExpr;
@@ -208,5 +208,5 @@
 
 Expression *Mutator::mutate( CastExpr *castExpr ) {
-	mutateAll( castExpr->get_results(), *this );
+	castExpr->set_result( maybeMutate( castExpr->get_result(), *this ) );
 	castExpr->set_arg( maybeMutate( castExpr->get_arg(), *this ) );
 	return castExpr;
@@ -214,22 +214,23 @@
 
 Expression *Mutator::mutate( UntypedMemberExpr *memberExpr ) {
-	mutateAll( memberExpr->get_results(), *this );
+	memberExpr->set_result( maybeMutate( memberExpr->get_result(), *this ) );
+	memberExpr->set_aggregate( maybeMutate( memberExpr->get_aggregate(), *this ) );
+	memberExpr->set_member( maybeMutate( memberExpr->get_member(), *this ) );
+	return memberExpr;
+}
+
+Expression *Mutator::mutate( MemberExpr *memberExpr ) {
+	memberExpr->set_result( maybeMutate( memberExpr->get_result(), *this ) );
 	memberExpr->set_aggregate( maybeMutate( memberExpr->get_aggregate(), *this ) );
 	return memberExpr;
 }
 
-Expression *Mutator::mutate( MemberExpr *memberExpr ) {
-	mutateAll( memberExpr->get_results(), *this );
-	memberExpr->set_aggregate( maybeMutate( memberExpr->get_aggregate(), *this ) );
-	return memberExpr;
-}
-
 Expression *Mutator::mutate( VariableExpr *variableExpr ) {
-	mutateAll( variableExpr->get_results(), *this );
+	variableExpr->set_result( maybeMutate( variableExpr->get_result(), *this ) );
 	return variableExpr;
 }
 
 Expression *Mutator::mutate( ConstantExpr *constantExpr ) {
-	mutateAll( constantExpr->get_results(), *this );
+	constantExpr->set_result( maybeMutate( constantExpr->get_result(), *this ) );
 //  maybeMutate( constantExpr->get_constant(), *this )
 	return constantExpr;
@@ -237,5 +238,5 @@
 
 Expression *Mutator::mutate( SizeofExpr *sizeofExpr ) {
-	mutateAll( sizeofExpr->get_results(), *this );
+	sizeofExpr->set_result( maybeMutate( sizeofExpr->get_result(), *this ) );
 	if ( sizeofExpr->get_isType() ) {
 		sizeofExpr->set_type( maybeMutate( sizeofExpr->get_type(), *this ) );
@@ -247,5 +248,5 @@
 
 Expression *Mutator::mutate( AlignofExpr *alignofExpr ) {
-	mutateAll( alignofExpr->get_results(), *this );
+	alignofExpr->set_result( maybeMutate( alignofExpr->get_result(), *this ) );
 	if ( alignofExpr->get_isType() ) {
 		alignofExpr->set_type( maybeMutate( alignofExpr->get_type(), *this ) );
@@ -257,5 +258,5 @@
 
 Expression *Mutator::mutate( UntypedOffsetofExpr *offsetofExpr ) {
-	mutateAll( offsetofExpr->get_results(), *this );
+	offsetofExpr->set_result( maybeMutate( offsetofExpr->get_result(), *this ) );
 	offsetofExpr->set_type( maybeMutate( offsetofExpr->get_type(), *this ) );
 	return offsetofExpr;
@@ -263,5 +264,5 @@
 
 Expression *Mutator::mutate( OffsetofExpr *offsetofExpr ) {
-	mutateAll( offsetofExpr->get_results(), *this );
+	offsetofExpr->set_result( maybeMutate( offsetofExpr->get_result(), *this ) );
 	offsetofExpr->set_type( maybeMutate( offsetofExpr->get_type(), *this ) );
 	offsetofExpr->set_member( maybeMutate( offsetofExpr->get_member(), *this ) );
@@ -270,5 +271,5 @@
 
 Expression *Mutator::mutate( OffsetPackExpr *offsetPackExpr ) {
-	mutateAll( offsetPackExpr->get_results(), *this );
+	offsetPackExpr->set_result( maybeMutate( offsetPackExpr->get_result(), *this ) );
 	offsetPackExpr->set_type( maybeMutate( offsetPackExpr->get_type(), *this ) );
 	return offsetPackExpr;
@@ -276,5 +277,5 @@
 
 Expression *Mutator::mutate( AttrExpr *attrExpr ) {
-	mutateAll( attrExpr->get_results(), *this );
+	attrExpr->set_result( maybeMutate( attrExpr->get_result(), *this ) );
 	if ( attrExpr->get_isType() ) {
 		attrExpr->set_type( maybeMutate( attrExpr->get_type(), *this ) );
@@ -286,5 +287,5 @@
 
 Expression *Mutator::mutate( LogicalExpr *logicalExpr ) {
-	mutateAll( logicalExpr->get_results(), *this );
+	logicalExpr->set_result( maybeMutate( logicalExpr->get_result(), *this ) );
 	logicalExpr->set_arg1( maybeMutate( logicalExpr->get_arg1(), *this ) );
 	logicalExpr->set_arg2( maybeMutate( logicalExpr->get_arg2(), *this ) );
@@ -293,5 +294,5 @@
 
 Expression *Mutator::mutate( ConditionalExpr *conditionalExpr ) {
-	mutateAll( conditionalExpr->get_results(), *this );
+	conditionalExpr->set_result( maybeMutate( conditionalExpr->get_result(), *this ) );
 	conditionalExpr->set_arg1( maybeMutate( conditionalExpr->get_arg1(), *this ) );
 	conditionalExpr->set_arg2( maybeMutate( conditionalExpr->get_arg2(), *this ) );
@@ -301,5 +302,5 @@
 
 Expression *Mutator::mutate( CommaExpr *commaExpr ) {
-	mutateAll( commaExpr->get_results(), *this );
+	commaExpr->set_result( maybeMutate( commaExpr->get_result(), *this ) );
 	commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) );
 	commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) );
@@ -307,18 +308,6 @@
 }
 
-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 );
+	typeExpr->set_result( maybeMutate( typeExpr->get_result(), *this ) );
 	typeExpr->set_type( maybeMutate( typeExpr->get_type(), *this ) );
 	return typeExpr;
@@ -340,5 +329,5 @@
 
 Expression* Mutator::mutate( ConstructorExpr *ctorExpr ) {
-	mutateAll( ctorExpr->get_results(), *this );
+	ctorExpr->set_result( maybeMutate( ctorExpr->get_result(), *this ) );
 	ctorExpr->set_callExpr( maybeMutate( ctorExpr->get_callExpr(), *this ) );
 	return ctorExpr;
@@ -346,5 +335,5 @@
 
 Expression *Mutator::mutate( CompoundLiteralExpr *compLitExpr ) {
-	mutateAll( compLitExpr->get_results(), *this );
+	compLitExpr->set_result( maybeMutate( compLitExpr->get_result(), *this ) );
 	compLitExpr->set_type( maybeMutate( compLitExpr->get_type(), *this ) );
 	compLitExpr->set_initializer( maybeMutate( compLitExpr->get_initializer(), *this ) );
@@ -353,5 +342,5 @@
 
 Expression *Mutator::mutate( UntypedValofExpr *valofExpr ) {
-	mutateAll( valofExpr->get_results(), *this );
+	valofExpr->set_result( maybeMutate( valofExpr->get_result(), *this ) );
 	return valofExpr;
 }
@@ -361,4 +350,42 @@
 	rangeExpr->set_high( maybeMutate( rangeExpr->get_high(), *this ) );
 	return rangeExpr;
+}
+
+Expression *Mutator::mutate( TupleExpr *tupleExpr ) {
+	tupleExpr->set_result( maybeMutate( tupleExpr->get_result(), *this ) );
+	mutateAll( tupleExpr->get_exprs(), *this );
+	return tupleExpr;
+}
+
+Expression *Mutator::mutate( TupleIndexExpr *tupleExpr ) {
+	tupleExpr->set_result( maybeMutate( tupleExpr->get_result(), *this ) );
+	tupleExpr->set_tuple( maybeMutate( tupleExpr->get_tuple(), *this ) );
+	return tupleExpr;
+}
+
+Expression *Mutator::mutate( MemberTupleExpr *tupleExpr ) {
+	tupleExpr->set_result( maybeMutate( tupleExpr->get_result(), *this ) );
+	tupleExpr->set_member( maybeMutate( tupleExpr->get_member(), *this ) );
+	tupleExpr->set_aggregate( maybeMutate( tupleExpr->get_aggregate(), *this ) );
+	return tupleExpr;
+}
+
+Expression *Mutator::mutate( TupleAssignExpr *assignExpr ) {
+	assignExpr->set_result( maybeMutate( assignExpr->get_result(), *this ) );
+	mutateAll( assignExpr->get_tempDecls(), *this );
+	mutateAll( assignExpr->get_assigns(), *this );
+	return assignExpr;
+}
+
+Expression *Mutator::mutate( StmtExpr *stmtExpr ) {
+	stmtExpr->set_result( maybeMutate( stmtExpr->get_result(), *this ) );
+	stmtExpr->set_statements( maybeMutate( stmtExpr->get_statements(), *this ) );
+	return stmtExpr;
+}
+
+Expression *Mutator::mutate( UniqueExpr *uniqueExpr ) {
+	uniqueExpr->set_result( maybeMutate( uniqueExpr->get_result(), *this ) );
+	uniqueExpr->set_expr( maybeMutate( uniqueExpr->get_expr(), *this ) );
+	return uniqueExpr;
 }
 
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/Mutator.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -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,4 +78,10 @@
 	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( TupleAssignExpr *assignExpr );
+	virtual Expression* mutate( StmtExpr * stmtExpr );
+	virtual Expression* mutate( UniqueExpr * uniqueExpr );
 
 	virtual Type* mutate( VoidType *basicType );
Index: src/SynTree/ReferenceToType.cc
===================================================================
--- src/SynTree/ReferenceToType.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/ReferenceToType.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -56,4 +56,6 @@
 	}
 } // namespace
+
+StructInstType::StructInstType( const Type::Qualifiers & tq, StructDecl * baseStruct ) : Parent( tq, baseStruct->get_name() ), baseStruct( baseStruct ) {}
 
 std::string StructInstType::typeString() const { return "struct"; }
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/SynTree.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -76,6 +76,4 @@
 class ConditionalExpr;
 class CommaExpr;
-class TupleExpr;
-class SolvedTupleExpr;
 class TypeExpr;
 class AsmExpr;
@@ -85,4 +83,10 @@
 class UntypedValofExpr;
 class RangeExpr;
+class TupleExpr;
+class TupleIndexExpr;
+class MemberTupleExpr;
+class TupleAssignExpr;
+class StmtExpr;
+class UniqueExpr;
 
 class Type;
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/TupleExpr.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// TupleExpr.cc -- 
+// TupleExpr.cc --
 //
 // Author           : Richard C. Bilson
@@ -16,6 +16,15 @@
 #include "Expression.h"
 #include "Common/utility.h"
+#include "Type.h"
+#include "Declaration.h"
+#include "Tuples/Tuples.h"
+#include "VarExprReplacer.h"
 
-TupleExpr::TupleExpr( Expression *_aname ) : Expression( _aname ) {
+TupleExpr::TupleExpr( const std::list< Expression * > & exprs, Expression *_aname ) : Expression( _aname ), exprs( exprs ) {
+	if ( ! exprs.empty() ) {
+		if ( std::all_of( exprs.begin(), exprs.end(), [](Expression * expr) { return expr->get_result(); } ) ) {
+			set_result( Tuples::makeTupleType( exprs ) );
+		}
+	}
 }
 
@@ -29,22 +38,94 @@
 
 void TupleExpr::print( std::ostream &os, int indent ) const {
-	os << std::string( indent, ' ' ) << "Tuple:" << std::endl;
+	os << "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));
+TupleIndexExpr::TupleIndexExpr( Expression * tuple, unsigned int index ) : tuple( tuple ), index( index )  {
+	TupleType * type = safe_dynamic_cast< TupleType * >( tuple->get_result() );
+	assert( type->size() > index );
+	set_result( (*std::next( type->get_types().begin(), index ))->clone() );
+	get_result()->set_isLvalue( type->get_isLvalue() );
 }
 
-SolvedTupleExpr::SolvedTupleExpr( const SolvedTupleExpr &other ) : Expression( other ) {
-	cloneAll( other.exprs, exprs );
+TupleIndexExpr::TupleIndexExpr( const TupleIndexExpr &other ) : Expression( other ), tuple( other.tuple->clone() ), index( other.index ) {
 }
 
-void SolvedTupleExpr::print( std::ostream &os, int indent ) const {
-	os << std::string( indent, ' ' ) << "Solved Tuple:" << std::endl;
-	printAll( exprs, os, indent+2 );
+TupleIndexExpr::~TupleIndexExpr() {
+	delete tuple;
+}
+
+void TupleIndexExpr::print( std::ostream &os, int indent ) const {
+	os << "Tuple Index Expression, with tuple:" << std::endl;
+	os << std::string( indent+2, ' ' );
+	tuple->print( os, indent+2 );
+	os << std::string( indent+2, ' ' ) << "with index: " << index << std::endl;
 	Expression::print( os, indent );
 }
+
+MemberTupleExpr::MemberTupleExpr( Expression * member, Expression * aggregate, Expression * _aname ) : Expression( _aname ) {
+	set_result( maybeClone( member->get_result() ) ); // xxx - ???
+}
+
+MemberTupleExpr::MemberTupleExpr( const MemberTupleExpr &other ) : Expression( other ), member( other.member->clone() ), aggregate( other.aggregate->clone() ) {
+}
+
+MemberTupleExpr::~MemberTupleExpr() {
+	delete member;
+	delete aggregate;
+}
+
+void MemberTupleExpr::print( std::ostream &os, int indent ) const {
+	os << "Member Tuple Expression, with aggregate:" << std::endl;
+	os << std::string( indent+2, ' ' );
+	aggregate->print( os, indent+2 );
+	os << std::string( indent+2, ' ' ) << "with member: " << std::endl;
+	os << std::string( indent+2, ' ' );
+	member->print( os, indent+2 );
+	Expression::print( os, indent );
+}
+
+
+TupleAssignExpr::TupleAssignExpr( const std::list< Expression * > & assigns, const std::list< ObjectDecl * > & tempDecls, Expression * _aname ) : Expression( _aname ), assigns( assigns ), tempDecls( tempDecls ) {
+	set_result( Tuples::makeTupleType( assigns ) );
+}
+
+TupleAssignExpr::TupleAssignExpr( const TupleAssignExpr &other ) : Expression( other ) {
+	cloneAll( other.assigns, assigns );
+	cloneAll( other.tempDecls, tempDecls );
+
+	// clone needs to go into assigns and replace tempDecls
+	VarExprReplacer::DeclMap declMap;
+	std::list< ObjectDecl * >::const_iterator origit = other.tempDecls.begin();
+	for ( ObjectDecl * temp : tempDecls ) {
+		assert( origit != other.tempDecls.end() );
+		ObjectDecl * origTemp = *origit++;
+		assert( origTemp );
+		assert( temp->get_name() == origTemp->get_name() );
+		declMap[ origTemp ] = temp;
+	}
+	if ( ! declMap.empty() ) {
+		VarExprReplacer replacer( declMap );
+		for ( Expression * assn : assigns ) {
+			assn->accept( replacer );
+		}
+	}
+}
+
+TupleAssignExpr::~TupleAssignExpr() {
+	deleteAll( assigns );
+	// deleteAll( tempDecls );
+}
+
+void TupleAssignExpr::print( std::ostream &os, int indent ) const {
+	os << "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: //
Index: src/SynTree/TupleType.cc
===================================================================
--- src/SynTree/TupleType.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/TupleType.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -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 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/Type.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -20,4 +20,5 @@
 #include "Visitor.h"
 #include "Mutator.h"
+#include "Common/utility.h"
 
 class Type {
@@ -27,4 +28,5 @@
 		Qualifiers( bool isConst, bool isVolatile, bool isRestrict, bool isLvalue, bool isAtomic, bool isAttribute ): isConst( isConst ), isVolatile( isVolatile ), isRestrict( isRestrict ), isLvalue( isLvalue ), isAtomic( isAtomic ), isAttribute( isAttribute ) {}
 
+		Qualifiers &operator&=( const Qualifiers &other );
 		Qualifiers &operator+=( const Qualifiers &other );
 		Qualifiers &operator-=( const Qualifiers &other );
@@ -63,5 +65,11 @@
 	void set_isAtomic( bool newValue ) { tq.isAtomic = newValue; }
 	void set_isAttribute( bool newValue ) { tq.isAttribute = newValue; }
-	std::list<TypeDecl*>& get_forall() { return forall; }
+
+	typedef std::list<TypeDecl *> ForallList;
+	ForallList& get_forall() { return forall; }
+
+	/// How many elemental types are represented by this type
+	virtual unsigned size() const { return 1; };
+	virtual bool isVoid() const { return size() == 0; }
 
 	virtual Type *clone() const = 0;
@@ -71,5 +79,5 @@
   private:
 	Qualifiers tq;
-	std::list<TypeDecl*> forall;
+	ForallList forall;
 };
 
@@ -77,4 +85,6 @@
   public:
 	VoidType( const Type::Qualifiers &tq );
+
+	virtual unsigned size() const { return 0; };
 
 	virtual VoidType *clone() const { return new VoidType( *this ); }
@@ -234,4 +244,5 @@
   public:
 	StructInstType( const Type::Qualifiers &tq, const std::string &name ) : Parent( tq, name ), baseStruct( 0 ) {}
+	StructInstType( const Type::Qualifiers &tq, StructDecl * baseStruct );
 	StructInstType( const StructInstType &other ) : Parent( other ), baseStruct( other.baseStruct ) {}
 
@@ -348,9 +359,16 @@
 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();
 
+	typedef std::list<Type*> value_type;
+	typedef value_type::iterator iterator;
+
 	std::list<Type*>& get_types() { return types; }
+	virtual unsigned size() const { return types.size(); };
+
+	iterator begin() { return types.begin(); }
+	iterator end() { return types.end(); }
 
 	virtual TupleType *clone() const { return new TupleType( *this ); }
@@ -442,4 +460,13 @@
 };
 
+inline Type::Qualifiers &Type::Qualifiers::operator&=( const Type::Qualifiers &other ) {
+	isConst &= other.isConst;
+	isVolatile &= other.isVolatile;
+	isRestrict &= other.isRestrict;
+	isLvalue &= other.isLvalue;
+	isAtomic &= other.isAtomic;
+	return *this;
+}
+
 inline Type::Qualifiers &Type::Qualifiers::operator+=( const Type::Qualifiers &other ) {
 	isConst |= other.isConst;
Index: src/SynTree/TypeSubstitution.cc
===================================================================
--- src/SynTree/TypeSubstitution.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/TypeSubstitution.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -72,23 +72,23 @@
 Type *TypeSubstitution::lookup( std::string formalType ) const {
 	TypeEnvType::const_iterator i = typeEnv.find( formalType );
-	
+
 	// break on not in substitution set
 	if ( i == typeEnv.end() ) return 0;
-	
+
 	// attempt to transitively follow TypeInstType links.
 	while ( TypeInstType *actualType = dynamic_cast< TypeInstType* >( i->second ) ) {
 		const std::string& typeName = actualType->get_name();
-		
+
 		// break cycles in the transitive follow
 		if ( formalType == typeName ) break;
-		
+
 		// Look for the type this maps to, returning previous mapping if none-such
 		i = typeEnv.find( typeName );
 		if ( i == typeEnv.end() ) return actualType;
 	}
-	
+
 	// return type from substitution set
 	return i->second;
-	
+
 #if 0
 	if ( i == typeEnv.end() ) {
@@ -149,5 +149,5 @@
 	// bind type variables from forall-qualifiers
 	if ( freeOnly ) {
-		for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
+		for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
 			boundVars.insert( (*tyvar )->get_name() );
 		} // for
@@ -163,5 +163,5 @@
 	// bind type variables from forall-qualifiers
 	if ( freeOnly ) {
-		for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
+		for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
 			boundVars.insert( (*tyvar )->get_name() );
 		} // for
Index: src/SynTree/VarExprReplacer.cc
===================================================================
--- src/SynTree/VarExprReplacer.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/SynTree/VarExprReplacer.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,26 @@
+//
+// 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.
+//
+// VarExprReplacer.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Jan 13 16:29:30 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:27:52 2016
+// Update Count     : 5
+//
+
+#include "Expression.h"
+#include "VarExprReplacer.h"
+
+VarExprReplacer::VarExprReplacer( const DeclMap & declMap ) : declMap( declMap ) {}
+
+// replace variable with new node from decl map
+void VarExprReplacer::visit( VariableExpr * varExpr ) {
+  if ( declMap.count( varExpr->get_var() ) ) {
+    varExpr->set_var( declMap.at( varExpr->get_var() ) );
+  }
+}
Index: src/SynTree/VarExprReplacer.h
===================================================================
--- src/SynTree/VarExprReplacer.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/SynTree/VarExprReplacer.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,42 @@
+//
+// 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.
+//
+// VarExprReplacer.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Jan 13 16:29:30 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:27:52 2016
+// Update Count     : 5
+//
+
+#ifndef VAR_EXPR_REPLACER_H
+#define VAR_EXPR_REPLACER_H
+
+#include <map>
+
+#include "SynTree/SynTree.h"
+
+/// Visitor that replaces the declarations that VariableExprs refer to, according to the supplied mapping
+class VarExprReplacer : public Visitor {
+public:
+	typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
+private:
+	const DeclMap & declMap;
+public:
+	VarExprReplacer( const DeclMap & declMap );
+
+	// replace variable with new node from decl map
+	virtual void visit( VariableExpr * varExpr );
+};
+
+#endif // VAR_EXPR_REPLACER_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/Visitor.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -150,5 +150,5 @@
 
 void Visitor::visit( ApplicationExpr *applicationExpr ) {
-	acceptAll( applicationExpr->get_results(), *this );
+	maybeAccept( applicationExpr->get_result(), *this );
 	maybeAccept( applicationExpr->get_function(), *this );
 	acceptAll( applicationExpr->get_args(), *this );
@@ -156,48 +156,49 @@
 
 void Visitor::visit( UntypedExpr *untypedExpr ) {
-	acceptAll( untypedExpr->get_results(), *this );
+	maybeAccept( untypedExpr->get_result(), *this );
 	acceptAll( untypedExpr->get_args(), *this );
 }
 
 void Visitor::visit( NameExpr *nameExpr ) {
-	acceptAll( nameExpr->get_results(), *this );
+	maybeAccept( nameExpr->get_result(), *this );
 }
 
 void Visitor::visit( AddressExpr *addressExpr ) {
-	acceptAll( addressExpr->get_results(), *this );
+	maybeAccept( addressExpr->get_result(), *this );
 	maybeAccept( addressExpr->get_arg(), *this );
 }
 
 void Visitor::visit( LabelAddressExpr *labAddressExpr ) {
-	acceptAll( labAddressExpr->get_results(), *this );
+	maybeAccept( labAddressExpr->get_result(), *this );
 	maybeAccept( labAddressExpr->get_arg(), *this );
 }
 
 void Visitor::visit( CastExpr *castExpr ) {
-	acceptAll( castExpr->get_results(), *this );
+	maybeAccept( castExpr->get_result(), *this );
 	maybeAccept( castExpr->get_arg(), *this );
 }
 
 void Visitor::visit( UntypedMemberExpr *memberExpr ) {
-	acceptAll( memberExpr->get_results(), *this );
+	maybeAccept( memberExpr->get_result(), *this );
 	maybeAccept( memberExpr->get_aggregate(), *this );
+	maybeAccept( memberExpr->get_member(), *this );
 }
 
 void Visitor::visit( MemberExpr *memberExpr ) {
-	acceptAll( memberExpr->get_results(), *this );
+	maybeAccept( memberExpr->get_result(), *this );
 	maybeAccept( memberExpr->get_aggregate(), *this );
 }
 
 void Visitor::visit( VariableExpr *variableExpr ) {
-	acceptAll( variableExpr->get_results(), *this );
+	maybeAccept( variableExpr->get_result(), *this );
 }
 
 void Visitor::visit( ConstantExpr *constantExpr ) {
-	acceptAll( constantExpr->get_results(), *this );
+	maybeAccept( constantExpr->get_result(), *this );
 	maybeAccept( constantExpr->get_constant(), *this );
 }
 
 void Visitor::visit( SizeofExpr *sizeofExpr ) {
-	acceptAll( sizeofExpr->get_results(), *this );
+	maybeAccept( sizeofExpr->get_result(), *this );
 	if ( sizeofExpr->get_isType() ) {
 		maybeAccept( sizeofExpr->get_type(), *this );
@@ -208,5 +209,5 @@
 
 void Visitor::visit( AlignofExpr *alignofExpr ) {
-	acceptAll( alignofExpr->get_results(), *this );
+	maybeAccept( alignofExpr->get_result(), *this );
 	if ( alignofExpr->get_isType() ) {
 		maybeAccept( alignofExpr->get_type(), *this );
@@ -217,10 +218,10 @@
 
 void Visitor::visit( UntypedOffsetofExpr *offsetofExpr ) {
-	acceptAll( offsetofExpr->get_results(), *this );
+	maybeAccept( offsetofExpr->get_result(), *this );
 	maybeAccept( offsetofExpr->get_type(), *this );
 }
 
 void Visitor::visit( OffsetofExpr *offsetofExpr ) {
-	acceptAll( offsetofExpr->get_results(), *this );
+	maybeAccept( offsetofExpr->get_result(), *this );
 	maybeAccept( offsetofExpr->get_type(), *this );
 	maybeAccept( offsetofExpr->get_member(), *this );
@@ -228,10 +229,10 @@
 
 void Visitor::visit( OffsetPackExpr *offsetPackExpr ) {
-	acceptAll( offsetPackExpr->get_results(), *this );
+	maybeAccept( offsetPackExpr->get_result(), *this );
 	maybeAccept( offsetPackExpr->get_type(), *this );
 }
 
 void Visitor::visit( AttrExpr *attrExpr ) {
-	acceptAll( attrExpr->get_results(), *this );
+	maybeAccept( attrExpr->get_result(), *this );
 	if ( attrExpr->get_isType() ) {
 		maybeAccept( attrExpr->get_type(), *this );
@@ -242,5 +243,5 @@
 
 void Visitor::visit( LogicalExpr *logicalExpr ) {
-	acceptAll( logicalExpr->get_results(), *this );
+	maybeAccept( logicalExpr->get_result(), *this );
 	maybeAccept( logicalExpr->get_arg1(), *this );
 	maybeAccept( logicalExpr->get_arg2(), *this );
@@ -248,5 +249,5 @@
 
 void Visitor::visit( ConditionalExpr *conditionalExpr ) {
-	acceptAll( conditionalExpr->get_results(), *this );
+	maybeAccept( conditionalExpr->get_result(), *this );
 	maybeAccept( conditionalExpr->get_arg1(), *this );
 	maybeAccept( conditionalExpr->get_arg2(), *this );
@@ -255,21 +256,11 @@
 
 void Visitor::visit( CommaExpr *commaExpr ) {
-	acceptAll( commaExpr->get_results(), *this );
+	maybeAccept( commaExpr->get_result(), *this );
 	maybeAccept( commaExpr->get_arg1(), *this );
 	maybeAccept( commaExpr->get_arg2(), *this );
 }
 
-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 );
+	maybeAccept( typeExpr->get_result(), *this );
 	maybeAccept( typeExpr->get_type(), *this );
 }
@@ -288,10 +279,10 @@
 
 void Visitor::visit( ConstructorExpr * ctorExpr ) {
-	acceptAll( ctorExpr->get_results(), *this );
+	maybeAccept( ctorExpr->get_result(), *this );
 	maybeAccept( ctorExpr->get_callExpr(), *this );
 }
 
 void Visitor::visit( CompoundLiteralExpr *compLitExpr ) {
-	acceptAll( compLitExpr->get_results(), *this );
+	maybeAccept( compLitExpr->get_result(), *this );
 	maybeAccept( compLitExpr->get_type(), *this );
 	maybeAccept( compLitExpr->get_initializer(), *this );
@@ -299,5 +290,5 @@
 
 void Visitor::visit( UntypedValofExpr *valofExpr ) {
-	acceptAll( valofExpr->get_results(), *this );
+	maybeAccept( valofExpr->get_result(), *this );
 	maybeAccept( valofExpr->get_body(), *this );
 }
@@ -306,4 +297,36 @@
 	maybeAccept( rangeExpr->get_low(), *this );
 	maybeAccept( rangeExpr->get_high(), *this );
+}
+
+void Visitor::visit( TupleExpr *tupleExpr ) {
+	maybeAccept( tupleExpr->get_result(), *this );
+	acceptAll( tupleExpr->get_exprs(), *this );
+}
+
+void Visitor::visit( TupleIndexExpr *tupleExpr ) {
+	maybeAccept( tupleExpr->get_result(), *this );
+	maybeAccept( tupleExpr->get_tuple(), *this );
+}
+
+void Visitor::visit( MemberTupleExpr *tupleExpr ) {
+	maybeAccept( tupleExpr->get_result(), *this );
+	maybeAccept( tupleExpr->get_member(), *this );
+	maybeAccept( tupleExpr->get_aggregate(), *this );
+}
+
+void Visitor::visit( TupleAssignExpr *assignExpr ) {
+	maybeAccept( assignExpr->get_result(), *this );
+	acceptAll( assignExpr->get_tempDecls(), *this );
+	acceptAll( assignExpr->get_assigns(), *this );
+}
+
+void Visitor::visit( StmtExpr *stmtExpr ) {
+	maybeAccept( stmtExpr->get_result(), *this );
+	maybeAccept( stmtExpr->get_statements(), *this );
+}
+
+void Visitor::visit( UniqueExpr *uniqueExpr ) {
+	maybeAccept( uniqueExpr->get_result(), *this );
+	maybeAccept( uniqueExpr->get_expr(), *this );
 }
 
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/Visitor.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -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,4 +78,10 @@
 	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( TupleAssignExpr *assignExpr );
+	virtual void visit( StmtExpr * stmtExpr );
+	virtual void visit( UniqueExpr * uniqueExpr );
 
 	virtual void visit( VoidType *basicType );
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/SynTree/module.mk	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -49,4 +49,5 @@
        SynTree/AddStmtVisitor.cc \
        SynTree/TypeSubstitution.cc \
-       SynTree/Attribute.cc
+       SynTree/Attribute.cc \
+       SynTree/VarExprReplacer.cc
 
Index: src/Tuples/Explode.cc
===================================================================
--- src/Tuples/Explode.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/Tuples/Explode.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,82 @@
+//
+// 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.
+//
+// Explode.cc --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Nov 9 13:12:24 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Nov 9 13:20:24 2016
+// Update Count     : 2
+//
+
+#include "Explode.h"
+#include "SynTree/Mutator.h"
+
+namespace Tuples {
+	namespace {
+		struct AddrExploder : public Mutator {
+			bool foundUniqueExpr = false;
+			Expression * applyAddr( Expression * expr, bool first = true ) {
+				if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){
+					std::list< Expression * > exprs;
+					for ( Expression *& expr : tupleExpr->get_exprs() ) {
+						// move & into tuple exprs
+						exprs.push_back( applyAddr( expr, false ) );
+					}
+					// want the top-level expression to be address-taken, but not nested
+					// tuple expressions
+					if ( first ) {
+						return new AddressExpr( new TupleExpr( exprs ) );
+					} else {
+						return new TupleExpr( exprs );
+					}
+				}
+				// anything else should be address-taken as normal
+				return new AddressExpr( expr->clone() );
+			}
+
+			virtual Expression * mutate( UniqueExpr * uniqueExpr ) {
+				// move & into unique expr so that the unique expr has type T* rather than
+				// type T. In particular, this transformation helps with generating the
+				// correct code for address-taken member tuple expressions, since the result
+				// should now be a tuple of addresses rather than the address of a tuple.
+				// Still, this code is a bit awkward, and could use some improvement.
+				foundUniqueExpr = true;
+				UniqueExpr * newUniqueExpr = new UniqueExpr( applyAddr( uniqueExpr->get_expr() ), uniqueExpr->get_id() );
+				delete uniqueExpr;
+				UntypedExpr * deref = UntypedExpr::createDeref( Mutator::mutate( newUniqueExpr ) );
+				return deref;
+			}
+
+			virtual Expression * mutate( TupleIndexExpr * tupleExpr ) {
+				// tuple index expr needs to be rebuilt to ensure that the type of the
+				// field is consistent with the type of the tuple expr, since the field
+				// may have changed from type T to T*.
+				Expression * expr = tupleExpr->get_tuple()->acceptMutator( *this );
+				tupleExpr->set_tuple( nullptr );
+				TupleIndexExpr * ret = new TupleIndexExpr( expr, tupleExpr->get_index() );
+				delete tupleExpr;
+				return ret;
+			}
+		};
+	} // namespace
+
+	Expression * distributeAddr( Expression * expr ) {
+		AddrExploder addrExploder;
+		expr = expr->acceptMutator( addrExploder );
+		if ( ! addrExploder.foundUniqueExpr ) {
+			expr = new AddressExpr( expr );
+		}
+		return expr;
+	}
+} // namespace Tuples
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/Explode.h
===================================================================
--- src/Tuples/Explode.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/Tuples/Explode.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,97 @@
+//
+// 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.
+//
+// Explode.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Nov 9 13:12:24 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Nov 9 13:20:24 2016
+// Update Count     : 2
+//
+
+#ifndef _EXPLODE_H_
+#define _EXPLODE_H_
+
+#include "ResolvExpr/AlternativeFinder.h"
+#include "ResolvExpr/Resolver.h"
+
+#include "SynTree/Expression.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+
+#include "Tuples.h"
+
+namespace Tuples {
+	/// helper function used by explode to properly distribute
+	/// '&' across a tuple expression
+	Expression * distributeAddr( Expression * expr );
+
+	/// helper function used by explode
+	template< typename OutputIterator >
+	void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, const SymTab::Indexer & indexer, OutputIterator out ) {
+		Type * res = expr->get_result();
+		if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {
+			ResolvExpr::AltList alts;
+			explodeUnique( addrExpr->get_arg(), alt, indexer, back_inserter( alts ) );
+			for ( ResolvExpr::Alternative & alt : alts ) {
+				// distribute '&' over all components
+				alt.expr = distributeAddr( alt.expr );
+				*out++ = alt;
+			}
+		} else if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) {
+			if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) {
+				// can open tuple expr and dump its exploded components
+				for ( Expression * expr : tupleExpr->get_exprs() ) {
+					explodeUnique( expr, alt, indexer, out );
+				}
+			} else {
+				// tuple type, but not tuple expr - recursively index into its components
+				Expression * arg = expr->clone();
+				if ( Tuples::maybeImpure( arg ) && ! dynamic_cast< UniqueExpr * >( arg ) ) {
+					// expressions which may contain side effects require a single unique instance of the expression.
+					arg = new UniqueExpr( arg );
+				}
+				for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
+					TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i );
+					explodeUnique( idx, alt, indexer, out );
+					delete idx;
+				}
+				delete arg;
+			}
+		} else {
+			// atomic (non-tuple) type - output a clone of the expression in a new alternative
+			*out++ = ResolvExpr::Alternative( expr->clone(), alt.env, alt.cost, alt.cvtCost );
+		}
+	}
+
+	/// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type
+	template< typename OutputIterator >
+	void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer, OutputIterator out ) {
+		explodeUnique( alt.expr, alt, indexer, out );
+	}
+
+	// explode list of alternatives
+	template< typename AltIterator, typename OutputIterator >
+	void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer, OutputIterator out ) {
+		for ( ; altBegin != altEnd; ++altBegin ) {
+			explode( *altBegin, indexer, out );
+		}
+	}
+
+	template< typename OutputIterator >
+	void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, OutputIterator out ) {
+		explode( alts.begin(), alts.end(), indexer, out );
+	}
+} // namespace Tuples
+
+#endif // _TUPLE_ASSIGNMENT_H_
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/NameMatcher.cc
===================================================================
--- src/Tuples/NameMatcher.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ 	(revision )
@@ -1,67 +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.
-//
-// 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 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ 	(revision )
@@ -1,62 +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.
-//
-// 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 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Tuples/TupleAssignment.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -9,6 +9,6 @@
 // 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
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Nov 9 13:48:42 2016
 // Update Count     : 2
 //
@@ -18,6 +18,9 @@
 #include "ResolvExpr/typeops.h"
 #include "SynTree/Expression.h"
-#include "TupleAssignment.h"
+#include "SynTree/Initializer.h"
+#include "Tuples.h"
+#include "Explode.h"
 #include "Common/SemanticError.h"
+#include "InitTweak/InitTweak.h"
 
 #include <functional>
@@ -27,383 +30,228 @@
 #include <cassert>
 #include <set>
+#include <unordered_set>
 
 namespace Tuples {
-	TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder *f )
-		: currentFinder(f), matcher(0), hasMatched( false ) {}
-
-	bool TupleAssignSpotter::pointsToTuple( Expression *expr ) {
+	class TupleAssignSpotter {
+	  public:
+		// dispatcher for Tuple (multiple and mass) assignment operations
+		TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
+		void spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities );
+
+	  private:
+		void match();
+
+		struct Matcher {
+		  public:
+			Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
+			virtual ~Matcher() {}
+			virtual void match( std::list< Expression * > &out ) = 0;
+			ResolvExpr::AltList lhs, rhs;
+			TupleAssignSpotter &spotter;
+			std::list< ObjectDecl * > tmpDecls;
+		};
+
+		struct MassAssignMatcher : public Matcher {
+		  public:
+			MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
+			virtual void match( std::list< Expression * > &out );
+		};
+
+		struct MultipleAssignMatcher : public Matcher {
+		  public:
+			MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts );
+			virtual void match( std::list< Expression * > &out );
+		};
+
+		ResolvExpr::AlternativeFinder &currentFinder;
+		std::string fname;
+		std::unique_ptr< Matcher > matcher;
+	};
+
+	/// true if expr is an expression of tuple type, i.e. a tuple expression, tuple variable, or MRV (multiple-return-value) function
+	bool isTuple( Expression *expr ) {
+		if ( ! expr ) return false;
+		assert( expr->has_result() );
+		return dynamic_cast<TupleExpr *>(expr) || expr->get_result()->size() > 1;
+	}
+
+	template< typename AltIter >
+	bool isMultAssign( AltIter begin, AltIter end ) {
+		// multiple assignment if more than one alternative in the range or if
+		// the alternative is a tuple
+		if ( begin == end ) return false;
+		if ( isTuple( begin->expr ) ) return true;
+		return ++begin != end;
+	}
+
+	bool 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;
+		if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
+			return pointsToTuple( castExpr->get_arg() );
+		} else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) {
+			return isTuple( addr->get_arg() );
+		}
 		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
+	void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
+		TupleAssignSpotter spotter( currentFinder );
+		spotter.spot( expr, possibilities );
+	}
+
+	TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )
+		: currentFinder(f) {}
+
+	void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
+		if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
+			if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) {
+				fname = op->get_name();
+				for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
+					if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
+					if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) {
+						// what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it
+						continue;
+					}
+
+					assert( ! ali->empty() );
+					// grab args 2-N and group into a TupleExpr
+					const ResolvExpr::Alternative & alt1 = ali->front();
+					auto begin = std::next(ali->begin(), 1), end = ali->end();
+					if ( pointsToTuple(alt1.expr) ) {
+						if ( isMultAssign( begin, end ) ) {
+							matcher.reset( new MultipleAssignMatcher( *this, *ali ) );
+						} 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() ) );
+							matcher.reset( new MassAssignMatcher( *this,  *ali ) );
 						}
-					} 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() ) );
+						match();
 					}
 				}
 			}
 		}
-		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
+	}
+
+	void TupleAssignSpotter::match() {
+		assert ( matcher != 0 );
+
+		std::list< Expression * > new_assigns;
+		matcher->match( new_assigns );
+
+		if ( new_assigns.empty() ) return;
+		ResolvExpr::AltList current;
+		// now resolve new assignments
+		for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
+			ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
+			try {
+				finder.findWithAdjustment(*i);
+			} catch (...) {
+				return; // xxx - no match should not mean failure, it just means this particular tuple assignment isn't valid
+			}
+			// 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( alts.front() );
+		}
+
+		// 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??
+		ResolvExpr::TypeEnvironment compositeEnv;
+		simpleCombineEnvironments( current.begin(), current.end(), compositeEnv );
+		currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), compositeEnv, ResolvExpr::sumCost( current ) ) );
+	}
+
+	TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter) {
+		assert( ! alts.empty() );
+		ResolvExpr::Alternative lhsAlt = alts.front();
+		// peel off the cast that exists on ctor/dtor expressions
+		bool isCast = false;
+		if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( lhsAlt.expr ) ) {
+			lhsAlt.expr = castExpr->get_arg();
+			castExpr->set_arg( nullptr );
+			delete castExpr;
+			isCast = true;
+		}
+
+		// explode the lhs so that each field of the tuple-valued-expr is assigned.
+		explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs) );
+
+		// and finally, re-add the cast to each lhs expr, so that qualified tuple fields can be constructed
+		if ( isCast ) {
+			for ( ResolvExpr::Alternative & alt : lhs ) {
+				Expression *& expr = alt.expr;
+				Type * castType = expr->get_result()->clone();
+				Type * type = InitTweak::getPointerBase( castType );
+				assert( type );
+				type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
+				type->set_isLvalue( true ); // xxx - might not need this
+				expr = new CastExpr( expr, castType );
+			}
+		}
+	}
+
+	TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
+		assert( alts.size() == 1 || alts.size() == 2 );
+		if ( alts.size() == 2 ) {
+			rhs.push_back( alts.back() );
+		}
+	}
+
+	TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
+		// explode the rhs so that each field of the tuple-valued-expr is assigned.
+		explode( std::next(alts.begin(), 1), alts.end(), spotter.currentFinder.get_indexer(), back_inserter(rhs) );
+	}
+
+	UntypedExpr * createFunc( const std::string &fname, ObjectDecl *left, ObjectDecl *right ) {
+		assert( left );
+		std::list< Expression * > args;
+		args.push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( left ) ) ) );
+		// args.push_back( new AddressExpr( new VariableExpr( left ) ) );
+		if ( right ) args.push_back( new VariableExpr( right ) );
+		return new UntypedExpr( new NameExpr( fname ), args );
+	}
+
+	ObjectDecl * newObject( UniqueName & namer, Expression * expr ) {
+		assert( expr->has_result() && ! expr->get_result()->isVoid() );
+		return new ObjectDecl( namer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), 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 = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr;
+		for ( ResolvExpr::Alternative & lhsAlt : lhs ) {
+			ObjectDecl * ltmp = newObject( lhsNamer, lhsAlt.expr );
+			out.push_back( createFunc( spotter.fname, ltmp, rtmp ) );
+			tmpDecls.push_back( ltmp );
+		}
+		if ( rtmp ) 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 );
-			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;
+			std::list< ObjectDecl * > ltmp;
+			std::list< ObjectDecl * > rtmp;
+			std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( ResolvExpr::Alternative & alt ){
+				return newObject( lhsNamer, alt.expr );
+			});
+			std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( ResolvExpr::Alternative & alt ){
+				return newObject( rhsNamer, alt.expr );
+			});
+			zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), [&](ObjectDecl * obj1, ObjectDecl * obj2 ) { return createFunc(spotter.fname, obj1, obj2); } );
+			tmpDecls.splice( tmpDecls.end(), ltmp );
+			tmpDecls.splice( tmpDecls.end(), rtmp );
+		}
 	}
 } // namespace Tuples
Index: src/Tuples/TupleAssignment.h
===================================================================
--- src/Tuples/TupleAssignment.h	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ 	(revision )
@@ -1,136 +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 {
-	class TupleAssignSpotter {
-	  public:
-		// dispatcher for Tuple (multiple and mass) assignment operations
-		TupleAssignSpotter( ResolvExpr::AlternativeFinder * = 0 );
-		~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/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/Tuples/TupleExpansion.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,329 @@
+//
+// 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/DeclMutator.h"
+#include "SynTree/Mutator.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Initializer.h"
+#include "SymTab/Mangler.h"
+#include "Common/ScopedMap.h"
+#include "ResolvExpr/typeops.h"
+#include "InitTweak/GenInit.h"
+
+namespace Tuples {
+	namespace {
+		class MemberTupleExpander final : public Mutator {
+		public:
+			typedef Mutator Parent;
+			using Parent::mutate;
+
+			virtual Expression * mutate( UntypedMemberExpr * memberExpr ) override;
+		};
+
+		class UniqueExprExpander final : public GenPoly::DeclMutator {
+		public:
+			typedef GenPoly::DeclMutator Parent;
+			using Parent::mutate;
+
+			virtual Expression * mutate( UniqueExpr * unqExpr ) override;
+
+			std::map< int, Expression * > decls; // not vector, because order added may not be increasing order
+
+			~UniqueExprExpander() {
+				for ( std::pair<const int, Expression *> & p : decls ) {
+					delete p.second;
+				}
+			}
+		};
+
+		class TupleAssignExpander : public Mutator {
+		public:
+			typedef Mutator Parent;
+			using Parent::mutate;
+
+			virtual Expression * mutate( TupleAssignExpr * tupleExpr );
+		};
+
+		class TupleTypeReplacer : public GenPoly::DeclMutator {
+		  public:
+			typedef GenPoly::DeclMutator Parent;
+			using Parent::mutate;
+
+			virtual Type * mutate( TupleType * tupleType ) override;
+
+			virtual CompoundStmt * mutate( CompoundStmt * stmt ) override {
+				typeMap.beginScope();
+				stmt = Parent::mutate( stmt );
+				typeMap.endScope();
+				return stmt;
+			}
+		  private:
+			ScopedMap< std::string, StructDecl * > typeMap;
+		};
+
+		class TupleIndexExpander final : public Mutator {
+		public:
+			typedef Mutator Parent;
+			using Parent::mutate;
+
+			virtual Expression * mutate( TupleIndexExpr * tupleExpr ) override;
+		};
+
+		class TupleExprExpander final : public Mutator {
+		public:
+			typedef Mutator Parent;
+			using Parent::mutate;
+			
+			virtual Expression * mutate( TupleExpr * tupleExpr ) override;
+		};
+	}
+
+	void expandMemberTuples( std::list< Declaration * > & translationUnit ) {
+		MemberTupleExpander expander;
+		mutateAll( translationUnit, expander );
+	}
+
+	void expandUniqueExpr( std::list< Declaration * > & translationUnit ) {
+		UniqueExprExpander unqExpander;
+		unqExpander.mutateDeclarationList( translationUnit );
+	}
+
+	void expandTuples( std::list< Declaration * > & translationUnit ) {
+		TupleAssignExpander assnExpander;
+		mutateAll( translationUnit, assnExpander );
+
+		TupleTypeReplacer replacer;
+		replacer.mutateDeclarationList( translationUnit );
+
+		TupleIndexExpander idxExpander;
+		mutateAll( translationUnit, idxExpander );
+
+		TupleExprExpander exprExpander;
+		mutateAll( translationUnit, exprExpander );
+	}
+
+	namespace {
+		/// given a expression representing the member and an expression representing the aggregate,
+		/// reconstructs a flattened UntypedMemberExpr with the right precedence
+		Expression * reconstructMemberExpr( Expression * member, Expression * aggr ) {
+			if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( member ) ) {
+				// construct a new UntypedMemberExpr with the correct structure , and recursively
+				// expand that member expression.
+				MemberTupleExpander expander;
+				UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->get_member(), new UntypedMemberExpr( memberExpr->get_aggregate(), aggr->clone() ) );
+
+				memberExpr->set_member(nullptr);
+				memberExpr->set_aggregate(nullptr);
+				delete memberExpr;
+				return newMemberExpr->acceptMutator( expander );
+			} else {
+				// not a member expression, so there is nothing to do but attach and return
+				return new UntypedMemberExpr( member, aggr->clone() );
+			}
+		}
+	}
+
+	Expression * MemberTupleExpander::mutate( UntypedMemberExpr * memberExpr ) {
+		if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * > ( memberExpr->get_member() ) ) {
+			Expression * aggr = memberExpr->get_aggregate()->clone()->acceptMutator( *this );
+			// aggregate expressions which might be impure must be wrapped in unique expressions
+			// xxx - if there's a member-tuple expression nested in the aggregate, this currently generates the wrong code if a UniqueExpr is not used, and it's purely an optimization to remove the UniqueExpr
+			// if ( Tuples::maybeImpure( memberExpr->get_aggregate() ) ) aggr = new UniqueExpr( aggr );
+			aggr = new UniqueExpr( aggr );
+			for ( Expression *& expr : tupleExpr->get_exprs() ) {
+				expr = reconstructMemberExpr( expr, aggr );
+			}
+			delete aggr;
+			return tupleExpr;
+		} else {
+			// there may be a tuple expr buried in the aggregate
+			// xxx - this is a memory leak
+			return new UntypedMemberExpr( memberExpr->get_member()->clone(), memberExpr->get_aggregate()->acceptMutator( *this ) );
+		}
+	}
+
+	Expression * UniqueExprExpander::mutate( UniqueExpr * unqExpr ) {
+		unqExpr = safe_dynamic_cast< UniqueExpr * > ( Parent::mutate( unqExpr ) );
+		const int id = unqExpr->get_id();
+
+		// on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID,
+		// and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable.
+		if ( ! decls.count( id ) ) {
+			Expression * assignUnq;
+			Expression * var = unqExpr->get_var();
+			if ( unqExpr->get_object() ) {
+				// an object was generated to represent this unique expression -- it should be added to the list of declarations now
+				addDeclaration( unqExpr->get_object() );
+				unqExpr->set_object( nullptr );
+				// steal the expr from the unqExpr
+				assignUnq = UntypedExpr::createAssign( unqExpr->get_var()->clone(), unqExpr->get_expr() );
+				unqExpr->set_expr( nullptr );
+			} else {
+				// steal the already generated assignment to var from the unqExpr - this has been generated by FixInit
+				Expression * expr = unqExpr->get_expr();
+				CommaExpr * commaExpr = safe_dynamic_cast< CommaExpr * >( expr );
+				assignUnq = commaExpr->get_arg1();
+				commaExpr->set_arg1( nullptr );
+			}
+			BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
+			ObjectDecl * finished = new ObjectDecl( toString( "_unq_expr_finished_", id ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ), new SingleInit( new ConstantExpr( Constant( boolType->clone(), "0" ) ), noDesignators ) );
+			addDeclaration( finished );
+			// (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
+			// This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code.
+			Expression * assignFinished = UntypedExpr::createAssign( new VariableExpr(finished), new ConstantExpr( Constant( boolType->clone(), "1" ) ) );
+			ConditionalExpr * condExpr = new ConditionalExpr( new VariableExpr( finished ), var->clone(),
+				new CommaExpr( new CommaExpr( assignUnq, assignFinished ), var->clone() ) );
+			condExpr->set_result( var->get_result()->clone() );
+			decls[id] = condExpr;
+		}
+		delete unqExpr;
+		return decls[id]->clone();
+	}
+
+	Expression * TupleAssignExpander::mutate( TupleAssignExpr * assnExpr ) {
+		assnExpr = safe_dynamic_cast< TupleAssignExpr * >( Parent::mutate( assnExpr ) );
+		CompoundStmt * compoundStmt = new CompoundStmt( noLabels );
+		std::list< Statement * > & stmts = compoundStmt->get_kids();
+		for ( ObjectDecl * obj : assnExpr->get_tempDecls() ) {
+			stmts.push_back( new DeclStmt( noLabels, obj ) );
+		}
+		TupleExpr * tupleExpr = new TupleExpr( assnExpr->get_assigns() );
+		assert( tupleExpr->get_result() );
+		stmts.push_back( new ExprStmt( noLabels, tupleExpr ) );
+		assnExpr->get_tempDecls().clear();
+		assnExpr->get_assigns().clear();
+		delete assnExpr;
+		return new StmtExpr( compoundStmt );
+	}
+
+	Type * TupleTypeReplacer::mutate( TupleType * tupleType ) {
+		std::string mangleName = SymTab::Mangler::mangleType( tupleType );
+		TupleType * newType = safe_dynamic_cast< TupleType * > ( Parent::mutate( tupleType ) );
+		if ( ! typeMap.count( mangleName ) ) {
+			// generate struct type to replace tuple type
+			StructDecl * decl = new StructDecl( "_tuple_type_" + mangleName );
+			decl->set_body( true );
+			int cnt = 0;
+			for ( Type * t : *newType ) {
+				decl->get_members().push_back( new ObjectDecl( toString("field_", cnt++), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, t->clone(), nullptr ) );
+			}
+			typeMap[mangleName] = decl;
+			addDeclaration( decl );
+		}
+		Type::Qualifiers qualifiers = newType->get_qualifiers();
+		delete newType;
+		return new StructInstType( qualifiers, typeMap[mangleName] );
+	}
+
+	Expression * TupleIndexExpander::mutate( TupleIndexExpr * tupleExpr ) {
+		Expression * tuple = maybeMutate( tupleExpr->get_tuple(), *this );
+		assert( tuple );
+		tupleExpr->set_tuple( nullptr );
+		unsigned int idx = tupleExpr->get_index();
+		delete tupleExpr;
+
+		StructInstType * type = safe_dynamic_cast< StructInstType * >( tuple->get_result() );
+		StructDecl * structDecl = type->get_baseStruct();
+		assert( structDecl->get_members().size() > idx );
+		Declaration * member = *std::next(structDecl->get_members().begin(), idx);
+		return new MemberExpr( safe_dynamic_cast< DeclarationWithType * >( member ), tuple );
+	}
+
+	Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs ) {
+		if ( result->isVoid() ) {
+			// void result - don't need to produce a value for cascading - just output a chain of comma exprs
+			assert( ! exprs.empty() );
+			std::list< Expression * >::const_iterator iter = exprs.begin();
+			Expression * expr = *iter++;
+			for ( ; iter != exprs.end(); ++iter ) {
+				expr = new CommaExpr( expr, *iter );
+			}
+			return expr;
+		} else {
+			// typed tuple expression - produce a compound literal which performs each of the expressions
+			// as a distinct part of its initializer - the produced compound literal may be used as part of
+			// another expression
+			std::list< Initializer * > inits;
+			for ( Expression * expr : exprs ) {
+				inits.push_back( new SingleInit( expr ) );
+			}
+			return new CompoundLiteralExpr( result, new ListInit( inits ) );
+		}
+	}
+
+	Expression * TupleExprExpander::mutate( TupleExpr * tupleExpr ) {
+		// recursively expand sub-tuple-expressions
+		tupleExpr = safe_dynamic_cast<TupleExpr *>(Parent::mutate(tupleExpr));
+		Type * result = tupleExpr->get_result();
+		std::list< Expression * > exprs = tupleExpr->get_exprs();
+		assert( result );
+
+		// remove data from shell and delete it
+		tupleExpr->set_result( nullptr );
+		tupleExpr->get_exprs().clear();
+		delete tupleExpr;
+
+		return replaceTupleExpr( result, exprs );
+	}
+
+	Type * makeTupleType( const std::list< Expression * > & exprs ) {
+		// produce the TupleType which aggregates the types of the exprs
+		TupleType *tupleType = new TupleType( Type::Qualifiers(true, true, true, true, true, false) );
+		Type::Qualifiers &qualifiers = tupleType->get_qualifiers();
+		for ( Expression * expr : exprs ) {
+			assert( expr->get_result() );
+			if ( expr->get_result()->isVoid() ) {
+				// if the type of any expr is void, the type of the entire tuple is void
+				delete tupleType;
+				return new VoidType( Type::Qualifiers() );
+			}
+			Type * type = expr->get_result()->clone();
+			tupleType->get_types().push_back( type );
+			// the qualifiers on the tuple type are the qualifiers that exist on all component types
+			qualifiers &= type->get_qualifiers();
+		} // for
+		return tupleType;
+	}
+
+	namespace {
+		/// determines if impurity (read: side-effects) may exist in a piece of code. Currently gives a very crude approximation, wherein any function call expression means the code may be impure
+		class ImpurityDetector : public Visitor {
+		public:
+			typedef Visitor Parent;
+			virtual void visit( ApplicationExpr * appExpr ) { maybeImpure = true;	}
+			virtual void visit( UntypedExpr * untypedExpr ) { maybeImpure = true; }
+			bool maybeImpure = false;
+		};
+	} // namespace
+
+	bool maybeImpure( Expression * expr ) {
+		ImpurityDetector detector;
+		expr->accept( detector );
+		return detector.maybeImpure;
+	}
+} // namespace Tuples
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Tuples/Tuples.h
===================================================================
--- src/Tuples/Tuples.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/Tuples/Tuples.h	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,54 @@
+//
+// 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 : Rob Schluntz
+// Last Modified On : Wed Nov 9 13:17:58 2016
+// Update Count     : 15
+//
+
+#ifndef _TUPLES_H_
+#define _TUPLES_H_
+
+#include <string>
+
+#include "SynTree/Expression.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+
+#include "ResolvExpr/AlternativeFinder.h"
+
+namespace Tuples {
+	// TupleAssignment.cc
+	void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, const std::list<ResolvExpr::AltList> & possibilities );
+
+	// TupleExpansion.cc
+	/// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate
+	void expandMemberTuples( std::list< Declaration * > & translationUnit );
+
+	/// replaces tuple-related elements, such as TupleType, TupleExpr, TupleAssignExpr, etc.
+	void expandTuples( std::list< Declaration * > & translationUnit );
+
+	/// replaces UniqueExprs with a temporary variable and one call
+	void expandUniqueExpr( std::list< Declaration * > & translationUnit );
+
+	/// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
+	Type * makeTupleType( const std::list< Expression * > & exprs );
+
+	/// returns true if the expression may contain side-effects.
+	bool maybeImpure( Expression * expr );
+} // 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 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/Tuples/module.mk	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -6,5 +6,5 @@
 ## file "LICENCE" distributed with Cforall.
 ##
-## module.mk -- 
+## module.mk --
 ##
 ## Author           : Richard C. Bilson
@@ -16,3 +16,4 @@
 
 SRC += 	Tuples/TupleAssignment.cc \
-	Tuples/NameMatcher.cc
+	Tuples/TupleExpansion.cc \
+	Tuples/Explode.cc
Index: src/driver/cfa.cc
===================================================================
--- src/driver/cfa.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/driver/cfa.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -244,4 +244,6 @@
 		nargs += 1;
 	} // if
+	args[nargs] = "-I" CFA_INCDIR "/concurrency";
+	nargs += 1;
 	args[nargs] = "-I" CFA_INCDIR "/containers";
 	nargs += 1;
Index: src/examples/ArrayN.c
===================================================================
--- src/examples/ArrayN.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/examples/ArrayN.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,25 @@
+#include <fstream>
+
+// [unsigned, unsigned] offset_to_index(unsigned offset, unsigned sx, unsigned sy)
+// {
+//     return [offset / sx, offset % sy];
+// }
+
+forall(otype index_t)
+index_t offset_to_index(unsigned offset, index_t size)
+{
+    return [offset / size.0, offset % size.1];
+}
+
+int main(int argc, char* argv[])
+{
+    unsigned x = 0, y = 0, i = 0;
+    unsigned sx = 4, sy = 4;
+
+    i = 6;
+    [x, y] = offset_to_index(6, [sx, sy]);
+
+    sout | x | ' ' | y | endl;
+
+    return 0;
+}
Index: src/examples/coroutine.c
===================================================================
--- src/examples/coroutine.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/examples/coroutine.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,48 @@
+#include <fstream>
+#include <threads>
+
+struct Fibonacci {
+      coroutine c;
+      int fn; // used for communication
+};
+
+void ?{}(Fibonacci* this) {
+      this->fn = 0;
+}
+
+coroutine* this_coroutine(Fibonacci* this) {
+      return &this->c;
+}
+
+void co_main(Fibonacci* this) {
+      int fn1, fn2; 		// retained between resumes
+      this->fn = 0;
+      fn1 = this->fn;
+      suspend(); 		// return to last resume
+
+      this->fn = 1;
+      fn2 = fn1;
+      fn1 = this->fn;
+      suspend(); 		// return to last resume
+
+      for ( ;; ) {
+            this->fn = fn1 + fn2;
+            fn2 = fn1;
+            fn1 = this->fn;
+            suspend(); 	// return to last resume
+      }
+}
+
+int next(Fibonacci* this) {
+      resume(this); // transfer to last suspend
+      return this->fn;
+}
+
+int main() {
+      Fibonacci f1, f2;
+      for ( int i = 1; i <= 10; i += 1 ) {
+            sout | next(&f1) | ' ' | next(&f2) | endl;
+      }
+
+      return 0;
+}
Index: src/libcfa/Makefile.am
===================================================================
--- src/libcfa/Makefile.am	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/libcfa/Makefile.am	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -56,5 +56,6 @@
 CC = ${abs_top_srcdir}/src/driver/cfa
 
-headers = limits stdlib math iostream fstream iterator rational containers/vector
+headers = limits stdlib math iostream fstream iterator rational assert containers/vector concurrency/threads
+runtimehdrs = concurrency
 libobjs = ${headers:=.o}
 
Index: src/libcfa/Makefile.in
===================================================================
--- src/libcfa/Makefile.in	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/libcfa/Makefile.in	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -92,5 +92,6 @@
 am__objects_1 = limits.$(OBJEXT) stdlib.$(OBJEXT) math.$(OBJEXT) \
 	iostream.$(OBJEXT) fstream.$(OBJEXT) iterator.$(OBJEXT) \
-	rational.$(OBJEXT) containers/vector.$(OBJEXT)
+	rational.$(OBJEXT) assert.$(OBJEXT) \
+	containers/vector.$(OBJEXT) concurrency/threads.$(OBJEXT)
 am_libcfa_a_OBJECTS = libcfa-prelude.$(OBJEXT) $(am__objects_1)
 libcfa_a_OBJECTS = $(am_libcfa_a_OBJECTS)
@@ -234,5 +235,6 @@
 cfalib_DATA = builtins.cf extras.cf prelude.cf
 MAINTAINERCLEANFILES = builtins.cf extras.cf ${addprefix ${libdir}/,${cfalib_DATA}} ${addprefix ${libdir}/,${lib_LIBRARIES}}
-headers = limits stdlib math iostream fstream iterator rational containers/vector
+headers = limits stdlib math iostream fstream iterator rational assert containers/vector concurrency/threads
+runtimehdrs = concurrency
 libobjs = ${headers:=.o}
 libcfa_a_SOURCES = libcfa-prelude.c ${headers:=.c}
@@ -312,4 +314,12 @@
 containers/vector.$(OBJEXT): containers/$(am__dirstamp) \
 	containers/$(DEPDIR)/$(am__dirstamp)
+concurrency/$(am__dirstamp):
+	@$(MKDIR_P) concurrency
+	@: > concurrency/$(am__dirstamp)
+concurrency/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) concurrency/$(DEPDIR)
+	@: > concurrency/$(DEPDIR)/$(am__dirstamp)
+concurrency/threads.$(OBJEXT): concurrency/$(am__dirstamp) \
+	concurrency/$(DEPDIR)/$(am__dirstamp)
 libcfa.a: $(libcfa_a_OBJECTS) $(libcfa_a_DEPENDENCIES) $(EXTRA_libcfa_a_DEPENDENCIES) 
 	$(AM_V_at)-rm -f libcfa.a
@@ -319,4 +329,5 @@
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
+	-rm -f concurrency/threads.$(OBJEXT)
 	-rm -f containers/vector.$(OBJEXT)
 
@@ -324,4 +335,5 @@
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assert.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fstream.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iostream.Po@am__quote@
@@ -332,4 +344,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rational.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdlib.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/threads.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@containers/$(DEPDIR)/vector.Po@am__quote@
 
@@ -505,4 +518,6 @@
 	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
 	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-rm -f concurrency/$(DEPDIR)/$(am__dirstamp)
+	-rm -f concurrency/$(am__dirstamp)
 	-rm -f containers/$(DEPDIR)/$(am__dirstamp)
 	-rm -f containers/$(am__dirstamp)
@@ -517,5 +532,5 @@
 
 distclean: distclean-am
-	-rm -rf ./$(DEPDIR) containers/$(DEPDIR)
+	-rm -rf ./$(DEPDIR) concurrency/$(DEPDIR) containers/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
@@ -563,5 +578,5 @@
 
 maintainer-clean: maintainer-clean-am
-	-rm -rf ./$(DEPDIR) containers/$(DEPDIR)
+	-rm -rf ./$(DEPDIR) concurrency/$(DEPDIR) containers/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic \
Index: src/libcfa/assert
===================================================================
--- src/libcfa/assert	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/libcfa/assert	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,34 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// assert --
+//
+// Author           : Thierry Delisle
+// Created On       : Mon Nov 28 12:27:26 2016
+// Last Modified By : Thierry Delisle
+// Last Modified On : Mon Nov 28 12:27:26 2016
+// Update Count     : 0
+//
+
+#ifndef __ASSERT_H__
+#define __ASSERT_H__
+
+extern "C" {
+	#include <assert.h>
+
+	#define __STRINGIFY__(str) #str
+	#define __VSTRINGIFY__(str) __STRINGIFY__(str)
+	#define assertf(expr, fmt, ...) ((expr) ? ((void)2) : __assert_fail_f(__VSTRINGIFY__(expr), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, ## __VA_ARGS__ ))
+
+	void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) __attribute__((noreturn));
+}
+
+#endif // __ASSERT_H__
+
+// Local Variables: //
+// mode: c //
+// tab-width: 4 //
+// End: //
Index: src/libcfa/assert.c
===================================================================
--- src/libcfa/assert.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/libcfa/assert.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,47 @@
+//
+// 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.
+//
+// assert.c --
+//
+// Author           : Thierry Delisle
+// Created On       : Mon Nov 28 12:27:26 2016
+// Last Modified By : Thierry Delisle
+// Last Modified On : Mon Nov 28 12:27:26 2016
+// Update Count     : 0
+//
+
+#include "assert"
+#include "stdlib"										// abort
+
+extern "C" {
+	#include <stdarg.h>								// varargs
+	#include <stdio.h>								// fprintf
+
+	extern const char * __progname;						// global name of running executable (argv[0])
+
+	#define CFA_ASSERT_FMT "*CFA assertion error* from program \"%s\" in \"%s\" at line %d in file \"%s\""
+
+	// called by macro assert in assert.h
+	void __assert_fail( const char *assertion, const char *file, unsigned int line, const char *function ) {
+		fprintf( stderr, CFA_ASSERT_FMT ".\n", __progname, function, line, file );
+		abort();
+	}
+
+	// called by macro assertf
+	void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) {
+		fprintf( stderr, CFA_ASSERT_FMT ": ", __progname, function, line, file );
+		va_list args;
+		va_start( args, fmt );
+		vfprintf( stderr, fmt, args );
+		abort();
+	}
+
+}
+
+// Local Variables: //
+// mode: c //
+// tab-width: 4 //
+// End: //
Index: src/libcfa/concurrency/threads
===================================================================
--- src/libcfa/concurrency/threads	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/libcfa/concurrency/threads	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+// fstream --
+//
+// Author           : Peter A. Buhr
+// Created On       : Wed May 27 17:56:53 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Thu Apr 28 08:08:04 2016
+// Update Count     : 88
+//
+
+#ifndef __THREADS_H__
+#define __THREADS_H__
+
+#include <stdbool.h>
+
+struct coroutine {
+      coroutine* last;
+      const char* name;
+      bool notHalted;
+};
+
+void ?{}(coroutine* this);
+
+trait coroutine_t(dtype T) {
+      coroutine* this_coroutine(T* this);
+};
+
+void suspend(void);
+
+forall(dtype T | coroutine_t(T))
+void resume(T* cor);
+
+#endif //__THREADS_H__
Index: src/libcfa/concurrency/threads.c
===================================================================
--- src/libcfa/concurrency/threads.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/libcfa/concurrency/threads.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,54 @@
+#include "threads"
+#include "assert"
+
+#include <stddef.h>
+
+#include <fstream>
+ 
+static coroutine main_coroutine;
+static coroutine* current_coroutine = &main_coroutine;
+
+void ctxSwitchDirect(void* src, void* dst) {
+	current_coroutine = dst;
+}
+
+coroutine* this_coroutine() {
+	return current_coroutine;
+}
+
+void ?{}(coroutine* this)
+{
+	this->last = NULL;
+      this->name = "A Coroutine";
+      this->notHalted = true;
+}
+
+void suspend() {
+      coroutine* src = this_coroutine();		// optimization
+
+	assertf( src->last == (coroutine*)0, 
+		"Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n"
+		"Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
+		src->name, src );
+	assertf( src->last->notHalted, 
+		"Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n"
+		"Possible cause is terminated coroutine's main routine has already returned.",
+		src->name, src, src->last->name, src->last );
+
+	ctxSwitchDirect( src, src->last );
+}
+
+forall(dtype T | coroutine_t(T))
+void resume(T* cor) {
+	coroutine* src = this_coroutine();		// optimization
+	coroutine* dst = this_coroutine(cor);
+
+	if ( src != dst ) {				// not resuming self ?
+		assertf( dst->notHalted , 
+			"Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n"
+			"Possible cause is terminated coroutine's main routine has already returned.",
+			src->name, src, dst->name, dst );
+		dst->last = src;					// set last resumer
+	} // if
+	ctxSwitchDirect( src, dst );				// always done for performance testing
+}
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 3a2128f5aaa77a03c76ff6198907b91256d8c603)
+++ src/main.cc	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -43,4 +43,5 @@
 #include "Common/UnimplementedError.h"
 #include "../config.h"
+#include "Tuples/Tuples.h"
 
 using namespace std;
@@ -236,5 +237,6 @@
 		OPTPRINT( "tweakInit" )
 		InitTweak::genInit( translationUnit );
-
+		OPTPRINT( "expandMemberTuples" );
+		Tuples::expandMemberTuples( translationUnit );
 		if ( libcfap ) {
 			// generate the bodies of cfa library functions
@@ -261,4 +263,7 @@
 			return 0;
 		} // if
+
+		OPTPRINT( "expandUniqueExpr" ); // xxx - is this the right place for this? want to expand ASAP so that subsequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
+		Tuples::expandUniqueExpr( translationUnit );
 
 		OPTPRINT("instantiateGenerics")
@@ -277,4 +282,6 @@
 		OPTPRINT( "box" )
 		GenPoly::box( translationUnit );
+		OPTPRINT( "expandTuples" ); // xxx - is this the right place for this?
+		Tuples::expandTuples( translationUnit );
 
 		// print tree right before code generation
Index: src/tests/.expect/tupleAssign.txt
===================================================================
--- src/tests/.expect/tupleAssign.txt	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/tests/.expect/tupleAssign.txt	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,6 @@
+u=5 v=6 x=10 y=11 z=[100, 200]
+u=11 v=10 x=11 y=10 z=[11, 10]
+u=10 v=11 z=[10, 11]
+u=123 v=456 z=[111, 222]
+d=-2153.12 i=-2153 c=-105 t=[-2153, -2153.12, -2153]
+d=-2153.12 i=-2153 c=-105 t=[-2153, -2153.12, -2153]
Index: src/tests/.expect/tupleFunction.txt
===================================================================
--- src/tests/.expect/tupleFunction.txt	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/tests/.expect/tupleFunction.txt	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,12 @@
+foo([123, 456, 999.123, {321, 654, Q, 3.14}])
+a=123 b=456 c=999.123 d={321, 654, Q, 3.14}
+X=[123, 456, 999.123, {321, 654, Q, 3.14}]
+foo(...)=456
+bar([777, 2.76, 8675])
+bar([123, 999.123, 456])
+baz(777, 2.76, 8675)
+baz(123, 999.123, 456)
+qux([777, 2.76], 8675)
+qux([123, 999.123], 456)
+x=[3, 5.254, 4]
+x1=3 x2=5.254 x3=4
Index: src/tests/.expect/tupleMember.txt
===================================================================
--- src/tests/.expect/tupleMember.txt	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/tests/.expect/tupleMember.txt	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,4 @@
+called f!
+g(...)=13.5
+v.[f1, i.[f2, f3], f4]=[12, 11, 13, 3.14159]
+v.[f1, i.[f2, f3], f4]=[4, [987, 2], 6.28]
Index: src/tests/tupleAssign.c
===================================================================
--- src/tests/tupleAssign.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/tests/tupleAssign.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,40 @@
+int main() {
+	{
+		// test multiple assignment and cascading assignment
+		int u = 5, v = 6, x = 10, y = 11;
+		[int, int] z = [100, 200];
+
+		// swap x, y and store the new [x, y] in [u, v] and in z;
+		printf("u=%d v=%d x=%d y=%d z=[%d, %d]\n", u, v, x, y, z);
+		z = [u, v] = [x, y] = [y, x];
+		printf("u=%d v=%d x=%d y=%d z=[%d, %d]\n", u, v, x, y, z);
+
+		// shuffle elements -- v = z.0, z.0 = z.1, z.1 = u, u = v
+		[v, z, u] = [z, u, v];
+		printf("u=%d v=%d z=[%d, %d]\n", u, v, z);
+
+		// multiple assignment with tuple expression on right
+		z = [111, 222];
+		[u, v] = [123, 456];
+		printf("u=%d v=%d z=[%d, %d]\n", u, v, z);
+	}
+
+	{
+		// test mass assignment
+		double d = 0.0;
+		int i = 0;
+		char c = '\0';
+		struct X {
+			int z;
+		} x;
+		X ?=?(X * x, double d) {}
+		[int, double, int] t;
+
+		// no conversion from X to integral types, so this serves as a santiy
+		// check that as long as this compiles, ?=?(_, x) is not generated.
+		[t, x, d, i, c, x] = (double)-2153.12;
+		printf("d=%lg i=%d c=%d t=[%d, %lg, %d]\n", d, i, (int)c, t);
+		[x, c, i, d, x, t] = (double)-2153.12;
+		printf("d=%lg i=%d c=%d t=[%d, %lg, %d]\n", d, i, (int)c, t);
+	}
+}
Index: src/tests/tupleFunction.c
===================================================================
--- src/tests/tupleFunction.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/tests/tupleFunction.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,78 @@
+struct S {
+	int f1, f2;
+	char f3;
+	double f4;
+} v;
+
+[int] foo( [int, int, double, S] x ) {
+	printf("foo([%d, %d, %lg, {%d, %d, %c, %lg}])\n", x.0, x.1, x.2, x.3.[f1, f2, f3, f4]);
+	int a, b;
+	double c;
+	S d;
+	[a, b, c, d] = x;
+	[int, int, double, S] X = x;
+	printf("a=%d b=%d c=%lg d={%d, %d, %c, %lg}\n", a, b, c, d.[f1, f2, f3, f4]);
+	printf("X=[%d, %d, %lg, {%d, %d, %c, %lg}]\n", X.0, X.1, X.2, X.3.[f1, f2, f3, f4]);
+	return b;
+}
+
+[void] bar( [int, double, int] z ) {
+	printf("bar([%d, %lg, %d])\n", z);
+}
+
+[void] baz( int a, double b, int c ) {
+	printf("baz(%d, %lg, %d)\n", a, b, c);
+}
+
+[void] qux( [int, double] n, int m ) {
+	printf("qux([%d, %lg], %d)\n", n, m);
+}
+
+[int, double x, int] quux() {
+	return [3, 5.254, 4];
+}
+[[[int, double, int], [int, double]]] quuux() {
+	return [1, 2, 3, 4, 5];
+}
+
+// forall(otype T | { T ?+?(T, T); })
+// [T, T, T] ?+?([T, T, T] x, [T, T, T] y) {
+// 	T x1, x2, x3, y1, y2, y3;
+// 	[x1, x2, x3] = x;
+// 	[y1, y2, y3] = y;
+// 	return [x1+y1, x2+y2, x3+y3];
+// }
+
+int main() {
+  [int, double, int] x = [777, 2.76, 8675];
+  int x1 = 123, x3 = 456;
+  double x2 = 999.123;
+
+  printf("foo(...)=%d\n", foo(x1, x3, x2, (S){ 321, 654, 'Q', 3.14 }));
+
+	// call function with tuple parameter using tuple variable arg
+	bar(x);
+
+	// call function with tuple parameter using multiple values
+	bar(x1, x2, x3);
+
+	// call function with multiple parameters using tuple variable arg
+	baz(x);
+
+	// call function with multiple parameters using multiple args
+	baz(x1, x2, x3);
+
+	// call function with multiple parameters, one of which is a tuple using tuple variable arg
+	qux(x);
+
+	// call function with multiple parameters, one of which is a tuple using multiple args
+	qux(x1, x2, x3);
+
+	// call function with multiple return values and assign into a tuple variable
+	x = quux();
+	printf("x=[%d, %lg, %d]\n", x);
+
+	// call function with multiple return values and assign into a tuple expression
+	[x1, x2, x3] = quux();
+	printf("x1=%d x2=%lg x3=%d\n", x1, x2, x3);
+}
Index: src/tests/tupleMember.c
===================================================================
--- src/tests/tupleMember.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
+++ src/tests/tupleMember.c	(revision 1f44196dc72fd060b6183fe2bdc10f7b30f955d6)
@@ -0,0 +1,42 @@
+void f() {
+	printf("called f!\n");
+}
+
+double g(double x, char y, int z) {
+	return z-y+x;
+}
+
+struct V2	{
+	int f2, f3;
+};
+struct V {
+	int f1;
+	V2 i; // temporary
+	// struct V2 {
+	//   int f2, f3;
+	// } i;
+	double f4;
+} v;
+
+lvalue V h() {
+	static V local = { 111, { 222, 333 }, 444.5 };
+	return local;
+}
+
+int main() {
+	struct X {
+		int a;
+		double b;
+		char c;
+	} x = { 10, 12.5, '\x9' };
+
+	// should only call f once
+	printf("g(...)=%lg\n", g((f(), x).[b, c, a]));
+
+	v.[f1, i.[f2, f3], f4].[1.0, 2, 0, 1.1] = [11, 3.14159, 12, 13];
+
+	printf("v.[f1, i.[f2, f3], f4]=[%d, %d, %d, %lg]\n", v.[f1, i.[f2, f3], f4]);
+
+	h().[f1, i.[f2, f3], f4].[1.0, 2, 0, 1.1] = [987, 6.28, 4, 2];
+	printf("v.[f1, i.[f2, f3], f4]=[%d, [%d, %d], %lg]\n", h().[f1, i.[f2, f3], f4]);
+}
