Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision a2eda27b02ccf003bdab975c0b00b844f8618e59)
+++ src/GenPoly/InstantiateGeneric.cc	(revision 258eb5c9477f29166b1ae9152e4dfdd2443eac84)
@@ -36,107 +36,116 @@
 namespace GenPoly {
 
-	class Instantiate : public PolyMutator {
-	public:
-		/// Key for a unique concrete type; generic base type paired with type parameter list
-		struct ConcreteType {
-			ConcreteType() : base(NULL), params() {}
-
-			ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }
-
-			ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
-
-			/// Extracts types from a list of Expression* (which should be TypeExpr*)
-			ConcreteType(AggregateDecl *_base, const std::list< Expression* >& _params) : base(_base), params() {
-				for ( std::list< Expression* >::const_iterator it = _params.begin(); it != _params.end(); ++it ) {
-					TypeExpr *param = dynamic_cast< TypeExpr* >(*it);
-					assert(param && "Aggregate parameters should be type expressions");
-					params.push_back( param->get_type()->clone() );
+	/// Key for a unique concrete type; generic base type paired with type parameter list
+	struct ConcreteType {
+		ConcreteType() : base(NULL), params() {}
+
+		ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }
+
+		ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
+
+		/// Extracts types from a list of Expression* (which should be TypeExpr*)
+		ConcreteType(AggregateDecl *_base, const std::list< Expression* >& _params) : base(_base), params() {
+			for ( std::list< Expression* >::const_iterator it = _params.begin(); it != _params.end(); ++it ) {
+				TypeExpr *param = dynamic_cast< TypeExpr* >(*it);
+				assert(param && "Aggregate parameters should be type expressions");
+				params.push_back( param->get_type()->clone() );
+			}
+		}
+
+		ConcreteType& operator= (const ConcreteType& that) {
+			deleteAll( params );
+			params.clear();
+
+			base = that.base;
+			cloneAll( that.params, params );
+
+			return *this;
+		}
+
+		~ConcreteType() { deleteAll( params ); }
+
+		bool operator== (const ConcreteType& that) const {
+			SymTab::Indexer dummy;
+
+			if ( base != that.base ) return false;
+			if ( params.size() != that.params.size() ) return false;
+			for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
+				if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
+			}
+			return true;
+		}
+
+		AggregateDecl *base;        ///< Base generic type
+		std::list< Type* > params;  ///< Instantiation parameters
+	};
+
+	/// Maps a concrete type to the instantiated struct type, accounting for scope
+	class InstantiationMap {
+		/// Pair of concrete type and declaration that instantiates it
+		typedef std::pair< ConcreteType, AggregateDecl* > Instantiation;
+		/// Map of generic types to instantiations of them
+		typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
+
+		std::vector< Scope > scopes;  ///< list of scopes, from outermost to innermost
+
+	public:
+		/// Starts a new scope
+		void beginScope() {
+			Scope scope;
+			scopes.push_back(scope);
+		}
+
+		/// Ends a scope
+		void endScope() {
+			scopes.pop_back();
+		}
+
+		/// Default constructor initializes with one scope
+		InstantiationMap() { beginScope(); }
+
+	private:
+		/// Gets the declaration for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
+		/// Returns NULL on none such.
+		AggregateDecl* lookup( AggregateDecl *generic, std::list< Expression* >& params ) {
+			ConcreteType key(generic, params);
+			// scan scopes from innermost out
+			for ( std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {
+				// skip scope if no instantiations of this generic type
+				Scope::const_iterator insts = scope->find( generic );
+				if ( insts == scope->end() ) continue;
+				// look through instantiations for matches to concrete type
+				for ( std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
+					if ( inst->first == key ) return inst->second;
 				}
 			}
-
-			ConcreteType& operator= (const ConcreteType& that) {
-				deleteAll( params );
-				params.clear();
-				
-				base = that.base;
-				cloneAll( that.params, params );
-
-				return *this;
-			}
-
-			~ConcreteType() { deleteAll( params ); }
-			
-			bool operator== (const ConcreteType& that) const {
-				SymTab::Indexer dummy;
-				
-				if ( base != that.base ) return false;
-				if ( params.size() != that.params.size() ) return false;
-				for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
-					if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
-				}
-				return true;
-			}
-
-			AggregateDecl *base;        ///< Base generic type
-			std::list< Type* > params;  ///< Instantiation parameters
-		};
+			// no matching instantiation found
+			return NULL;
+		}
+	public:
+		StructDecl* lookup( StructInstType *inst ) { return (StructDecl*)lookup( inst->get_baseStruct(), inst->get_parameters() ); }
+		UnionDecl* lookup( UnionInstType *inst ) { return (UnionDecl*)lookup( inst->get_baseUnion(), inst->get_parameters() ); }
+
+	private:
+		/// Adds a declaration for a concrete type to the current scope
+		void insert( AggregateDecl *generic, std::list< Expression* >& params, AggregateDecl *decl ) {
+			ConcreteType key(generic, params);
+			scopes.back()[generic].push_back( std::make_pair( key, decl ) );
+		}
+	public:
+		void insert( StructInstType *inst, StructDecl *decl ) { insert( inst->get_baseStruct(), inst->get_parameters(), decl ); }
+		void insert( UnionInstType *inst, UnionDecl *decl ) { insert( inst->get_baseUnion(), inst->get_parameters(), decl ); }
+	};
+
+	/// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
+	class Instantiate : public PolyMutator {
+		InstantiationMap instantiations;
+		UniqueName typeNamer;
+
+	public:
+		Instantiate() : instantiations(), typeNamer("_conc_") {}
+
+		/// Mutates the whole translation unit, inserting new struct declarations as appropriate
+		void mutateAll( std::list< Declaration* >& translationUnit );
 		
-		/// Maps a concrete type to the instantiated struct type, accounting for scope
-		class InstantiationMap {
-			/// Pair of concrete type and declaration that instantiates it
-			typedef std::pair< ConcreteType, AggregateDecl* > Instantiation;
-			/// Map of generic types to instantiations of them
-			typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
-
-			std::vector< Scope > scopes;  ///< list of scopes, from outermost to innermost
-
-		public:
-			/// Starts a new scope
-			void beginScope() {
-				Scope scope;
-				scopes.push_back(scope);
-			}
-
-			/// Ends a scope
-			void endScope() {
-				scopes.pop_back();
-			}
-			
-			/// Default constructor initializes with one scope
-			InstantiationMap() { beginScope(); }
-
-		private:
-			/// Gets the declaration for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
-			/// Returns NULL on none such.
-			AggregateDecl* lookup( AggregateDecl *generic, std::list< Expression* >& params ) {
-				ConcreteType key(generic, params);
-				// scan scopes from innermost out
-				for ( std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {
-					// skip scope if no instantiations of this generic type
-					Scope::const_iterator insts = scope->find( generic );
-					if ( insts == scope->end() ) continue;
-					// look through instantiations for matches to concrete type
-					for ( std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
-						if ( inst->first == key ) return inst->second;
-					}
-				}
-				// no matching instantiation found
-				return NULL;
-			}
-		public:
-			StructDecl* lookup( StructInstType *inst ) { return (StructDecl*)lookup( inst->get_baseStruct(), inst->get_parameters() ); }
-			UnionDecl* lookup( UnionInstType *inst ) { return (UnionDecl*)lookup( inst->get_baseUnion(), inst->get_parameters() ); }
-
-		private:
-			/// Adds a declaration for a concrete type to the current scope
-			void insert( AggregateDecl *generic, std::list< Expression* >& params, AggregateDecl *decl ) {
-				ConcreteType key(generic, params);
-				scopes.back()[generic].push_back( std::make_pair( key, decl ) );
-			}
-		public:
-			void insert( StructInstType *inst, StructDecl *decl ) { insert( inst->get_baseStruct(), inst->get_parameters(), decl ); }
-			void insert( UnionInstType *inst, UnionDecl *decl ) { insert( inst->get_baseUnion(), inst->get_parameters(), decl ); }
-		};
-
 		virtual Type* mutate( StructInstType *inst );
 		virtual Type* mutate( UnionInstType *inst );
@@ -148,16 +157,39 @@
 		/// Adds a declaration to the current environment and the statements to add
 		void addDeclaration( AggregateDecl *decl ) {
-			std::list< Label > labels;
-			DeclStmt *stmt = new DeclStmt( labels, decl );
+			std::list< Label > nolabels;
+			DeclStmt *stmt = new DeclStmt( nolabels, decl );
 			PolyMutator::stmtsToAdd.push_back( stmt );
 		}
-		
-		InstantiationMap instantiations;
-		UniqueName typeNamer;
 	};
 	
 	void instantiateGeneric( std::list< Declaration* >& translationUnit ) {
 		Instantiate instantiator;
-		mutateAll( translationUnit, instantiator );
+//		mutateAll( translationUnit, instantiator );
+		instantiator.mutateAll( translationUnit );
+	}
+
+	void Instantiate::mutateAll( std::list< Declaration* >& translationUnit ) {
+		// below copied and modified from Mutator.h:mutateAll()
+		SemanticError errors;
+		for ( std::list< Declaration* >::iterator decl = translationUnit.begin(); decl != translationUnit.end(); ++decl ) {
+			try {
+				if ( *decl ) {
+					*decl = dynamic_cast< Declaration* >( (*decl)->acceptMutator( *this ) );
+					assert( *decl );
+					// account for missing top-level declarations
+					for ( std::list< Statement* >::const_iterator stmt = PolyMutator::stmtsToAdd.begin(); stmt != PolyMutator::stmtsToAdd.end(); ++stmt ) {
+						DeclStmt *declStmt = dynamic_cast< DeclStmt* >( *stmt );
+						assert( declStmt );
+						translationUnit.insert( decl, declStmt->get_decl() );
+					}
+					PolyMutator::stmtsToAdd.clear();
+				} // if
+			} catch( SemanticError &e ) {
+				errors.append( e );
+			} // try
+		} // for
+		if ( ! errors.isEmpty() ) {
+			throw errors;
+		} // if
 	}
 
