Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision a9a259cff14b8d1aebb4436ded3476b2d261f8c7)
+++ src/SymTab/Validate.cc	(revision 071a31a897b52a4c1abdb6c4c2536e3bfe6257fb)
@@ -698,5 +698,55 @@
 	}
 
-	Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
+	void makeStructFunctionBody( StructDecl *aggregateDecl, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric ) {
+		for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
+			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
+				// query the type qualifiers of this field and skip assigning it if it is marked const.
+				// If it is an array type, we need to strip off the array layers to find its qualifiers.
+				Type * type = dwt->get_type();
+				while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
+					type = at->get_base();
+				}
+
+				if ( type->get_qualifiers().isConst ) {
+					// don't assign const members
+					continue;
+				}
+
+				// temporary hack: for now only works for 2 parameters
+				assert( func->get_functionType()->get_parameters().size() == 2 );
+
+				ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
+				ObjectDecl * srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
+				ObjectDecl * returnVal;
+				if ( ! func->get_functionType()->get_returnVals().empty() ) {
+					returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
+				}
+
+				if ( isGeneric ) {
+					// rewrite member type in terms of the type variables on this operator
+					DeclarationWithType *fixedMember = dwt->clone();
+					genericSubs.apply( fixedMember );
+
+					// assign to both destination and return value
+					if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
+						makeArrayFunction( srcParam, dstParam, fixedMember, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+						if ( returnVal ) makeArrayFunction( srcParam, returnVal, fixedMember, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+					} else {
+						makeScalarFunction( srcParam, dstParam, fixedMember, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+						if ( returnVal ) makeScalarFunction( srcParam, returnVal, fixedMember, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+					} // if
+				} else {
+					// assign to destination
+					if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
+						makeArrayFunction( srcParam, dstParam, dwt, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+					} else {
+						makeScalarFunction( srcParam, dstParam, dwt, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+					} // if
+				} // if
+			} // if
+		} // for
+	} // makeStructFunctionBody
+
+	void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
 		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
 
@@ -715,121 +765,41 @@
 		}
 
+		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
+		assignType->get_parameters().push_back( dstParam );
+
+		// void ?{}(T *); void ^?{}(T *);
+		FunctionType *ctorType = assignType->clone();
+		FunctionType *dtorType = assignType->clone();
+
+		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
+		assignType->get_parameters().push_back( srcParam );
+
+		// void ?{}(T *, T);
+		FunctionType *copyCtorType = assignType->clone();
+
+		// T ?=?(T *, T);
 		ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
-
-		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
-		assignType->get_parameters().push_back( dstParam );
-
-		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
-		assignType->get_parameters().push_back( srcParam );
 
 		// Routines at global scope marked "static" to prevent multiple definitions is separate translation units
 		// because each unit generates copies of the default routines for each aggregate.
 		FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
 		assignDecl->fixUniqueId();
-
-		for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
-				// query the type qualifiers of this field and skip assigning it if it is marked const.
-				// If it is an array type, we need to strip off the array layers to find its qualifiers.
-				Type * type = dwt->get_type();
-				while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
-					type = at->get_base();
-				}
-
-				if ( type->get_qualifiers().isConst ) {
-					// don't assign const members
-					continue;
-				}
-
-				if ( isGeneric ) {
-					// rewrite member type in terms of the type variables on this operator
-					DeclarationWithType *fixedMember = dwt->clone();
-					genericSubs.apply( fixedMember );
-
-					// assign to both destination and return value
-					if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
-						makeArrayFunction( srcParam, dstParam, fixedMember, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-						makeArrayFunction( srcParam, returnVal, fixedMember, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-					} else {
-						makeScalarFunction( srcParam, dstParam, fixedMember, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-						makeScalarFunction( srcParam, returnVal, fixedMember, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-					} // if
-				} else {
-					// assign to destination
-					if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
-						makeArrayFunction( srcParam, dstParam, dwt, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-					} else {
-						makeScalarFunction( srcParam, dstParam, dwt, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-					} // if
-				} // if
-			} // if
-		} // for
-		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
-
-		return assignDecl;
-	}
-
-	void makeStructCtorDtor( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
-		FunctionType *ctorType = new FunctionType( Type::Qualifiers(), false );
-
-		// Make function polymorphic in same parameters as generic struct, if applicable
-		bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
-		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
-		std::list< Expression* > structParams;  // List of matching parameters to put on types
-		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
-			isGeneric = true;
-			TypeDecl *typeParam = (*param)->clone();
-			ctorType->get_forall().push_back( typeParam );
-			structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
-		}
-
-		ObjectDecl *thisParam = new ObjectDecl( "_this", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
-		ctorType->get_parameters().push_back( thisParam );
-
-		// Routines at global scope marked "static" to prevent multiple definitions is separate translation units
-		// because each unit generates copies of the default routines for each aggregate.
-		FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, 0, true, false );
-		FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType->clone(), 0, true, false );
-		FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType->clone(), 0, true, false );
 		ctorDecl->fixUniqueId();
 		copyCtorDecl->fixUniqueId();
 		dtorDecl->fixUniqueId();
 
-		// add definitions
-		// TODO: add in calls to default constructors and destructors for fields
-		ctorDecl->set_statements( new CompoundStmt( noLabels ) );
-		copyCtorDecl->set_statements( new CompoundStmt( noLabels ) );
-		dtorDecl->set_statements( new CompoundStmt( noLabels ) );
+		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+
+		makeStructFunctionBody( aggregateDecl, assignDecl, genericSubs, isGeneric );
+		makeStructFunctionBody( aggregateDecl, copyCtorDecl, genericSubs, isGeneric );
+
+		declsToAdd.push_back( assignDecl );
 		declsToAdd.push_back( ctorDecl );
 		declsToAdd.push_back( copyCtorDecl );
 		declsToAdd.push_back( dtorDecl );
-
-		ObjectDecl * srcParam = new ObjectDecl( "_other", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
-		copyCtorDecl->get_functionType()->get_parameters().push_back( srcParam );
-		for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
-				// query the type qualifiers of this field and skip assigning it if it is marked const.
-				// If it is an array type, we need to strip off the array layers to find its qualifiers.
-				Type * type = dwt->get_type();
-				while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
-					type = at->get_base();
-				}
-
-				if ( type->get_qualifiers().isConst ) {
-					// don't assign const members
-					continue;
-				}
-
-				if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
-					makeArrayFunction( srcParam, thisParam, dwt, array, "?{}", back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
-					// if ( isGeneric ) makeArrayFunction( srcParam, returnVal, dwt, array, back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
-				} else {
-					makeScalarFunction( srcParam, thisParam, dwt, "?{}", back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
-					// if ( isGeneric ) makeScalarCtor( srcParam, returnVal, dwt, back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
-				} // if
-			} // if
-		} // for
-		// if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
 	}
 
@@ -904,7 +874,5 @@
 			StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
 			structInst.set_baseStruct( structDecl );
-
-			declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
-			makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd );
+			makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );
 			structsDone.insert( structDecl->get_name() );
 		} // if
