Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision e3e16bcf91a7300a6d1f71eaad04e2f3f498cfc2)
+++ src/Concurrency/Keywords.cc	(revision d67cdb749954789d84d7a8bbabc0ec601347a7bb)
@@ -528,5 +528,4 @@
 		DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
 		auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
-		// if( type ) std::cerr << "FRED2" << std::endl;
 		if( type && type->get_baseStruct()->is_thread() ) {
 			addStartStatement( decl, param );
Index: src/Concurrency/Waitfor.cc
===================================================================
--- src/Concurrency/Waitfor.cc	(revision e3e16bcf91a7300a6d1f71eaad04e2f3f498cfc2)
+++ src/Concurrency/Waitfor.cc	(revision d67cdb749954789d84d7a8bbabc0ec601347a7bb)
@@ -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:
 
@@ -126,9 +126,11 @@
 
 		ObjectDecl * declare( unsigned long count, CompoundStmt * stmt );
+		ObjectDecl * declareFlag( CompoundStmt * stmt );
+		Statement  * makeSetter( ObjectDecl * flag );
 		ObjectDecl * declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt );
-		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();
+		void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * settter, CompoundStmt * stmt );
+		Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, Statement * settter, CompoundStmt * stmt );
+		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 ) {
@@ -140,15 +142,15 @@
 	  private:
 	  	FunctionDecl        * decl_waitfor    = nullptr;
+	  	StructDecl          * decl_mask       = nullptr;
 		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;
 
+		UniqueName namer_acc = "__acceptables_"s;
+		UniqueName namer_idx = "__index_"s;
+		UniqueName namer_flg = "__do_run_"s;
+		UniqueName namer_msk = "__mask_"s;
 		UniqueName namer_mon = "__monitors_"s;
-		UniqueName namer_acc = "__acceptables_"s;
 		UniqueName namer_tim = "__timeout_"s;
 	};
@@ -167,5 +169,5 @@
 	namespace {
 		Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
-			return new ApplicationExpr(
+			return new UntypedExpr(
 				new NameExpr( "?[?]" ),
 				{
@@ -177,5 +179,5 @@
 
 		Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
-			return new ApplicationExpr(
+			return new UntypedExpr(
 					new NameExpr( "?=?" ),
 					{ lhs, rhs }
@@ -183,22 +185,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 ) );
 		}
 
@@ -208,4 +209,19 @@
 			return new ConstantExpr( Constant::from_bool( ifnull ) );
 		}
+
+		VariableExpr * extractVariable( Expression * func ) {
+			if( VariableExpr * var = dynamic_cast< VariableExpr * >( func ) ) {
+				return var;
+			}
+
+			CastExpr * cast = strict_dynamic_cast< CastExpr * >( func );
+			return strict_dynamic_cast< VariableExpr * >( cast->arg );
+		}
+
+		Expression * detectIsDtor( Expression * func ) {
+			VariableExpr * typed_func = extractVariable( func );
+			bool is_dtor = InitTweak::isDestructor( typed_func->var );
+			return new ConstantExpr( Constant::from_bool( is_dtor ) );
+		}
 	};
 
@@ -216,5 +232,5 @@
 
 	void GenerateWaitForPass::premutate( FunctionDecl * decl) {
-		if( decl->name != "__accept_internal" ) return;
+		if( decl->name != "__waitfor_internal" ) return;
 
 		decl_waitfor = decl;
@@ -227,11 +243,8 @@
 			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 == "__waitfor_mask_t" ) {
+			assert( !decl_mask );
+			decl_mask = decl;
 		}
 		else if( decl->name == "monitor_desc" ) {
@@ -242,15 +255,15 @@
 
 	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 );
+		if( !decl_monitor || !decl_acceptable || !decl_mask ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
 
 		CompoundStmt * stmt = new CompoundStmt( noLabels );
 
 		ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
+		ObjectDecl * flag        = declareFlag( stmt );
+		Statement  * setter      = makeSetter( flag );
 
 		int index = 0;
 		for( auto & clause : waitfor->clauses ) {
-			init( acceptables, index, clause, stmt );
+			init( acceptables, index, clause, setter, stmt );
 
 			index++;
@@ -262,10 +275,19 @@
 			waitfor->orelse .statement,
 			waitfor->orelse .condition,
+			setter,
 			stmt
 		);
 
-		// Expression * result  = call( acceptables, timeout, orelse, stmt );
-
-		// choose( waitfor, result );
+		CompoundStmt * compound = new CompoundStmt( noLabels );
+		stmt->push_back( new IfStmt(
+			noLabels,
+			safeCond( new VariableExpr( flag ) ),
+			compound,
+			nullptr
+		));
+
+		Expression * result = call( waitfor->clauses.size(), acceptables, timeout, compound );
+
+		choose( waitfor, result, compound );
 
 		return stmt;
@@ -274,9 +296,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,
@@ -294,19 +313,63 @@
 		stmt->push_back( new DeclStmt( noLabels, acceptables) );
 
+		UntypedExpr * set = new UntypedExpr(
+			new NameExpr( "__builtin_memset" ),
+			{
+				new VariableExpr( acceptables ),
+				new ConstantExpr( Constant::from_int( 0 ) ),
+				new SizeofExpr( new VariableExpr( acceptables ) )
+			}
+		);
+
+		Expression * resolved_set = ResolvExpr::findVoidExpression( set, indexer );
+		delete set;
+
+		stmt->push_back( new ExprStmt( noLabels, resolved_set ) );
+
 		return acceptables;
 	}
 
+	ObjectDecl * GenerateWaitForPass::declareFlag( CompoundStmt * stmt ) {
+		ObjectDecl * flag = ObjectDecl::newObject(
+			namer_flg.newName(),
+			new BasicType(
+				noQualifiers,
+				BasicType::Bool
+			),
+			new SingleInit( new ConstantExpr( Constant::from_ulong( 0 ) ) )
+		);
+
+		stmt->push_back( new DeclStmt( noLabels, flag) );
+
+		return flag;
+	}
+
+	Statement * GenerateWaitForPass::makeSetter( ObjectDecl * flag ) {
+		Expression * untyped = new UntypedExpr(
+			new NameExpr( "?=?" ),
+			{
+				new VariableExpr( flag ),
+				new ConstantExpr( Constant::from_ulong( 1 ) )
+			}
+		);
+
+		Expression * expr = ResolvExpr::findVoidExpression( untyped, indexer );
+		delete untyped;
+
+		return new ExprStmt( noLabels, expr );
+	}
+
 	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,
-				new StructInstType(
+				new PointerType(
 					noQualifiers,
-					decl_monitor
+					new StructInstType(
+						noQualifiers,
+						decl_monitor
+					)
 				),
 				new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
@@ -316,5 +379,21 @@
 			new ListInit(
 				map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
-					return new SingleInit( expr );
+					Expression * untyped = new CastExpr(
+						new UntypedExpr(
+							new NameExpr( "get_monitor" ),
+							{ expr }
+						),
+						new PointerType(
+							noQualifiers,
+							new StructInstType(
+								noQualifiers,
+								decl_monitor
+							)
+						)
+					);
+
+					Expression * init = ResolvExpr::findSingleExpression( untyped, indexer );
+					delete untyped;
+					return new SingleInit( init );
 				})
 			)
@@ -326,18 +405,20 @@
 	}
 
-	void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
+	void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * setter, CompoundStmt * stmt ) {
 
 		ObjectDecl * monitors = declMon( clause, stmt );
 
-		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 ) ) ) );
+		Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
 
 		stmt->push_back( new IfStmt(
 			noLabels,
 			safeCond( clause.condition ),
-			compound,
+			new CompoundStmt({
+				makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
+				makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t )                            , indexer ),
+				makeAccStatement( acceptables, index, "list"   , new VariableExpr( monitors )                                              , indexer ),
+				makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
+				setter->clone()
+			}),
 			nullptr
 		));
@@ -353,11 +434,9 @@
 		bool has_else,
 		Expression *& else_cond,
+		Statement * setter,
 		CompoundStmt * stmt
 	) {
-		ObjectDecl * timeout = new ObjectDecl(
+		ObjectDecl * timeout = ObjectDecl::newObject(
 			namer_tim.newName(),
-			noStorage,
-			LinkageSpec::Cforall,
-			nullptr,
 			new BasicType(
 				noQualifiers,
@@ -374,12 +453,15 @@
 			stmt->push_back( new IfStmt(
 				noLabels,
-				safeCond( else_cond ),
-				new ExprStmt(
-					noLabels,
-					makeOpAssign(
-						new VariableExpr( timeout ),
-						time
-					)
-				),
+				safeCond( time_cond ),
+				new CompoundStmt({
+					new ExprStmt(
+						noLabels,
+						makeOpAssign(
+							new VariableExpr( timeout ),
+							time
+						)
+					),
+					setter->clone()
+				}),
 				nullptr
 			));
@@ -392,11 +474,14 @@
 				noLabels,
 				safeCond( else_cond ),
-				new ExprStmt(
-					noLabels,
-					makeOpAssign(
-						new VariableExpr( timeout ),
-						new ConstantExpr( Constant::from_ulong( 0 ) )
-					)
-				),
+				new CompoundStmt({
+					new ExprStmt(
+						noLabels,
+						makeOpAssign(
+							new VariableExpr( timeout ),
+							new ConstantExpr( Constant::from_ulong( 0 ) )
+						)
+					),
+					setter->clone()
+				}),
 				nullptr
 			));
@@ -405,5 +490,130 @@
 		}
 
+		delete setter;
+
 		return new VariableExpr( timeout );
+	}
+
+	Expression * GenerateWaitForPass::call(
+		size_t count,
+		ObjectDecl * acceptables,
+		Expression * timeout,
+		CompoundStmt * stmt
+	) {
+		ObjectDecl * index = ObjectDecl::newObject(
+			namer_idx.newName(),
+			new BasicType(
+				noQualifiers,
+				BasicType::ShortSignedInt
+			),
+			new SingleInit(
+				new ConstantExpr( Constant::from_int( -1 ) )
+			)
+		);
+
+		stmt->push_back( new DeclStmt( noLabels, index ) );
+
+		ObjectDecl * mask = ObjectDecl::newObject(
+			namer_msk.newName(),
+			new StructInstType(
+				noQualifiers,
+				decl_mask
+			),
+			new ListInit({
+				new SingleInit( new AddressExpr( new VariableExpr( index ) ) ),
+				new SingleInit( new VariableExpr( acceptables ) ),
+				new SingleInit( new ConstantExpr( Constant::from_ulong( count ) ) )
+			})
+		);
+
+		stmt->push_back( new DeclStmt( noLabels, mask ) );
+
+		stmt->push_back( new ExprStmt(
+			noLabels,
+			new ApplicationExpr(
+				VariableExpr::functionPointer( decl_waitfor ),
+				{
+					new CastExpr(
+						new VariableExpr( mask ),
+						new ReferenceType(
+							noQualifiers,
+							new StructInstType(
+								noQualifiers,
+								decl_mask
+							)
+						)
+					),
+					timeout
+				}
+			)
+		));
+
+		return new VariableExpr( index );
+	}
+
+	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_int( -2 ) ),
+					{
+						waitfor->timeout.statement,
+						new BranchStmt(
+							noLabels,
+							"",
+							BranchStmt::Break
+						)
+					}
+				)
+			);
+		}
+
+		if(waitfor->orelse.statement) {
+			swtch->statements.push_back(
+				new CaseStmt(
+					noLabels,
+					new ConstantExpr( Constant::from_int( -1 ) ),
+					{
+						waitfor->orelse.statement,
+						new BranchStmt(
+							noLabels,
+							"",
+							BranchStmt::Break
+						)
+					}
+				)
+			);
+		}
+
+		stmt->push_back( swtch );
 	}
 };
