Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
 /// <summary cref="M:Sigil.Emit`1.BeginFinallyBlock(Sigil.ExceptionBlock)" />
 public FinallyBlock BeginFinallyBlock(ExceptionBlock forTry)
 {
     return(InnerEmit.BeginFinallyBlock(forTry));
 }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
 /// <summary cref="M:Sigil.Emit`1.BeginCatchBlock(System.Type, Sigil.ExceptionBlock)" />
 public CatchBlock BeginCatchBlock(ExceptionBlock forTry, Type exceptionType)
 {
     return(InnerEmit.BeginCatchBlock(forTry, exceptionType));
 }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
 /// <summary cref="M:Sigil.Emit`1.BeginCatchBlock``1(Sigil.ExceptionBlock)" />
 public CatchBlock BeginCatchBlock <ExceptionType>(ExceptionBlock forTry)
 {
     return(BeginCatchBlock(forTry, typeof(ExceptionType)));
 }
Beispiel #8
0
        /// <summary cref="M:Sigil.Emit`1.BeginExceptionBlock" />
        public EmitShorthand <DelegateType> BeginExceptionBlock(out ExceptionBlock forTry)
        {
            forTry = BeginExceptionBlock();

            return(this);
        }
Beispiel #9
0
 internal FinallyBlock(ExceptionBlock forTry)
 {
     ExceptionBlock = forTry;
 }
Beispiel #10
0
 internal CatchBlock(Type exceptionType, ExceptionBlock forTry)
 {
     ExceptionType  = exceptionType;
     ExceptionBlock = forTry;
 }
Beispiel #11
0
        /// <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);
        }
Beispiel #12
0
 /// <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));
 }
Beispiel #13
0
        /// <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);
        }
Beispiel #14
0
        /// <summary cref="M:Sigil.Emit`1.BeginFinallyBlock(Sigil.ExceptionBlock)" />
        public EmitShorthand <DelegateType> BeginFinallyBlock(ExceptionBlock forTry, out FinallyBlock forFinally)
        {
            forFinally = BeginFinallyBlock(forTry);

            return(this);
        }
Beispiel #15
0
 internal CatchBlock(Type exceptionType, ExceptionBlock forTry)
 {
     ExceptionType = exceptionType;
     ExceptionBlock = forTry;
 }
Beispiel #16
0
        /// <summary cref="M:Sigil.Emit`1.EndExceptionBlock(Sigil.ExceptionBlock)" />
        public EmitShorthand <DelegateType> EndExceptionBlock(ExceptionBlock forTry)
        {
            InnerEmit.EndExceptionBlock(forTry);

            return(this);
        }
Beispiel #17
0
 internal FinallyBlock(ExceptionBlock forTry)
 {
     ExceptionBlock = forTry;
 }