Index: src/Concurrency/Actors.cpp
===================================================================
--- src/Concurrency/Actors.cpp	(revision 7a780ad23506507b6a1feccc46d18e12da183ceb)
+++ src/Concurrency/Actors.cpp	(revision ba97ebf4075c56eacf19495c1452730cedf50fa1)
@@ -28,68 +28,68 @@
 
 struct CollectactorStructDecls : public ast::WithGuards {
-    unordered_set<const StructDecl *> & actorStructDecls;
-    unordered_set<const StructDecl *>  & messageStructDecls;
-    const StructDecl ** requestDecl;
-    const EnumDecl ** allocationDecl;
-    const StructDecl ** actorDecl;
-    const StructDecl ** msgDecl;
-    StructDecl * parentDecl;
-    bool insideStruct = false;
-    bool namedDecl = false;
-
-    // finds and sets a ptr to the allocation enum, which is needed in the next pass
-    void previsit( const EnumDecl * decl ) {
-        if( decl->name == "allocation" ) *allocationDecl = decl;
-    }
-
-    // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
-    void previsit( const StructDecl * decl ) {
-        if ( !decl->body ) return;
-        if ( decl->name == "actor" ) {
-            actorStructDecls.insert( decl ); // skip inserting fwd decl
-            *actorDecl = decl;
-        } else if( decl->name == "message" ) {
-            messageStructDecls.insert( decl ); // skip inserting fwd decl
-            *msgDecl = decl;
-        } else if( decl->name == "request" ) *requestDecl = decl;
-        else {
-            GuardValue(insideStruct);
-            insideStruct = true;
-            parentDecl = mutate( decl );
-        }
-	}
-
-    // this catches structs of the form:
-    //     struct dummy_actor { actor a; };
-    // since they should be:
-    //     struct dummy_actor { inline actor; };
-    void previsit ( const ObjectDecl * decl ) {
-        if ( insideStruct && ! decl->name.empty() ) {
-            GuardValue(namedDecl);
-            namedDecl = true;
-        }
-    }
-
-    // this collects the derived actor and message struct decl ptrs
-    void postvisit( const StructInstType * node ) {
-        if ( ! *actorDecl || ! *msgDecl ) return;
-        if ( insideStruct && !namedDecl ) {
-            auto actorIter = actorStructDecls.find( node->aggr() );    
-            if ( actorIter != actorStructDecls.end() ) {
-                actorStructDecls.insert( parentDecl );
-                return;
-            }
-            auto messageIter = messageStructDecls.find( node->aggr() );
-            if ( messageIter != messageStructDecls.end() ) {
-                messageStructDecls.insert( parentDecl );
-            }
-        }
+	unordered_set<const StructDecl *> & actorStructDecls;
+	unordered_set<const StructDecl *>  & messageStructDecls;
+	const StructDecl ** requestDecl;
+	const EnumDecl ** allocationDecl;
+	const StructDecl ** actorDecl;
+	const StructDecl ** msgDecl;
+	StructDecl * parentDecl;
+	bool insideStruct = false;
+	bool namedDecl = false;
+
+	// finds and sets a ptr to the allocation enum, which is needed in the next pass
+	void previsit( const EnumDecl * decl ) {
+		if( decl->name == "allocation" ) *allocationDecl = decl;
+	}
+
+	// finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
+	void previsit( const StructDecl * decl ) {
+		if ( !decl->body ) return;
+		if ( decl->name == "actor" ) {
+			actorStructDecls.insert( decl ); // skip inserting fwd decl
+			*actorDecl = decl;
+		} else if( decl->name == "message" ) {
+			messageStructDecls.insert( decl ); // skip inserting fwd decl
+			*msgDecl = decl;
+		} else if( decl->name == "request" ) *requestDecl = decl;
+		else {
+			GuardValue(insideStruct);
+			insideStruct = true;
+			parentDecl = mutate( decl );
+		}
+	}
+
+	// this catches structs of the form:
+	//     struct dummy_actor { actor a; };
+	// since they should be:
+	//     struct dummy_actor { inline actor; };
+	void previsit ( const ObjectDecl * decl ) {
+		if ( insideStruct && ! decl->name.empty() ) {
+			GuardValue(namedDecl);
+			namedDecl = true;
+		}
+	}
+
+	// this collects the derived actor and message struct decl ptrs
+	void postvisit( const StructInstType * node ) {
+		if ( ! *actorDecl || ! *msgDecl ) return;
+		if ( insideStruct && !namedDecl ) {
+			auto actorIter = actorStructDecls.find( node->aggr() );
+			if ( actorIter != actorStructDecls.end() ) {
+				actorStructDecls.insert( parentDecl );
+				return;
+			}
+			auto messageIter = messageStructDecls.find( node->aggr() );
+			if ( messageIter != messageStructDecls.end() ) {
+				messageStructDecls.insert( parentDecl );
+			}
+		}
 	}
 
   public:
-    CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
-        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl ) 
-        : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ), 
-        allocationDecl( allocationDecl ), actorDecl(actorDecl), msgDecl(msgDecl) {}
+	CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
+		const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl )
+		: actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ),
+		allocationDecl( allocationDecl ), actorDecl(actorDecl), msgDecl(msgDecl) {}
 };
 
@@ -97,353 +97,353 @@
 class FwdDeclTable {
 
-    // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
-    struct FwdDeclData { 
-        const StructDecl * actorDecl;
-        const StructDecl * msgDecl;
-        FunctionDecl * fwdDecl;
-        bool actorFound;
-        bool msgFound;
-
-        bool readyToInsert() { return actorFound && msgFound; }
-        bool foundActor() { actorFound = true; return readyToInsert(); }
-        bool foundMsg() { msgFound = true; return readyToInsert(); }
-
-        FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
-            actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
-    };
-
-    // map indexed by actor struct ptr
-    // value is map of all FwdDeclData that contains said actor struct ptr
-    // inner map is indexed by the message struct ptr of FwdDeclData
-    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
-
-    // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
-    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
-
-    void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
-        auto iter = map.find( decl );
-        if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
-            iter->second.emplace( make_pair( otherDecl, data ) );
-        } else { // else create inner map for key
-            map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
-        }
-    }
+	// tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
+	struct FwdDeclData {
+		const StructDecl * actorDecl;
+		const StructDecl * msgDecl;
+		FunctionDecl * fwdDecl;
+		bool actorFound;
+		bool msgFound;
+
+		bool readyToInsert() { return actorFound && msgFound; }
+		bool foundActor() { actorFound = true; return readyToInsert(); }
+		bool foundMsg() { msgFound = true; return readyToInsert(); }
+
+		FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
+			actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
+	};
+
+	// map indexed by actor struct ptr
+	// value is map of all FwdDeclData that contains said actor struct ptr
+	// inner map is indexed by the message struct ptr of FwdDeclData
+	unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
+
+	// this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
+	unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
+
+	void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
+		auto iter = map.find( decl );
+		if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
+			iter->second.emplace( make_pair( otherDecl, data ) );
+		} else { // else create inner map for key
+			map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
+		}
+	}
 
   public:
-    // insert decl into table so that we can fwd declare it later (average cost: O(1))
-    void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
-        FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
-        insert( actorDecl, msgDecl, actorMap, declToInsert );
-        insert( msgDecl, actorDecl, msgMap, declToInsert );
-    }
-
-    // returns list of decls to insert after current struct decl
-    // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
-    list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
-        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
-        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
-        auto iter = map.find( decl );
-        list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
-        if ( iter == map.end() ) return toInsertAfter;
-        
-        // iterate over inner map
-        unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
-        for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
-            FwdDeclData * currentDatum = innerIter->second;
-            bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
-            if ( ! readyToInsert ) { ++innerIter; continue; }
-            
-            // readyToInsert is true so we are good to insert the forward decl of the message fn
-            toInsertAfter.push_back( currentDatum->fwdDecl );
-
-            // need to remove from other map before deleting
-            // find inner map in other map ( other map is actor map if original is msg map and vice versa )
-            const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
-            auto otherMapIter = otherMap.find( otherDecl );
-
-            unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
-
-            // find the FwdDeclData we need to remove in the other inner map
-            auto otherInnerIter = otherInnerMap.find( decl );
-
-            // remove references to deleted FwdDeclData from current inner map
-            innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
-
-            // remove references to deleted FwdDeclData from other inner map
-            otherInnerMap.erase( otherInnerIter );
-            
-            // if other inner map is now empty, remove key from other outer map
-            if ( otherInnerMap.empty() )
-                otherMap.erase( otherDecl );
-
-            // now we are safe to delete the FwdDeclData since we are done with it
-            // and we have removed all references to it from our data structures
-            delete currentDatum;
-        }
-
-        // if current inner map is now empty, remove key from outer map.
-        // Have to do this after iterating for safety
-        if ( currInnerMap.empty() )
-            map.erase( decl );
-
-        return toInsertAfter;
-    }
+	// insert decl into table so that we can fwd declare it later (average cost: O(1))
+	void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
+		FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
+		insert( actorDecl, msgDecl, actorMap, declToInsert );
+		insert( msgDecl, actorDecl, msgMap, declToInsert );
+	}
+
+	// returns list of decls to insert after current struct decl
+	// Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
+	list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
+		unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
+		unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
+		auto iter = map.find( decl );
+		list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
+		if ( iter == map.end() ) return toInsertAfter;
+
+		// iterate over inner map
+		unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
+		for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
+			FwdDeclData * currentDatum = innerIter->second;
+			bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
+			if ( ! readyToInsert ) { ++innerIter; continue; }
+
+			// readyToInsert is true so we are good to insert the forward decl of the message fn
+			toInsertAfter.push_back( currentDatum->fwdDecl );
+
+			// need to remove from other map before deleting
+			// find inner map in other map ( other map is actor map if original is msg map and vice versa )
+			const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
+			auto otherMapIter = otherMap.find( otherDecl );
+
+			unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
+
+			// find the FwdDeclData we need to remove in the other inner map
+			auto otherInnerIter = otherInnerMap.find( decl );
+
+			// remove references to deleted FwdDeclData from current inner map
+			innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
+
+			// remove references to deleted FwdDeclData from other inner map
+			otherInnerMap.erase( otherInnerIter );
+
+			// if other inner map is now empty, remove key from other outer map
+			if ( otherInnerMap.empty() )
+				otherMap.erase( otherDecl );
+
+			// now we are safe to delete the FwdDeclData since we are done with it
+			// and we have removed all references to it from our data structures
+			delete currentDatum;
+		}
+
+		// if current inner map is now empty, remove key from outer map.
+		// Have to do this after iterating for safety
+		if ( currInnerMap.empty() )
+			map.erase( decl );
+
+		return toInsertAfter;
+	}
 };
 
 // generates the definitions of send operators for actors
-// collects data needed for next pass that does the circular defn resolution 
+// collects data needed for next pass that does the circular defn resolution
 //     for message send operators (via table above)
 struct GenFuncsCreateTables : public ast::WithDeclsToAdd<> {
-    unordered_set<const StructDecl *> & actorStructDecls;
-    unordered_set<const StructDecl *>  & messageStructDecls;
-    const StructDecl ** requestDecl;
-    const EnumDecl ** allocationDecl;
-    const StructDecl ** actorDecl;
-    const StructDecl ** msgDecl;
-    FwdDeclTable & forwardDecls;
-
-    // generates the operator for actor message sends
+	unordered_set<const StructDecl *> & actorStructDecls;
+	unordered_set<const StructDecl *>  & messageStructDecls;
+	const StructDecl ** requestDecl;
+	const EnumDecl ** allocationDecl;
+	const StructDecl ** actorDecl;
+	const StructDecl ** msgDecl;
+	FwdDeclTable & forwardDecls;
+
+	// generates the operator for actor message sends
 	void postvisit( const FunctionDecl * decl ) {
-        // return if not of the form receive( param1, param2 ) or if it is a forward decl
-        if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
-
-        // the params should be references
-        const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
-        const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
-        if ( !derivedActorRef || !derivedMsgRef ) return;
-
-        // the references should be to struct instances
-        const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
-        const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
-        if ( !arg1InstType || !arg2InstType ) return;
-
-        // If the struct instances are derived actor and message types then generate the message send routine
-        auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
-        auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
-        if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
-            //////////////////////////////////////////////////////////////////////
-            // The following generates this wrapper for all receive(derived_actor &, derived_msg &) functions
-            /* base_actor and base_msg are output params
-            static inline allocation __CFA_receive_wrap( derived_actor & receiver, derived_msg & msg, actor ** base_actor, message ** base_msg ) {
-                base_actor = &receiver;
-                base_msg = &msg;
-                return receive( receiver, msg );
-            }
-            */
-            CompoundStmt * wrapBody = new CompoundStmt( decl->location );
-
-            // generates: base_actor = &receiver;
-            wrapBody->push_back( new ExprStmt( decl->location,
-                UntypedExpr::createAssign( decl->location, 
-                    UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_actor" ) ),
-                    new AddressExpr( decl->location, new NameExpr( decl->location, "receiver" ) )
-                )
-            ));
-
-            // generates: base_msg = &msg;
-            wrapBody->push_back( new ExprStmt( decl->location,
-                UntypedExpr::createAssign( decl->location, 
-                    UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_msg" ) ),
-                    new AddressExpr( decl->location, new NameExpr( decl->location, "msg" ) )
-                )
-            ));
-
-            // generates: return receive( receiver, msg );
-            wrapBody->push_back( new ReturnStmt( decl->location,
-                new UntypedExpr ( decl->location,
-                    new NameExpr( decl->location, "receive" ),
-                    {
-                        new NameExpr( decl->location, "receiver" ),
-                        new NameExpr( decl->location, "msg" )
-                    }
-                )
-            ));
-
-            // create receive wrapper to extract base message and actor pointer
-            // put it all together into the complete function decl from above
-            FunctionDecl * receiveWrapper = new FunctionDecl(
-                decl->location,
-                "__CFA_receive_wrap",
-                {
-                    new ObjectDecl(
-                        decl->location,
-                        "receiver",
-                        ast::deepCopy( derivedActorRef )
-                    ),
-                    new ObjectDecl(
-                        decl->location,
-                        "msg",
-                        ast::deepCopy( derivedMsgRef )
-                    ),
-                    new ObjectDecl(
-                        decl->location,
-                        "base_actor",
-                        new PointerType( new PointerType( new StructInstType( *actorDecl ) ) )
-                    ),
-                    new ObjectDecl(
-                        decl->location,
-                        "base_msg",
-                        new PointerType( new PointerType( new StructInstType( *msgDecl ) ) )
-                    )
-                },                      // params
-                {
-                    new ObjectDecl(
-                        decl->location,
-                        "__CFA_receive_wrap_ret",
-                        new EnumInstType( *allocationDecl )
-                    )
-                },
-                wrapBody,               // body
-                { Storage::Static },    // storage
-                Linkage::Cforall,       // linkage
-                {},                     // attributes
-                { Function::Inline }
-            );
-
-            declsToAddAfter.push_back( receiveWrapper );
-
-            //////////////////////////////////////////////////////////////////////
-            // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions
-            /*
-                static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) {
-                    request new_req;
-                    allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
-                    __receive_fn fn = (__receive_fn)my_work_fn;
-                    new_req{ &receiver, &msg, fn };
-                    send( receiver, new_req );
-                    return receiver;
-                }
-            */ 
-            CompoundStmt * sendBody = new CompoundStmt( decl->location );
-
-            // Generates: request new_req;
-            sendBody->push_back( new DeclStmt(
-                decl->location,
-                new ObjectDecl(
-                    decl->location,
-                    "new_req",
-                    new StructInstType( *requestDecl )
-                )
-            ));
-            
-            // Function type is: allocation (*)( derived_actor &, derived_msg &, actor **, message ** )
-            FunctionType * derivedReceive = new FunctionType();
-            derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) );
-            derivedReceive->params.push_back( ast::deepCopy( derivedMsgRef ) );
-            derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
-            derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
-            derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
-
-            // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg &, actor **, message ** ) = receive;
-            sendBody->push_back( new DeclStmt(
-                decl->location,
-                new ObjectDecl(
-                    decl->location,
-                    "my_work_fn",
-                    new PointerType( derivedReceive ),
-                    new SingleInit( decl->location, new NameExpr( decl->location, "__CFA_receive_wrap" ) )
-                )
-            ));
-
-            // Function type is: allocation (*)( actor &, message & )
-            FunctionType * genericReceive = new FunctionType();
-            genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) );
-            genericReceive->params.push_back( new ReferenceType( new StructInstType( *msgDecl ) ) );
-            genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
-            genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
-            genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
-
-            // Generates: allocation (*fn)( actor &, message & ) = (allocation (*)( actor &, message & ))my_work_fn;
-            // More readable synonymous code: 
-            //     typedef allocation (*__receive_fn)(actor &, message &);
-            //     __receive_fn fn = (__receive_fn)my_work_fn;
-            sendBody->push_back( new DeclStmt(
-                decl->location,
-                new ObjectDecl(
-                    decl->location,
-                    "fn",
-                    new PointerType( genericReceive ),
-                    new SingleInit( decl->location, 
-                        new CastExpr( decl->location, new NameExpr( decl->location, "my_work_fn" ), new PointerType( genericReceive ), ExplicitCast )
-                    )
-                )
-            ));
-
-            // Generates: new_req{ (actor *)&receiver, (message *)&msg, fn };
-            sendBody->push_back( new ExprStmt(
-                decl->location,
+		// return if not of the form receive( param1, param2 ) or if it is a forward decl
+		if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
+
+		// the params should be references
+		const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
+		const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
+		if ( !derivedActorRef || !derivedMsgRef ) return;
+
+		// the references should be to struct instances
+		const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
+		const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
+		if ( !arg1InstType || !arg2InstType ) return;
+
+		// If the struct instances are derived actor and message types then generate the message send routine
+		auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
+		auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
+		if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
+			//////////////////////////////////////////////////////////////////////
+			// The following generates this wrapper for all receive(derived_actor &, derived_msg &) functions
+			/* base_actor and base_msg are output params
+			static inline allocation __CFA_receive_wrap( derived_actor & receiver, derived_msg & msg, actor ** base_actor, message ** base_msg ) {
+				base_actor = &receiver;
+				base_msg = &msg;
+				return receive( receiver, msg );
+			}
+			*/
+			CompoundStmt * wrapBody = new CompoundStmt( decl->location );
+
+			// generates: base_actor = &receiver;
+			wrapBody->push_back( new ExprStmt( decl->location,
+				UntypedExpr::createAssign( decl->location,
+					UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_actor" ) ),
+					new AddressExpr( decl->location, new NameExpr( decl->location, "receiver" ) )
+				)
+			));
+
+			// generates: base_msg = &msg;
+			wrapBody->push_back( new ExprStmt( decl->location,
+				UntypedExpr::createAssign( decl->location,
+					UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_msg" ) ),
+					new AddressExpr( decl->location, new NameExpr( decl->location, "msg" ) )
+				)
+			));
+
+			// generates: return receive( receiver, msg );
+			wrapBody->push_back( new ReturnStmt( decl->location,
+				new UntypedExpr ( decl->location,
+					new NameExpr( decl->location, "receive" ),
+					{
+						new NameExpr( decl->location, "receiver" ),
+						new NameExpr( decl->location, "msg" )
+					}
+				)
+			));
+
+			// create receive wrapper to extract base message and actor pointer
+			// put it all together into the complete function decl from above
+			FunctionDecl * receiveWrapper = new FunctionDecl(
+				decl->location,
+				"__CFA_receive_wrap",
+				{
+					new ObjectDecl(
+						decl->location,
+						"receiver",
+						ast::deepCopy( derivedActorRef )
+					),
+					new ObjectDecl(
+						decl->location,
+						"msg",
+						ast::deepCopy( derivedMsgRef )
+					),
+					new ObjectDecl(
+						decl->location,
+						"base_actor",
+						new PointerType( new PointerType( new StructInstType( *actorDecl ) ) )
+					),
+					new ObjectDecl(
+						decl->location,
+						"base_msg",
+						new PointerType( new PointerType( new StructInstType( *msgDecl ) ) )
+					)
+				},                      // params
+				{
+					new ObjectDecl(
+						decl->location,
+						"__CFA_receive_wrap_ret",
+						new EnumInstType( *allocationDecl )
+					)
+				},
+				wrapBody,               // body
+				{ Storage::Static },    // storage
+				Linkage::Cforall,       // linkage
+				{},                     // attributes
+				{ Function::Inline }
+			);
+
+			declsToAddAfter.push_back( receiveWrapper );
+
+			//////////////////////////////////////////////////////////////////////
+			// The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions
+			/*
+				static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) {
+					request new_req;
+					allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
+					__receive_fn fn = (__receive_fn)my_work_fn;
+					new_req{ &receiver, &msg, fn };
+					send( receiver, new_req );
+					return receiver;
+				}
+			*/
+			CompoundStmt * sendBody = new CompoundStmt( decl->location );
+
+			// Generates: request new_req;
+			sendBody->push_back( new DeclStmt(
+				decl->location,
+				new ObjectDecl(
+					decl->location,
+					"new_req",
+					new StructInstType( *requestDecl )
+				)
+			));
+
+			// Function type is: allocation (*)( derived_actor &, derived_msg &, actor **, message ** )
+			FunctionType * derivedReceive = new FunctionType();
+			derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) );
+			derivedReceive->params.push_back( ast::deepCopy( derivedMsgRef ) );
+			derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
+			derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
+			derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
+
+			// Generates: allocation (*my_work_fn)( derived_actor &, derived_msg &, actor **, message ** ) = receive;
+			sendBody->push_back( new DeclStmt(
+				decl->location,
+				new ObjectDecl(
+					decl->location,
+					"my_work_fn",
+					new PointerType( derivedReceive ),
+					new SingleInit( decl->location, new NameExpr( decl->location, "__CFA_receive_wrap" ) )
+				)
+			));
+
+			// Function type is: allocation (*)( actor &, message & )
+			FunctionType * genericReceive = new FunctionType();
+			genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) );
+			genericReceive->params.push_back( new ReferenceType( new StructInstType( *msgDecl ) ) );
+			genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
+			genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
+			genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
+
+			// Generates: allocation (*fn)( actor &, message & ) = (allocation (*)( actor &, message & ))my_work_fn;
+			// More readable synonymous code:
+			//     typedef allocation (*__receive_fn)(actor &, message &);
+			//     __receive_fn fn = (__receive_fn)my_work_fn;
+			sendBody->push_back( new DeclStmt(
+				decl->location,
+				new ObjectDecl(
+					decl->location,
+					"fn",
+					new PointerType( genericReceive ),
+					new SingleInit( decl->location,
+						new CastExpr( decl->location, new NameExpr( decl->location, "my_work_fn" ), new PointerType( genericReceive ), ExplicitCast )
+					)
+				)
+			));
+
+			// Generates: new_req{ (actor *)&receiver, (message *)&msg, fn };
+			sendBody->push_back( new ExprStmt(
+				decl->location,
 				new UntypedExpr (
-                    decl->location, 
+					decl->location,
 					new NameExpr( decl->location, "?{}" ),
 					{
 						new NameExpr( decl->location, "new_req" ),
-                        new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "receiver" ) ), new PointerType( new StructInstType( *actorDecl ) ), ExplicitCast ),
-                        new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "msg" ) ), new PointerType( new StructInstType( *msgDecl ) ), ExplicitCast ),
-                        new NameExpr( decl->location, "fn" )
+						new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "receiver" ) ), new PointerType( new StructInstType( *actorDecl ) ), ExplicitCast ),
+						new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "msg" ) ), new PointerType( new StructInstType( *msgDecl ) ), ExplicitCast ),
+						new NameExpr( decl->location, "fn" )
 					}
 				)
 			));
 
-            // Generates: send( receiver, new_req );
-            sendBody->push_back( new ExprStmt(
-                decl->location,
+			// Generates: send( receiver, new_req );
+			sendBody->push_back( new ExprStmt(
+				decl->location,
 				new UntypedExpr (
-                    decl->location,
+					decl->location,
 					new NameExpr( decl->location, "send" ),
 					{
 						{
-                            new NameExpr( decl->location, "receiver" ),
-                            new NameExpr( decl->location, "new_req" )
-                        }
+							new NameExpr( decl->location, "receiver" ),
+							new NameExpr( decl->location, "new_req" )
+						}
 					}
 				)
 			));
 
-            // Generates: return receiver;
-            sendBody->push_back( new ReturnStmt( decl->location, new NameExpr( decl->location, "receiver" ) ) );
-
-            // put it all together into the complete function decl from above
-            FunctionDecl * sendOperatorFunction = new FunctionDecl(
-                decl->location,
-                "?|?",
-                {
-                    new ObjectDecl(
-                        decl->location,
-                        "receiver",
-                        ast::deepCopy( derivedActorRef )
-                    ),
-                    new ObjectDecl(
-                        decl->location,
-                        "msg",
-                        ast::deepCopy( derivedMsgRef )
-                    )
-                },                      // params
-                {
-                    new ObjectDecl(
-                        decl->location,
-                        "receiver_ret",
-                        ast::deepCopy( derivedActorRef )
-                    )
-                },
-                nullptr,               // body
-                { Storage::Static },    // storage
-                Linkage::Cforall,       // linkage
-                {},                     // attributes
-                { Function::Inline }
-            );
-
-            // forward decls to resolve use before decl problem for '|' routines
-            forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
-
-            sendOperatorFunction->stmts = sendBody;
-            declsToAddAfter.push_back( sendOperatorFunction );
-        }
+			// Generates: return receiver;
+			sendBody->push_back( new ReturnStmt( decl->location, new NameExpr( decl->location, "receiver" ) ) );
+
+			// put it all together into the complete function decl from above
+			FunctionDecl * sendOperatorFunction = new FunctionDecl(
+				decl->location,
+				"?|?",
+				{
+					new ObjectDecl(
+						decl->location,
+						"receiver",
+						ast::deepCopy( derivedActorRef )
+					),
+					new ObjectDecl(
+						decl->location,
+						"msg",
+						ast::deepCopy( derivedMsgRef )
+					)
+				},                      // params
+				{
+					new ObjectDecl(
+						decl->location,
+						"receiver_ret",
+						ast::deepCopy( derivedActorRef )
+					)
+				},
+				nullptr,               // body
+				{ Storage::Static },    // storage
+				Linkage::Cforall,       // linkage
+				{},                     // attributes
+				{ Function::Inline }
+			);
+
+			// forward decls to resolve use before decl problem for '|' routines
+			forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
+
+			sendOperatorFunction->stmts = sendBody;
+			declsToAddAfter.push_back( sendOperatorFunction );
+		}
 	}
 
   public:
-    GenFuncsCreateTables( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
-        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl, 
-        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), 
-        requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
+	GenFuncsCreateTables( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
+		const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
+		FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
+		requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
 };
 
@@ -452,76 +452,75 @@
 // generates the forward declarations of the send operator for actor routines
 struct FwdDeclOperator : public ast::WithDeclsToAdd<> {
-    unordered_set<const StructDecl *> & actorStructDecls;
-    unordered_set<const StructDecl *>  & messageStructDecls;
-    FwdDeclTable & forwardDecls;
-
-    // handles forward declaring the message operator
-    void postvisit( const StructDecl * decl ) {
-        list<FunctionDecl *> toAddAfter;
-        auto actorIter = actorStructDecls.find( decl );
-        if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
-            // get list of fwd decls that we can now insert
-            toAddAfter = forwardDecls.updateDecl( decl, false );
-
-            // get rid of decl from actorStructDecls since we no longer need it
-            actorStructDecls.erase( actorIter );
-        } else {
-            auto messageIter = messageStructDecls.find( decl );
-            if ( messageIter == messageStructDecls.end() ) return;
-
-            toAddAfter = forwardDecls.updateDecl( decl, true );
-
-            // get rid of decl from messageStructDecls since we no longer need it
-            messageStructDecls.erase( messageIter );
-        }
-
-        // add the fwd decls to declsToAddAfter
-        for ( FunctionDecl * func : toAddAfter ) {
-            declsToAddAfter.push_back( func );
-        }
-    }
+	unordered_set<const StructDecl *> & actorStructDecls;
+	unordered_set<const StructDecl *>  & messageStructDecls;
+	FwdDeclTable & forwardDecls;
+
+	// handles forward declaring the message operator
+	void postvisit( const StructDecl * decl ) {
+		list<FunctionDecl *> toAddAfter;
+		auto actorIter = actorStructDecls.find( decl );
+		if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
+			// get list of fwd decls that we can now insert
+			toAddAfter = forwardDecls.updateDecl( decl, false );
+
+			// get rid of decl from actorStructDecls since we no longer need it
+			actorStructDecls.erase( actorIter );
+		} else {
+			auto messageIter = messageStructDecls.find( decl );
+			if ( messageIter == messageStructDecls.end() ) return;
+
+			toAddAfter = forwardDecls.updateDecl( decl, true );
+
+			// get rid of decl from messageStructDecls since we no longer need it
+			messageStructDecls.erase( messageIter );
+		}
+
+		// add the fwd decls to declsToAddAfter
+		for ( FunctionDecl * func : toAddAfter ) {
+			declsToAddAfter.push_back( func );
+		}
+	}
 
   public:
-    FwdDeclOperator( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls, 
-        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), forwardDecls(forwardDecls) {}
+	FwdDeclOperator( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
+		FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), forwardDecls(forwardDecls) {}
 };
 
 void implementActors( TranslationUnit & translationUnit ) {
-    // unordered_maps to collect all derived actor and message types
-    unordered_set<const StructDecl *> actorStructDecls;
-    unordered_set<const StructDecl *> messageStructDecls;
-    FwdDeclTable forwardDecls;
-
-    // for storing through the passes
-    // these are populated with various important struct decls
-    const StructDecl * requestDeclPtr = nullptr;
-    const EnumDecl * allocationDeclPtr = nullptr;
-    const StructDecl * actorDeclPtr = nullptr;
-    const StructDecl * msgDeclPtr = nullptr;
-
-    // double pointer to modify local ptrs above
-    const StructDecl ** requestDecl = &requestDeclPtr;
-    const EnumDecl ** allocationDecl = &allocationDeclPtr;
-    const StructDecl ** actorDecl = &actorDeclPtr;
-    const StructDecl ** msgDecl = &msgDeclPtr;
-
-    // first pass collects ptrs to allocation enum, request type, and generic receive fn typedef
-    // also populates maps of all derived actors and messages
-    Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, 
-        allocationDecl, actorDecl, msgDecl );
-
-    // check that we have found all the decls we need from <actor.hfa>, if not no need to run the rest of this pass
-    if ( !allocationDeclPtr || !requestDeclPtr || !actorDeclPtr || !msgDeclPtr ) 
-        return;
-
-    // second pass locates all receive() routines that overload the generic receive fn
-    // it then generates the appropriate operator '|' send routines for the receive routines
-    Pass<GenFuncsCreateTables>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, 
-        allocationDecl, actorDecl, msgDecl, forwardDecls );
-
-    // The third pass forward declares operator '|' send routines
-    Pass<FwdDeclOperator>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );
+	// unordered_maps to collect all derived actor and message types
+	unordered_set<const StructDecl *> actorStructDecls;
+	unordered_set<const StructDecl *> messageStructDecls;
+	FwdDeclTable forwardDecls;
+
+	// for storing through the passes
+	// these are populated with various important struct decls
+	const StructDecl * requestDeclPtr = nullptr;
+	const EnumDecl * allocationDeclPtr = nullptr;
+	const StructDecl * actorDeclPtr = nullptr;
+	const StructDecl * msgDeclPtr = nullptr;
+
+	// double pointer to modify local ptrs above
+	const StructDecl ** requestDecl = &requestDeclPtr;
+	const EnumDecl ** allocationDecl = &allocationDeclPtr;
+	const StructDecl ** actorDecl = &actorDeclPtr;
+	const StructDecl ** msgDecl = &msgDeclPtr;
+
+	// first pass collects ptrs to allocation enum, request type, and generic receive fn typedef
+	// also populates maps of all derived actors and messages
+	Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
+		allocationDecl, actorDecl, msgDecl );
+
+	// check that we have found all the decls we need from <actor.hfa>, if not no need to run the rest of this pass
+	if ( !allocationDeclPtr || !requestDeclPtr || !actorDeclPtr || !msgDeclPtr )
+		return;
+
+	// second pass locates all receive() routines that overload the generic receive fn
+	// it then generates the appropriate operator '|' send routines for the receive routines
+	Pass<GenFuncsCreateTables>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
+		allocationDecl, actorDecl, msgDecl, forwardDecls );
+
+	// The third pass forward declares operator '|' send routines
+	Pass<FwdDeclOperator>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );
 }
-
 
 } // namespace Concurrency
Index: src/Concurrency/Corun.cpp
===================================================================
--- src/Concurrency/Corun.cpp	(revision 7a780ad23506507b6a1feccc46d18e12da183ceb)
+++ src/Concurrency/Corun.cpp	(revision ba97ebf4075c56eacf19495c1452730cedf50fa1)
@@ -26,274 +26,274 @@
 
 struct CorunKeyword : public WithDeclsToAdd<>, public WithStmtsToAdd<> {
-    UniqueName CorunFnNamer = "__CFA_corun_lambda_"s;
-    UniqueName CoforFnNamer = "__CFA_cofor_lambda_"s;
-    // UniqueName CoforFnVarNamer = "__CFA_cofor_lambda_var"s;
-    UniqueName RunnerBlockNamer = "__CFA_corun_block_"s;
-    
-    string coforArgName = "__CFA_cofor_lambda_arg";
-    string numProcsName = "__CFA_cofor_num_procs";
-    string currProcsName = "__CFA_cofor_curr_procs";
-    string thdArrName = "__CFA_cofor_thread_array";
-    string loopTempName = "__CFA_cofor_loop_temp";
-    
-
-    const StructDecl * runnerBlockDecl = nullptr;
-    const StructDecl * coforRunnerDecl = nullptr;
-
-    // Finds runner_block (corun task) and cofor_runner (cofor task) decls
-    void previsit( const StructDecl * decl ) {
-        if ( !decl->body ) {
-            return;
-        } else if ( "runner_block" == decl->name ) {
-            assert( !runnerBlockDecl );
-            runnerBlockDecl = decl;
-        } else if ( "cofor_runner" == decl->name ) {
-            assert( !coforRunnerDecl );
-            coforRunnerDecl = decl;
-        }
-    }
-
-    // codegen for cofor statements
-    Stmt * postvisit( const CoforStmt * stmt ) {
-        if ( !runnerBlockDecl || !coforRunnerDecl )
-            SemanticError( stmt->location, "To use cofor statements add #include <cofor.hfa>" );
-
-        if ( stmt->inits.size() != 1 )
-            SemanticError( stmt->location, "Cofor statements must have a single initializer in the loop control" );
-
-        if ( !stmt->body )
-            return nullptr;
-
-        const CodeLocation & loc = stmt->location;
-        const string fnName = CoforFnNamer.newName();
-
-        CompoundStmt * body = new CompoundStmt( loc );
-
-        // push back cofor initializer to generated body
-        body->push_back( deepCopy( stmt->inits.at(0) ) );
-
-        CompoundStmt * fnBody = new CompoundStmt( loc );
-
-        const DeclStmt * declStmtPtr = dynamic_cast<const DeclStmt *>(stmt->inits.at(0).get());
-        if ( ! declStmtPtr )
-            SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl statement?" );
-
-        const Decl * declPtr = dynamic_cast<const Decl *>(declStmtPtr->decl.get());
-        if ( ! declPtr )
-            SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl?" );
-
-        Type * initType = new TypeofType( new NameExpr( loc, declPtr->name ) );
-
-        // Generates:
-        // typeof(init) __CFA_cofor_lambda_var = *((typeof(init) *)val);
-        fnBody->push_back( new DeclStmt( loc, 
-            new ObjectDecl( loc,
-                declPtr->name,
-                initType,
-                new SingleInit( loc,
-                    UntypedExpr::createDeref( loc,
-                        new CastExpr( loc, 
-                            new NameExpr( loc, coforArgName ), 
-                            new PointerType( initType ), ExplicitCast
-                        )
-                    )
-                )
-            )
-        ));
-
-        // push rest of cofor body into loop lambda
-        fnBody->push_back( deepCopy( stmt->body ) );
-
-        // Generates:
-        // void __CFA_cofor_lambda_() {
-        //    typeof(init) __CFA_cofor_lambda_var = *((typeof(init) *)val);
-        //    stmt->body;
-        // }
-        Stmt * coforLambda = new DeclStmt( loc,
-            new FunctionDecl( loc,
-                fnName,                                             // name
-                {
-                    new ObjectDecl( loc,
-                        coforArgName,
-                        new ast::PointerType( new ast::VoidType() )
-                    )
-                },                                                  // params
-                {},                                                 // return
-                fnBody   // body
-            )
-        );
-        body->push_back( coforLambda );
-
-        // Generates:
-        // unsigned __CFA_cofor_num_procs = get_proc_count();
-        body->push_back( new DeclStmt( loc,
-                new ObjectDecl( loc,
-                    numProcsName,
-                    new BasicType( BasicKind::UnsignedInt ),
-                    new SingleInit( loc, 
-                        new UntypedExpr( loc,
-                            new NameExpr( loc, "get_proc_count" ),
-                            {}
-                        )
-                    )
-                )
-            )
-        );
-
-        // Generates:
-        // unsigned __CFA_cofor_curr_procs = 0;
-        body->push_back( new DeclStmt( loc,
-                new ObjectDecl( loc,
-                    currProcsName,
-                    new BasicType( BasicKind::UnsignedInt ),
-                    new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
-                )
-            )
-        );
-
-        // Generates:
-        // unsigned cofor_runner __CFA_cofor_thread_array[nprocs];
-        body->push_back( new DeclStmt( loc,
-                new ObjectDecl( loc,
-                    thdArrName,
-                    new ast::ArrayType(
-                        new StructInstType( coforRunnerDecl ),
-                        new NameExpr( loc, numProcsName ),
-                        ast::FixedLen,
-                        ast::DynamicDim
-                    )
-                )
-            )
-        );
-
-        // Generates:
-        // start_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs, __CFA_cofor_lambda_ );
-        body->push_back( new ExprStmt( loc,
-            new UntypedExpr( loc,
-                new NameExpr( loc, "start_runners" ),
-                {
-                    new NameExpr( loc, thdArrName ),
-                    new NameExpr( loc, numProcsName ),
-                    new NameExpr( loc, fnName )
-                }
-            )
-        ));
-
-        // Generates:
-        // typeof(initializer) * __CFA_cofor_loop_temp = malloc();
-        CompoundStmt * forLoopBody = new CompoundStmt( loc );
-        forLoopBody->push_back( new DeclStmt( loc,
-                new ObjectDecl( loc,
-                    loopTempName,
-                    new PointerType( initType ),
-                    new SingleInit( loc, 
-                        new UntypedExpr( loc,
-                            new NameExpr( loc, "malloc" ),
-                            {}
-                        )
-                    )
-                )
-            )
-        );
-
-        // Generates:
-        // *__CFA_cofor_loop_temp = initializer;
-        forLoopBody->push_back( new ExprStmt( loc,
-            UntypedExpr::createAssign( loc,
-                UntypedExpr::createDeref( loc, new NameExpr( loc, loopTempName ) ),
-                new NameExpr( loc, declPtr->name )
-            )
-        ));
-
-        // Generates:
-        // send_work( __CFA_cofor_thread_array, __CFA_cofor_num_procs,
-        //     __CFA_cofor_curr_procs, __CFA_cofor_loop_temp );
-        forLoopBody->push_back( new ExprStmt( loc,
-            new UntypedExpr( loc,
-                new NameExpr( loc, "send_work" ),
-                {
-                    new NameExpr( loc, thdArrName ),
-                    new NameExpr( loc, numProcsName ),
-                    new NameExpr( loc, currProcsName ),
-                    new NameExpr( loc, loopTempName )
-                }
-            )
-        ));
-
-        body->push_back( new ForStmt( loc,
-            {},
-            deepCopy( stmt->cond ),
-            deepCopy( stmt->inc ),
-            forLoopBody
-        ));
-
-        // Generates:
-        // end_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs );
-        body->push_back( new ExprStmt( loc,
-            new UntypedExpr( loc,
-                new NameExpr( loc, "end_runners" ),
-                {
-                    new NameExpr( loc, thdArrName ),
-                    new NameExpr( loc, numProcsName )
-                }
-            )
-        ));
-
-        return body;
-    }
-
-    // codegen for corun statements
-    Stmt * postvisit( const CorunStmt * stmt ) {
-        if ( !runnerBlockDecl || !coforRunnerDecl )
-            SemanticError( stmt->location, "To use corun statements add #include <cofor.hfa>" );
-
-        if ( !stmt->stmt )
-            return nullptr;
-
-        const CodeLocation & loc = stmt->location;
-        const string fnName = CorunFnNamer.newName();
-        const string objName = RunnerBlockNamer.newName();
-
-        // Generates:
-        // void __CFA_corun_lambda_() { ... stmt->stmt ... }
-        Stmt * runnerLambda = new DeclStmt( loc,
-            new FunctionDecl( loc,
-                fnName,                                             // name
-                {},                                                 // params
-                {},                                                 // return
-                new CompoundStmt( loc, { deepCopy(stmt->stmt) } )   // body
-            )
-        );
-
-        // Generates:
-        // runner_block __CFA_corun_block_;
-        Stmt * objDecl = new DeclStmt( loc,
-            new ObjectDecl( loc,
-                objName,
-                new StructInstType( runnerBlockDecl )
-            )
-        );
-
-        // Generates:
-        // __CFA_corun_block_{ __CFA_corun_lambda_ };
-        Stmt * threadStart = new ExprStmt( loc,
-            new UntypedExpr ( loc,
-                new NameExpr( loc, "?{}" ),
-                {
-                    new NameExpr( loc, objName ),
-                    new NameExpr( loc, fnName )
-                }
-            )
-        );
-
-        stmtsToAddBefore.push_back( runnerLambda );
-        stmtsToAddBefore.push_back( objDecl );
-
-        return threadStart;
-    }
+	UniqueName CorunFnNamer = "__CFA_corun_lambda_"s;
+	UniqueName CoforFnNamer = "__CFA_cofor_lambda_"s;
+	// UniqueName CoforFnVarNamer = "__CFA_cofor_lambda_var"s;
+	UniqueName RunnerBlockNamer = "__CFA_corun_block_"s;
+
+	string coforArgName = "__CFA_cofor_lambda_arg";
+	string numProcsName = "__CFA_cofor_num_procs";
+	string currProcsName = "__CFA_cofor_curr_procs";
+	string thdArrName = "__CFA_cofor_thread_array";
+	string loopTempName = "__CFA_cofor_loop_temp";
+
+
+	const StructDecl * runnerBlockDecl = nullptr;
+	const StructDecl * coforRunnerDecl = nullptr;
+
+	// Finds runner_block (corun task) and cofor_runner (cofor task) decls
+	void previsit( const StructDecl * decl ) {
+		if ( !decl->body ) {
+			return;
+		} else if ( "runner_block" == decl->name ) {
+			assert( !runnerBlockDecl );
+			runnerBlockDecl = decl;
+		} else if ( "cofor_runner" == decl->name ) {
+			assert( !coforRunnerDecl );
+			coforRunnerDecl = decl;
+		}
+	}
+
+	// codegen for cofor statements
+	Stmt * postvisit( const CoforStmt * stmt ) {
+		if ( !runnerBlockDecl || !coforRunnerDecl )
+			SemanticError( stmt->location, "To use cofor statements add #include <cofor.hfa>" );
+
+		if ( stmt->inits.size() != 1 )
+			SemanticError( stmt->location, "Cofor statements must have a single initializer in the loop control" );
+
+		if ( !stmt->body )
+			return nullptr;
+
+		const CodeLocation & loc = stmt->location;
+		const string fnName = CoforFnNamer.newName();
+
+		CompoundStmt * body = new CompoundStmt( loc );
+
+		// push back cofor initializer to generated body
+		body->push_back( deepCopy( stmt->inits.at(0) ) );
+
+		CompoundStmt * fnBody = new CompoundStmt( loc );
+
+		const DeclStmt * declStmtPtr = dynamic_cast<const DeclStmt *>(stmt->inits.at(0).get());
+		if ( ! declStmtPtr )
+			SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl statement?" );
+
+		const Decl * declPtr = dynamic_cast<const Decl *>(declStmtPtr->decl.get());
+		if ( ! declPtr )
+			SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl?" );
+
+		Type * initType = new TypeofType( new NameExpr( loc, declPtr->name ) );
+
+		// Generates:
+		// typeof(init) __CFA_cofor_lambda_var = *((typeof(init) *)val);
+		fnBody->push_back( new DeclStmt( loc,
+			new ObjectDecl( loc,
+				declPtr->name,
+				initType,
+				new SingleInit( loc,
+					UntypedExpr::createDeref( loc,
+						new CastExpr( loc,
+							new NameExpr( loc, coforArgName ),
+							new PointerType( initType ), ExplicitCast
+						)
+					)
+				)
+			)
+		));
+
+		// push rest of cofor body into loop lambda
+		fnBody->push_back( deepCopy( stmt->body ) );
+
+		// Generates:
+		// void __CFA_cofor_lambda_() {
+		//    typeof(init) __CFA_cofor_lambda_var = *((typeof(init) *)val);
+		//    stmt->body;
+		// }
+		Stmt * coforLambda = new DeclStmt( loc,
+			new FunctionDecl( loc,
+				fnName,                                             // name
+				{
+					new ObjectDecl( loc,
+						coforArgName,
+						new ast::PointerType( new ast::VoidType() )
+					)
+				},                                                  // params
+				{},                                                 // return
+				fnBody   // body
+			)
+		);
+		body->push_back( coforLambda );
+
+		// Generates:
+		// unsigned __CFA_cofor_num_procs = get_proc_count();
+		body->push_back( new DeclStmt( loc,
+				new ObjectDecl( loc,
+					numProcsName,
+					new BasicType( BasicKind::UnsignedInt ),
+					new SingleInit( loc,
+						new UntypedExpr( loc,
+							new NameExpr( loc, "get_proc_count" ),
+							{}
+						)
+					)
+				)
+			)
+		);
+
+		// Generates:
+		// unsigned __CFA_cofor_curr_procs = 0;
+		body->push_back( new DeclStmt( loc,
+				new ObjectDecl( loc,
+					currProcsName,
+					new BasicType( BasicKind::UnsignedInt ),
+					new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
+				)
+			)
+		);
+
+		// Generates:
+		// unsigned cofor_runner __CFA_cofor_thread_array[nprocs];
+		body->push_back( new DeclStmt( loc,
+				new ObjectDecl( loc,
+					thdArrName,
+					new ast::ArrayType(
+						new StructInstType( coforRunnerDecl ),
+						new NameExpr( loc, numProcsName ),
+						ast::FixedLen,
+						ast::DynamicDim
+					)
+				)
+			)
+		);
+
+		// Generates:
+		// start_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs, __CFA_cofor_lambda_ );
+		body->push_back( new ExprStmt( loc,
+			new UntypedExpr( loc,
+				new NameExpr( loc, "start_runners" ),
+				{
+					new NameExpr( loc, thdArrName ),
+					new NameExpr( loc, numProcsName ),
+					new NameExpr( loc, fnName )
+				}
+			)
+		));
+
+		// Generates:
+		// typeof(initializer) * __CFA_cofor_loop_temp = malloc();
+		CompoundStmt * forLoopBody = new CompoundStmt( loc );
+		forLoopBody->push_back( new DeclStmt( loc,
+				new ObjectDecl( loc,
+					loopTempName,
+					new PointerType( initType ),
+					new SingleInit( loc,
+						new UntypedExpr( loc,
+							new NameExpr( loc, "malloc" ),
+							{}
+						)
+					)
+				)
+			)
+		);
+
+		// Generates:
+		// *__CFA_cofor_loop_temp = initializer;
+		forLoopBody->push_back( new ExprStmt( loc,
+			UntypedExpr::createAssign( loc,
+				UntypedExpr::createDeref( loc, new NameExpr( loc, loopTempName ) ),
+				new NameExpr( loc, declPtr->name )
+			)
+		));
+
+		// Generates:
+		// send_work( __CFA_cofor_thread_array, __CFA_cofor_num_procs,
+		//     __CFA_cofor_curr_procs, __CFA_cofor_loop_temp );
+		forLoopBody->push_back( new ExprStmt( loc,
+			new UntypedExpr( loc,
+				new NameExpr( loc, "send_work" ),
+				{
+					new NameExpr( loc, thdArrName ),
+					new NameExpr( loc, numProcsName ),
+					new NameExpr( loc, currProcsName ),
+					new NameExpr( loc, loopTempName )
+				}
+			)
+		));
+
+		body->push_back( new ForStmt( loc,
+			{},
+			deepCopy( stmt->cond ),
+			deepCopy( stmt->inc ),
+			forLoopBody
+		));
+
+		// Generates:
+		// end_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs );
+		body->push_back( new ExprStmt( loc,
+			new UntypedExpr( loc,
+				new NameExpr( loc, "end_runners" ),
+				{
+					new NameExpr( loc, thdArrName ),
+					new NameExpr( loc, numProcsName )
+				}
+			)
+		));
+
+		return body;
+	}
+
+	// codegen for corun statements
+	Stmt * postvisit( const CorunStmt * stmt ) {
+		if ( !runnerBlockDecl || !coforRunnerDecl )
+			SemanticError( stmt->location, "To use corun statements add #include <cofor.hfa>" );
+
+		if ( !stmt->stmt )
+			return nullptr;
+
+		const CodeLocation & loc = stmt->location;
+		const string fnName = CorunFnNamer.newName();
+		const string objName = RunnerBlockNamer.newName();
+
+		// Generates:
+		// void __CFA_corun_lambda_() { ... stmt->stmt ... }
+		Stmt * runnerLambda = new DeclStmt( loc,
+			new FunctionDecl( loc,
+				fnName,                                             // name
+				{},                                                 // params
+				{},                                                 // return
+				new CompoundStmt( loc, { deepCopy(stmt->stmt) } )   // body
+			)
+		);
+
+		// Generates:
+		// runner_block __CFA_corun_block_;
+		Stmt * objDecl = new DeclStmt( loc,
+			new ObjectDecl( loc,
+				objName,
+				new StructInstType( runnerBlockDecl )
+			)
+		);
+
+		// Generates:
+		// __CFA_corun_block_{ __CFA_corun_lambda_ };
+		Stmt * threadStart = new ExprStmt( loc,
+			new UntypedExpr ( loc,
+				new NameExpr( loc, "?{}" ),
+				{
+					new NameExpr( loc, objName ),
+					new NameExpr( loc, fnName )
+				}
+			)
+		);
+
+		stmtsToAddBefore.push_back( runnerLambda );
+		stmtsToAddBefore.push_back( objDecl );
+
+		return threadStart;
+	}
 };
 
 void implementCorun( TranslationUnit & translationUnit ) {
-    Pass<CorunKeyword>::run( translationUnit );
+	Pass<CorunKeyword>::run( translationUnit );
 }
 
Index: src/Concurrency/Keywords.cpp
===================================================================
--- src/Concurrency/Keywords.cpp	(revision 7a780ad23506507b6a1feccc46d18e12da183ceb)
+++ src/Concurrency/Keywords.cpp	(revision ba97ebf4075c56eacf19495c1452730cedf50fa1)
@@ -991,5 +991,5 @@
 	ast::CompoundStmt * body =
 			new ast::CompoundStmt( stmt->location, { stmt->stmt } );
-	
+
 	return addStatements( body, stmt->mutexObjs );;
 }
@@ -1180,5 +1180,5 @@
 
 // generates a cast to the void ptr to the appropriate lock type and dereferences it before calling lock or unlock on it
-// used to undo the type erasure done by storing all the lock pointers as void 
+// used to undo the type erasure done by storing all the lock pointers as void
 ast::ExprStmt * MutexKeyword::genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param ) {
 	return new ast::ExprStmt( location,
@@ -1187,5 +1187,5 @@
 				ast::UntypedExpr::createDeref(
 					location,
-					new ast::CastExpr( location, 
+					new ast::CastExpr( location,
 						param,
 						new ast::PointerType( new ast::TypeofType( new ast::UntypedExpr(
@@ -1208,5 +1208,5 @@
 	//adds an if/elif clause for each lock to assign type from void ptr based on ptr address
 	for ( long unsigned int i = 0; i < args.size(); i++ ) {
-		
+
 		ast::UntypedExpr * ifCond = new ast::UntypedExpr( location,
 			new ast::NameExpr( location, "?==?" ), {
@@ -1216,10 +1216,10 @@
 		);
 
-		ast::IfStmt * currLockIf = new ast::IfStmt( 
+		ast::IfStmt * currLockIf = new ast::IfStmt(
 			location,
 			ifCond,
 			genVirtLockUnlockExpr( fnName, args.at(i), location, ast::deepCopy( thisParam ) )
 		);
-		
+
 		if ( i == 0 ) {
 			outerLockIf = currLockIf;
@@ -1235,9 +1235,9 @@
 
 void flattenTuple( const ast::UntypedTupleExpr * tuple, std::vector<ast::ptr<ast::Expr>> & output ) {
-    for ( auto & expr : tuple->exprs ) {
-        const ast::UntypedTupleExpr * innerTuple = dynamic_cast<const ast::UntypedTupleExpr *>(expr.get());
-        if ( innerTuple ) flattenTuple( innerTuple, output );
-        else output.emplace_back( ast::deepCopy( expr ));
-    }
+	for ( auto & expr : tuple->exprs ) {
+		const ast::UntypedTupleExpr * innerTuple = dynamic_cast<const ast::UntypedTupleExpr *>(expr.get());
+		if ( innerTuple ) flattenTuple( innerTuple, output );
+		else output.emplace_back( ast::deepCopy( expr ));
+	}
 }
 
@@ -1255,11 +1255,11 @@
 	// std::string unlockFnName = mutex_func_namer.newName();
 
-    // If any arguments to the mutex stmt are tuples, flatten them
-    std::vector<ast::ptr<ast::Expr>> flattenedArgs;
-    for ( auto & arg : args ) {
-        const ast::UntypedTupleExpr * tuple = dynamic_cast<const ast::UntypedTupleExpr *>(args.at(0).get());
-        if ( tuple ) flattenTuple( tuple, flattenedArgs );
-        else flattenedArgs.emplace_back( ast::deepCopy( arg ));
-    }
+	// If any arguments to the mutex stmt are tuples, flatten them
+	std::vector<ast::ptr<ast::Expr>> flattenedArgs;
+	for ( auto & arg : args ) {
+		const ast::UntypedTupleExpr * tuple = dynamic_cast<const ast::UntypedTupleExpr *>(args.at(0).get());
+		if ( tuple ) flattenTuple( tuple, flattenedArgs );
+		else flattenedArgs.emplace_back( ast::deepCopy( arg ));
+	}
 
 	// Make pointer to the monitors.
@@ -1302,5 +1302,5 @@
 	// adds a nested try stmt for each lock we are locking
 	for ( long unsigned int i = 0; i < flattenedArgs.size(); i++ ) {
-		ast::UntypedExpr * innerAccess = new ast::UntypedExpr( 
+		ast::UntypedExpr * innerAccess = new ast::UntypedExpr(
 			location,
 			new ast::NameExpr( location,"?[?]" ), {
@@ -1426,5 +1426,5 @@
 	// 	);
 
-	// 	ast::IfStmt * currLockIf = new ast::IfStmt( 
+	// 	ast::IfStmt * currLockIf = new ast::IfStmt(
 	// 		location,
 	// 		ast::deepCopy( ifCond ),
@@ -1432,10 +1432,10 @@
 	// 	);
 
-	// 	ast::IfStmt * currUnlockIf = new ast::IfStmt( 
+	// 	ast::IfStmt * currUnlockIf = new ast::IfStmt(
 	// 		location,
 	// 		ifCond,
 	// 		genVirtLockUnlockExpr( "unlock", args.at(i), location, ast::deepCopy( thisParam ) )
 	// 	);
-		
+
 	// 	if ( i == 0 ) {
 	// 		outerLockIf = currLockIf;
@@ -1450,5 +1450,5 @@
 	// 	lastUnlockIf = currUnlockIf;
 	// }
-	
+
 	// // add pointer typing if/elifs to body of routines
 	// lock_decl->stmts = new ast::CompoundStmt( location, { outerLockIf } );
Index: src/Concurrency/Waituntil.cpp
===================================================================
--- src/Concurrency/Waituntil.cpp	(revision 7a780ad23506507b6a1feccc46d18e12da183ceb)
+++ src/Concurrency/Waituntil.cpp	(revision ba97ebf4075c56eacf19495c1452730cedf50fa1)
@@ -31,7 +31,7 @@
 /* So this is what this pass dones:
 {
-    when ( condA ) waituntil( A ){ doA(); } 
-    or when ( condB ) waituntil( B ){ doB(); } 
-    and when ( condC ) waituntil( C ) { doC(); }
+	when ( condA ) waituntil( A ){ doA(); }
+	or when ( condB ) waituntil( B ){ doB(); }
+	and when ( condC ) waituntil( C ) { doC(); }
 }
 		 ||
@@ -42,89 +42,89 @@
 Generates these two routines:
 static inline bool is_full_sat_1( int * clause_statuses ) {
-    return clause_statuses[0] 
-        || clause_statuses[1]
-        && clause_statuses[2];
+	return clause_statuses[0]
+		|| clause_statuses[1]
+		&& clause_statuses[2];
 }
 
 static inline bool is_done_sat_1( int * clause_statuses ) {
-    return has_run(clause_statuses[0])
-        || has_run(clause_statuses[1])
-        && has_run(clause_statuses[2]);
+	return has_run(clause_statuses[0])
+		|| has_run(clause_statuses[1])
+		&& has_run(clause_statuses[2]);
 }
 
 Replaces the waituntil statement above with the following code:
 {
-    // used with atomic_dec/inc to get binary semaphore behaviour
-    int park_counter = 0;
-
-    // status (one for each clause)
-    int clause_statuses[3] = { 0 };
-
-    bool whenA = condA;
-    bool whenB = condB;
-    bool whenC = condC;
-
-    if ( !whenB ) clause_statuses[1] = __SELECT_RUN;
-    if ( !whenC ) clause_statuses[2] = __SELECT_RUN;
-
-    // some other conditional settors for clause_statuses are set here, see genSubtreeAssign and related routines
-
-    // three blocks
-    // for each block, create, setup, then register select_node
-    select_node clause1;
-    select_node clause2;
-    select_node clause3;
-
-    try {
-        if ( whenA ) { register_select(A, clause1); setup_clause( clause1, &clause_statuses[0], &park_counter ); }
-        ... repeat ^ for B and C ... 
-
-        // if else clause is defined a separate branch can occur here to set initial values, see genWhenStateConditions
-
-        // loop & park until done
-        while( !is_full_sat_1( clause_statuses ) ) {
-            
-            // binary sem P();
-            if ( __atomic_sub_fetch( &park_counter, 1, __ATOMIC_SEQ_CST) < 0 )
-                park();
-            
-            // execute any blocks available with status set to 0
-            for ( int i = 0; i < 3; i++ ) {
-                if (clause_statuses[i] == __SELECT_SAT) {
-                    switch (i) {
-                        case 0:
-                            try {
-                                    on_selected( A, clause1 );
-                                    doA();
-                            }
-                            finally { clause_statuses[i] = __SELECT_RUN; unregister_select(A, clause1); }
-                            break;
-                        case 1:
-                            ... same gen as A but for B and clause2 ...
-                            break;
-                        case 2:
-                            ... same gen as A but for C and clause3 ...
-                            break;
-                    }
-                }
-            }
-        }
-
-        // ensure that the blocks that triggered is_full_sat_1 are run
-        // by running every un-run block that is SAT from the start until
-        // the predicate is SAT when considering RUN status = true
-        for ( int i = 0; i < 3; i++ ) {
-            if (is_done_sat_1( clause_statuses )) break;
-            if (clause_statuses[i] == __SELECT_SAT)
-                ... Same if body here as in loop above ...
-        }
-    } finally {
-        // the unregister and on_selected calls are needed to support primitives where the acquire has side effects
-        // so the corresponding block MUST be run for those primitives to not lose state (example is channels)
-        if ( !has_run(clause_statuses[0]) && whenA && unregister_select(A, clause1) )
-            on_selected( A, clause1 )
-            doA(); 
-        ... repeat if above for B and C ...
-    }
+	// used with atomic_dec/inc to get binary semaphore behaviour
+	int park_counter = 0;
+
+	// status (one for each clause)
+	int clause_statuses[3] = { 0 };
+
+	bool whenA = condA;
+	bool whenB = condB;
+	bool whenC = condC;
+
+	if ( !whenB ) clause_statuses[1] = __SELECT_RUN;
+	if ( !whenC ) clause_statuses[2] = __SELECT_RUN;
+
+	// some other conditional settors for clause_statuses are set here, see genSubtreeAssign and related routines
+
+	// three blocks
+	// for each block, create, setup, then register select_node
+	select_node clause1;
+	select_node clause2;
+	select_node clause3;
+
+	try {
+		if ( whenA ) { register_select(A, clause1); setup_clause( clause1, &clause_statuses[0], &park_counter ); }
+		... repeat ^ for B and C ...
+
+		// if else clause is defined a separate branch can occur here to set initial values, see genWhenStateConditions
+
+		// loop & park until done
+		while( !is_full_sat_1( clause_statuses ) ) {
+
+			// binary sem P();
+			if ( __atomic_sub_fetch( &park_counter, 1, __ATOMIC_SEQ_CST) < 0 )
+				park();
+
+			// execute any blocks available with status set to 0
+			for ( int i = 0; i < 3; i++ ) {
+				if (clause_statuses[i] == __SELECT_SAT) {
+				    switch (i) {
+				        case 0:
+				            try {
+				                    on_selected( A, clause1 );
+				                    doA();
+				            }
+				            finally { clause_statuses[i] = __SELECT_RUN; unregister_select(A, clause1); }
+				            break;
+				        case 1:
+				            ... same gen as A but for B and clause2 ...
+				            break;
+				        case 2:
+				            ... same gen as A but for C and clause3 ...
+				            break;
+				    }
+				}
+			}
+		}
+
+		// ensure that the blocks that triggered is_full_sat_1 are run
+		// by running every un-run block that is SAT from the start until
+		// the predicate is SAT when considering RUN status = true
+		for ( int i = 0; i < 3; i++ ) {
+			if (is_done_sat_1( clause_statuses )) break;
+			if (clause_statuses[i] == __SELECT_SAT)
+				... Same if body here as in loop above ...
+		}
+	} finally {
+		// the unregister and on_selected calls are needed to support primitives where the acquire has side effects
+		// so the corresponding block MUST be run for those primitives to not lose state (example is channels)
+		if ( !has_run(clause_statuses[0]) && whenA && unregister_select(A, clause1) )
+			on_selected( A, clause1 )
+			doA();
+		... repeat if above for B and C ...
+	}
 }
 
@@ -134,63 +134,63 @@
 
 class GenerateWaitUntilCore final {
-    vector<FunctionDecl *> & satFns;
+	vector<FunctionDecl *> & satFns;
 	UniqueName namer_sat = "__is_full_sat_"s;
-    UniqueName namer_run = "__is_run_sat_"s;
+	UniqueName namer_run = "__is_run_sat_"s;
 	UniqueName namer_park = "__park_counter_"s;
 	UniqueName namer_status = "__clause_statuses_"s;
 	UniqueName namer_node = "__clause_"s;
-    UniqueName namer_target = "__clause_target_"s;
-    UniqueName namer_when = "__when_cond_"s;
-    UniqueName namer_label = "__waituntil_label_"s;
-
-    string idxName = "__CFA_clause_idx_";
-
-    struct ClauseData {
-        string nodeName;
-        string targetName;
-        string whenName;
-        int index;
-        string & statusName;
-        ClauseData( int index, string & statusName ) : index(index), statusName(statusName) {}
-    };
-
-    const StructDecl * selectNodeDecl = nullptr;
-
-    // This first set of routines are all used to do the complicated job of 
-    //    dealing with how to set predicate statuses with certain when_conds T/F
-    //    so that the when_cond == F effectively makes that clause "disappear"
-    void updateAmbiguousWhen( WaitUntilStmt::ClauseNode * currNode, bool andAbove, bool orAbove, bool andBelow, bool orBelow );
-    void paintWhenTree( WaitUntilStmt::ClauseNode * currNode, bool andAbove, bool orAbove, bool & andBelow, bool & orBelow );
-    bool paintWhenTree( WaitUntilStmt::ClauseNode * currNode );
-    void collectWhens( WaitUntilStmt::ClauseNode * currNode, vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigIdxs, vector<int> & andIdxs, int & index, bool parentAmbig, bool parentAnd );
-    void collectWhens( WaitUntilStmt::ClauseNode * currNode, vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigIdxs, vector<int> & andIdxs );
-    void updateWhenState( WaitUntilStmt::ClauseNode * currNode );
-    void genSubtreeAssign( const WaitUntilStmt * stmt, WaitUntilStmt::ClauseNode * currNode, bool status, int & idx, CompoundStmt * retStmt, vector<ClauseData *> & clauseData );
-    void genStatusAssign( const WaitUntilStmt * stmt, WaitUntilStmt::ClauseNode * currNode, int & idx, CompoundStmt * retStmt, vector<ClauseData *> & clauseData );
-    CompoundStmt * getStatusAssignment( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData );
-    Stmt * genWhenStateConditions( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigClauses, vector<pair<int, WaitUntilStmt::ClauseNode *>>::size_type ambigIdx );
-
-    // These routines are just code-gen helpers
-    void addPredicates( const WaitUntilStmt * stmt, string & satName, string & runName );
-    void setUpClause( const WhenClause * clause, ClauseData * data, string & pCountName, CompoundStmt * body );
-    CompoundStmt * genStatusCheckFor( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, string & predName );
-    Expr * genSelectTraitCall( const WhenClause * clause, const ClauseData * data, string fnName );
-    CompoundStmt * genStmtBlock( const WhenClause * clause, const ClauseData * data );
-    Stmt * genElseClauseBranch( const WaitUntilStmt * stmt, string & runName, string & arrName, vector<ClauseData *> & clauseData );
-    Stmt * genNoElseClauseBranch( const WaitUntilStmt * stmt, string & runName, string & arrName, string & pCountName, vector<ClauseData *> & clauseData );
-    void genClauseInits( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, CompoundStmt * body, string & statusName, string & elseWhenName );
-    Stmt * recursiveOrIfGen( const WaitUntilStmt * stmt, vector<ClauseData *> & data, vector<ClauseData*>::size_type idx, string & elseWhenName );
-    Stmt * buildOrCaseSwitch( const WaitUntilStmt * stmt, string & statusName, vector<ClauseData *> & data );
-    Stmt * genAllOr( const WaitUntilStmt * stmt );
+	UniqueName namer_target = "__clause_target_"s;
+	UniqueName namer_when = "__when_cond_"s;
+	UniqueName namer_label = "__waituntil_label_"s;
+
+	string idxName = "__CFA_clause_idx_";
+
+	struct ClauseData {
+		string nodeName;
+		string targetName;
+		string whenName;
+		int index;
+		string & statusName;
+		ClauseData( int index, string & statusName ) : index(index), statusName(statusName) {}
+	};
+
+	const StructDecl * selectNodeDecl = nullptr;
+
+	// This first set of routines are all used to do the complicated job of
+	//    dealing with how to set predicate statuses with certain when_conds T/F
+	//    so that the when_cond == F effectively makes that clause "disappear"
+	void updateAmbiguousWhen( WaitUntilStmt::ClauseNode * currNode, bool andAbove, bool orAbove, bool andBelow, bool orBelow );
+	void paintWhenTree( WaitUntilStmt::ClauseNode * currNode, bool andAbove, bool orAbove, bool & andBelow, bool & orBelow );
+	bool paintWhenTree( WaitUntilStmt::ClauseNode * currNode );
+	void collectWhens( WaitUntilStmt::ClauseNode * currNode, vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigIdxs, vector<int> & andIdxs, int & index, bool parentAmbig, bool parentAnd );
+	void collectWhens( WaitUntilStmt::ClauseNode * currNode, vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigIdxs, vector<int> & andIdxs );
+	void updateWhenState( WaitUntilStmt::ClauseNode * currNode );
+	void genSubtreeAssign( const WaitUntilStmt * stmt, WaitUntilStmt::ClauseNode * currNode, bool status, int & idx, CompoundStmt * retStmt, vector<ClauseData *> & clauseData );
+	void genStatusAssign( const WaitUntilStmt * stmt, WaitUntilStmt::ClauseNode * currNode, int & idx, CompoundStmt * retStmt, vector<ClauseData *> & clauseData );
+	CompoundStmt * getStatusAssignment( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData );
+	Stmt * genWhenStateConditions( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigClauses, vector<pair<int, WaitUntilStmt::ClauseNode *>>::size_type ambigIdx );
+
+	// These routines are just code-gen helpers
+	void addPredicates( const WaitUntilStmt * stmt, string & satName, string & runName );
+	void setUpClause( const WhenClause * clause, ClauseData * data, string & pCountName, CompoundStmt * body );
+	CompoundStmt * genStatusCheckFor( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, string & predName );
+	Expr * genSelectTraitCall( const WhenClause * clause, const ClauseData * data, string fnName );
+	CompoundStmt * genStmtBlock( const WhenClause * clause, const ClauseData * data );
+	Stmt * genElseClauseBranch( const WaitUntilStmt * stmt, string & runName, string & arrName, vector<ClauseData *> & clauseData );
+	Stmt * genNoElseClauseBranch( const WaitUntilStmt * stmt, string & runName, string & arrName, string & pCountName, vector<ClauseData *> & clauseData );
+	void genClauseInits( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, CompoundStmt * body, string & statusName, string & elseWhenName );
+	Stmt * recursiveOrIfGen( const WaitUntilStmt * stmt, vector<ClauseData *> & data, vector<ClauseData*>::size_type idx, string & elseWhenName );
+	Stmt * buildOrCaseSwitch( const WaitUntilStmt * stmt, string & statusName, vector<ClauseData *> & data );
+	Stmt * genAllOr( const WaitUntilStmt * stmt );
 
   public:
-    void previsit( const StructDecl * decl );
+	void previsit( const StructDecl * decl );
 	Stmt * postvisit( const WaitUntilStmt * stmt );
-    GenerateWaitUntilCore( vector<FunctionDecl *> & satFns ): satFns(satFns) {}
+	GenerateWaitUntilCore( vector<FunctionDecl *> & satFns ): satFns(satFns) {}
 };
 
 // Finds select_node decl
 void GenerateWaitUntilCore::previsit( const StructDecl * decl ) {
-    if ( !decl->body ) {
+	if ( !decl->body ) {
 		return;
 	} else if ( "select_node" == decl->name ) {
@@ -201,9 +201,9 @@
 
 void GenerateWaitUntilCore::updateAmbiguousWhen( WaitUntilStmt::ClauseNode * currNode, bool andAbove, bool orAbove, bool andBelow, bool orBelow ) {
-    // all children when-ambiguous
-    if ( currNode->left->ambiguousWhen && currNode->right->ambiguousWhen )
-        // true iff an ancestor/descendant has a different operation
-        currNode->ambiguousWhen = (orAbove || orBelow) && (andBelow || andAbove);
-    // ambiguousWhen is initially false so theres no need to set it here
+	// all children when-ambiguous
+	if ( currNode->left->ambiguousWhen && currNode->right->ambiguousWhen )
+		// true iff an ancestor/descendant has a different operation
+		currNode->ambiguousWhen = (orAbove || orBelow) && (andBelow || andAbove);
+	// ambiguousWhen is initially false so theres no need to set it here
 }
 
@@ -215,36 +215,36 @@
 // - All of its descendent clauses are optional, i.e. they have a when_cond defined on the WhenClause
 void GenerateWaitUntilCore::paintWhenTree( WaitUntilStmt::ClauseNode * currNode, bool andAbove, bool orAbove, bool & andBelow, bool & orBelow ) {
-    bool aBelow = false; // updated by child nodes
-    bool oBelow = false; // updated by child nodes
-    switch (currNode->op) {
-        case WaitUntilStmt::ClauseNode::AND:
-            paintWhenTree( currNode->left, true, orAbove, aBelow, oBelow );
-            paintWhenTree( currNode->right, true, orAbove, aBelow, oBelow );
-
-            // update currNode's when flag based on conditions listed in fn signature comment above
-            updateAmbiguousWhen(currNode, true, orAbove, aBelow, oBelow );
-
-            // set return flags to tell parents which decendant ops have been seen
-            andBelow = true;
-            orBelow = oBelow;
-            return;
-        case WaitUntilStmt::ClauseNode::OR:
-            paintWhenTree( currNode->left, andAbove, true, aBelow, oBelow );
-            paintWhenTree( currNode->right, andAbove, true, aBelow, oBelow );
-
-            // update currNode's when flag based on conditions listed in fn signature comment above
-            updateAmbiguousWhen(currNode, andAbove, true, aBelow, oBelow );
-
-            // set return flags to tell parents which decendant ops have been seen
-            andBelow = aBelow;
-            orBelow = true;
-            return;
-        case WaitUntilStmt::ClauseNode::LEAF:
-            if ( currNode->leaf->when_cond )
-                currNode->ambiguousWhen = true;
-            return;
-        default:
-            assertf(false, "Unreachable waituntil clause node type. How did you get here???");
-    }
+	bool aBelow = false; // updated by child nodes
+	bool oBelow = false; // updated by child nodes
+	switch (currNode->op) {
+		case WaitUntilStmt::ClauseNode::AND:
+			paintWhenTree( currNode->left, true, orAbove, aBelow, oBelow );
+			paintWhenTree( currNode->right, true, orAbove, aBelow, oBelow );
+
+			// update currNode's when flag based on conditions listed in fn signature comment above
+			updateAmbiguousWhen(currNode, true, orAbove, aBelow, oBelow );
+
+			// set return flags to tell parents which decendant ops have been seen
+			andBelow = true;
+			orBelow = oBelow;
+			return;
+		case WaitUntilStmt::ClauseNode::OR:
+			paintWhenTree( currNode->left, andAbove, true, aBelow, oBelow );
+			paintWhenTree( currNode->right, andAbove, true, aBelow, oBelow );
+
+			// update currNode's when flag based on conditions listed in fn signature comment above
+			updateAmbiguousWhen(currNode, andAbove, true, aBelow, oBelow );
+
+			// set return flags to tell parents which decendant ops have been seen
+			andBelow = aBelow;
+			orBelow = true;
+			return;
+		case WaitUntilStmt::ClauseNode::LEAF:
+			if ( currNode->leaf->when_cond )
+				currNode->ambiguousWhen = true;
+			return;
+		default:
+			assertf(false, "Unreachable waituntil clause node type. How did you get here???");
+	}
 }
 
@@ -252,18 +252,18 @@
 // returns true if entire tree is OR's (special case)
 bool GenerateWaitUntilCore::paintWhenTree( WaitUntilStmt::ClauseNode * currNode ) {
-    bool aBelow = false, oBelow = false; // unused by initial call
-    paintWhenTree( currNode, false, false, aBelow, oBelow );
-    return !aBelow;
+	bool aBelow = false, oBelow = false; // unused by initial call
+	paintWhenTree( currNode, false, false, aBelow, oBelow );
+	return !aBelow;
 }
 
 // Helper: returns Expr that represents arrName[index]
 Expr * genArrAccessExpr( const CodeLocation & loc, int index, string arrName ) {
-    return new UntypedExpr ( loc, 
-        new NameExpr( loc, "?[?]" ),
-        {
-            new NameExpr( loc, arrName ),
-            ConstantExpr::from_int( loc, index )
-        }
-    );
+	return new UntypedExpr ( loc,
+		new NameExpr( loc, "?[?]" ),
+		{
+			new NameExpr( loc, arrName ),
+			ConstantExpr::from_int( loc, index )
+		}
+	);
 }
 
@@ -273,35 +273,35 @@
 // - updates LEAF nodes to be when-ambiguous if their direct parent is when-ambiguous.
 void GenerateWaitUntilCore::collectWhens( WaitUntilStmt::ClauseNode * currNode, vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigIdxs, vector<int> & andIdxs, int & index, bool parentAmbig, bool parentAnd ) {
-    switch (currNode->op) {
-        case WaitUntilStmt::ClauseNode::AND:
-            collectWhens( currNode->left, ambigIdxs, andIdxs, index, currNode->ambiguousWhen, true );
-            collectWhens( currNode->right,  ambigIdxs, andIdxs, index, currNode->ambiguousWhen, true );
-            return;
-        case WaitUntilStmt::ClauseNode::OR:
-            collectWhens( currNode->left,  ambigIdxs, andIdxs, index, currNode->ambiguousWhen, false );
-            collectWhens( currNode->right,  ambigIdxs, andIdxs, index, currNode->ambiguousWhen, false );
-            return;
-        case WaitUntilStmt::ClauseNode::LEAF:
-            if ( parentAmbig ) {
-                ambigIdxs.push_back(make_pair(index, currNode));
-            }
-            if ( parentAnd && currNode->leaf->when_cond ) {
-                currNode->childOfAnd = true;
-                andIdxs.push_back(index);
-            }
-            index++;
-            return;
-        default:
-            assertf(false, "Unreachable waituntil clause node type. How did you get here???");
-    }
+	switch (currNode->op) {
+		case WaitUntilStmt::ClauseNode::AND:
+			collectWhens( currNode->left, ambigIdxs, andIdxs, index, currNode->ambiguousWhen, true );
+			collectWhens( currNode->right,  ambigIdxs, andIdxs, index, currNode->ambiguousWhen, true );
+			return;
+		case WaitUntilStmt::ClauseNode::OR:
+			collectWhens( currNode->left,  ambigIdxs, andIdxs, index, currNode->ambiguousWhen, false );
+			collectWhens( currNode->right,  ambigIdxs, andIdxs, index, currNode->ambiguousWhen, false );
+			return;
+		case WaitUntilStmt::ClauseNode::LEAF:
+			if ( parentAmbig ) {
+				ambigIdxs.push_back(make_pair(index, currNode));
+			}
+			if ( parentAnd && currNode->leaf->when_cond ) {
+				currNode->childOfAnd = true;
+				andIdxs.push_back(index);
+			}
+			index++;
+			return;
+		default:
+			assertf(false, "Unreachable waituntil clause node type. How did you get here???");
+	}
 }
 
 // overloaded wrapper for collectWhens that sets initial values
 void GenerateWaitUntilCore::collectWhens( WaitUntilStmt::ClauseNode * currNode, vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigIdxs, vector<int> & andIdxs ) {
-    int idx = 0;
-    collectWhens( currNode, ambigIdxs, andIdxs, idx, false, false );
-}
-
-// recursively updates ClauseNode whenState on internal nodes so that next pass can see which 
+	int idx = 0;
+	collectWhens( currNode, ambigIdxs, andIdxs, idx, false, false );
+}
+
+// recursively updates ClauseNode whenState on internal nodes so that next pass can see which
 //    subtrees are "turned off"
 // sets whenState = false iff both children have whenState == false.
@@ -309,11 +309,11 @@
 // since the ambiguous clauses were filtered in paintWhenTree we don't need to worry about that here
 void GenerateWaitUntilCore::updateWhenState( WaitUntilStmt::ClauseNode * currNode ) {
-    if ( currNode->op == WaitUntilStmt::ClauseNode::LEAF ) return;
-    updateWhenState( currNode->left );
-    updateWhenState( currNode->right );
-    if ( !currNode->left->whenState && !currNode->right->whenState )
-        currNode->whenState = false;
-    else 
-        currNode->whenState = true;
+	if ( currNode->op == WaitUntilStmt::ClauseNode::LEAF ) return;
+	updateWhenState( currNode->left );
+	updateWhenState( currNode->right );
+	if ( !currNode->left->whenState && !currNode->right->whenState )
+		currNode->whenState = false;
+	else
+		currNode->whenState = true;
 }
 
@@ -321,152 +321,152 @@
 // assumes that this will only be called on subtrees that are entirely whenState == false
 void GenerateWaitUntilCore::genSubtreeAssign( const WaitUntilStmt * stmt, WaitUntilStmt::ClauseNode * currNode, bool status, int & idx, CompoundStmt * retStmt, vector<ClauseData *> & clauseData ) {
-    if ( ( currNode->op == WaitUntilStmt::ClauseNode::AND && status )
-        || ( currNode->op == WaitUntilStmt::ClauseNode::OR && !status ) ) {
-        // need to recurse on both subtrees if && subtree needs to be true or || subtree needs to be false
-        genSubtreeAssign( stmt, currNode->left, status, idx, retStmt, clauseData );
-        genSubtreeAssign( stmt, currNode->right, status, idx, retStmt, clauseData );
-    } else if ( ( currNode->op == WaitUntilStmt::ClauseNode::OR && status )
-        || ( currNode->op == WaitUntilStmt::ClauseNode::AND && !status ) ) {
-        // only one subtree needs to evaluate to status if && subtree needs to be true or || subtree needs to be false
-        CompoundStmt * leftStmt = new CompoundStmt( stmt->location );
-        CompoundStmt * rightStmt = new CompoundStmt( stmt->location );
-
-        // only one side needs to evaluate to status so we recurse on both subtrees
-        //    but only keep the statements from the subtree with minimal statements
-        genSubtreeAssign( stmt, currNode->left, status, idx, leftStmt, clauseData );
-        genSubtreeAssign( stmt, currNode->right, status, idx, rightStmt, clauseData );
-        
-        // append minimal statements to retStmt
-        if ( leftStmt->kids.size() < rightStmt->kids.size() ) {
-            retStmt->kids.splice( retStmt->kids.end(), leftStmt->kids );
-        } else {
-            retStmt->kids.splice( retStmt->kids.end(), rightStmt->kids );
-        }
-        
-        delete leftStmt;
-        delete rightStmt;
-    } else if ( currNode->op == WaitUntilStmt::ClauseNode::LEAF ) {
-        const CodeLocation & loc = stmt->location;
-        if ( status && !currNode->childOfAnd ) {
-            retStmt->push_back(
-                new ExprStmt( loc, 
-                    UntypedExpr::createAssign( loc,
-                        genArrAccessExpr( loc, idx, clauseData.at(idx)->statusName ),
-                        new NameExpr( loc, "__SELECT_RUN" )
-                    )
-                )
-            );
-        } else if ( !status && currNode->childOfAnd ) {
-            retStmt->push_back(
-                new ExprStmt( loc, 
-                    UntypedExpr::createAssign( loc,
-                        genArrAccessExpr( loc, idx, clauseData.at(idx)->statusName ),
-                        new NameExpr( loc, "__SELECT_UNSAT" )
-                    )
-                )
-            );
-        }
-
-        // No need to generate statements for the following cases since childOfAnd are always set to true
-        //    and !childOfAnd are always false
-        // - status && currNode->childOfAnd
-        // - !status && !currNode->childOfAnd
-        idx++;
-    }
+	if ( ( currNode->op == WaitUntilStmt::ClauseNode::AND && status )
+		|| ( currNode->op == WaitUntilStmt::ClauseNode::OR && !status ) ) {
+		// need to recurse on both subtrees if && subtree needs to be true or || subtree needs to be false
+		genSubtreeAssign( stmt, currNode->left, status, idx, retStmt, clauseData );
+		genSubtreeAssign( stmt, currNode->right, status, idx, retStmt, clauseData );
+	} else if ( ( currNode->op == WaitUntilStmt::ClauseNode::OR && status )
+		|| ( currNode->op == WaitUntilStmt::ClauseNode::AND && !status ) ) {
+		// only one subtree needs to evaluate to status if && subtree needs to be true or || subtree needs to be false
+		CompoundStmt * leftStmt = new CompoundStmt( stmt->location );
+		CompoundStmt * rightStmt = new CompoundStmt( stmt->location );
+
+		// only one side needs to evaluate to status so we recurse on both subtrees
+		//    but only keep the statements from the subtree with minimal statements
+		genSubtreeAssign( stmt, currNode->left, status, idx, leftStmt, clauseData );
+		genSubtreeAssign( stmt, currNode->right, status, idx, rightStmt, clauseData );
+
+		// append minimal statements to retStmt
+		if ( leftStmt->kids.size() < rightStmt->kids.size() ) {
+			retStmt->kids.splice( retStmt->kids.end(), leftStmt->kids );
+		} else {
+			retStmt->kids.splice( retStmt->kids.end(), rightStmt->kids );
+		}
+
+		delete leftStmt;
+		delete rightStmt;
+	} else if ( currNode->op == WaitUntilStmt::ClauseNode::LEAF ) {
+		const CodeLocation & loc = stmt->location;
+		if ( status && !currNode->childOfAnd ) {
+			retStmt->push_back(
+				new ExprStmt( loc,
+				    UntypedExpr::createAssign( loc,
+				        genArrAccessExpr( loc, idx, clauseData.at(idx)->statusName ),
+				        new NameExpr( loc, "__SELECT_RUN" )
+				    )
+				)
+			);
+		} else if ( !status && currNode->childOfAnd ) {
+			retStmt->push_back(
+				new ExprStmt( loc,
+				    UntypedExpr::createAssign( loc,
+				        genArrAccessExpr( loc, idx, clauseData.at(idx)->statusName ),
+				        new NameExpr( loc, "__SELECT_UNSAT" )
+				    )
+				)
+			);
+		}
+
+		// No need to generate statements for the following cases since childOfAnd are always set to true
+		//    and !childOfAnd are always false
+		// - status && currNode->childOfAnd
+		// - !status && !currNode->childOfAnd
+		idx++;
+	}
 }
 
 void GenerateWaitUntilCore::genStatusAssign( const WaitUntilStmt * stmt, WaitUntilStmt::ClauseNode * currNode, int & idx, CompoundStmt * retStmt, vector<ClauseData *> & clauseData ) {
-    switch (currNode->op) {
-        case WaitUntilStmt::ClauseNode::AND:
-            // check which subtrees have all whenState == false (disabled)
-            if (!currNode->left->whenState && !currNode->right->whenState) {
-                // this case can only occur when whole tree is disabled since otherwise 
-                //    genStatusAssign( ... ) isn't called on nodes with whenState == false
-                assert( !currNode->whenState ); // paranoidWWW
-                // whole tree disabled so pass true so that select is SAT vacuously
-                genSubtreeAssign( stmt, currNode, true, idx, retStmt, clauseData );
-            } else if ( !currNode->left->whenState ) {
-                // pass true since x && true === x
-                genSubtreeAssign( stmt, currNode->left, true, idx, retStmt, clauseData );
-                genStatusAssign( stmt, currNode->right, idx, retStmt, clauseData );
-            } else if ( !currNode->right->whenState ) {
-                genStatusAssign( stmt, currNode->left, idx, retStmt, clauseData );
-                genSubtreeAssign( stmt, currNode->right, true, idx, retStmt, clauseData );
-            } else { 
-                // if no children with whenState == false recurse normally via break
-                break;
-            }
-            return;
-        case WaitUntilStmt::ClauseNode::OR:
-            if (!currNode->left->whenState && !currNode->right->whenState) {
-                assert( !currNode->whenState ); // paranoid
-                genSubtreeAssign( stmt, currNode, true, idx, retStmt, clauseData );
-            } else if ( !currNode->left->whenState ) {
-                // pass false since x || false === x
-                genSubtreeAssign( stmt, currNode->left, false, idx, retStmt, clauseData );
-                genStatusAssign( stmt, currNode->right, idx, retStmt, clauseData );
-            } else if ( !currNode->right->whenState ) {
-                genStatusAssign( stmt, currNode->left, idx, retStmt, clauseData );
-                genSubtreeAssign( stmt, currNode->right, false, idx, retStmt, clauseData );
-            } else { 
-                break;
-            }
-            return;
-        case WaitUntilStmt::ClauseNode::LEAF:
-            idx++;
-            return;
-        default:
-            assertf(false, "Unreachable waituntil clause node type. How did you get here???");
-    }
-    genStatusAssign( stmt, currNode->left, idx, retStmt, clauseData );
-    genStatusAssign( stmt, currNode->right, idx, retStmt, clauseData );
+	switch (currNode->op) {
+		case WaitUntilStmt::ClauseNode::AND:
+			// check which subtrees have all whenState == false (disabled)
+			if (!currNode->left->whenState && !currNode->right->whenState) {
+				// this case can only occur when whole tree is disabled since otherwise
+				//    genStatusAssign( ... ) isn't called on nodes with whenState == false
+				assert( !currNode->whenState ); // paranoidWWW
+				// whole tree disabled so pass true so that select is SAT vacuously
+				genSubtreeAssign( stmt, currNode, true, idx, retStmt, clauseData );
+			} else if ( !currNode->left->whenState ) {
+				// pass true since x && true === x
+				genSubtreeAssign( stmt, currNode->left, true, idx, retStmt, clauseData );
+				genStatusAssign( stmt, currNode->right, idx, retStmt, clauseData );
+			} else if ( !currNode->right->whenState ) {
+				genStatusAssign( stmt, currNode->left, idx, retStmt, clauseData );
+				genSubtreeAssign( stmt, currNode->right, true, idx, retStmt, clauseData );
+			} else {
+				// if no children with whenState == false recurse normally via break
+				break;
+			}
+			return;
+		case WaitUntilStmt::ClauseNode::OR:
+			if (!currNode->left->whenState && !currNode->right->whenState) {
+				assert( !currNode->whenState ); // paranoid
+				genSubtreeAssign( stmt, currNode, true, idx, retStmt, clauseData );
+			} else if ( !currNode->left->whenState ) {
+				// pass false since x || false === x
+				genSubtreeAssign( stmt, currNode->left, false, idx, retStmt, clauseData );
+				genStatusAssign( stmt, currNode->right, idx, retStmt, clauseData );
+			} else if ( !currNode->right->whenState ) {
+				genStatusAssign( stmt, currNode->left, idx, retStmt, clauseData );
+				genSubtreeAssign( stmt, currNode->right, false, idx, retStmt, clauseData );
+			} else {
+				break;
+			}
+			return;
+		case WaitUntilStmt::ClauseNode::LEAF:
+			idx++;
+			return;
+		default:
+			assertf(false, "Unreachable waituntil clause node type. How did you get here???");
+	}
+	genStatusAssign( stmt, currNode->left, idx, retStmt, clauseData );
+	genStatusAssign( stmt, currNode->right, idx, retStmt, clauseData );
 }
 
 // generates a minimal set of assignments for status arr based on which whens are toggled on/off
 CompoundStmt * GenerateWaitUntilCore::getStatusAssignment( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData ) {
-    updateWhenState( stmt->predicateTree );
-    CompoundStmt * retval = new CompoundStmt( stmt->location );
-    int idx = 0;
-    genStatusAssign( stmt, stmt->predicateTree, idx, retval, clauseData );
-    return retval;
+	updateWhenState( stmt->predicateTree );
+	CompoundStmt * retval = new CompoundStmt( stmt->location );
+	int idx = 0;
+	genStatusAssign( stmt, stmt->predicateTree, idx, retval, clauseData );
+	return retval;
 }
 
 // generates nested if/elses for all possible assignments of ambiguous when_conds
 // exponential size of code gen but linear runtime O(n), where n is number of ambiguous whens()
-Stmt * GenerateWaitUntilCore::genWhenStateConditions( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, 
-    vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigClauses, vector<pair<int, WaitUntilStmt::ClauseNode *>>::size_type ambigIdx ) {
-    // I hate C++ sometimes, using vector<pair<int, WaitUntilStmt::ClauseNode *>>::size_type for size() comparison seems silly.
-    //    Why is size_type parameterized on the type stored in the vector?????
-
-    const CodeLocation & loc = stmt->location;
-    int clauseIdx = ambigClauses.at(ambigIdx).first;
-    WaitUntilStmt::ClauseNode * currNode = ambigClauses.at(ambigIdx).second;
-    Stmt * thenStmt;
-    Stmt * elseStmt;
-    
-    if ( ambigIdx == ambigClauses.size() - 1 ) { // base case
-        currNode->whenState = true;
-        thenStmt = getStatusAssignment( stmt, clauseData );
-        currNode->whenState = false;
-        elseStmt = getStatusAssignment( stmt, clauseData );
-    } else {
-        // recurse both with when enabled and disabled to generate all possible cases
-        currNode->whenState = true;
-        thenStmt = genWhenStateConditions( stmt, clauseData, ambigClauses, ambigIdx + 1 );
-        currNode->whenState = false;
-        elseStmt = genWhenStateConditions( stmt, clauseData, ambigClauses, ambigIdx + 1 );
-    }
-
-    // insert first recursion result in if ( __when_cond_ ) { ... }
-    // insert second recursion result in else { ... }
-    return new CompoundStmt ( loc,
-        {
-            new IfStmt( loc,
-                new NameExpr( loc, clauseData.at(clauseIdx)->whenName ),
-                thenStmt,
-                elseStmt
-            )
-        }
-    );
+Stmt * GenerateWaitUntilCore::genWhenStateConditions( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData,
+	vector<pair<int, WaitUntilStmt::ClauseNode *>> & ambigClauses, vector<pair<int, WaitUntilStmt::ClauseNode *>>::size_type ambigIdx ) {
+	// I hate C++ sometimes, using vector<pair<int, WaitUntilStmt::ClauseNode *>>::size_type for size() comparison seems silly.
+	//    Why is size_type parameterized on the type stored in the vector?????
+
+	const CodeLocation & loc = stmt->location;
+	int clauseIdx = ambigClauses.at(ambigIdx).first;
+	WaitUntilStmt::ClauseNode * currNode = ambigClauses.at(ambigIdx).second;
+	Stmt * thenStmt;
+	Stmt * elseStmt;
+
+	if ( ambigIdx == ambigClauses.size() - 1 ) { // base case
+		currNode->whenState = true;
+		thenStmt = getStatusAssignment( stmt, clauseData );
+		currNode->whenState = false;
+		elseStmt = getStatusAssignment( stmt, clauseData );
+	} else {
+		// recurse both with when enabled and disabled to generate all possible cases
+		currNode->whenState = true;
+		thenStmt = genWhenStateConditions( stmt, clauseData, ambigClauses, ambigIdx + 1 );
+		currNode->whenState = false;
+		elseStmt = genWhenStateConditions( stmt, clauseData, ambigClauses, ambigIdx + 1 );
+	}
+
+	// insert first recursion result in if ( __when_cond_ ) { ... }
+	// insert second recursion result in else { ... }
+	return new CompoundStmt ( loc,
+		{
+			new IfStmt( loc,
+				new NameExpr( loc, clauseData.at(clauseIdx)->whenName ),
+				thenStmt,
+				elseStmt
+			)
+		}
+	);
 }
 
@@ -478,13 +478,13 @@
 // mutates index to be index + 1
 Expr * genSatExpr( const CodeLocation & loc, int & index ) {
-    return genArrAccessExpr( loc, index++, "clause_statuses" );
+	return genArrAccessExpr( loc, index++, "clause_statuses" );
 }
 
 // return Expr that represents has_run(clause_statuses[index])
 Expr * genRunExpr( const CodeLocation & loc, int & index ) {
-    return new UntypedExpr ( loc, 
-        new NameExpr( loc, "__CFA_has_clause_run" ),
-        { genSatExpr( loc, index ) }
-    );
+	return new UntypedExpr ( loc,
+		new NameExpr( loc, "__CFA_has_clause_run" ),
+		{ genSatExpr( loc, index ) }
+	);
 }
 
@@ -492,32 +492,32 @@
 // the predicate expr used inside the predicate functions
 Expr * genPredExpr( const CodeLocation & loc, WaitUntilStmt::ClauseNode * currNode, int & idx, GenLeafExpr genLeaf ) {
-    Expr * leftExpr, * rightExpr;
-    switch (currNode->op) {
-        case WaitUntilStmt::ClauseNode::AND:
-            leftExpr = genPredExpr( loc, currNode->left, idx, genLeaf );
-            rightExpr = genPredExpr( loc, currNode->right, idx, genLeaf );
-            return new LogicalExpr( loc, 
-                new CastExpr( loc, leftExpr, new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast ),
-                new CastExpr( loc, rightExpr, new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast ), 
-                LogicalFlag::AndExpr 
-            );
-            break;
-        case WaitUntilStmt::ClauseNode::OR:
-            leftExpr = genPredExpr( loc, currNode->left, idx, genLeaf );
-            rightExpr = genPredExpr( loc, currNode->right, idx, genLeaf );
-            return new LogicalExpr( loc,
-                new CastExpr( loc, leftExpr, new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast ),
-                new CastExpr( loc, rightExpr, new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast ), 
-                LogicalFlag::OrExpr );
-            break;
-        case WaitUntilStmt::ClauseNode::LEAF:
-            return genLeaf( loc, idx );
-            break;
-        default:
-            assertf(false, "Unreachable waituntil clause node type. How did you get here???");\
-            return nullptr;
-            break;
-    }
-    return nullptr;
+	Expr * leftExpr, * rightExpr;
+	switch (currNode->op) {
+		case WaitUntilStmt::ClauseNode::AND:
+			leftExpr = genPredExpr( loc, currNode->left, idx, genLeaf );
+			rightExpr = genPredExpr( loc, currNode->right, idx, genLeaf );
+			return new LogicalExpr( loc,
+				new CastExpr( loc, leftExpr, new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast ),
+				new CastExpr( loc, rightExpr, new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast ),
+				LogicalFlag::AndExpr
+			);
+			break;
+		case WaitUntilStmt::ClauseNode::OR:
+			leftExpr = genPredExpr( loc, currNode->left, idx, genLeaf );
+			rightExpr = genPredExpr( loc, currNode->right, idx, genLeaf );
+			return new LogicalExpr( loc,
+				new CastExpr( loc, leftExpr, new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast ),
+				new CastExpr( loc, rightExpr, new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast ),
+				LogicalFlag::OrExpr );
+			break;
+		case WaitUntilStmt::ClauseNode::LEAF:
+			return genLeaf( loc, idx );
+			break;
+		default:
+			assertf(false, "Unreachable waituntil clause node type. How did you get here???");\
+			return nullptr;
+			break;
+	}
+	return nullptr;
 }
 
@@ -526,19 +526,19 @@
 /* Ex:
 {
-    waituntil( A ){ doA(); } 
-    or waituntil( B ){ doB(); } 
-    and waituntil( C ) { doC(); }
+	waituntil( A ){ doA(); }
+	or waituntil( B ){ doB(); }
+	and waituntil( C ) { doC(); }
 }
 generates =>
 static inline bool is_full_sat_1( int * clause_statuses ) {
-    return clause_statuses[0] 
-        || clause_statuses[1]
-        && clause_statuses[2];
+	return clause_statuses[0]
+		|| clause_statuses[1]
+		&& clause_statuses[2];
 }
 
 static inline bool is_done_sat_1( int * clause_statuses ) {
-    return has_run(clause_statuses[0])
-        || has_run(clause_statuses[1])
-        && has_run(clause_statuses[2]);
+	return has_run(clause_statuses[0])
+		|| has_run(clause_statuses[1])
+		&& has_run(clause_statuses[2]);
 }
 */
@@ -546,36 +546,36 @@
 // predName and genLeaf determine if this generates an is_done or an is_full predicate
 FunctionDecl * buildPredicate( const WaitUntilStmt * stmt, GenLeafExpr genLeaf, string & predName ) {
-    int arrIdx = 0;
-    const CodeLocation & loc = stmt->location;
-    CompoundStmt * body = new CompoundStmt( loc );
-    body->push_back( new ReturnStmt( loc, genPredExpr( loc,  stmt->predicateTree, arrIdx, genLeaf ) ) );
-
-    return new FunctionDecl( loc,
-        predName,
-        {
-            new ObjectDecl( loc,
-                "clause_statuses",
-                new PointerType( new BasicType( BasicKind::LongUnsignedInt ) )
-            )
-        },
-        {
-            new ObjectDecl( loc,
-                "sat_ret",
-                new BasicType( BasicKind::Bool )
-            )
-        },
-        body,               // body
-        { Storage::Static },    // storage
-        Linkage::Cforall,       // linkage
-        {},                     // attributes
-        { Function::Inline }
-    );
+	int arrIdx = 0;
+	const CodeLocation & loc = stmt->location;
+	CompoundStmt * body = new CompoundStmt( loc );
+	body->push_back( new ReturnStmt( loc, genPredExpr( loc,  stmt->predicateTree, arrIdx, genLeaf ) ) );
+
+	return new FunctionDecl( loc,
+		predName,
+		{
+			new ObjectDecl( loc,
+				"clause_statuses",
+				new PointerType( new BasicType( BasicKind::LongUnsignedInt ) )
+			)
+		},
+		{
+			new ObjectDecl( loc,
+				"sat_ret",
+				new BasicType( BasicKind::Bool )
+			)
+		},
+		body,               // body
+		{ Storage::Static },    // storage
+		Linkage::Cforall,       // linkage
+		{},                     // attributes
+		{ Function::Inline }
+	);
 }
 
 // Creates is_done and is_full predicates
 void GenerateWaitUntilCore::addPredicates( const WaitUntilStmt * stmt, string & satName, string & runName ) {
-    if ( !stmt->else_stmt || stmt->else_cond ) // don't need SAT predicate when else variation with no else_cond
-        satFns.push_back( Concurrency::buildPredicate( stmt, genSatExpr, satName ) ); 
-    satFns.push_back( Concurrency::buildPredicate( stmt, genRunExpr, runName ) );
+	if ( !stmt->else_stmt || stmt->else_cond ) // don't need SAT predicate when else variation with no else_cond
+		satFns.push_back( Concurrency::buildPredicate( stmt, genSatExpr, satName ) );
+	satFns.push_back( Concurrency::buildPredicate( stmt, genRunExpr, runName ) );
 }
 
@@ -585,232 +585,232 @@
 //      register_select(A, clause1);
 // }
-void GenerateWaitUntilCore::setUpClause( const WhenClause * clause, ClauseData * data, string & pCountName, CompoundStmt * body ) {    
-    CompoundStmt * currBody = body;
-    const CodeLocation & loc = clause->location;
-
-    // If we have a when_cond make the initialization conditional
-    if ( clause->when_cond )
-        currBody = new CompoundStmt( loc );
-
-    // Generates: setup_clause( clause1, &clause_statuses[0], &park_counter );
-    currBody->push_back( new ExprStmt( loc,
-        new UntypedExpr ( loc,
-            new NameExpr( loc, "setup_clause" ),
-            {
-                new NameExpr( loc, data->nodeName ),
-                new AddressExpr( loc, genArrAccessExpr( loc, data->index, data->statusName ) ),
-                new AddressExpr( loc, new NameExpr( loc, pCountName ) )
-            }
-        )
-    ));
-
-    // Generates: register_select(A, clause1);
-    currBody->push_back( new ExprStmt( loc, genSelectTraitCall( clause, data, "register_select" ) ) );
-
-    // generates: if ( when_cond ) { ... currBody ... }
-    if ( clause->when_cond )
-        body->push_back( 
-            new IfStmt( loc,
-                new NameExpr( loc, data->whenName ),
-                currBody
-            )
-        );
+void GenerateWaitUntilCore::setUpClause( const WhenClause * clause, ClauseData * data, string & pCountName, CompoundStmt * body ) {
+	CompoundStmt * currBody = body;
+	const CodeLocation & loc = clause->location;
+
+	// If we have a when_cond make the initialization conditional
+	if ( clause->when_cond )
+		currBody = new CompoundStmt( loc );
+
+	// Generates: setup_clause( clause1, &clause_statuses[0], &park_counter );
+	currBody->push_back( new ExprStmt( loc,
+		new UntypedExpr ( loc,
+			new NameExpr( loc, "setup_clause" ),
+			{
+				new NameExpr( loc, data->nodeName ),
+				new AddressExpr( loc, genArrAccessExpr( loc, data->index, data->statusName ) ),
+				new AddressExpr( loc, new NameExpr( loc, pCountName ) )
+			}
+		)
+	));
+
+	// Generates: register_select(A, clause1);
+	currBody->push_back( new ExprStmt( loc, genSelectTraitCall( clause, data, "register_select" ) ) );
+
+	// generates: if ( when_cond ) { ... currBody ... }
+	if ( clause->when_cond )
+		body->push_back(
+			new IfStmt( loc,
+				new NameExpr( loc, data->whenName ),
+				currBody
+			)
+		);
 }
 
 // Used to generate a call to one of the select trait routines
 Expr * GenerateWaitUntilCore::genSelectTraitCall( const WhenClause * clause, const ClauseData * data, string fnName ) {
-    const CodeLocation & loc = clause->location;
-    return new UntypedExpr ( loc,
-        new NameExpr( loc, fnName ),
-        {
-            new NameExpr( loc, data->targetName ),
-            new NameExpr( loc, data->nodeName )
-        }
-    );
+	const CodeLocation & loc = clause->location;
+	return new UntypedExpr ( loc,
+		new NameExpr( loc, fnName ),
+		{
+			new NameExpr( loc, data->targetName ),
+			new NameExpr( loc, data->nodeName )
+		}
+	);
 }
 
 // Generates:
-/* on_selected( target_1, node_1 ); ... corresponding body of target_1 ... 
+/* on_selected( target_1, node_1 ); ... corresponding body of target_1 ...
 */
 CompoundStmt * GenerateWaitUntilCore::genStmtBlock( const WhenClause * clause, const ClauseData * data ) {
-    const CodeLocation & cLoc = clause->location;
-    return new CompoundStmt( cLoc,
-        {
-            new IfStmt( cLoc,
-                genSelectTraitCall( clause, data, "on_selected" ),
-                ast::deepCopy( clause->stmt )
-            )
-        }
-    );
+	const CodeLocation & cLoc = clause->location;
+	return new CompoundStmt( cLoc,
+		{
+			new IfStmt( cLoc,
+				genSelectTraitCall( clause, data, "on_selected" ),
+				ast::deepCopy( clause->stmt )
+			)
+		}
+	);
 }
 
 // this routine generates and returns the following
 /*for ( int i = 0; i < numClauses; i++ ) {
-    if ( predName(clause_statuses) ) break;
-    if (clause_statuses[i] == __SELECT_SAT) {
-        switch (i) {
-            case 0:
-                try {
-                    on_selected( target1, clause1 );
-                    dotarget1stmt();
-                }
-                finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); }
-                break;
-            ...
-            case N:
-                ...
-                break;
-        }
-    }
+	if ( predName(clause_statuses) ) break;
+	if (clause_statuses[i] == __SELECT_SAT) {
+		switch (i) {
+			case 0:
+				try {
+				    on_selected( target1, clause1 );
+				    dotarget1stmt();
+				}
+				finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); }
+				break;
+			...
+			case N:
+				...
+				break;
+		}
+	}
 }*/
 CompoundStmt * GenerateWaitUntilCore::genStatusCheckFor( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, string & predName ) {
-    CompoundStmt * ifBody = new CompoundStmt( stmt->location );
-    const CodeLocation & loc = stmt->location;
-
-    string switchLabel = namer_label.newName();
-
-    /* generates:
-    switch (i) {
-        case 0:
-            try {
-                on_selected( target1, clause1 );
-                dotarget1stmt();
-            }
-            finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); }
-            break;
-            ...
-        case N:
-            ...
-            break;
-    }*/
-    std::vector<ptr<CaseClause>> switchCases;
-    int idx = 0;
-    for ( const auto & clause: stmt->clauses ) {
-        const CodeLocation & cLoc = clause->location;
-        switchCases.push_back(
-            new CaseClause( cLoc,
-                ConstantExpr::from_int( cLoc, idx ),
-                {
-                    new CompoundStmt( cLoc,
-                        {
-                            new ast::TryStmt( cLoc,
-                                genStmtBlock( clause, clauseData.at(idx) ),
-                                {},
-                                new ast::FinallyClause( cLoc, 
-                                    new CompoundStmt( cLoc,
-                                        {
-                                            new ExprStmt( loc,
-                                                new UntypedExpr ( loc,
-                                                    new NameExpr( loc, "?=?" ),
-                                                    {
-                                                        new UntypedExpr ( loc, 
-                                                            new NameExpr( loc, "?[?]" ),
-                                                            {
-                                                                new NameExpr( loc, clauseData.at(0)->statusName ),
-                                                                new NameExpr( loc, idxName )
-                                                            }
-                                                        ),
-                                                        new NameExpr( loc, "__SELECT_RUN" )
-                                                    }
-                                                )
-                                            ),
-                                            new ExprStmt( loc, genSelectTraitCall( clause, clauseData.at(idx), "unregister_select" ) )
-                                        }
-                                    )
-                                )
-                            ),
-                            new BranchStmt( cLoc, BranchStmt::Kind::Break, Label( cLoc, switchLabel ) )
-                        }
-                    )
-                }
-            )
-        );
-        idx++;
-    }
-
-    ifBody->push_back(
-        new SwitchStmt( loc,
-            new NameExpr( loc, idxName ),
-            std::move( switchCases ),
-            { Label( loc, switchLabel ) }
-        )
-    );
-
-    // gens:
-    // if (clause_statuses[i] == __SELECT_SAT) {
-    //      ... ifBody  ...
-    // }
-    IfStmt * ifSwitch = new IfStmt( loc,
-        new UntypedExpr ( loc,
-            new NameExpr( loc, "?==?" ),
-            {
-                new UntypedExpr ( loc, 
-                    new NameExpr( loc, "?[?]" ),
-                    {
-                        new NameExpr( loc, clauseData.at(0)->statusName ),
-                        new NameExpr( loc, idxName )
-                    }
-                ),
-                new NameExpr( loc, "__SELECT_SAT" )
-            }
-        ),      // condition
-        ifBody  // body
-    );
-
-    string forLabel = namer_label.newName();
-
-    // we hoist init here so that this pass can happen after hoistdecls pass
-    return new CompoundStmt( loc,
-        {
-            new DeclStmt( loc,
-                new ObjectDecl( loc,
-                    idxName,
-                    new BasicType( BasicKind::SignedInt ),
-                    new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
-                )
-            ),
-            new ForStmt( loc,
-                {},  // inits
-                new UntypedExpr ( loc,
-                    new NameExpr( loc, "?<?" ),
-                    {
-                        new NameExpr( loc, idxName ),
-                        ConstantExpr::from_int( loc, stmt->clauses.size() )
-                    }
-                ),  // cond
-                new UntypedExpr ( loc,
-                    new NameExpr( loc, "?++" ),
-                    { new NameExpr( loc, idxName ) }
-                ),  // inc
-                new CompoundStmt( loc,
-                    {
-                        new IfStmt( loc,
-                            new UntypedExpr ( loc,
-                                new NameExpr( loc, predName ),
-                                { new NameExpr( loc, clauseData.at(0)->statusName ) }
-                            ),
-                            new BranchStmt( loc, BranchStmt::Kind::Break, Label( loc, forLabel ) )
-                        ),
-                        ifSwitch
-                    }
-                ),   // body
-                { Label( loc, forLabel ) }
-            )
-        }
-    );
+	CompoundStmt * ifBody = new CompoundStmt( stmt->location );
+	const CodeLocation & loc = stmt->location;
+
+	string switchLabel = namer_label.newName();
+
+	/* generates:
+	switch (i) {
+		case 0:
+			try {
+				on_selected( target1, clause1 );
+				dotarget1stmt();
+			}
+			finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); }
+			break;
+			...
+		case N:
+			...
+			break;
+	}*/
+	std::vector<ptr<CaseClause>> switchCases;
+	int idx = 0;
+	for ( const auto & clause: stmt->clauses ) {
+		const CodeLocation & cLoc = clause->location;
+		switchCases.push_back(
+			new CaseClause( cLoc,
+				ConstantExpr::from_int( cLoc, idx ),
+				{
+				    new CompoundStmt( cLoc,
+				        {
+				            new ast::TryStmt( cLoc,
+				                genStmtBlock( clause, clauseData.at(idx) ),
+				                {},
+				                new ast::FinallyClause( cLoc,
+				                    new CompoundStmt( cLoc,
+				                        {
+				                            new ExprStmt( loc,
+				                                new UntypedExpr ( loc,
+				                                    new NameExpr( loc, "?=?" ),
+				                                    {
+				                                        new UntypedExpr ( loc,
+				                                            new NameExpr( loc, "?[?]" ),
+				                                            {
+				                                                new NameExpr( loc, clauseData.at(0)->statusName ),
+				                                                new NameExpr( loc, idxName )
+				                                            }
+				                                        ),
+				                                        new NameExpr( loc, "__SELECT_RUN" )
+				                                    }
+				                                )
+				                            ),
+				                            new ExprStmt( loc, genSelectTraitCall( clause, clauseData.at(idx), "unregister_select" ) )
+				                        }
+				                    )
+				                )
+				            ),
+				            new BranchStmt( cLoc, BranchStmt::Kind::Break, Label( cLoc, switchLabel ) )
+				        }
+				    )
+				}
+			)
+		);
+		idx++;
+	}
+
+	ifBody->push_back(
+		new SwitchStmt( loc,
+			new NameExpr( loc, idxName ),
+			std::move( switchCases ),
+			{ Label( loc, switchLabel ) }
+		)
+	);
+
+	// gens:
+	// if (clause_statuses[i] == __SELECT_SAT) {
+	//      ... ifBody  ...
+	// }
+	IfStmt * ifSwitch = new IfStmt( loc,
+		new UntypedExpr ( loc,
+			new NameExpr( loc, "?==?" ),
+			{
+				new UntypedExpr ( loc,
+				    new NameExpr( loc, "?[?]" ),
+				    {
+				        new NameExpr( loc, clauseData.at(0)->statusName ),
+				        new NameExpr( loc, idxName )
+				    }
+				),
+				new NameExpr( loc, "__SELECT_SAT" )
+			}
+		),      // condition
+		ifBody  // body
+	);
+
+	string forLabel = namer_label.newName();
+
+	// we hoist init here so that this pass can happen after hoistdecls pass
+	return new CompoundStmt( loc,
+		{
+			new DeclStmt( loc,
+				new ObjectDecl( loc,
+				    idxName,
+				    new BasicType( BasicKind::SignedInt ),
+				    new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
+				)
+			),
+			new ForStmt( loc,
+				{},  // inits
+				new UntypedExpr ( loc,
+				    new NameExpr( loc, "?<?" ),
+				    {
+				        new NameExpr( loc, idxName ),
+				        ConstantExpr::from_int( loc, stmt->clauses.size() )
+				    }
+				),  // cond
+				new UntypedExpr ( loc,
+				    new NameExpr( loc, "?++" ),
+				    { new NameExpr( loc, idxName ) }
+				),  // inc
+				new CompoundStmt( loc,
+				    {
+				        new IfStmt( loc,
+				            new UntypedExpr ( loc,
+				                new NameExpr( loc, predName ),
+				                { new NameExpr( loc, clauseData.at(0)->statusName ) }
+				            ),
+				            new BranchStmt( loc, BranchStmt::Kind::Break, Label( loc, forLabel ) )
+				        ),
+				        ifSwitch
+				    }
+				),   // body
+				{ Label( loc, forLabel ) }
+			)
+		}
+	);
 }
 
 // Generates: !is_full_sat_n() / !is_run_sat_n()
 Expr * genNotSatExpr( const WaitUntilStmt * stmt, string & satName, string & arrName ) {
-    const CodeLocation & loc = stmt->location;
-    return new UntypedExpr ( loc,
-        new NameExpr( loc, "!?" ),
-        {
-            new UntypedExpr ( loc,
-                new NameExpr( loc, satName ),
-                { new NameExpr( loc, arrName ) }
-            )
-        }
-    );
+	const CodeLocation & loc = stmt->location;
+	return new UntypedExpr ( loc,
+		new NameExpr( loc, "!?" ),
+		{
+			new UntypedExpr ( loc,
+				new NameExpr( loc, satName ),
+				{ new NameExpr( loc, arrName ) }
+			)
+		}
+	);
 }
 
@@ -819,40 +819,40 @@
 // If not enough have run to satisfy predicate after one pass then the else is run
 Stmt * GenerateWaitUntilCore::genElseClauseBranch( const WaitUntilStmt * stmt, string & runName, string & arrName, vector<ClauseData *> & clauseData ) {
-    return new CompoundStmt( stmt->else_stmt->location,
-        {
-            genStatusCheckFor( stmt, clauseData, runName ),
-            new IfStmt( stmt->else_stmt->location,
-                genNotSatExpr( stmt, runName, arrName ),
-                ast::deepCopy( stmt->else_stmt )
-            )
-        }
-    );
+	return new CompoundStmt( stmt->else_stmt->location,
+		{
+			genStatusCheckFor( stmt, clauseData, runName ),
+			new IfStmt( stmt->else_stmt->location,
+				genNotSatExpr( stmt, runName, arrName ),
+				ast::deepCopy( stmt->else_stmt )
+			)
+		}
+	);
 }
 
 Stmt * GenerateWaitUntilCore::genNoElseClauseBranch( const WaitUntilStmt * stmt, string & runName, string & arrName, string & pCountName, vector<ClauseData *> & clauseData ) {
-    CompoundStmt * whileBody = new CompoundStmt( stmt->location );
-    const CodeLocation & loc = stmt->location;
-
-    // generates: __CFA_maybe_park( &park_counter );
-    whileBody->push_back(
-        new ExprStmt( loc,
-            new UntypedExpr ( loc,
-                new NameExpr( loc, "__CFA_maybe_park" ),
-                { new AddressExpr( loc, new NameExpr( loc, pCountName ) ) }
-            )
-        )
-    );
-
-    whileBody->push_back( genStatusCheckFor( stmt, clauseData, runName ) );
-
-    return new CompoundStmt( loc,
-        {
-            new WhileDoStmt( loc,
-                genNotSatExpr( stmt, runName, arrName ),
-                whileBody,  // body
-                {}          // no inits
-            )
-        }
-    );
+	CompoundStmt * whileBody = new CompoundStmt( stmt->location );
+	const CodeLocation & loc = stmt->location;
+
+	// generates: __CFA_maybe_park( &park_counter );
+	whileBody->push_back(
+		new ExprStmt( loc,
+			new UntypedExpr ( loc,
+				new NameExpr( loc, "__CFA_maybe_park" ),
+				{ new AddressExpr( loc, new NameExpr( loc, pCountName ) ) }
+			)
+		)
+	);
+
+	whileBody->push_back( genStatusCheckFor( stmt, clauseData, runName ) );
+
+	return new CompoundStmt( loc,
+		{
+			new WhileDoStmt( loc,
+				genNotSatExpr( stmt, runName, arrName ),
+				whileBody,  // body
+				{}          // no inits
+			)
+		}
+	);
 }
 
@@ -862,63 +862,63 @@
 // select_node clause1;
 void GenerateWaitUntilCore::genClauseInits( const WaitUntilStmt * stmt, vector<ClauseData *> & clauseData, CompoundStmt * body, string & statusName, string & elseWhenName ) {
-    ClauseData * currClause;
-    for ( vector<ClauseData*>::size_type i = 0; i < stmt->clauses.size(); i++ ) {
-        currClause = new ClauseData( i, statusName );
-        currClause->nodeName = namer_node.newName();
-        currClause->targetName = namer_target.newName();
-        currClause->whenName = namer_when.newName();
-        clauseData.push_back(currClause);
-        const CodeLocation & cLoc = stmt->clauses.at(i)->location;
-
-        // typeof(target) & __clause_target_0 = target;
-        body->push_back(
-            new DeclStmt( cLoc,
-                new ObjectDecl( cLoc,
-                    currClause->targetName,
-                    new ReferenceType( 
-                        new TypeofType( new UntypedExpr( cLoc,
-                            new NameExpr( cLoc, "__CFA_select_get_type" ),
-                            { ast::deepCopy( stmt->clauses.at(i)->target ) }
-                        ))
-                    ),
-                    new SingleInit( cLoc, ast::deepCopy( stmt->clauses.at(i)->target ) )
-                )
-            )
-        );
-
-        // bool __when_cond_0 = when_cond; // only generated if when_cond defined
-        if ( stmt->clauses.at(i)->when_cond )
-            body->push_back(
-                new DeclStmt( cLoc,
-                    new ObjectDecl( cLoc,
-                        currClause->whenName,
-                        new BasicType( BasicKind::Bool ),
-                        new SingleInit( cLoc, ast::deepCopy( stmt->clauses.at(i)->when_cond ) )
-                    )
-                )
-            );
-        
-        // select_node clause1;
-        body->push_back(
-            new DeclStmt( cLoc,
-                new ObjectDecl( cLoc,
-                    currClause->nodeName,
-                    new StructInstType( selectNodeDecl )
-                )
-            )
-        );
-    }
-
-    if ( stmt->else_stmt && stmt->else_cond ) {
-        body->push_back(
-            new DeclStmt( stmt->else_cond->location,
-                new ObjectDecl( stmt->else_cond->location,
-                    elseWhenName,
-                    new BasicType( BasicKind::Bool ),
-                    new SingleInit( stmt->else_cond->location, ast::deepCopy( stmt->else_cond ) )
-                )
-            )
-        );
-    }
+	ClauseData * currClause;
+	for ( vector<ClauseData*>::size_type i = 0; i < stmt->clauses.size(); i++ ) {
+		currClause = new ClauseData( i, statusName );
+		currClause->nodeName = namer_node.newName();
+		currClause->targetName = namer_target.newName();
+		currClause->whenName = namer_when.newName();
+		clauseData.push_back(currClause);
+		const CodeLocation & cLoc = stmt->clauses.at(i)->location;
+
+		// typeof(target) & __clause_target_0 = target;
+		body->push_back(
+			new DeclStmt( cLoc,
+				new ObjectDecl( cLoc,
+				    currClause->targetName,
+				    new ReferenceType(
+				        new TypeofType( new UntypedExpr( cLoc,
+				            new NameExpr( cLoc, "__CFA_select_get_type" ),
+				            { ast::deepCopy( stmt->clauses.at(i)->target ) }
+				        ))
+				    ),
+				    new SingleInit( cLoc, ast::deepCopy( stmt->clauses.at(i)->target ) )
+				)
+			)
+		);
+
+		// bool __when_cond_0 = when_cond; // only generated if when_cond defined
+		if ( stmt->clauses.at(i)->when_cond )
+			body->push_back(
+				new DeclStmt( cLoc,
+				    new ObjectDecl( cLoc,
+				        currClause->whenName,
+				        new BasicType( BasicKind::Bool ),
+				        new SingleInit( cLoc, ast::deepCopy( stmt->clauses.at(i)->when_cond ) )
+				    )
+				)
+			);
+
+		// select_node clause1;
+		body->push_back(
+			new DeclStmt( cLoc,
+				new ObjectDecl( cLoc,
+				    currClause->nodeName,
+				    new StructInstType( selectNodeDecl )
+				)
+			)
+		);
+	}
+
+	if ( stmt->else_stmt && stmt->else_cond ) {
+		body->push_back(
+			new DeclStmt( stmt->else_cond->location,
+				new ObjectDecl( stmt->else_cond->location,
+				    elseWhenName,
+				    new BasicType( BasicKind::Bool ),
+				    new SingleInit( stmt->else_cond->location, ast::deepCopy( stmt->else_cond ) )
+				)
+			)
+		);
+	}
 }
 
@@ -929,27 +929,27 @@
 */
 Stmt * GenerateWaitUntilCore::buildOrCaseSwitch( const WaitUntilStmt * stmt, string & statusName, vector<ClauseData *> & data ) {
-    const CodeLocation & loc = stmt->location;
-
-    IfStmt * outerIf = nullptr;
+	const CodeLocation & loc = stmt->location;
+
+	IfStmt * outerIf = nullptr;
 	IfStmt * lastIf = nullptr;
 
 	//adds an if/elif clause for each select clause address to run the corresponding clause stmt
 	for ( long unsigned int i = 0; i < data.size(); i++ ) {
-        const CodeLocation & cLoc = stmt->clauses.at(i)->location;
+		const CodeLocation & cLoc = stmt->clauses.at(i)->location;
 
 		IfStmt * currIf = new IfStmt( cLoc,
-			new UntypedExpr( cLoc, 
-                new NameExpr( cLoc, "?==?" ), 
-                {
-                    new NameExpr( cLoc, statusName ),
-                    new CastExpr( cLoc, 
-                        new AddressExpr( cLoc, new NameExpr( cLoc, data.at(i)->nodeName ) ),
-                        new BasicType( BasicKind::LongUnsignedInt ), GeneratedFlag::ExplicitCast 
-                    )
-                }
-            ),
-            genStmtBlock( stmt->clauses.at(i), data.at(i) )
-		);
-		
+			new UntypedExpr( cLoc,
+				new NameExpr( cLoc, "?==?" ),
+				{
+				    new NameExpr( cLoc, statusName ),
+				    new CastExpr( cLoc,
+				        new AddressExpr( cLoc, new NameExpr( cLoc, data.at(i)->nodeName ) ),
+				        new BasicType( BasicKind::LongUnsignedInt ), GeneratedFlag::ExplicitCast
+				    )
+				}
+			),
+			genStmtBlock( stmt->clauses.at(i), data.at(i) )
+		);
+
 		if ( i == 0 ) {
 			outerIf = currIf;
@@ -962,92 +962,92 @@
 	}
 
-    return new CompoundStmt( loc,
-        {
-            new ExprStmt( loc, new UntypedExpr( loc, new NameExpr( loc, "park" ) ) ),
-            outerIf
-        }
-    );
+	return new CompoundStmt( loc,
+		{
+			new ExprStmt( loc, new UntypedExpr( loc, new NameExpr( loc, "park" ) ) ),
+			outerIf
+		}
+	);
 }
 
 Stmt * GenerateWaitUntilCore::recursiveOrIfGen( const WaitUntilStmt * stmt, vector<ClauseData *> & data, vector<ClauseData*>::size_type idx, string & elseWhenName ) {
-    if ( idx == data.size() ) {   // base case, gen last else
-        const CodeLocation & cLoc = stmt->else_stmt->location;
-        if ( !stmt->else_stmt ) // normal non-else gen
-            return buildOrCaseSwitch( stmt, data.at(0)->statusName, data );
-
-        Expr * raceFnCall = new UntypedExpr( stmt->location,
-            new NameExpr( stmt->location, "__select_node_else_race" ),
-            { new NameExpr( stmt->location, data.at(0)->nodeName ) }
-        );
-
-        if ( stmt->else_stmt && stmt->else_cond ) { // return else conditional on both when and race
-            return new IfStmt( cLoc,
-                new LogicalExpr( cLoc,
-                    new CastExpr( cLoc,
-                        new NameExpr( cLoc, elseWhenName ),
-                        new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-                    ),
-                    new CastExpr( cLoc,
-                        raceFnCall,
-                        new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-                    ),
-                    LogicalFlag::AndExpr
-                ),
-                ast::deepCopy( stmt->else_stmt ),
-                buildOrCaseSwitch( stmt, data.at(0)->statusName, data )
-            );
-        }
-
-        // return else conditional on race
-        return new IfStmt( stmt->else_stmt->location,
-            raceFnCall,
-            ast::deepCopy( stmt->else_stmt ),
-            buildOrCaseSwitch( stmt, data.at(0)->statusName, data )
-        );
-    }
-    const CodeLocation & cLoc = stmt->clauses.at(idx)->location;
-
-    Expr * baseCond = genSelectTraitCall( stmt->clauses.at(idx), data.at(idx), "register_select" );
-    Expr * ifCond;
-
-    // If we have a when_cond make the register call conditional on it
-    if ( stmt->clauses.at(idx)->when_cond ) {
-        ifCond = new LogicalExpr( cLoc,
-            new CastExpr( cLoc,
-                new NameExpr( cLoc, data.at(idx)->whenName ), 
-                new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-            ),
-            new CastExpr( cLoc,
-                baseCond,
-                new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-            ),
-            LogicalFlag::AndExpr
-        );
-    } else ifCond = baseCond;
-
-    return new CompoundStmt( cLoc,
-        {   // gens: setup_clause( clause1, &status, 0p );
-            new ExprStmt( cLoc,
-                new UntypedExpr ( cLoc,
-                    new NameExpr( cLoc, "setup_clause" ),
-                    {
-                        new NameExpr( cLoc, data.at(idx)->nodeName ),
-                        new AddressExpr( cLoc, new NameExpr( cLoc, data.at(idx)->statusName ) ),
-                        ConstantExpr::null( cLoc, new PointerType( new BasicType( BasicKind::SignedInt ) ) )
-                    }
-                )
-            ),
-            // gens: if (__when_cond && register_select()) { clause body } else { ... recursiveOrIfGen ... }
-            new IfStmt( cLoc,
-                ifCond,
-                genStmtBlock( stmt->clauses.at(idx), data.at(idx) ),
-                recursiveOrIfGen( stmt, data, idx + 1, elseWhenName )
-            )
-        }
-    );
+	if ( idx == data.size() ) {   // base case, gen last else
+		const CodeLocation & cLoc = stmt->else_stmt->location;
+		if ( !stmt->else_stmt ) // normal non-else gen
+			return buildOrCaseSwitch( stmt, data.at(0)->statusName, data );
+
+		Expr * raceFnCall = new UntypedExpr( stmt->location,
+			new NameExpr( stmt->location, "__select_node_else_race" ),
+			{ new NameExpr( stmt->location, data.at(0)->nodeName ) }
+		);
+
+		if ( stmt->else_stmt && stmt->else_cond ) { // return else conditional on both when and race
+			return new IfStmt( cLoc,
+				new LogicalExpr( cLoc,
+				    new CastExpr( cLoc,
+				        new NameExpr( cLoc, elseWhenName ),
+				        new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+				    ),
+				    new CastExpr( cLoc,
+				        raceFnCall,
+				        new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+				    ),
+				    LogicalFlag::AndExpr
+				),
+				ast::deepCopy( stmt->else_stmt ),
+				buildOrCaseSwitch( stmt, data.at(0)->statusName, data )
+			);
+		}
+
+		// return else conditional on race
+		return new IfStmt( stmt->else_stmt->location,
+			raceFnCall,
+			ast::deepCopy( stmt->else_stmt ),
+			buildOrCaseSwitch( stmt, data.at(0)->statusName, data )
+		);
+	}
+	const CodeLocation & cLoc = stmt->clauses.at(idx)->location;
+
+	Expr * baseCond = genSelectTraitCall( stmt->clauses.at(idx), data.at(idx), "register_select" );
+	Expr * ifCond;
+
+	// If we have a when_cond make the register call conditional on it
+	if ( stmt->clauses.at(idx)->when_cond ) {
+		ifCond = new LogicalExpr( cLoc,
+			new CastExpr( cLoc,
+				new NameExpr( cLoc, data.at(idx)->whenName ),
+				new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+			),
+			new CastExpr( cLoc,
+				baseCond,
+				new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+			),
+			LogicalFlag::AndExpr
+		);
+	} else ifCond = baseCond;
+
+	return new CompoundStmt( cLoc,
+		{   // gens: setup_clause( clause1, &status, 0p );
+			new ExprStmt( cLoc,
+				new UntypedExpr ( cLoc,
+				    new NameExpr( cLoc, "setup_clause" ),
+				    {
+				        new NameExpr( cLoc, data.at(idx)->nodeName ),
+				        new AddressExpr( cLoc, new NameExpr( cLoc, data.at(idx)->statusName ) ),
+				        ConstantExpr::null( cLoc, new PointerType( new BasicType( BasicKind::SignedInt ) ) )
+				    }
+				)
+			),
+			// gens: if (__when_cond && register_select()) { clause body } else { ... recursiveOrIfGen ... }
+			new IfStmt( cLoc,
+				ifCond,
+				genStmtBlock( stmt->clauses.at(idx), data.at(idx) ),
+				recursiveOrIfGen( stmt, data, idx + 1, elseWhenName )
+			)
+		}
+	);
 }
 
 // This gens the special case of an all OR waituntil:
-/* 
+/*
 int status = 0;
 
@@ -1058,340 +1058,340 @@
 
 try {
-    setup_clause( clause1, &status, 0p );
-    if ( __when_cond_0 && register_select( 1 ) ) {
-        ... clause 1 body ...
-    } else {
-        ... recursively gen for each of n clauses ...
-        setup_clause( clausen, &status, 0p );
-        if ( __when_cond_n-1 && register_select( n ) ) {
-            ... clause n body ...
-        } else {
-            if ( else_when ) ... else clause body ...
-            else {
-                park();
-
-                // after winning the race and before unpark() clause_status is set to be the winning clause index + 1 
-                if ( clause_status == &clause1) ... clause 1 body ...
-                ...
-                elif ( clause_status == &clausen ) ... clause n body ...
-            }
-        }
-    }
-}
-finally { 
-    if ( __when_cond_1 && clause1.status != 0p) unregister_select( 1 ); // if registered unregister
-    ...
-    if ( __when_cond_n && clausen.status != 0p) unregister_select( n );
+	setup_clause( clause1, &status, 0p );
+	if ( __when_cond_0 && register_select( 1 ) ) {
+		... clause 1 body ...
+	} else {
+		... recursively gen for each of n clauses ...
+		setup_clause( clausen, &status, 0p );
+		if ( __when_cond_n-1 && register_select( n ) ) {
+			... clause n body ...
+		} else {
+			if ( else_when ) ... else clause body ...
+			else {
+				park();
+
+				// after winning the race and before unpark() clause_status is set to be the winning clause index + 1
+				if ( clause_status == &clause1) ... clause 1 body ...
+				...
+				elif ( clause_status == &clausen ) ... clause n body ...
+			}
+		}
+	}
+}
+finally {
+	if ( __when_cond_1 && clause1.status != 0p) unregister_select( 1 ); // if registered unregister
+	...
+	if ( __when_cond_n && clausen.status != 0p) unregister_select( n );
 }
 */
 Stmt * GenerateWaitUntilCore::genAllOr( const WaitUntilStmt * stmt ) {
-    const CodeLocation & loc = stmt->location;
-    string statusName = namer_status.newName();
-    string elseWhenName = namer_when.newName();
-    int numClauses = stmt->clauses.size();
-    CompoundStmt * body = new CompoundStmt( stmt->location );
-
-    // Generates: unsigned long int status = 0;
-    body->push_back( new DeclStmt( loc,
-        new ObjectDecl( loc,
-            statusName,
-            new BasicType( BasicKind::LongUnsignedInt ),
-            new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
-        )
-    ));
-
-    vector<ClauseData *> clauseData;
-    genClauseInits( stmt, clauseData, body, statusName, elseWhenName );
-
-    vector<int> whenIndices; // track which clauses have whens
-
-    CompoundStmt * unregisters = new CompoundStmt( loc );
-    Expr * ifCond;
-    for ( int i = 0; i < numClauses; i++ ) {
-        const CodeLocation & cLoc = stmt->clauses.at(i)->location;
-        // Gens: node.status != 0p
-        UntypedExpr * statusPtrCheck = new UntypedExpr( cLoc, 
-            new NameExpr( cLoc, "?!=?" ), 
-            {
-                ConstantExpr::null( cLoc, new PointerType( new BasicType( BasicKind::LongUnsignedInt ) ) ),
-                new UntypedExpr( cLoc, 
-                    new NameExpr( cLoc, "__get_clause_status" ), 
-                    { new NameExpr( cLoc, clauseData.at(i)->nodeName ) } 
-                ) 
-            }
-        );
-
-        // If we have a when_cond make the unregister call conditional on it
-        if ( stmt->clauses.at(i)->when_cond ) {
-            whenIndices.push_back(i);
-            ifCond = new LogicalExpr( cLoc,
-                new CastExpr( cLoc,
-                    new NameExpr( cLoc, clauseData.at(i)->whenName ), 
-                    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-                ),
-                new CastExpr( cLoc,
-                    statusPtrCheck,
-                    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-                ),
-                LogicalFlag::AndExpr
-            );
-        } else ifCond = statusPtrCheck;
-        
-        unregisters->push_back(
-            new IfStmt( cLoc,
-                ifCond,
-                new ExprStmt( cLoc, genSelectTraitCall( stmt->clauses.at(i), clauseData.at(i), "unregister_select" ) ) 
-            )
-        );
-    }
-
-    if ( whenIndices.empty() || whenIndices.size() != stmt->clauses.size() ) {
-        body->push_back(
-                new ast::TryStmt( loc,
-                new CompoundStmt( loc, { recursiveOrIfGen( stmt, clauseData, 0, elseWhenName ) } ),
-                {},
-                new ast::FinallyClause( loc, unregisters )
-            )
-        );
-    } else { // If all clauses have whens, we need to skip the waituntil if they are all false
-        Expr * outerIfCond = new NameExpr( loc, clauseData.at( whenIndices.at(0) )->whenName );
-        Expr * lastExpr = outerIfCond;
-
-        for ( vector<int>::size_type i = 1; i < whenIndices.size(); i++ ) {
-            outerIfCond = new LogicalExpr( loc,
-                new CastExpr( loc,
-                    new NameExpr( loc, clauseData.at( whenIndices.at(i) )->whenName ), 
-                    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-                ),
-                new CastExpr( loc,
-                    lastExpr,
-                    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-                ),
-                LogicalFlag::OrExpr
-            );
-            lastExpr = outerIfCond;
-        }
-
-        body->push_back(
-                new ast::TryStmt( loc,
-                new CompoundStmt( loc, 
-                    {
-                        new IfStmt( loc,
-                            outerIfCond,
-                            recursiveOrIfGen( stmt, clauseData, 0, elseWhenName )
-                        )
-                    }
-                ),
-                {},
-                new ast::FinallyClause( loc, unregisters )
-            )
-        );
-    }
-
-    for ( ClauseData * datum : clauseData )
-        delete datum;
-
-    return body;
+	const CodeLocation & loc = stmt->location;
+	string statusName = namer_status.newName();
+	string elseWhenName = namer_when.newName();
+	int numClauses = stmt->clauses.size();
+	CompoundStmt * body = new CompoundStmt( stmt->location );
+
+	// Generates: unsigned long int status = 0;
+	body->push_back( new DeclStmt( loc,
+		new ObjectDecl( loc,
+			statusName,
+			new BasicType( BasicKind::LongUnsignedInt ),
+			new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
+		)
+	));
+
+	vector<ClauseData *> clauseData;
+	genClauseInits( stmt, clauseData, body, statusName, elseWhenName );
+
+	vector<int> whenIndices; // track which clauses have whens
+
+	CompoundStmt * unregisters = new CompoundStmt( loc );
+	Expr * ifCond;
+	for ( int i = 0; i < numClauses; i++ ) {
+		const CodeLocation & cLoc = stmt->clauses.at(i)->location;
+		// Gens: node.status != 0p
+		UntypedExpr * statusPtrCheck = new UntypedExpr( cLoc,
+			new NameExpr( cLoc, "?!=?" ),
+			{
+				ConstantExpr::null( cLoc, new PointerType( new BasicType( BasicKind::LongUnsignedInt ) ) ),
+				new UntypedExpr( cLoc,
+				    new NameExpr( cLoc, "__get_clause_status" ),
+				    { new NameExpr( cLoc, clauseData.at(i)->nodeName ) }
+				)
+			}
+		);
+
+		// If we have a when_cond make the unregister call conditional on it
+		if ( stmt->clauses.at(i)->when_cond ) {
+			whenIndices.push_back(i);
+			ifCond = new LogicalExpr( cLoc,
+				new CastExpr( cLoc,
+				    new NameExpr( cLoc, clauseData.at(i)->whenName ),
+				    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+				),
+				new CastExpr( cLoc,
+				    statusPtrCheck,
+				    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+				),
+				LogicalFlag::AndExpr
+			);
+		} else ifCond = statusPtrCheck;
+
+		unregisters->push_back(
+			new IfStmt( cLoc,
+				ifCond,
+				new ExprStmt( cLoc, genSelectTraitCall( stmt->clauses.at(i), clauseData.at(i), "unregister_select" ) )
+			)
+		);
+	}
+
+	if ( whenIndices.empty() || whenIndices.size() != stmt->clauses.size() ) {
+		body->push_back(
+				new ast::TryStmt( loc,
+				new CompoundStmt( loc, { recursiveOrIfGen( stmt, clauseData, 0, elseWhenName ) } ),
+				{},
+				new ast::FinallyClause( loc, unregisters )
+			)
+		);
+	} else { // If all clauses have whens, we need to skip the waituntil if they are all false
+		Expr * outerIfCond = new NameExpr( loc, clauseData.at( whenIndices.at(0) )->whenName );
+		Expr * lastExpr = outerIfCond;
+
+		for ( vector<int>::size_type i = 1; i < whenIndices.size(); i++ ) {
+			outerIfCond = new LogicalExpr( loc,
+				new CastExpr( loc,
+				    new NameExpr( loc, clauseData.at( whenIndices.at(i) )->whenName ),
+				    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+				),
+				new CastExpr( loc,
+				    lastExpr,
+				    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+				),
+				LogicalFlag::OrExpr
+			);
+			lastExpr = outerIfCond;
+		}
+
+		body->push_back(
+				new ast::TryStmt( loc,
+				new CompoundStmt( loc,
+				    {
+				        new IfStmt( loc,
+				            outerIfCond,
+				            recursiveOrIfGen( stmt, clauseData, 0, elseWhenName )
+				        )
+				    }
+				),
+				{},
+				new ast::FinallyClause( loc, unregisters )
+			)
+		);
+	}
+
+	for ( ClauseData * datum : clauseData )
+		delete datum;
+
+	return body;
 }
 
 Stmt * GenerateWaitUntilCore::postvisit( const WaitUntilStmt * stmt ) {
-    if ( !selectNodeDecl )
-        SemanticError( stmt, "waituntil statement requires #include <waituntil.hfa>" );
-
-    // Prep clause tree to figure out how to set initial statuses
-    // setTreeSizes( stmt->predicateTree );
-    if ( paintWhenTree( stmt->predicateTree ) ) // if this returns true we can special case since tree is all OR's
-        return genAllOr( stmt );
-
-    CompoundStmt * tryBody = new CompoundStmt( stmt->location );
-    CompoundStmt * body = new CompoundStmt( stmt->location );
-    string statusArrName = namer_status.newName();
-    string pCountName = namer_park.newName();
-    string satName = namer_sat.newName();
-    string runName = namer_run.newName();
-    string elseWhenName = namer_when.newName();
-    int numClauses = stmt->clauses.size();
-    addPredicates( stmt, satName, runName );
-
-    const CodeLocation & loc = stmt->location;
-
-    // Generates: int park_counter = 0;
-    body->push_back( new DeclStmt( loc,
-        new ObjectDecl( loc,
-            pCountName,
-            new BasicType( BasicKind::SignedInt ),
-            new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
-        )
-    ));
-
-    // Generates: int clause_statuses[3] = { 0 };
-    body->push_back( new DeclStmt( loc,
-        new ObjectDecl( loc,
-            statusArrName,
-            new ArrayType( new BasicType( BasicKind::LongUnsignedInt ), ConstantExpr::from_int( loc, numClauses ), LengthFlag::FixedLen, DimensionFlag::DynamicDim ),
-            new ListInit( loc,
-                {
-                    new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
-                }
-            )
-        )
-    ));
-
-    vector<ClauseData *> clauseData;
-    genClauseInits( stmt, clauseData, body, statusArrName, elseWhenName );
-
-    vector<pair<int, WaitUntilStmt::ClauseNode *>> ambiguousClauses;       // list of ambiguous clauses
-    vector<int> andWhenClauses;    // list of clauses that have an AND op as a direct parent and when_cond defined
-
-    collectWhens( stmt->predicateTree, ambiguousClauses, andWhenClauses );
-
-    // This is only needed for clauses that have AND as a parent and a when_cond defined
-    // generates: if ( ! when_cond_0 ) clause_statuses_0 = __SELECT_RUN;
-    for ( int idx : andWhenClauses ) {
-        const CodeLocation & cLoc = stmt->clauses.at(idx)->location;
-        body->push_back( 
-            new IfStmt( cLoc,
-                new UntypedExpr ( cLoc,
-                    new NameExpr( cLoc, "!?" ),
-                    { new NameExpr( cLoc, clauseData.at(idx)->whenName ) }
-                ),  // IfStmt cond
-                new ExprStmt( cLoc,
-                    new UntypedExpr ( cLoc,
-                        new NameExpr( cLoc, "?=?" ),
-                        {
-                            new UntypedExpr ( cLoc, 
-                                new NameExpr( cLoc, "?[?]" ),
-                                {
-                                    new NameExpr( cLoc, statusArrName ),
-                                    ConstantExpr::from_int( cLoc, idx )
-                                }
-                            ),
-                            new NameExpr( cLoc, "__SELECT_RUN" )
-                        }
-                    )
-                )  // IfStmt then
-            )
-        );
-    }
-
-    // Only need to generate conditional initial state setting for ambiguous when clauses
-    if ( !ambiguousClauses.empty() ) {
-        body->push_back( genWhenStateConditions( stmt, clauseData, ambiguousClauses, 0 ) );
-    }
-
-    // generates the following for each clause:
-    // setup_clause( clause1, &clause_statuses[0], &park_counter );
-    // register_select(A, clause1);
-    for ( int i = 0; i < numClauses; i++ ) {
-        setUpClause( stmt->clauses.at(i), clauseData.at(i), pCountName, tryBody );
-    }
-
-    // generate satisfy logic based on if there is an else clause and if it is conditional
-    if ( stmt->else_stmt && stmt->else_cond ) { // gen both else/non else branches
-        tryBody->push_back(
-            new IfStmt( stmt->else_cond->location,
-                new NameExpr( stmt->else_cond->location, elseWhenName ),
-                genElseClauseBranch( stmt, runName, statusArrName, clauseData ),
-                genNoElseClauseBranch( stmt, runName, statusArrName, pCountName, clauseData )
-            )
-        );
-    } else if ( !stmt->else_stmt ) { // normal gen
-        tryBody->push_back( genNoElseClauseBranch( stmt, runName, statusArrName, pCountName, clauseData ) );
-    } else { // generate just else
-        tryBody->push_back( genElseClauseBranch( stmt, runName, statusArrName, clauseData ) );
-    }
-
-    // Collection of unregister calls on resources to be put in finally clause
-    // for each clause: 
-    // if ( !__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei ) ) { ... clausei stmt ... }
-    // OR if when( ... ) defined on resource
-    // if ( when_cond_i && (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei ) ) { ... clausei stmt ... }
-    CompoundStmt * unregisters = new CompoundStmt( loc );
-
-    Expr * statusExpr; // !__CFA_has_clause_run( clause_statuses[i] )
-    for ( int i = 0; i < numClauses; i++ ) {
-        const CodeLocation & cLoc = stmt->clauses.at(i)->location;
-
-        // Generates: !__CFA_has_clause_run( clause_statuses[i] )
-        statusExpr = new UntypedExpr ( cLoc,
-            new NameExpr( cLoc, "!?" ),
-            {
-                new UntypedExpr ( cLoc, 
-                    new NameExpr( cLoc, "__CFA_has_clause_run" ),
-                    {
-                        genArrAccessExpr( cLoc, i, statusArrName )
-                    }
-                )
-            }
-        );
-        
-        // Generates:
-        // (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei );
-        statusExpr = new LogicalExpr( cLoc,
-            new CastExpr( cLoc,
-                statusExpr, 
-                new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-            ),
-            new CastExpr( cLoc,
-                genSelectTraitCall( stmt->clauses.at(i), clauseData.at(i), "unregister_select" ),
-                new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-            ),
-            LogicalFlag::AndExpr
-        );
-        
-        // if when cond defined generates:
-        // when_cond_i && (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei );
-        if ( stmt->clauses.at(i)->when_cond )
-            statusExpr = new LogicalExpr( cLoc,
-                new CastExpr( cLoc,
-                    new NameExpr( cLoc, clauseData.at(i)->whenName ), 
-                    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-                ),
-                new CastExpr( cLoc,
-                    statusExpr,
-                    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast 
-                ),
-                LogicalFlag::AndExpr
-            );
-
-        // generates:
-        // if ( statusExpr ) { ... clausei stmt ... }
-        unregisters->push_back( 
-            new IfStmt( cLoc,
-                statusExpr,
-                new CompoundStmt( cLoc,
-                    {
-                        new IfStmt( cLoc,
-                            genSelectTraitCall( stmt->clauses.at(i), clauseData.at(i), "on_selected" ),
-                            ast::deepCopy( stmt->clauses.at(i)->stmt )
-                        )
-                    }
-                )
-            )
-        );
-
-        // // generates:
-        // // if ( statusExpr ) { ... clausei stmt ... }
-        // unregisters->push_back( 
-        //     new IfStmt( cLoc,
-        //         statusExpr,
-        //         genStmtBlock( stmt->clauses.at(i), clauseData.at(i) )
-        //     )
-        // );
-    }
-
-    body->push_back( 
-        new ast::TryStmt(
-            loc,
-            tryBody,
-            {},
-            new ast::FinallyClause( loc, unregisters )
-        )
-    );
-
-    for ( ClauseData * datum : clauseData )
-        delete datum;
-
-    return body;
+	if ( !selectNodeDecl )
+		SemanticError( stmt, "waituntil statement requires #include <waituntil.hfa>" );
+
+	// Prep clause tree to figure out how to set initial statuses
+	// setTreeSizes( stmt->predicateTree );
+	if ( paintWhenTree( stmt->predicateTree ) ) // if this returns true we can special case since tree is all OR's
+		return genAllOr( stmt );
+
+	CompoundStmt * tryBody = new CompoundStmt( stmt->location );
+	CompoundStmt * body = new CompoundStmt( stmt->location );
+	string statusArrName = namer_status.newName();
+	string pCountName = namer_park.newName();
+	string satName = namer_sat.newName();
+	string runName = namer_run.newName();
+	string elseWhenName = namer_when.newName();
+	int numClauses = stmt->clauses.size();
+	addPredicates( stmt, satName, runName );
+
+	const CodeLocation & loc = stmt->location;
+
+	// Generates: int park_counter = 0;
+	body->push_back( new DeclStmt( loc,
+		new ObjectDecl( loc,
+			pCountName,
+			new BasicType( BasicKind::SignedInt ),
+			new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
+		)
+	));
+
+	// Generates: int clause_statuses[3] = { 0 };
+	body->push_back( new DeclStmt( loc,
+		new ObjectDecl( loc,
+			statusArrName,
+			new ArrayType( new BasicType( BasicKind::LongUnsignedInt ), ConstantExpr::from_int( loc, numClauses ), LengthFlag::FixedLen, DimensionFlag::DynamicDim ),
+			new ListInit( loc,
+				{
+				    new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
+				}
+			)
+		)
+	));
+
+	vector<ClauseData *> clauseData;
+	genClauseInits( stmt, clauseData, body, statusArrName, elseWhenName );
+
+	vector<pair<int, WaitUntilStmt::ClauseNode *>> ambiguousClauses;       // list of ambiguous clauses
+	vector<int> andWhenClauses;    // list of clauses that have an AND op as a direct parent and when_cond defined
+
+	collectWhens( stmt->predicateTree, ambiguousClauses, andWhenClauses );
+
+	// This is only needed for clauses that have AND as a parent and a when_cond defined
+	// generates: if ( ! when_cond_0 ) clause_statuses_0 = __SELECT_RUN;
+	for ( int idx : andWhenClauses ) {
+		const CodeLocation & cLoc = stmt->clauses.at(idx)->location;
+		body->push_back(
+			new IfStmt( cLoc,
+				new UntypedExpr ( cLoc,
+				    new NameExpr( cLoc, "!?" ),
+				    { new NameExpr( cLoc, clauseData.at(idx)->whenName ) }
+				),  // IfStmt cond
+				new ExprStmt( cLoc,
+				    new UntypedExpr ( cLoc,
+				        new NameExpr( cLoc, "?=?" ),
+				        {
+				            new UntypedExpr ( cLoc,
+				                new NameExpr( cLoc, "?[?]" ),
+				                {
+				                    new NameExpr( cLoc, statusArrName ),
+				                    ConstantExpr::from_int( cLoc, idx )
+				                }
+				            ),
+				            new NameExpr( cLoc, "__SELECT_RUN" )
+				        }
+				    )
+				)  // IfStmt then
+			)
+		);
+	}
+
+	// Only need to generate conditional initial state setting for ambiguous when clauses
+	if ( !ambiguousClauses.empty() ) {
+		body->push_back( genWhenStateConditions( stmt, clauseData, ambiguousClauses, 0 ) );
+	}
+
+	// generates the following for each clause:
+	// setup_clause( clause1, &clause_statuses[0], &park_counter );
+	// register_select(A, clause1);
+	for ( int i = 0; i < numClauses; i++ ) {
+		setUpClause( stmt->clauses.at(i), clauseData.at(i), pCountName, tryBody );
+	}
+
+	// generate satisfy logic based on if there is an else clause and if it is conditional
+	if ( stmt->else_stmt && stmt->else_cond ) { // gen both else/non else branches
+		tryBody->push_back(
+			new IfStmt( stmt->else_cond->location,
+				new NameExpr( stmt->else_cond->location, elseWhenName ),
+				genElseClauseBranch( stmt, runName, statusArrName, clauseData ),
+				genNoElseClauseBranch( stmt, runName, statusArrName, pCountName, clauseData )
+			)
+		);
+	} else if ( !stmt->else_stmt ) { // normal gen
+		tryBody->push_back( genNoElseClauseBranch( stmt, runName, statusArrName, pCountName, clauseData ) );
+	} else { // generate just else
+		tryBody->push_back( genElseClauseBranch( stmt, runName, statusArrName, clauseData ) );
+	}
+
+	// Collection of unregister calls on resources to be put in finally clause
+	// for each clause:
+	// if ( !__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei ) ) { ... clausei stmt ... }
+	// OR if when( ... ) defined on resource
+	// if ( when_cond_i && (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei ) ) { ... clausei stmt ... }
+	CompoundStmt * unregisters = new CompoundStmt( loc );
+
+	Expr * statusExpr; // !__CFA_has_clause_run( clause_statuses[i] )
+	for ( int i = 0; i < numClauses; i++ ) {
+		const CodeLocation & cLoc = stmt->clauses.at(i)->location;
+
+		// Generates: !__CFA_has_clause_run( clause_statuses[i] )
+		statusExpr = new UntypedExpr ( cLoc,
+			new NameExpr( cLoc, "!?" ),
+			{
+				new UntypedExpr ( cLoc,
+				    new NameExpr( cLoc, "__CFA_has_clause_run" ),
+				    {
+				        genArrAccessExpr( cLoc, i, statusArrName )
+				    }
+				)
+			}
+		);
+
+		// Generates:
+		// (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei );
+		statusExpr = new LogicalExpr( cLoc,
+			new CastExpr( cLoc,
+				statusExpr,
+				new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+			),
+			new CastExpr( cLoc,
+				genSelectTraitCall( stmt->clauses.at(i), clauseData.at(i), "unregister_select" ),
+				new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+			),
+			LogicalFlag::AndExpr
+		);
+
+		// if when cond defined generates:
+		// when_cond_i && (!__CFA_has_clause_run( clause_statuses[i] )) && unregister_select( ... , clausei );
+		if ( stmt->clauses.at(i)->when_cond )
+			statusExpr = new LogicalExpr( cLoc,
+				new CastExpr( cLoc,
+				    new NameExpr( cLoc, clauseData.at(i)->whenName ),
+				    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+				),
+				new CastExpr( cLoc,
+				    statusExpr,
+				    new BasicType( BasicKind::Bool ), GeneratedFlag::ExplicitCast
+				),
+				LogicalFlag::AndExpr
+			);
+
+		// generates:
+		// if ( statusExpr ) { ... clausei stmt ... }
+		unregisters->push_back(
+			new IfStmt( cLoc,
+				statusExpr,
+				new CompoundStmt( cLoc,
+				    {
+				        new IfStmt( cLoc,
+				            genSelectTraitCall( stmt->clauses.at(i), clauseData.at(i), "on_selected" ),
+				            ast::deepCopy( stmt->clauses.at(i)->stmt )
+				        )
+				    }
+				)
+			)
+		);
+
+		// // generates:
+		// // if ( statusExpr ) { ... clausei stmt ... }
+		// unregisters->push_back(
+		//     new IfStmt( cLoc,
+		//         statusExpr,
+		//         genStmtBlock( stmt->clauses.at(i), clauseData.at(i) )
+		//     )
+		// );
+	}
+
+	body->push_back(
+		new ast::TryStmt(
+			loc,
+			tryBody,
+			{},
+			new ast::FinallyClause( loc, unregisters )
+		)
+	);
+
+	for ( ClauseData * datum : clauseData )
+		delete datum;
+
+	return body;
 }
 
@@ -1399,25 +1399,25 @@
 // Predicates are added after "struct select_node { ... };"
 class AddPredicateDecls final : public WithDeclsToAdd<> {
-    vector<FunctionDecl *> & satFns;
-    const StructDecl * selectNodeDecl = nullptr;
+	vector<FunctionDecl *> & satFns;
+	const StructDecl * selectNodeDecl = nullptr;
 
   public:
-    void previsit( const StructDecl * decl ) {
-        if ( !decl->body ) {
-            return;
-        } else if ( "select_node" == decl->name ) {
-            assert( !selectNodeDecl );
-            selectNodeDecl = decl;
-            for ( FunctionDecl * fn : satFns )
-                declsToAddAfter.push_back(fn);            
-        }
-    }
-    AddPredicateDecls( vector<FunctionDecl *> & satFns ): satFns(satFns) {}
+	void previsit( const StructDecl * decl ) {
+		if ( !decl->body ) {
+			return;
+		} else if ( "select_node" == decl->name ) {
+			assert( !selectNodeDecl );
+			selectNodeDecl = decl;
+			for ( FunctionDecl * fn : satFns )
+				declsToAddAfter.push_back(fn);
+		}
+	}
+	AddPredicateDecls( vector<FunctionDecl *> & satFns ): satFns(satFns) {}
 };
 
 void generateWaitUntil( TranslationUnit & translationUnit ) {
-    vector<FunctionDecl *> satFns;
+	vector<FunctionDecl *> satFns;
 	Pass<GenerateWaitUntilCore>::run( translationUnit, satFns );
-    Pass<AddPredicateDecls>::run( translationUnit, satFns );
+	Pass<AddPredicateDecls>::run( translationUnit, satFns );
 }
 
