Index: trunk/abdev/BasicCompiler_Common/src/Exception.cpp
===================================================================
--- trunk/abdev/BasicCompiler_Common/src/Exception.cpp	(revision 358)
+++ trunk/abdev/BasicCompiler_Common/src/Exception.cpp	(revision 359)
@@ -13,7 +13,29 @@
 class TryScope
 {
+	bool isCatched;
+	bool isDefinedFinally;
+
+	std::vector<const PertialSchedule *> finallySchedules;
+	void JmpFinally()
+	{
+		finallySchedules.push_back(
+			compiler.codeGenerator.op_jmp( 0, sizeof(long), true )
+		);
+	}
+	void ResolveJmpFinally()
+	{
+		BOOST_FOREACH( const PertialSchedule *pPertialSchedule, finallySchedules )
+		{
+			compiler.codeGenerator.opfix_JmpPertialSchedule( pPertialSchedule );
+		}
+	}
+
+	const PertialSchedule *pPertialScheduleForFinallyAddress;
+
 public:
 	const PertialSchedule *pPertialScheduleForCatchAddress;
 	TryScope()
+		: isCatched( false )
+		, isDefinedFinally( false )
 	{
 	}
@@ -22,15 +44,63 @@
 	}
 
+	bool IsCatched() const
+	{
+		return isCatched;
+	}
+	bool IsDefinedFinally() const
+	{
+		return isDefinedFinally;
+	}
+
 	void RegistPertialScheduleForCatchAddress( const PertialSchedule *pPertialScheduleForCatchAddress )
 	{
 		this->pPertialScheduleForCatchAddress = pPertialScheduleForCatchAddress;
 	}
-
-	void AddCatch()
-	{
+	void RegistPertialScheduleForFinallyAddress( const PertialSchedule *pPertialScheduleForFinallyAddress )
+	{
+		this->pPertialScheduleForFinallyAddress = pPertialScheduleForFinallyAddress;
+	}
+	const PertialSchedule *GetPertialScheduleForFinallyAddress() const
+	{
+		return pPertialScheduleForFinallyAddress;
+	}
+	
+	
+
+	void Try()
+	{
+	}
+
+	void Catch()
+	{
+		if( isDefinedFinally )
+		{
+			SetError(71,NULL,cp);
+			return;
+		}
+
+		isCatched = true;
+
+		JmpFinally();
+	}
+	void Finally()
+	{
+		if( isDefinedFinally )
+		{
+			SetError(70,NULL,cp);
+			return;
+		}
+
+		isDefinedFinally = true;
+
+		ResolveJmpFinally();
 	}
 
 	void EndTry()
 	{
+		if( !isDefinedFinally )
+		{
+			Finally();
+		}
 	}
 };
@@ -47,26 +117,63 @@
 
 	tryScopes.push_back( TryScope() );
-
-	int backCp = cp;
-
-	char temporary[1024];
-	lstrcpy( temporary, "ExceptionService.BeginTryScope( _System_GetNowScopeCatchAddresses() As VoidPtr, _System_GetBp() As LONG_PTR, _System_GetSp() As LONG_PTR )" );
-	MakeMiddleCode( temporary );
-	ChangeOpcode( temporary );
-
-	cp = backCp;
-}
-void CatchCommand()
-{
-	if( tryScopes.size() == 0 )
-	{
-		SetError(1,NULL,cp);
-		return;
-	}
-
+	tryScopes.back().Try();
+
+	int backCp = cp;
+
+	char temporary[1024];
+	lstrcpy( temporary, "ExceptionService.BeginTryScope( _System_GetNowScopeCatchAddresses() As VoidPtr, _System_GetNowScopeFinallyAddresses() As VoidPtr, _System_GetBp() As LONG_PTR, _System_GetSp() As LONG_PTR )" );
+	MakeMiddleCode( temporary );
+	ChangeOpcode( temporary );
+
+	cp = backCp;
+}
+void CatchCommand( const char *parameter )
+{
+	if( tryScopes.size() == 0 )
+	{
+		SetError(1,NULL,cp);
+		return;
+	}
+
+	Type paramType;
+	if( parameter[0] )
+	{
+		char varName[VN_SIZE], typeName[VN_SIZE];
+		SplitSyntacticForAs( parameter, varName, typeName );
+		if( !typeName[0] )
+		{
+			SetError(72,NULL,cp);
+		}
+		else
+		{
+			if( !compiler.StringToType( typeName, paramType ) )
+			{
+				SetError(73,NULL,cp);
+			}
+		}
+	}
+
+	// パラメータの扱いが未完成
+
+	tryScopes.back().Catch();
+
+	// _System_GetNowScopeCatchAddressesを解決
 	compiler.codeGenerator.opfix( tryScopes.back().pPertialScheduleForCatchAddress, compiler.codeGenerator.GetNativeCodeSize() );
 }
 void FinallyCommand()
 {
+	tryScopes.back().Finally();
+
+	int backCp = cp;
+
+	char temporary[1024];
+	lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->FinishFinally()" );
+	MakeMiddleCode( temporary );
+	ChangeOpcode( temporary );
+
+	cp = backCp;
+
+	//Tryスコープに入るときに引き渡されるパラメータ値を解決
+	compiler.codeGenerator.opfix( tryScopes.back().GetPertialScheduleForFinallyAddress(), compiler.codeGenerator.GetNativeCodeSize() );
 }
 void EndTryCommand()
@@ -80,4 +187,16 @@
 	int backCp = cp;
 
+	if( !tryScopes.back().IsCatched() )
+	{
+		// _System_GetNowScopeCatchAddressesを解決
+		compiler.codeGenerator.opfix( tryScopes.back().pPertialScheduleForCatchAddress, 0 );
+	}
+
+	if( !tryScopes.back().IsDefinedFinally() )
+	{
+		// Finallyが定義されていないときは空のFinallyを定義しておく
+		FinallyCommand();
+	}
+
 	char temporary[1024];
 	lstrcpy( temporary, "_System_pobj_AllThreads->GetCurrentException()->EndTryScope()" );
@@ -87,4 +206,5 @@
 	cp = backCp;
 
+	tryScopes.back().EndTry();
 	tryScopes.pop_back();
 }
@@ -133,4 +253,35 @@
 }
 
+void Opcode_Func_System_GetNowScopeFinallyAddress()
+{
+	if( tryScopes.size() == 0 )
+	{
+		SetError(1,NULL,cp);
+		return;
+	}
+
+#ifdef _WIN64
+	//mov rax,finallyAddress
+	const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( sizeof(long), REG_RAX, 0, Schedule::CatchAddress, true );
+#else
+	//mov eax,finallyAddress
+	const PertialSchedule *pPertialSchedule = compiler.codeGenerator.op_mov_RV( REG_EAX, 0, Schedule::CatchAddress, true );
+#endif
+
+	tryScopes.back().RegistPertialScheduleForFinallyAddress( pPertialSchedule );
+
+	/*
+	int dataTableOffset = compiler.GetObjectModule().dataTable.Add( static_cast<LONG_PTR>(0) );
+
+#ifdef _WIN64
+	//mov rax,dataTableOffset
+	compiler.codeGenerator.op_mov_RV( sizeof(_int64), REG_RAX, dataTableOffset, Schedule::DataTable);
+#else
+	//mov eax,dataTableOffset
+	compiler.codeGenerator.op_mov_RV( REG_EAX, dataTableOffset, Schedule::DataTable);
+#endif
+	*/
+}
+
 
 }	// Exception
