Index: src/Concurrency/Waitfor.cc
===================================================================
--- src/Concurrency/Waitfor.cc	(revision e3e16bcf91a7300a6d1f71eaad04e2f3f498cfc2)
+++ src/Concurrency/Waitfor.cc	(revision 1dcd955480c332b81ce157f2b7ccf8e34ad2acd3)
@@ -27,5 +27,5 @@
 #include "InitTweak/InitTweak.h"   // for getPointerBase
 #include "Parser/LinkageSpec.h"    // for Cforall
-#include "SymTab/AddVisit.h"       // for acceptAndAdd
+#include "ResolvExpr/Resolver.h"   // for findVoidExpression
 #include "SynTree/Constant.h"      // for Constant
 #include "SynTree/Declaration.h"   // for StructDecl, FunctionDecl, ObjectDecl
@@ -112,5 +112,5 @@
 	//=============================================================================================
 
-	class GenerateWaitForPass final : public WithStmtsToAdd {
+	class GenerateWaitForPass final : public WithIndexer {
 	  public:
 
@@ -129,6 +129,6 @@
 		void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt );
 		Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, CompoundStmt * stmt );
-		Expression * call();
-		void choose();
+		Expression * call(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
+		void         choose( WaitForStmt * waitfor, Expression  * result, CompoundStmt * stmt );
 
 		static void implement( std::list< Declaration * > & translationUnit ) {
@@ -142,8 +142,4 @@
 		StructDecl          * decl_acceptable = nullptr;
 		StructDecl          * decl_monitor    = nullptr;
-		DeclarationWithType * decl_m_func     = nullptr;
-		DeclarationWithType * decl_m_count    = nullptr;
-		DeclarationWithType * decl_m_monitors = nullptr;
-		DeclarationWithType * decl_m_isdtor   = nullptr;
 
 		static std::unique_ptr< Type > generic_func;
@@ -152,4 +148,5 @@
 		UniqueName namer_acc = "__acceptables_"s;
 		UniqueName namer_tim = "__timeout_"s;
+		UniqueName namer_ret = "__return_"s;
 	};
 
@@ -167,5 +164,5 @@
 	namespace {
 		Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
-			return new ApplicationExpr(
+			return new UntypedExpr(
 				new NameExpr( "?[?]" ),
 				{
@@ -177,5 +174,5 @@
 
 		Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
-			return new ApplicationExpr(
+			return new UntypedExpr(
 					new NameExpr( "?=?" ),
 					{ lhs, rhs }
@@ -183,22 +180,21 @@
 		}
 
-		Expression * makeOpMember( Expression * sue, DeclarationWithType * mem ) {
-			return new MemberExpr( mem, sue );
-		}
-
-		Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, DeclarationWithType * member, Expression * value ) {
-			return new ExprStmt(
-				noLabels,
-				makeOpAssign(
-					makeOpMember(
-						makeOpIndex(
-							object,
-							index
-						),
-						member
+		Expression * makeOpMember( Expression * sue, const std::string & mem ) {
+			return new UntypedMemberExpr( new NameExpr( mem ), sue );
+		}
+
+		Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
+			std::unique_ptr< Expression > expr( makeOpAssign(
+				makeOpMember(
+					makeOpIndex(
+						object,
+						index
 					),
-					value
-				)
-			);
+					member
+				),
+				value
+			) );
+
+			return new ExprStmt( noLabels, ResolvExpr::findVoidExpression( expr.get(), indexer ) );
 		}
 
@@ -227,11 +223,4 @@
 			assert( !decl_acceptable );
 			decl_acceptable = decl;
-			for( Declaration * field : decl_acceptable->members ) {
-				     if( field->name == "func"    ) decl_m_func     = strict_dynamic_cast< DeclarationWithType * >( field );
-				else if( field->name == "count"   ) decl_m_count    = strict_dynamic_cast< DeclarationWithType * >( field );
-				else if( field->name == "monitor" ) decl_m_monitors = strict_dynamic_cast< DeclarationWithType * >( field );
-				else if( field->name == "is_dtor" ) decl_m_isdtor   = strict_dynamic_cast< DeclarationWithType * >( field );
-			}
-
 		}
 		else if( decl->name == "monitor_desc" ) {
@@ -242,6 +231,4 @@
 
 	Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
-		return waitfor;
-
 		if( !decl_monitor || !decl_acceptable ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
 
@@ -265,7 +252,7 @@
 		);
 
-		// Expression * result  = call( acceptables, timeout, orelse, stmt );
-
-		// choose( waitfor, result );
+		Expression * result = call( waitfor->clauses.size(), acceptables, timeout, stmt );
+
+		choose( waitfor, result, stmt );
 
 		return stmt;
@@ -274,9 +261,6 @@
 	ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
 	{
-		ObjectDecl * acceptables = new ObjectDecl(
+		ObjectDecl * acceptables = ObjectDecl::newObject(
 			namer_acc.newName(),
-			noStorage,
-			LinkageSpec::Cforall,
-			nullptr,
 			new ArrayType(
 				noQualifiers,
@@ -299,9 +283,6 @@
 	ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
 
-		ObjectDecl * mon = new ObjectDecl(
+		ObjectDecl * mon = ObjectDecl::newObject(
 			namer_mon.newName(),
-			noStorage,
-			LinkageSpec::Cforall,
-			nullptr,
 			new ArrayType(
 				noQualifiers,
@@ -330,9 +311,11 @@
 		ObjectDecl * monitors = declMon( clause, stmt );
 
+		Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
+
 		CompoundStmt * compound = new CompoundStmt( noLabels );
-		compound->push_back( makeAccStatement( acceptables, index, decl_m_func    , clause.target.function ) );
-		compound->push_back( makeAccStatement( acceptables, index, decl_m_count   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ) ) );
-		compound->push_back( makeAccStatement( acceptables, index, decl_m_monitors, new VariableExpr( monitors ) ) );
-		compound->push_back( makeAccStatement( acceptables, index, decl_m_isdtor  , new ConstantExpr( Constant::from_bool( true ) ) ) );
+		compound->push_back( makeAccStatement( acceptables, index, "func"    , new CastExpr( clause.target.function, fptr_t )                            , indexer ) );
+		compound->push_back( makeAccStatement( acceptables, index, "count"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ) );
+		compound->push_back( makeAccStatement( acceptables, index, "monitors", new VariableExpr( monitors )                                              , indexer ) );
+		compound->push_back( makeAccStatement( acceptables, index, "is_dtor" , new ConstantExpr( Constant::from_bool( true ) )                           , indexer ) );
 
 		stmt->push_back( new IfStmt(
@@ -355,9 +338,6 @@
 		CompoundStmt * stmt
 	) {
-		ObjectDecl * timeout = new ObjectDecl(
+		ObjectDecl * timeout = ObjectDecl::newObject(
 			namer_tim.newName(),
-			noStorage,
-			LinkageSpec::Cforall,
-			nullptr,
 			new BasicType(
 				noQualifiers,
@@ -374,5 +354,5 @@
 			stmt->push_back( new IfStmt(
 				noLabels,
-				safeCond( else_cond ),
+				safeCond( time_cond ),
 				new ExprStmt(
 					noLabels,
@@ -407,4 +387,99 @@
 		return new VariableExpr( timeout );
 	}
+
+	Expression * GenerateWaitForPass::call(
+		size_t count,
+		ObjectDecl * acceptables,
+		Expression * timeout,
+		CompoundStmt * stmt
+	) {
+		ObjectDecl * decl = ObjectDecl::newObject(
+			namer_ret.newName(),
+			new BasicType(
+				noQualifiers,
+				BasicType::LongLongUnsignedInt
+			),
+			new SingleInit(
+				new UntypedExpr(
+					VariableExpr::functionPointer( decl_waitfor ),
+					{
+						new ConstantExpr( Constant::from_ulong( count ) ),
+						new VariableExpr( acceptables ),
+						timeout
+					}
+				)
+			)
+		);
+
+		stmt->push_back( new DeclStmt( noLabels, decl ) );
+
+		return new VariableExpr( decl );
+	}
+
+	void GenerateWaitForPass::choose(
+		WaitForStmt * waitfor,
+		Expression  * result,
+		CompoundStmt * stmt
+	) {
+		SwitchStmt * swtch = new SwitchStmt(
+			noLabels,
+			result,
+			std::list<Statement *>()
+		);
+
+		unsigned long i = 0;
+		for( auto & clause : waitfor->clauses ) {
+			swtch->statements.push_back(
+				new CaseStmt(
+					noLabels,
+					new ConstantExpr( Constant::from_ulong( i++ ) ),
+					{
+						clause.statement,
+						new BranchStmt(
+							noLabels,
+							"",
+							BranchStmt::Break
+						)
+					}
+				)
+			);
+		}
+
+		if(waitfor->timeout.statement) {
+			swtch->statements.push_back(
+				new CaseStmt(
+					noLabels,
+					new ConstantExpr( Constant::from_ulong( i++ ) ),
+					{
+						waitfor->timeout.statement,
+						new BranchStmt(
+							noLabels,
+							"",
+							BranchStmt::Break
+						)
+					}
+				)
+			);
+		}
+
+		if(waitfor->orelse.statement) {
+			swtch->statements.push_back(
+				new CaseStmt(
+					noLabels,
+					new ConstantExpr( Constant::from_ulong( i++ ) ),
+					{
+						waitfor->orelse.statement,
+						new BranchStmt(
+							noLabels,
+							"",
+							BranchStmt::Break
+						)
+					}
+				)
+			);
+		}
+
+		stmt->push_back( swtch );
+	}
 };
 
