IMethod CreateDisposeMethod()
{
BooMethodBuilder mn = _enumerator.AddVirtualMethod("Dispose", TypeSystemServices.VoidType);
mn.Method.LexicalInfo = this.LexicalInfo;
LabelStatement noEnsure = CodeBuilder.CreateLabel(_generator.Method, "noEnsure").LabelStatement;
mn.Body.Add(noEnsure);
mn.Body.Add(SetStateTo(_finishedStateNumber));
mn.Body.Add(new ReturnStatement());
// Create a section calling all ensure methods for each converted try block
LabelStatement[] disposeLabels = new LabelStatement[_labels.Count];
for (int i = 0; i < _convertedTryStatements.Count; i++) {
TryStatementInfo info = _convertedTryStatements[i];
disposeLabels[info._stateNumber] = CodeBuilder.CreateLabel(_generator.Method, "$ensure_" + info._stateNumber).LabelStatement;
mn.Body.Add(disposeLabels[info._stateNumber]);
mn.Body.Add(SetStateTo(_finishedStateNumber));
Block block = mn.Body;
while (info._parent != null) {
TryStatement ts = new TryStatement();
block.Add(ts);
ts.ProtectedBlock.Add(CallMethodOnSelf(info._ensureMethod));
block = ts.EnsureBlock = new Block();
info = info._parent;
}
block.Add(CallMethodOnSelf(info._ensureMethod));
mn.Body.Add(new ReturnStatement());
}
// now map the labels of the suspended states to the labels we just created
for (int i = 0; i < _labels.Count; i++) {
if (_tryStatementInfoForLabels[i] == null)
disposeLabels[i] = noEnsure;
else
disposeLabels[i] = disposeLabels[_tryStatementInfoForLabels[i]._stateNumber];
}
mn.Body.Insert(0, CodeBuilder.CreateSwitch(
this.LexicalInfo,
CodeBuilder.CreateMemberReference(_state),
disposeLabels));
return mn.Entity;
}