Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision 4f6dda063e7b3a906904ff494b7cf4bb41f5a5c5)
+++ src/Concurrency/Keywords.cc	(revision 080d2d7ba50a3655c63a98c65438678da072eee0)
@@ -1204,5 +1204,5 @@
 					//new TypeofType( noQualifiers, args.front()->clone() )
 					new TypeofType( noQualifiers, new UntypedExpr(
-							new NameExpr( "__get_type" ),
+							new NameExpr( "__get_mutexstmt_lock_type" ),
 							{ args.front()->clone() }
 						) 
@@ -1216,5 +1216,5 @@
 				map_range < std::list<Initializer*> > ( args, [](Expression * var ){
 					return new SingleInit( new UntypedExpr(
-							new NameExpr( "__get_ptr" ),
+							new NameExpr( "__get_mutexstmt_lock_ptr" ),
 							{ var }
 					) );
@@ -1227,5 +1227,5 @@
 		TypeExpr * lock_type_expr = new TypeExpr( 
 			new TypeofType( noQualifiers, new UntypedExpr(
-				new NameExpr( "__get_type" ),
+				new NameExpr( "__get_mutexstmt_lock_type" ),
 				{ args.front()->clone() }
 				) 
Index: src/Concurrency/KeywordsNew.cpp
===================================================================
--- src/Concurrency/KeywordsNew.cpp	(revision 4f6dda063e7b3a906904ff494b7cf4bb41f5a5c5)
+++ src/Concurrency/KeywordsNew.cpp	(revision 080d2d7ba50a3655c63a98c65438678da072eee0)
@@ -14,4 +14,6 @@
 //
 
+#include <iostream>
+
 #include "Concurrency/Keywords.h"
 
@@ -26,4 +28,5 @@
 #include "Common/Examine.h"
 #include "Common/utility.h"
+#include "Common/UniqueName.h"
 #include "ControlStruct/LabelGeneratorNew.hpp"
 #include "InitTweak/InitTweak.h"
@@ -167,4 +170,5 @@
 	const ast::StructDecl * typeid_decl = nullptr;
 	const ast::StructDecl * vtable_decl = nullptr;
+
 };
 
@@ -874,5 +878,5 @@
 
 // --------------------------------------------------------------------------
-struct MutexKeyword final {
+struct MutexKeyword final : public ast::WithDeclsToAdd<> {
 	const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl );
 	void postvisit( const ast::StructDecl * decl );
@@ -887,5 +891,6 @@
 	ast::CompoundStmt * addStatements( const ast::CompoundStmt * body, const std::vector<ast::ptr<ast::Expr>> & args );
 	ast::CompoundStmt * addThreadDtorStatements( const ast::FunctionDecl* func, const ast::CompoundStmt * body, const std::vector<const ast::DeclWithType *> & args );
-
+	ast::ExprStmt * genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param);
+	ast::IfStmt * genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam );
 private:
 	const ast::StructDecl * monitor_decl = nullptr;
@@ -896,4 +901,6 @@
 
 	static ast::ptr<ast::Type> generic_func;
+
+	UniqueName mutex_func_namer = UniqueName("__lock_unlock_curr");
 };
 
@@ -999,6 +1006,6 @@
 	ast::CompoundStmt * body =
 			new ast::CompoundStmt( stmt->location, { stmt->stmt } );
-	addStatements( body, stmt->mutexObjs );
-	return body;
+	
+	return addStatements( body, stmt->mutexObjs );;
 }
 
@@ -1195,11 +1202,71 @@
 }
 
+// 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 
+ast::ExprStmt * MutexKeyword::genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param ) {
+	return new ast::ExprStmt( location,
+		new ast::UntypedExpr( location,
+			new ast::NameExpr( location, fnName ), {
+				ast::UntypedExpr::createDeref(
+					location,
+					new ast::CastExpr( location, 
+						param,
+						new ast::PointerType( new ast::TypeofType( new ast::UntypedExpr(
+							expr->location,
+							new ast::NameExpr( expr->location, "__get_mutexstmt_lock_type" ),
+							{ expr }
+						) ) ),
+						ast::GeneratedFlag::ExplicitCast
+					)
+				)
+			}
+		)
+	);
+}
+
+ast::IfStmt * MutexKeyword::genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam ) {
+	ast::IfStmt * outerLockIf = nullptr;
+	ast::IfStmt * lastLockIf = nullptr;
+
+	//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, "?==?" ), {
+				ast::deepCopy( thisParam ),
+				new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() ))
+			}
+		);
+
+		ast::IfStmt * currLockIf = new ast::IfStmt( 
+			location,
+			ifCond,
+			genVirtLockUnlockExpr( fnName, args.at(i), location, ast::deepCopy( thisParam ) )
+		);
+		
+		if ( i == 0 ) {
+			outerLockIf = currLockIf;
+		} else {
+			// add ifstmt to else of previous stmt
+			lastLockIf->else_ = currLockIf;
+		}
+
+		lastLockIf = currLockIf;
+	}
+	return outerLockIf;
+}
+
 ast::CompoundStmt * MutexKeyword::addStatements(
 		const ast::CompoundStmt * body,
 		const std::vector<ast::ptr<ast::Expr>> & args ) {
-	ast::CompoundStmt * mutBody = ast::mutate( body );
 
 	// Code is generated near the beginning of the compound statement.
-	const CodeLocation & location = mutBody->location;
+	const CodeLocation & location = body->location;
+
+		// final body to return
+	ast::CompoundStmt * newBody = new ast::CompoundStmt( location );
+
+	// std::string lockFnName = mutex_func_namer.newName();
+	// std::string unlockFnName = mutex_func_namer.newName();
 
 	// Make pointer to the monitors.
@@ -1209,11 +1276,5 @@
 		new ast::ArrayType(
 			new ast::PointerType(
-				new ast::TypeofType(
-					new ast::UntypedExpr(
-						location,
-						new ast::NameExpr( location, "__get_type" ),
-						{ args.front() }
-					)
-				)
+				new ast::VoidType()
 			),
 			ast::ConstantExpr::from_ulong( location, args.size() ),
@@ -1229,5 +1290,5 @@
 						new ast::UntypedExpr(
 							expr->location,
-							new ast::NameExpr( expr->location, "__get_ptr" ),
+							new ast::NameExpr( expr->location, "__get_mutexstmt_lock_ptr" ),
 							{ expr }
 						)
@@ -1242,20 +1303,53 @@
 	ast::StructInstType * lock_guard_struct =
 			new ast::StructInstType( lock_guard_decl );
-	ast::TypeExpr * lock_type_expr = new ast::TypeExpr(
-		location,
-		new ast::TypeofType(
-			new ast::UntypedExpr(
-				location,
-				new ast::NameExpr( location, "__get_type" ),
-				{ args.front() }
-			)
-		)
-	);
-
-	lock_guard_struct->params.push_back( lock_type_expr );
-
-	// In reverse order:
+
+	// use try stmts to lock and finally to unlock
+	ast::TryStmt * outerTry = nullptr;
+	ast::TryStmt * currentTry;
+	ast::CompoundStmt * lastBody = nullptr;
+
+	// adds a nested try stmt for each lock we are locking
+	for ( long unsigned int i = 0; i < args.size(); i++ ) {
+		ast::UntypedExpr * innerAccess = new ast::UntypedExpr( 
+			location,
+			new ast::NameExpr( location,"?[?]" ), {
+				new ast::NameExpr( location, "__monitors" ),
+				ast::ConstantExpr::from_int( location, i )
+			}
+		);
+
+		// make the try body
+		ast::CompoundStmt * currTryBody = new ast::CompoundStmt( location );
+		ast::IfStmt * lockCall = genTypeDiscrimLockUnlock( "lock", args, location, innerAccess );
+		currTryBody->push_back( lockCall );
+
+		// make the finally stmt
+		ast::CompoundStmt * currFinallyBody = new ast::CompoundStmt( location );
+		ast::IfStmt * unlockCall = genTypeDiscrimLockUnlock( "unlock", args, location, innerAccess );
+		currFinallyBody->push_back( unlockCall );
+
+		// construct the current try
+		currentTry = new ast::TryStmt( 
+			location, 
+			currTryBody, 
+			{}, 
+			new ast::FinallyStmt( location, currFinallyBody )
+		);
+		if ( i == 0 ) outerTry = currentTry;
+		else {
+			// pushback try into the body of the outer try
+			lastBody->push_back( currentTry );
+		}
+		lastBody = currTryBody;
+	}
+
+	// push body into innermost try body
+	if ( lastBody != nullptr ) {
+		lastBody->push_back( body );
+		newBody->push_front( outerTry );
+	}	
+
 	// monitor_guard_t __guard = { __monitors, # };
-	mutBody->push_front(
+	newBody->push_front(
 		new ast::DeclStmt(
 			location,
@@ -1284,7 +1378,100 @@
 
 	// monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
-	mutBody->push_front( new ast::DeclStmt( location, monitors ) );
-
-	return mutBody;
+	newBody->push_front( new ast::DeclStmt( location, monitors ) );
+
+	// // The parameter for both __lock_curr/__unlock_curr routines.
+	// ast::ObjectDecl * this_decl = new ast::ObjectDecl(
+	// 	location,
+	// 	"this",
+	// 	new ast::PointerType( new ast::VoidType() ),
+	// 	nullptr,
+	// 	{},
+	// 	ast::Linkage::Cforall
+	// );
+
+	// ast::FunctionDecl * lock_decl = new ast::FunctionDecl(
+	// 	location,
+	// 	lockFnName,
+	// 	{ /* forall */ },
+	// 	{
+	// 		// Copy the declaration of this.
+	// 		this_decl,
+	// 	},
+	// 	{ /* returns */ },
+	// 	nullptr,
+	// 	0,
+	// 	ast::Linkage::Cforall,
+	// 	{ /* attributes */ },
+	// 	ast::Function::Inline
+	// );
+
+	// ast::FunctionDecl * unlock_decl = new ast::FunctionDecl(
+	// 	location,
+	// 	unlockFnName,
+	// 	{ /* forall */ },
+	// 	{
+	// 		// Copy the declaration of this.
+	// 		ast::deepCopy( this_decl ),
+	// 	},
+	// 	{ /* returns */ },
+	// 	nullptr,
+	// 	0,
+	// 	ast::Linkage::Cforall,
+	// 	{ /* attributes */ },
+	// 	ast::Function::Inline
+	// );
+
+	// ast::IfStmt * outerLockIf = nullptr;
+	// ast::IfStmt * outerUnlockIf = nullptr;
+	// ast::IfStmt * lastLockIf = nullptr;
+	// ast::IfStmt * lastUnlockIf = nullptr;
+
+	// //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::VariableExpr * thisParam = new ast::VariableExpr( location, InitTweak::getParamThis( lock_decl ) );
+	// 	ast::UntypedExpr * ifCond = new ast::UntypedExpr( location,
+	// 		new ast::NameExpr( location, "?==?" ), {
+	// 			thisParam,
+	// 			new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() ))
+	// 		}
+	// 	);
+
+	// 	ast::IfStmt * currLockIf = new ast::IfStmt( 
+	// 		location,
+	// 		ast::deepCopy( ifCond ),
+	// 		genVirtLockUnlockExpr( "lock", args.at(i), location, ast::deepCopy( thisParam ) )
+	// 	);
+
+	// 	ast::IfStmt * currUnlockIf = new ast::IfStmt( 
+	// 		location,
+	// 		ifCond,
+	// 		genVirtLockUnlockExpr( "unlock", args.at(i), location, ast::deepCopy( thisParam ) )
+	// 	);
+		
+	// 	if ( i == 0 ) {
+	// 		outerLockIf = currLockIf;
+	// 		outerUnlockIf = currUnlockIf;
+	// 	} else {
+	// 		// add ifstmt to else of previous stmt
+	// 		lastLockIf->else_ = currLockIf;
+	// 		lastUnlockIf->else_ = currUnlockIf;
+	// 	}
+
+	// 	lastLockIf = currLockIf;
+	// 	lastUnlockIf = currUnlockIf;
+	// }
+	
+	// // add pointer typing if/elifs to body of routines
+	// lock_decl->stmts = new ast::CompoundStmt( location, { outerLockIf } );
+	// unlock_decl->stmts = new ast::CompoundStmt( location, { outerUnlockIf } );
+
+	// // add routines to scope
+	// declsToAddBefore.push_back( lock_decl );
+	// declsToAddBefore.push_back( unlock_decl );
+
+	// newBody->push_front(new ast::DeclStmt( location, lock_decl ));
+	// newBody->push_front(new ast::DeclStmt( location, unlock_decl ));
+
+	return newBody;
 }
 
