public CompiledTryCatchFinallyBlock(TryCatchFinallyBlock block)
 {
     BeginTry = block.BeginTry;
     BeginCatch = block.BeginCatch;
     BeginFinally = block.BeginFinally;
     EndTry = block.EndTry;
 }
示例#2
0
        protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics)
        {
            if(stackSemantics == StackSemantics.Value)
                throw new NotSupportedException("Try-catch-finally blocks cannot be used with value stack semantics (They don't produce values)");

            var prefix = "try\\" + Guid.NewGuid().ToString("N") + "\\";
            var beginTryLabel = prefix + "beginTry";
            var beginFinallyLabel = prefix + "beginFinally";
            var beginCatchLabel = prefix + "beginCatch";
            var endTry = prefix + "endTry";

            if (TryBlock.IsEmpty)
                if (FinallyBlock.IsEmpty)
                    return;
                else
                {
                    //The finally block is not protected
                    //  A trycatchfinally with just a finally block is equivalent to the contents of the finally block
                    //  " try {} finally { $code } " => " $code "
                    FinallyBlock.EmitEffectCode(target);
                    return;
                }

            //Emit try block
            target.EmitLabel(Position, beginTryLabel);
            target.Emit(Position,OpCode.@try);
            TryBlock.EmitEffectCode(target);

            //Emit finally block
            target.EmitLabel(FinallyBlock.Position, beginFinallyLabel);
            var beforeEmit = target.Code.Count;
            FinallyBlock.EmitEffectCode(target);
            if (FinallyBlock.Count > 0 && target.Code.Count == beforeEmit)
                target.Emit(FinallyBlock.Position, OpCode.nop);
            target.EmitLeave(FinallyBlock.Position, endTry);

            //Emit catch block
            target.EmitLabel(CatchBlock.Position, beginCatchLabel);
            var usesException = ExceptionVar != null;
            var justRethrow = CatchBlock.IsEmpty && !usesException;

            if (usesException)
            {
                //Assign exception
                ExceptionVar = _GetOptimizedNode(target, ExceptionVar) as AstGetSet ?? ExceptionVar;
                ExceptionVar.Arguments.Add(new AstGetException(File, Line, Column));
                ExceptionVar.Call = PCall.Set;
                ExceptionVar.EmitEffectCode(target);
            }

            if (!justRethrow)
            {
                //Exception handled
                CatchBlock.EmitEffectCode(target);
            }
            else
            {
                //Exception not handled => rethrow.
                // * Rethrow is implemented in the runtime *
                //AstThrow th = new AstThrow(File, Line, Column);
                //th.Expression = new AstGetException(File, Line, Column);
                //th.EmitCode(target);
            }

            target.EmitLabel(Position, endTry);
            target.Emit(Position,OpCode.nop);

            var block =
                new TryCatchFinallyBlock(
                    _getAddress(target, beginTryLabel), _getAddress(target, endTry))
                    {
                        BeginFinally =
                            (!FinallyBlock.IsEmpty ? _getAddress(target, beginFinallyLabel) : -1),
                        BeginCatch = (!justRethrow ? _getAddress(target, beginCatchLabel) : -1),
                        UsesException = usesException
                    };

            //Register try-catch-finally block
            target.Function.Meta.AddTo(TryCatchFinallyBlock.MetaKey, block);
            target.Function.InvalidateTryCatchFinallyBlocks();
        }
示例#3
0
        public TryCatchFinallyBlock Build()
        {
            var tryCatchFinallyBlock = new TryCatchFinallyBlock(_block);

            tryCatchFinallyBlock.TryBlock = new TryBlockBuilder(_reader, _block).Build();

            /*
             * build catch block or finally block
             *
             */
            if (!_reader.HasNext())
            {
                return(tryCatchFinallyBlock);
            }

            _reader.Next();

            if (_reader.Current().Value == Keywords.FINALLY)
            {
                tryCatchFinallyBlock.FinallyBlock = new FinalyBlockBuilder(_reader, _block).Build();

                return(tryCatchFinallyBlock);
            }
            else if (_reader.Current().Value == Keywords.CATCH)
            {
                tryCatchFinallyBlock.CatchBlock = new CatchBuilder(_reader, _block).Build();
            }
            else
            {
                _reader.Back();

                return(tryCatchFinallyBlock);
            }

            /*
             * build finally block
             *
             */
            if (!_reader.HasNext())
            {
                return(tryCatchFinallyBlock);
            }

            _reader.Next();

            if (_reader.Current().Value == Keywords.FINALLY)
            {
                /*
                 * finally block has been set;
                 */
                if (tryCatchFinallyBlock.FinallyBlock != null)
                {
                    throwError("incorrect try-catch-finally block!");
                }

                tryCatchFinallyBlock.FinallyBlock = new FinalyBlockBuilder(_reader, _block).Build();
            }
            else if (_reader.Current().Value == Keywords.CATCH)
            {
                /*
                 * can not exist mutiple catch block  or finally block before catch block
                 */
                throwError("incorrect try-catch-finally block!");
            }
            else
            {
                _reader.Back();

                return(tryCatchFinallyBlock);
            }

            return(tryCatchFinallyBlock);
        }
 public static CompiledTryCatchFinallyBlock Create(TryCatchFinallyBlock block)
 {
     return new CompiledTryCatchFinallyBlock(block);
 }
示例#5
0
        public override bool TryHandleException(Exception exc)
        {
            //Pointer has already been incremented.
            var address = _pointer - 1;

            var block =
                TryCatchFinallyBlock.Closest(address, _implementation.TryCatchFinallyBlocks);

            if (block == null) //No try-catch-finally block handles exceptions at the given address.
                return false;

            _currentException = exc;

            if (block.HasFinally)
            {
#if Verbose
                Console.WriteLine("Exception handled by finally-catch. " + block);
#endif
                _isHandlingException.Pop();
                _isHandlingException.Push(true);
                _pointer = block.BeginFinally;
                _currentTry = block;
            }
            else if (block.HasCatch)
            {
#if Verbose
                Console.WriteLine("Exception handled by catch." + block);
#endif
                _pointer = block.BeginCatch;
            }
            else
            {
                //Fix #9 (Different handling of exception blocks in CIL implementation)
                // The CLR defaults to rethrowing exceptions.
                return false;
            }

            return true;
        }