/// <summary> /// Begins a finally block on the given exception block. /// /// Only one finally block can be defined per exception block, and the block cannot appear within a catch block. /// /// The given exception block must still be open. /// </summary> public FinallyBlock BeginFinallyBlock(ExceptionBlock forTry) { if (forTry == null) { throw new ArgumentNullException("forTry"); } if (((IOwned)forTry).Owner != this) { FailOwnership(forTry); } var tryBlock = TryBlocks[forTry]; if (tryBlock.Item2 != -1) { throw new InvalidOperationException("BeginFinallyBlock expects an unclosed exception block, but " + forTry + " is already closed"); } if (CurrentExceptionBlock.Count > 0 && forTry != CurrentExceptionBlock.Peek()) { throw new InvalidOperationException("Cannot begin FinallyBlock on " + forTry + " while inner ExceptionBlock " + CurrentExceptionBlock.Peek() + " is still open"); } if (FinallyBlocks.Any(kv => kv.Key.ExceptionBlock == forTry)) { throw new InvalidOperationException("There can only be one finally block per ExceptionBlock, and one is already defined for " + forTry); } if (MustMark) { MarkLabel(DefineLabel(AutoNamer.Next(this, "__autolabel"))); } UpdateState(Wrap(new[] { new StackTransition(0) }, "BeginFinallyBlock")); var ret = new FinallyBlock(forTry); IL.BeginFinallyBlock(); FinallyBlocks[ret] = SigilTuple.Create(IL.Index, -1); return(ret); }
/// <summary> /// Start a new exception block. This is roughly analogous to a `try` block in C#, but an exception block contains it's catch and finally blocks. /// </summary> public ExceptionBlock BeginExceptionBlock() { if (MustMark) { MarkLabel(DefineLabel(AutoNamer.Next(this, "__autolabel"))); } UpdateState(Wrap(new[] { new StackTransition(0) }, "BeginExceptionBlock")); var labelDel = IL.BeginExceptionBlock(); var label = new Label(this, labelDel, AutoNamer.Next(this, "__exceptionBlockEnd")); CurrentLabels[label.Name] = label; var ret = new ExceptionBlock(label); TryBlocks[ret] = SigilTuple.Create(IL.Index, -1); CurrentExceptionBlock.Push(ret); return(ret); }
/// <summary cref="M:Sigil.Emit`1.BeginFinallyBlock(Sigil.ExceptionBlock)" /> public FinallyBlock BeginFinallyBlock(ExceptionBlock forTry) { return(InnerEmit.BeginFinallyBlock(forTry)); }
/// <summary cref="M:Sigil.Emit`1.BeginCatchBlock(System.Type, Sigil.ExceptionBlock)" /> public EmitShorthand <DelegateType> BeginCatchBlock(ExceptionBlock forTry, Type exceptionType, out CatchBlock forCatch) { forCatch = BeginCatchBlock(forTry, exceptionType); return(this); }
/// <summary cref="M:Sigil.Emit`1.BeginCatchBlock(System.Type, Sigil.ExceptionBlock)" /> public CatchBlock BeginCatchBlock(ExceptionBlock forTry, Type exceptionType) { return(InnerEmit.BeginCatchBlock(forTry, exceptionType)); }
/// <summary cref="M:Sigil.Emit`1.BeginCatchBlock``1(Sigil.ExceptionBlock)" /> public EmitShorthand <DelegateType> BeginCatchBlock <ExceptionType>(ExceptionBlock forTry, out CatchBlock tryCatch) { tryCatch = BeginCatchBlock <ExceptionType>(forTry); return(this); }
/// <summary cref="M:Sigil.Emit`1.BeginCatchBlock``1(Sigil.ExceptionBlock)" /> public CatchBlock BeginCatchBlock <ExceptionType>(ExceptionBlock forTry) { return(BeginCatchBlock(forTry, typeof(ExceptionType))); }
/// <summary cref="M:Sigil.Emit`1.BeginExceptionBlock" /> public EmitShorthand <DelegateType> BeginExceptionBlock(out ExceptionBlock forTry) { forTry = BeginExceptionBlock(); return(this); }
internal FinallyBlock(ExceptionBlock forTry) { ExceptionBlock = forTry; }
internal CatchBlock(Type exceptionType, ExceptionBlock forTry) { ExceptionType = exceptionType; ExceptionBlock = forTry; }
/// <summary> /// Begins a catch block for all exceptions in the given exception block /// /// The given exception block must still be open. /// /// Equivalent to BeginCatchBlock(typeof(Exception), forTry). /// </summary> public Emit <DelegateType> BeginCatchAllBlock(ExceptionBlock forTry, out CatchBlock forCatch) { forCatch = BeginCatchAllBlock(forTry); return(this); }
/// <summary> /// Begins a catch block for all exceptions in the given exception block /// /// The given exception block must still be open. /// /// Equivalent to BeginCatchBlock(typeof(Exception), forTry). /// </summary> public CatchBlock BeginCatchAllBlock(ExceptionBlock forTry) { return(BeginCatchBlock <Exception>(forTry)); }
/// <summary> /// Ends the given exception block. /// /// All catch and finally blocks associated with the given exception block must be ended before this method is called. /// </summary> public Emit <DelegateType> EndExceptionBlock(ExceptionBlock forTry) { if (forTry == null) { throw new ArgumentNullException("forTry"); } if (((IOwned)forTry).Owner != this) { FailOwnership(forTry); } var location = TryBlocks[forTry]; // Can't close the same exception block twice if (location.Item2 != -1) { throw new InvalidOperationException("ExceptionBlock has already been ended"); } if (CurrentExceptionBlock.Count > 0 && forTry != CurrentExceptionBlock.Peek()) { throw new InvalidOperationException("Cannot end outer ExceptionBlock " + forTry + " while inner EmitExceptionBlock " + CurrentExceptionBlock.Peek() + " is open"); } // Can't close an exception block while there are outstanding catch blocks foreach (var kv in CatchBlocks.AsEnumerable()) { if (kv.Key.ExceptionBlock != forTry) { continue; } if (kv.Value.Item2 == -1) { throw new InvalidOperationException("Cannot end ExceptionBlock, CatchBlock " + kv.Key + " has not been ended"); } } foreach (var kv in FinallyBlocks.AsEnumerable()) { if (kv.Key.ExceptionBlock != forTry) { continue; } if (kv.Value.Item2 == -1) { throw new InvalidOperationException("Cannot end ExceptionBlock, FinallyBlock " + kv.Key + " has not been ended"); } } if (!CatchBlocks.Any(k => k.Key.ExceptionBlock == forTry) && !FinallyBlocks.Any(k => k.Key.ExceptionBlock == forTry)) { throw new InvalidOperationException("Cannot end ExceptionBlock without defining at least one of a catch or finally block"); } IL.EndExceptionBlock(); TryBlocks[forTry] = SigilTuple.Create(location.Item1, IL.Index); Marks[forTry.Label] = IL.Index; CurrentExceptionBlock.Pop(); if (MustMark) { MarkLabel(DefineLabel(AutoNamer.Next(this, "__autolabel"))); } return(this); }
/// <summary cref="M:Sigil.Emit`1.BeginFinallyBlock(Sigil.ExceptionBlock)" /> public EmitShorthand <DelegateType> BeginFinallyBlock(ExceptionBlock forTry, out FinallyBlock forFinally) { forFinally = BeginFinallyBlock(forTry); return(this); }
/// <summary cref="M:Sigil.Emit`1.EndExceptionBlock(Sigil.ExceptionBlock)" /> public EmitShorthand <DelegateType> EndExceptionBlock(ExceptionBlock forTry) { InnerEmit.EndExceptionBlock(forTry); return(this); }