diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index dfce9116..77904683 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -5889,7 +5889,7 @@ void BfModule::DoForLess(BfForEachStatement* forEachStmt) } void BfModule::Visit(BfForEachStatement* forEachStmt) -{ +{ if ((forEachStmt->mInToken != NULL) && ((forEachStmt->mInToken->GetToken() == BfToken_LChevron) || (forEachStmt->mInToken->GetToken() == BfToken_LessEquals))) { @@ -5900,7 +5900,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) auto autoComplete = mCompiler->GetAutoComplete(); UpdateSrcPos(forEachStmt); - BfScopeData scopeData; + BfScopeData scopeData; // We set mIsLoop after the non-looped initializations if (forEachStmt->mLabelNode != NULL) scopeData.mLabelNode = forEachStmt->mLabelNode->mLabel; @@ -6287,7 +6287,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) localDef->mAddr = itr.mValue; localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional; localDef->mReadFromId = 0; - localDef->Init(); + localDef->Init(); UpdateSrcPos(forEachStmt); CheckVariableDef(localDef); AddLocalVariableDef(localDef, true); @@ -6400,7 +6400,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) varTypedVal = BfTypedValue(varInst, varType, true); } } - + // Iterator if (itr) { @@ -6422,9 +6422,13 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) AddDeferredCall(moduleMethodInstance, functionBindResult.mIRArgs, mCurMethodState->mCurScope); } } - } + } - scopeData.mIsLoop = true; + BfScopeData innerScopeData; + innerScopeData.mValueScopeStart = ValueScopeStart(); + mCurMethodState->AddScope(&innerScopeData); + NewScopeState(true, false); + innerScopeData.mIsLoop = true; if ((autoComplete != NULL) && (forEachStmt->mVariableTypeRef != NULL)) autoComplete->CheckVarResolution(forEachStmt->mVariableTypeRef, varType); @@ -6432,7 +6436,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) if (isArray || isSizedArray) mBfIRBuilder->CreateStore(GetConstValue(0), itr.mValue); - auto valueScopeStartInner = ValueScopeStart(); + auto valueScopeStartInner = ValueScopeStart(); // We may have a call in the loop body mCurMethodState->mMayNeedThisAccessCheck = true; @@ -6445,7 +6449,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) BfBreakData breakData; breakData.mIRContinueBlock = incBB; breakData.mIRBreakBlock = endBB; - breakData.mScope = &scopeData; + breakData.mScope = &innerScopeData; breakData.mInnerValueScopeStart = valueScopeStartInner; breakData.mPrevBreakData = mCurMethodState->mBreakData; SetAndRestoreValue prevBreakData(mCurMethodState->mBreakData, &breakData); @@ -6679,6 +6683,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) mCurMethodState->mLeftBlockCond = false; RestoreScopeState(); + RestoreScopeState(); } void BfModule::Visit(BfDeferStatement* deferStmt) diff --git a/IDEHelper/Tests/src/Loops.bf b/IDEHelper/Tests/src/Loops.bf index b08a07c2..88efae87 100644 --- a/IDEHelper/Tests/src/Loops.bf +++ b/IDEHelper/Tests/src/Loops.bf @@ -1,6 +1,7 @@ #pragma warning disable 168 using System; +using System.Collections; namespace Tests { @@ -12,6 +13,21 @@ namespace Tests public int32 mB; } + class EnumeratorTest : IEnumerator, IDisposable + { + public int mDispCount; + + public void Dispose() + { + mDispCount++; + } + + public Result GetNext() + { + return .Err; + } + } + [Test] public static void TestBasics() { @@ -26,6 +42,37 @@ namespace Tests StructA sa = val; int idx = @val; } + + var e = scope EnumeratorTest(); + for (var val in e) + { + } + Test.Assert(e.mDispCount == 1); + for (var val in e) + { + break; + } + Test.Assert(e.mDispCount == 2); + TestEnumerator1(e); + Test.Assert(e.mDispCount == 3); + TestEnumerator2(e); + Test.Assert(e.mDispCount == 4); + } + + public static void TestEnumerator1(EnumeratorTest e) + { + for (var val in e) + { + return; + } + } + + public static void TestEnumerator2(EnumeratorTest e) + { + for (var val in e) + { + return; + } } } }