Index: BasicCompiler_Common/LexicalScoping.cpp
===================================================================
--- BasicCompiler_Common/LexicalScoping.cpp	(revision 5)
+++ BasicCompiler_Common/LexicalScoping.cpp	(revision 34)
@@ -9,27 +9,79 @@
 CLexicalScopes obj_LexScopes;
 
+
+CScope::CScope( int level, int addr, SCOPE_TYPE TypeOfStatement ){
+	this->level = level;
+	this->StartAddress = addr;
+	this->TypeOfStatement = TypeOfStatement;
+
+	pBreakSchedule = (DWORD *)malloc( 1 );
+	nBreakSchedule = 0;
+}
+CScope::~CScope(){
+	free( pBreakSchedule );
+}
+
+int CScope::GetStartAddress(){
+	return StartAddress;
+}
+SCOPE_TYPE CScope::GetTypeOfStatement(){
+	return TypeOfStatement;
+}
+
+void CScope::Break(){
+	//未解放のローカルオブジェクトを解放する
+	obj_LexScopes.CallDestructorsOfReturn( level );
+
+	//jmp ...(Next addr)
+	OpBuffer[obp++]=(char)0xE9;
+
+	pBreakSchedule=(DWORD *)realloc( pBreakSchedule, ( nBreakSchedule + 1 ) * sizeof(DWORD) );
+	pBreakSchedule[nBreakSchedule]=obp;
+	nBreakSchedule++;
+
+	obp+=sizeof(long);
+}
+void CScope::RunScheduleOfBreak(){
+	for(int i=0;i<nBreakSchedule;i++){
+		*((long *)(OpBuffer+pBreakSchedule[i]))=obp-(pBreakSchedule[i]+sizeof(long));
+	}
+}
+
+
+CScope *CLexicalScopes::SearchScope( SCOPE_TYPE TypeOfStatement ){
+	for( int i = level; i>=0; i-- ){
+		if( ppScopes[i]->GetTypeOfStatement() == TypeOfStatement ){
+			return ppScopes[i];
+		}
+	}
+	return NULL;
+}
+
 CLexicalScopes::CLexicalScopes(){
+	ppScopes = (CScope **)malloc( 1 );
 	level=0;
 }
 CLexicalScopes::~CLexicalScopes(){
+	free( ppScopes );
 }
 void CLexicalScopes::Init(int addr){
-	level=0;
-	StartAddresses[level]=addr;
-}
-void CLexicalScopes::LevelUp(int addr){
+	// TODO: エラーチェック
+
+	level = -1;
+	Start( addr, SCOPE_TYPE_BASE );
+}
+void CLexicalScopes::Start( int addr, SCOPE_TYPE TypeOfStatement ){
 	level++;
-	StartAddresses[level]=addr;
-}
-void CLexicalScopes::LevelDown(void){
-	//デストラクタを呼ぶ
-	CallDestrouctorsOfScope();
-
-	//スコープレベルを下げる
-	level--;
-	if(level<0){
+	ppScopes = (CScope **)realloc( ppScopes, ( level + 1 ) * sizeof( CScope * ) );
+	ppScopes[level] = new CScope( level, addr, TypeOfStatement );
+}
+void CLexicalScopes::End(){
+	if( level <= 0 ){
 		SetError(300,NULL,cp);
 		return;
 	}
+
+	//デストラクタを呼ぶ
+	CallDestructorsOfScopeEnd();
 
 	extern BOOL bCompilingGlobal;
@@ -51,6 +103,7 @@
 	}
 
+	//使用済みローカル変数の生存チェックを外す
 	for(int i=0;i<num;i++){
-		if(pVar[i].bLiving&&pVar[i].ScopeLevel==level+1){
+		if(pVar[i].bLiving&&pVar[i].ScopeLevel==level){
 			pVar[i].bLiving=0;
 			extern int obp;
@@ -58,10 +111,200 @@
 		}
 	}
-}
-
-int CLexicalScopes::GetNowLevel(void){
+
+
+	//スコープ抜け出しスケジュール
+	ppScopes[level]->RunScheduleOfBreak();
+
+
+	//スコープレベルを下げる
+	delete ppScopes[level];
+	level--;
+}
+
+void CLexicalScopes::ExitFor(){
+	CScope *pScope = SearchScope( SCOPE_TYPE_FOR );
+	if( !pScope ){
+		SetError(12,"Exit For",cp);
+		return;
+	}
+
+	pScope->Break();
+}
+void CLexicalScopes::ExitWhile(){
+	CScope *pScope = SearchScope( SCOPE_TYPE_WHILE );
+	if( !pScope ){
+		SetError(12,"Exit While",cp);
+		return;
+	}
+
+	pScope->Break();
+}
+void CLexicalScopes::ExitDo(){
+	CScope *pScope = SearchScope( SCOPE_TYPE_DO );
+	if( !pScope ){
+		SetError(12,"Exit Do",cp);
+		return;
+	}
+
+	pScope->Break();
+}
+
+int CLexicalScopes::GetNowLevel(){
 	return level;
 }
-int CLexicalScopes::GetStartAddress(void){
-	return StartAddresses[level];
-}
+void CLexicalScopes::SetNowLevel( int level ){
+	this->level = level;
+}
+int CLexicalScopes::GetStartAddress(){
+	return ppScopes[level]->GetStartAddress();
+}
+
+
+// スコープ終了時のデストラクタ呼び出し
+void CLexicalScopes::CallDestructorsOfScopeEnd(){
+	extern BOOL bCompilingGlobal;
+	VARIABLE *pVar;
+	int num;
+	if(bCompilingGlobal){
+		//グローバルオブジェクトの解放処理
+		extern VARIABLE *GlobalVar;
+		extern int MaxGlobalVarNum;
+		pVar=GlobalVar;
+		num=MaxGlobalVarNum;
+	}
+	else{
+		//ローカルオブジェクトの解放処理
+		extern VARIABLE *LocalVar;
+		extern int MaxLocalVarNum;
+		pVar=LocalVar;
+		num=MaxLocalVarNum;
+	}
+
+
+	int i3,i4,i5;
+	int indexSystemGC=-1;
+	for( i3 = num - 1; i3 >= 0; i3-- ){		//確保したのと逆順序で解放するため、バックサーチにする
+
+		if( bCompilingGlobal && GetNowLevel() == 0 ){
+			if(lstrcmp(pVar[i3].name,"_System_GC")==0){
+				indexSystemGC=i3;
+				continue;
+			}
+		}
+
+		//同一レベルのレキシカルスコープのみを検知
+		if(!pVar[i3].bLiving) continue;
+		if( pVar[i3].ScopeLevel != GetNowLevel() ) continue;
+
+		if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef&OBJECT_PARAMETER){
+			//実態オブジェクトのパラメータを持つとき
+
+			//デストラクタを呼び出す
+			i5=pVar[i3].u.pobj_c->DestructorMemberSubIndex;
+			if(i5!=-1)
+				Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,pVar[i3].name,DEF_OBJECT);
+
+			//メモリを解放する
+
+#ifdef _AMD64_
+			//x64ビットコード
+
+			//mov rcx,qword ptr[rsp+offset]
+			op_mov_RM(sizeof(_int64),REG_RCX,REG_RSP,
+				-pVar[i3].offset,
+				MOD_BASE_DISP32);
+			obp-=sizeof(long);
+			AddLocalVarAddrSchedule();
+			obp+=sizeof(long);
+#else
+			//x86コード
+
+			//mov ecx,dword ptr[ebp+offset]
+			op_mov_RM(sizeof(long),REG_ECX,REG_EBP,-pVar[i3].offset,MOD_BASE_DISP32);
+			obp-=sizeof(long);
+			AddLocalVarAddrSchedule();
+			obp+=sizeof(long);
+
+			//push ecx
+			op_push(REG_ECX);
+#endif
+
+			//call free
+			extern SUBINFO *pSub_free;
+			op_call(pSub_free);
+
+
+			if(bCompilingGlobal){
+				//ここには来ないハズ
+				SetError(300,NULL,cp);
+			}
+		}
+		else if(pVar[i3].type==DEF_OBJECT&&pVar[i3].fRef==0){
+			//デストラクタの呼び出し
+			i5=pVar[i3].u.pobj_c->DestructorMemberSubIndex;
+			if(i5!=-1){
+				int ss[MAX_ARRAYDIM];
+				memset(ss,0,MAX_ARRAYDIM*sizeof(int));
+				if(pVar[i3].SubScripts[0]!=-1){
+					while(1){
+						for(i4=0;;i4++){
+							if(pVar[i3].SubScripts[i4]==-1) break;
+
+							if(ss[i4]>pVar[i3].SubScripts[i4]){
+								ss[i4]=0;
+								ss[i4+1]++;
+							}
+							else break;
+						}
+						if(pVar[i3].SubScripts[i4]==-1) break;
+						char temporary[VN_SIZE];
+						sprintf(temporary,"%s[%d",pVar[i3].name,ss[0]);
+						for(i4=1;;i4++){
+							if(pVar[i3].SubScripts[i4]==-1) break;
+
+							sprintf(temporary+lstrlen(temporary),",%d",ss[i4]);
+						}
+						lstrcat(temporary,"]");
+						Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,temporary,DEF_OBJECT);
+
+						ss[0]++;
+
+
+						//ネイティブコードバッファの再確保
+						extern int obp_AllocSize;
+						if(obp_AllocSize<obp+8192){
+							obp_AllocSize+=8192;
+							OpBuffer=(char *)HeapReAlloc(hHeap,0,OpBuffer,obp_AllocSize); //matea
+						}
+					}
+				}
+				else{
+					Opcode_CallProc("",pVar[i3].u.pobj_c->ppobj_Method[i5]->psi,0,pVar[i3].name,DEF_OBJECT);
+				}
+			}
+		}
+	}
+
+	if(indexSystemGC!=-1){
+		//_System_GCオブジェクトのデストラクタの呼び出し処理
+		i3=pVar[indexSystemGC].u.pobj_c->DestructorMemberSubIndex;
+		if(i3!=-1){
+			Opcode_CallProc("",pVar[indexSystemGC].u.pobj_c->ppobj_Method[i3]->psi,0,pVar[indexSystemGC].name,DEF_OBJECT);
+		}
+	}
+}
+
+// Returnステートメントで発行されるデストラクタを生成
+void CLexicalScopes::CallDestructorsOfReturn( int BaseLevel ){
+	//現在のスコープレベルを退避
+	int backupScopeLevel = GetNowLevel();
+
+	for( int i = GetNowLevel(); i >= BaseLevel; i-- ){
+		SetNowLevel( i );
+
+		CallDestructorsOfScopeEnd();
+	}
+
+	//現在のスコープレベルを復元
+	SetNowLevel( backupScopeLevel );
+}
