상속: Expression
            protected override SystemLinq.Expression VisitTry(SystemLinq.TryExpression node)
            {
                var body     = Visit(node.Body).Unwrap();
                var fault    = Visit(node.Fault).UnwrapNullable();
                var @finally = Visit(node.Finally).UnwrapNullable();
                var handlers = node.Handlers?.Select(VisitCatch);

                return(new RemoteLinq.TryExpression(_typeInfoProvider.GetTypeInfo(node.Type), body, fault, @finally, handlers).Wrap());
            }
        /// <summary>
        /// Updates the specified try expression using the specified handlers, finally, and fault blocks.
        /// This method protects against invalid updates of try expressions and can return the body of the
        /// original try expression if no handlers or finally or fault blocks remain.
        /// </summary>
        /// <param name="node">The node to update.</param>
        /// <param name="body">The new body.</param>
        /// <param name="handlers">The new catch handlers.</param>
        /// <param name="finally">The new finally block.</param>
        /// <param name="fault">The new fault block.</param>
        /// <returns>The updated expression or the original expression if nothing changed.</returns>
        private Expression Update(TryExpression node, Expression body, IList <CatchBlock> handlers, Expression @finally, Expression fault)
        {
            if ((handlers == null || handlers.Count == 0) && @finally == null && fault == null)
            {
                return(ChangeType(body, node.Type));
            }

            return(node.Update(body, handlers, @finally, fault));
        }
예제 #3
0
 /// <summary>
 /// Visits the children of the <see cref="TryExpression"/>.
 /// </summary>
 /// <param name="node">The expression to visit.</param>
 /// <returns>The modified expression, if it or any subexpression was modified;
 /// otherwise, returns the original expression.</returns>
 protected internal virtual Expression VisitTry(TryExpression node)
 {
     return(node.Update(
                Visit(node.Body),
                Visit(node.Handlers, VisitCatchBlock),
                Visit(node.Finally),
                Visit(node.Fault)
                ));
 }
        protected override Expression VisitTry(TryExpression node)
        {
            var res = default(Expression);

            if (node.Finally != null || node.Fault != null)
            {
                var body = Visit(node.Body);
                var handlers = Visit(node.Handlers, VisitCatchBlock);

                if (node.Finally != null)
                {
                    Debug.Assert(node.Fault == null);

                    var @finally = default(Expression);

                    if (VisitAndFindAwait(node.Finally, out @finally))
                    {
                        if (handlers.Count != 0)
                        {
                            body = Expression.TryCatch(body, handlers.ToArray());
                        }

                        res = RewriteHandler(body, @finally, isFault: false);
                    }
                    else
                    {
                        res = node.Update(body, handlers, @finally, null);
                    }
                }
                else
                {
                    Debug.Assert(node.Finally == null);

                    var fault = default(Expression);

                    if (VisitAndFindAwait(node.Fault, out fault))
                    {
                        Debug.Assert(handlers.Count == 0);

                        res = RewriteHandler(body, fault, isFault: true);
                    }
                    else
                    {
                        res = node.Update(body, handlers, null, fault);
                    }
                }
            }
            else
            {
                res = base.VisitTry(node);
            }

            return res;
        }
        // NB: This optimization takes away 

        protected override Expression VisitTry(TryExpression node)
        {
            var res = base.VisitTry(node);

            var tryStmt = res as TryExpression;
            if (tryStmt != null)
            {
                // NB: It's safe to take away empty fault and finally blocks; they don't have side-
                //     effects, don't alter exception propagation, and don't have useful properties.

                var @finally = tryStmt.Finally;
                MakeNullIfEmpty(ref @finally);

                var fault = tryStmt.Fault;
                MakeNullIfEmpty(ref fault);

                // NB: We obviously can't take away empty handlers; that'd cause subsequent handlers
                //     to get considered or the exception to propagate.

                var handlers = tryStmt.Handlers;

                // NB: However, we can take away *all* handlers if we know that the body of the try
                //     statement can't throw under any circumstance, so we check for purity below.
                //
                //     Note that we *can't* take away finally or fault blocks because they can be
                //     used for their runtime guarantees of being non-interrupted, e.g.
                //
                //       try { } finally { /* critical code */ }
                //
                //     This is a common pattern we shall not break by optimization of course.
                
                var body = tryStmt.Body;
                if (body.IsPure(true))
                {
                    handlers = null;
                }

                // NB: It's possible it all goes away, so we simply return the body in that case, which
                //     can be a non-empty pure expression.

                if ((handlers == null || handlers.Count == 0) && @finally == null && fault == null)
                {
                    return body;
                }

                // NB: As long as any of { handlers, finally, fault } exists, Update is fine to morph
                //     the original expression into a new one.

                return tryStmt.Update(body, handlers, @finally, fault);
            }

            return res;
        }
        protected override Expression VisitTry(TryExpression node)
        {
            if (node.Fault != null)
            {
                return RewriteFaultHandler(node);
            }
            else if (node.Handlers.Any(h => h.Filter != null))
            {
                return RewriteFilterHandler(node);
            }

            return base.VisitTry(node);
        }
        protected override Expression VisitTry(TryExpression node)
        {
            if (node.Fault != null)
            {
                return(RewriteFaultHandler(node));
            }
            else if (node.Handlers.Any(h => h.Filter != null))
            {
                return(RewriteFilterHandler(node));
            }

            return(base.VisitTry(node));
        }
예제 #8
0
        /// <summary>
        ///     Visits the children of the <see cref="TryExpression" />.
        /// </summary>
        /// <param name="node">The expression to visit.</param>
        /// <returns>
        ///     The modified expression, if it or any subexpression was modified;
        ///     otherwise, returns the original expression.
        /// </returns>
        protected internal virtual Expression VisitTry(TryExpression node)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            return(node.Update
                   (
                       Visit(node.Body),
                       Visit(node.Handlers, VisitCatchBlock),
                       Visit(node.Finally),
                       Visit(node.Fault)
                   ));
        }
예제 #9
0
        protected internal virtual Expression VisitTry(TryExpression node)
        {
            Expression b = Visit(node.Body);
            ReadOnlyCollection <CatchBlock> h = Visit(node.Handlers, VisitCatchBlock);
            Expression y = Visit(node.Finally);
            Expression f = Visit(node.Fault);

            if (b == node.Body &&
                h == node.Handlers &&
                y == node.Finally &&
                f == node.Fault)
            {
                return(node);
            }
            return(Expression.MakeTry(b, y, f, h));
        }
        /// <summary>
        /// Simplifies the specified try expression by removing unreachable handlers.
        /// </summary>
        /// <param name="node">The try expression to simplify.</param>
        /// <returns>The result of simplifying the specified try expression.</returns>
        private Expression SimplifyTry(TryExpression node)
        {
            var oldHandlers = node.Handlers;
            var newHandlers = (IList <CatchBlock>)oldHandlers;

            var handlerCount = oldHandlers.Count;

            if (handlerCount > 0)
            {
                var newHandlerList = default(List <CatchBlock>);

                for (var i = 0; i < handlerCount; i++)
                {
                    var handler = oldHandlers[i];

                    if (HasUnreachableFilter(handler) || IsRethrow(handler))
                    {
                        if (newHandlerList == null)
                        {
                            newHandlerList = new List <CatchBlock>(handlerCount);

                            for (var j = 0; j < i; j++)
                            {
                                newHandlerList.Add(oldHandlers[j]);
                            }
                        }
                    }
                    else
                    {
                        newHandlerList?.Add(handler);
                    }
                }

                if (newHandlerList != null)
                {
                    newHandlers = newHandlerList;
                }
            }

            var oldFinally = node.Finally;
            var newFinally = NullIfEmpty(oldFinally);

            var oldFault = node.Fault;
            var newFault = NullIfEmpty(oldFault);

            return(Update(node, node.Body, newHandlers, newFinally, newFault));
        }
        private static Expression CreateRewrittenTry(TryExpression node, HandlerRewriter rewriter, Expression call)
        {
            var assignLeaveResult = Expression.Assign(rewriter.LeaveResult, call);
            var leaveResultValue  = Expression.PropertyOrField(rewriter.LeaveResult, "Value");

            //
            // 1. Create jump table.
            //
            var dispatch = rewriter.GetDispatchTable();

            //
            // 2. Count number of expressions needed in resulting block.
            //
            var n          = (node.Type == typeof(void) ? 0 : 1) + (dispatch != null ? 1 : 0) + 1;
            var statements = new Expression[n];

            //
            // 3. Store result of call in temporary.
            //
            var i = 0;

            statements[i++] = assignLeaveResult;

            //
            // 4. For non-emptyu dispatch tables, emit the dispatch.
            //
            if (dispatch != null)
            {
                statements[i++] = dispatch;
            }

            //
            // 5. For non-null nodes, extract the result.
            //
            if (node.Type != typeof(void))
            {
                statements[i++] = Expression.Convert(leaveResultValue, node.Type);
            }

            //
            // 6. Put everything together in a block.
            //
            var res = Expression.Block(node.Type, new[] { rewriter.LeaveResult }, statements);

            return(res);
        }
        private Expression RewriteFilterHandler(TryExpression node)
        {
            if (node.Handlers.Count == 1 && node.Finally == null)
            {
                //
                // 0. Recurse into the children.
                //
                var body    = Visit(node.Body);
                var handler = VisitCatchBlock(node.Handlers[0]);

                //
                // 1. Initialize rewriter.
                //
                var rewriter = new HandlerRewriter();

                //
                // 2. Obtain rewriters for the body and the handler.
                //
                var bodyRewriter  = rewriter.Rewrite(body);
                var catchRewriter = rewriter.Rewrite(handler.Body); // TODO: verify we can't jump out of the filter

                //
                // 3. Rewrite body, handler, and filter.
                //
                var rewrittenTry           = bodyRewriter();
                var rewrittenTryHandler    = Expression.Lambda <Func <LeaveHandlerData> >(rewrittenTry);
                var rewrittenCatch         = catchRewriter();
                var rewrittenCatchHandler  = Expression.Lambda(rewrittenCatch, handler.Variable);
                var rewrittenFilterHandler = Expression.Lambda(handler.Filter, handler.Variable);

                //
                // 4. Emit call to TryFilter helper.
                //
                var tryFilter = Expression.Call(s_tryFilter.MakeGenericMethod(handler.Test), rewrittenTryHandler, rewrittenFilterHandler, rewrittenCatchHandler);

                //
                // 4. Create resulting expression.
                //
                return(CreateRewrittenTry(node, rewriter, tryFilter));
            }
            else
            {
                return(Visit(Expand(node)));
            }
        }
        private Expression RewriteFilterHandler(TryExpression node)
        {
            if (node.Handlers.Count == 1 && node.Finally == null)
            {
                //
                // 0. Recurse into the children.
                //
                var body = Visit(node.Body);
                var handler = VisitCatchBlock(node.Handlers[0]);

                //
                // 1. Initialize rewriter.
                //
                var rewriter = new HandlerRewriter();

                //
                // 2. Obtain rewriters for the body and the handler.
                //
                var bodyRewriter = rewriter.Rewrite(body);
                var catchRewriter = rewriter.Rewrite(handler.Body); // TODO: verify we can't jump out of the filter

                //
                // 3. Rewrite body, handler, and filter.
                //
                var rewrittenTry = bodyRewriter();
                var rewrittenTryHandler = Expression.Lambda<Func<LeaveHandlerData>>(rewrittenTry);
                var rewrittenCatch = catchRewriter();
                var rewrittenCatchHandler = Expression.Lambda(rewrittenCatch, handler.Variable);
                var rewrittenFilterHandler = Expression.Lambda(handler.Filter, handler.Variable);

                //
                // 4. Emit call to TryFilter helper.
                //
                var tryFilter = Expression.Call(s_tryFilter.MakeGenericMethod(handler.Test), rewrittenTryHandler, rewrittenFilterHandler, rewrittenCatchHandler);

                //
                // 4. Create resulting expression.
                //
                return CreateRewrittenTry(node, rewriter, tryFilter);
            }
            else
            {
                return Visit(Expand(node));
            }
        }
        // NB: We never take out empty try blocks that have a finally or fault handler, because
        //     these handlers provide the guarantee of not being interrupted by asynchronous
        //     exceptions and are often used for concurrency-safe programming.

        /// <summary>
        /// Visits a try expression to perform optimization steps.
        /// </summary>
        /// <param name="node">The try expression to visit.</param>
        /// <returns>The result of optimizing the try expression.</returns>
        protected override Expression VisitTry(TryExpression node)
        {
            var res = (TryExpression)base.VisitTry(node);

            AssertTypes(node, res);

            var opt = SimplifyTry(res);

            AssertTypes(node, opt);

            if (opt.NodeType != ExpressionType.Try)
            {
                return(opt);
            }

            var optimizedTry = (TryExpression)opt;

            var body     = optimizedTry.Body;
            var @finally = optimizedTry.Finally;

            if (IsPure(body))
            {
                if (@finally == null || HasConstantValue(@finally))
                {
                    return(ChangeType(body, optimizedTry.Type));
                }
                else
                {
                    return(Expression.MakeTry(optimizedTry.Type, body, @finally, fault: null, handlers: null));
                }
            }
            else if (AlwaysThrows(body))
            {
                // NB: We can possibly evaluate pure catch blocks ahead of time if we know the
                //     body throws. However, we'd need to know the exact runtime type of the
                //     exception being thrown.

                return(EvaluateTryThrow(optimizedTry));
            }

            return(optimizedTry);
        }
        private static Expression Expand(TryExpression expression)
        {
            var res = expression.Body;

            var handlers = default(List <CatchBlock>);

            foreach (var handler in expression.Handlers)
            {
                if (handler.Filter != null)
                {
                    if (handlers != null)
                    {
                        res      = Expression.TryCatch(res, handlers.ToArray());
                        handlers = null;
                    }

                    res = Expression.TryCatch(res, handler);
                }
                else
                {
                    if (handlers == null)
                    {
                        handlers = new List <CatchBlock>();
                    }

                    handlers.Add(handler);
                }
            }

            if (handlers != null)
            {
                res = Expression.TryCatch(res, handlers.ToArray());
            }

            if (expression.Finally != null)
            {
                res = Expression.TryFinally(res, expression.Finally);
            }

            return(res);
        }
예제 #16
0
        protected override Expression VisitTry(TryExpression node)
        {
            var args = new List <object>();

            args.Add(new XElement(nameof(node.Body), Visit(node.Body)));

            if (node.Handlers.Count > 0)
            {
                args.Add(Visit(nameof(node.Handlers), node.Handlers, Visit));
            }

            if (node.Finally != null)
            {
                args.Add(new XElement(nameof(node.Finally), Visit(node.Finally)));
            }

            if (node.Fault != null)
            {
                args.Add(new XElement(nameof(node.Fault), Visit(node.Fault)));
            }

            return(Push(node, args));
        }
예제 #17
0
 protected internal override Expression VisitTry(TryExpression node)
 {
     this.Out(".Try {", Flow.NewLine);
     this.Indent();
     this.Visit(node.Body);
     this.Dedent();
     ExpressionVisitor.Visit <CatchBlock>(node.Handlers, new Func <CatchBlock, CatchBlock>(this.VisitCatchBlock));
     if (node.Finally != null)
     {
         this.Out(Flow.NewLine, "} .Finally {", Flow.NewLine);
         this.Indent();
         this.Visit(node.Finally);
         this.Dedent();
     }
     else if (node.Fault != null)
     {
         this.Out(Flow.NewLine, "} .Fault {", Flow.NewLine);
         this.Indent();
         this.Visit(node.Fault);
         this.Dedent();
     }
     this.Out(Flow.NewLine, "}");
     return(node);
 }
    public virtual bool IsEvaluatableTry (TryExpression node)
    {
      ArgumentUtility.CheckNotNull ("node", node);

      return true;
    }
        private static Expression CreateRewrittenTry(TryExpression node, HandlerRewriter rewriter, Expression call)
        {
            var assignLeaveResult = Expression.Assign(rewriter.LeaveResult, call);
            var leaveResultValue = Expression.PropertyOrField(rewriter.LeaveResult, "Value");

            //
            // 1. Create jump table.
            //
            var dispatch = rewriter.GetDispatchTable();

            //
            // 2. Count number of expressions needed in resulting block.
            //
            var n = (node.Type == typeof(void) ? 0 : 1) + (dispatch != null ? 1 : 0) + 1;
            var statements = new Expression[n];

            //
            // 3. Store result of call in temporary.
            //
            var i = 0;
            statements[i++] = assignLeaveResult;

            //
            // 4. For non-emptyu dispatch tables, emit the dispatch.
            //
            if (dispatch != null)
            {
                statements[i++] = dispatch;
            }

            //
            // 5. For non-null nodes, extract the result.
            //
            if (node.Type != typeof(void))
            {
                statements[i++] = Expression.Convert(leaveResultValue, node.Type);
            }

            //
            // 6. Put everything together in a block.
            //
            var res = Expression.Block(node.Type, new[] { rewriter.LeaveResult }, statements);
            return res;
        }
 protected internal virtual Expression VisitTry(TryExpression node)
 {
     return(node.Update(this.Visit(node.Body), Visit <CatchBlock>(node.Handlers, new Func <CatchBlock, CatchBlock>(this.VisitCatchBlock)), this.Visit(node.Finally), this.Visit(node.Fault)));
 }
예제 #21
0
        protected override Expression VisitTry(TryExpression node)
        {
            this.WriteLine("try");
            using (this.AcquireIndentationContext(BraceLanguageStyleIndentationOptions.IncludeBraces))
            {
                this.Visit(node.Body);
            }

            foreach (var handler in node.Handlers)
            {
                this.WriteLine();
                this.Write("catch (");
                this.Write(handler.Test.Name);
                this.WriteLine(" exception)");

                using (this.AcquireIndentationContext(BraceLanguageStyleIndentationOptions.IncludeBraces))
                {
                    this.Visit(handler.Body);
                }
            }

            if (node.Finally != null)
            {
                this.WriteLine();
                this.WriteLine("finally");
                using (this.AcquireIndentationContext(BraceLanguageStyleIndentationOptions.IncludeBraces))
                {
                    this.Visit(node.Finally);
                }
            }

            this.WriteLine();

            return node;
        }
예제 #22
0
        protected internal virtual new Expression VisitTry(TryExpression node)
        {
            Contract.Requires(node != null);

            return(default(Expression));
        }
        /// <summary>
        /// Makes an slim expression representing a TryExpression with the given children.
        /// </summary>
        /// <param name="node">Original expression.</param>
        /// <param name="body">Body expression slim.</param>
        /// <param name="finally">Finally expression slim.</param>
        /// <param name="fault">Fault expression slim.</param>
        /// <param name="handlers">Catch handler slims.</param>
        /// <returns>Slim representation of the original expression.</returns>
        protected override ExpressionSlim MakeTry(TryExpression node, ExpressionSlim body, ExpressionSlim @finally, ExpressionSlim fault, ReadOnlyCollection <CatchBlockSlim> handlers)
        {
            var type = MakeType(node.Type);

            return(_factory.MakeTry(type, body, @finally, fault, handlers));
        }
		}//end static method
		internal XElement TryExpressionToXElement(TryExpression e)
		{
			object value;
			string xName = "TryExpression";
			object[] XElementValues = new object[7];
			value = ((TryExpression)e).Type;
			XElementValues[0] = GenerateXmlFromProperty(typeof(System.Type),
				"Type", value ?? string.Empty);
			value = ((TryExpression)e).NodeType;
			XElementValues[1] = GenerateXmlFromProperty(typeof(System.Linq.Expressions.ExpressionType),
				"NodeType", value ?? string.Empty);
			value = ((TryExpression)e).Body;
			XElementValues[2] = GenerateXmlFromProperty(typeof(System.Linq.Expressions.Expression),
				"Body", value ?? string.Empty);
			value = ((TryExpression)e).Handlers;
			XElementValues[3] = GenerateXmlFromProperty(typeof(System.Collections.ObjectModel.ReadOnlyCollection<System.Linq.Expressions.CatchBlock>),
				"Handlers", value ?? string.Empty);
			value = ((TryExpression)e).Finally;
			XElementValues[4] = GenerateXmlFromProperty(typeof(System.Linq.Expressions.Expression),
				"Finally", value ?? string.Empty);
			value = ((TryExpression)e).Fault;
			XElementValues[5] = GenerateXmlFromProperty(typeof(System.Linq.Expressions.Expression),
				"Fault", value ?? string.Empty);
			value = ((TryExpression)e).CanReduce;
			XElementValues[6] = GenerateXmlFromProperty(typeof(System.Boolean),
				"CanReduce", value ?? string.Empty);
			return new XElement(xName, XElementValues);
		}//end static method
 protected internal virtual new Expression VisitTry(TryExpression node)
 {
     return(default(Expression));
 }
예제 #26
0
파일: Try.cs 프로젝트: takeshik/yacq
 internal static Try Try(TryExpression expression)
 {
     return new Try()
     {
         Type = expression.Type != expression.Body.Type
             ? TypeRef.Serialize(expression.Type)
             : null,
         Body = Serialize(expression.Body),
         Handlers = expression.Handlers.Select(CatchBlock.Serialize).ToArray(),
         Fault = expression.Fault.Null(e => Serialize(e)),
         Finally = expression.Finally.Null(e => Serialize(e)),
     }.If(n => n.Type == null, n => n.TypeHint = TypeRef.Serialize(expression.Type));
 }
예제 #27
0
 public TryExpressionProxy(TryExpression node)
 {
     _node = node;
 }
예제 #28
0
        protected override Expression VisitTry(TryExpression node)
        {
            _jumpTables.Push(new List<SwitchCase>());

            var res = base.VisitTry(node);

            var table = _jumpTables.Pop();

            if (table.Count > 0)
            {
                var dispatch = Expression.Switch(_localStateVariable, table.ToArray());

                var originalTry = (TryExpression)res;
                var newTry = originalTry.Update(
                    Expression.Block(
                        dispatch,
                        originalTry.Body
                    ),
                    originalTry.Handlers,
                    RewriteHandler(originalTry.Finally),
                    RewriteHandler(originalTry.Fault)
                );

                var beforeTry = Expression.Label("__enterTry");
                var enterTry = Expression.Goto(beforeTry);

                if (table.Count > 0)
                {
                    var states = new List<Expression>();
                    foreach (var jump in table)
                    {
                        var indexes = jump.TestValues;
                        states.AddRange(indexes);
                    }

                    var previousTable = _jumpTables.Peek();
                    previousTable.Add(Expression.SwitchCase(enterTry, states));
                }

                res = Expression.Block(
                    Expression.Label(beforeTry),
                    newTry
                );
            }

            return res;
        }
 public TryExpressionProxy(TryExpression node)
 {
     ContractUtils.RequiresNotNull(node, nameof(node));
     _node = node;
 }
        private Expression RewriteFaultHandler(TryExpression node)
        {
            //
            // 0. Recurse into the children.
            //
            var body = Visit(node.Body);
            var fault = Visit(node.Fault);

            //
            // 1. Initialize rewriter.
            //
            var rewriter = new HandlerRewriter();

            //
            // 2. Rewrite body and handler.
            //
            var rewrittenTry = rewriter.Rewrite(body)();
            var rewrittenTryHandler = Expression.Lambda<Func<LeaveHandlerData>>(rewrittenTry);
            var rewrittenFaultHandler = Expression.Lambda<Action>(fault);

            //
            // 3. Emit call to TryFault helper.
            //
            var tryFault = Expression.Call(s_tryFault, rewrittenTryHandler, rewrittenFaultHandler);

            //
            // 4. Create resulting expression.
            //
            return CreateRewrittenTry(node, rewriter, tryFault);
        }
        /// <summary>
        /// Evaluates a try expression containing a throw expression in its body at compile time.
        /// </summary>
        /// <param name="node">The try expression to evaluate.</param>
        /// <returns>The original expression if no evaluation took place; otherwise, the result of partial evaluation.</returns>
        private Expression EvaluateTryThrow(TryExpression node)
        {
            var body = node.Body;

            while (AlwaysThrows(body))
            {
                var handlers = node.Handlers;

                var handlerCount = handlers.Count;
                if (handlerCount == 0)
                {
                    break;
                }

                var @throw    = (UnaryExpression)body;
                var exception = @throw.Operand;

                var exceptionType = GetRuntimeExceptionType(exception);
                if (exceptionType == null)
                {
                    break;
                }

                var caught       = default(CatchBlock);
                var handlerIndex = -1;

                for (var i = 0; i < handlerCount; i++)
                {
                    var handler = handlers[i];

                    if (handler.Filter != null)
                    {
                        break; // NB: An earlier rewrite should have taken constant filters out.
                    }

                    if (handler.Test.IsAssignableFrom(exceptionType))
                    {
                        caught       = handler;
                        handlerIndex = i;
                        break;
                    }
                }

                if (caught == null)
                {
                    break;
                }

                var newBody = caught.Body;

                var variable = caught.Variable;
                if (variable != null)
                {
                    // REVIEW: Does this make the new expression potentially much bigger? Alternatively,
                    //         we could just prune unreachable handlers and retain a try..catch.. block.

                    newBody =
                        Expression.Block(
                            new[] { variable },
                            Expression.Assign(variable, exception),
                            newBody
                            );
                }

                var newHandlers = GetRemainingHandlers(handlers, handlerIndex);

                var updated = Update(node, newBody, newHandlers, node.Finally, node.Fault);
                if (updated.NodeType != ExpressionType.Try)
                {
                    return(updated);
                }

                node = (TryExpression)updated;

                body = newBody;
            }

            return(node);
        }
예제 #32
0
 public TryExpressionProxy(TryExpression node) {
     _node = node;
 }
예제 #33
0
        private Variable VisitTry(TryExpression node)
        {
            throw new NotSupportedException("Expression of type " + node.NodeType + " is not supported");

            //this.Out("try { ... }");
        }
예제 #34
0
        protected override Expression VisitTry(TryExpression node)
        {
            var res = default(Expression);

            var type = node.Type;

            var handlers = node.Handlers;
            var n = handlers.Count;

            if (n > 0)
            {
                res = Visit(node.Body);

                var newHandlers = new List<CatchBlock>();

                for (var i = 0; i < n; i++)
                {
                    var handler = handlers[i];

                    var newBody = default(Expression);

                    if (VisitAndFindAwait(handler.Body, out newBody))
                    {
                        if (newHandlers.Count > 0)
                        {
                            res = Expression.MakeTry(type, res, null, null, newHandlers.ToArray());
                            newHandlers.Clear();
                        }

                        var catchExceptionVariable = Expression.Parameter(handler.Test, "__caughtException");
                        var exceptionVariable = handler.Variable ?? Expression.Parameter(handler.Test, "__exception");

                        var handlerBody =
                            Expression.Block(
                                Expression.Assign(exceptionVariable, catchExceptionVariable),
                                Expression.Default(handler.Body.Type)
                            );

                        var newFilter = default(Expression);

                        if (handler.Filter != null)
                        {
                            newFilter = ParameterSubstitutor.Substitute(handler.Filter, exceptionVariable, catchExceptionVariable);
                        }

                        var rethrow = Utils.CreateRethrow(exceptionVariable);
                        newBody = RethrowRewriter.Rewrite(newBody, rethrow);

                        var newHandler = handler.Update(catchExceptionVariable, newFilter, handlerBody);
                        var newTry = Expression.MakeTry(type, res, null, null, new[] { newHandler });

                        if (newTry.Type != typeof(void))
                        {
                            var tryResult = Expression.Parameter(newTry.Type, "__tryValue");

                            res =
                                Expression.Block(
                                    new[] { tryResult, exceptionVariable },
                                    // NB: Assignment with default is important here; the whole node could execute
                                    //     many times, e.g. in the body of a loop, causing the same local to be
                                    //     reused. We don't want to pick up the result of a previous evaluation.
                                    Expression.Assign(exceptionVariable, Expression.Default(exceptionVariable.Type)),
                                    Expression.Assign(tryResult, newTry),
                                    Expression.Condition(
                                        Expression.NotEqual(exceptionVariable, Expression.Default(exceptionVariable.Type)),
                                        newBody,
                                        tryResult
                                    )
                                );
                        }
                        else
                        {
                            res =
                                Expression.Block(
                                    new[] { exceptionVariable },
                                    // NB: Assignment with default is important here; the whole node could execute
                                    //     many times, e.g. in the body of a loop, causing the same local to be
                                    //     reused. We don't want to pick up the result of a previous evaluation.
                                    Expression.Assign(exceptionVariable, Expression.Default(exceptionVariable.Type)),
                                    newTry,
                                    Expression.IfThen(
                                        Expression.NotEqual(exceptionVariable, Expression.Default(exceptionVariable.Type)),
                                        newBody
                                    )
                                );
                        }

                        // TODO: pend/unpend branches out of the handler body
                    }
                    else
                    {
                        newHandlers.Add(handler.Update(handler.Variable, handler.Filter, newBody)); // NB: filters with await are rejected by the Checker
                    }
                }

                if (newHandlers.Count > 0)
                {
                    res = Expression.MakeTry(type, res, null, null, newHandlers.ToArray());
                }

                if (node.Finally != null)
                {
                    res = Expression.MakeTry(type, res, Visit(node.Finally), null, null);
                }

                Debug.Assert(node.Fault == null); // NB: Factories in LINQ prevent the combo of handlers with fault
            }
            else
            {
                res = base.VisitTry(node);
            }

            return res;
        }
예제 #35
0
 public TryExpressionProxy(TryExpression node)
 {
     ContractUtils.RequiresNotNull(node, nameof(node));
     _node = node;
 }
예제 #36
0
        protected override MSAst.Expression VisitTry(MSAst.TryExpression node)
        {
            MSAst.Expression b = Visit(node.Body);
            ReadOnlyCollection <MSAst.CatchBlock> h = Visit(node.Handlers, VisitCatchBlock);

            MSAst.Expression y = Visit(node.Finally);
            MSAst.Expression f;

            _insideConditionalBlock = true;
            try {
                f = Visit(node.Fault);
            } finally {
                _insideConditionalBlock = false;
            }

            node = Ast.MakeTry(node.Type, b, y, f, h);

            List <MSAst.CatchBlock> newHandlers = null;

            MSAst.Expression newFinally = null;

            // If the TryStatement has any Catch blocks we need to insert the exception
            // event as a first statement so that we can be notified of first-chance exceptions.
            if (node.Handlers != null && node.Handlers.Count > 0)
            {
                newHandlers = new List <MSAst.CatchBlock>();

                foreach (var catchBlock in node.Handlers)
                {
                    MSAst.ParameterExpression exceptionVar = catchBlock.Variable != null ? catchBlock.Variable : Ast.Parameter(catchBlock.Test, null);

                    MSAst.Expression debugMarker, thread;
                    if (_transformToGenerator)
                    {
                        debugMarker = Ast.Call(
                            typeof(RuntimeOps).GetMethod("GetCurrentSequencePointForGeneratorFrame"),
                            _frame
                            );

                        thread = Ast.Call(typeof(RuntimeOps).GetMethod("GetThread"), _frame);
                    }
                    else
                    {
                        debugMarker = _debugMarker;
                        thread      = _thread;
                    }

                    MSAst.Expression exceptionEvent = Ast.Block(
                        // Rethrow ForceToGeneratorLoopException
                        AstUtils.If(
                            Ast.TypeIs(
                                exceptionVar,
                                typeof(ForceToGeneratorLoopException)
                                ),
                            Ast.Throw(exceptionVar)
                            ),
                        AstUtils.If(
                            Ast.Equal(_globalDebugMode, AstUtils.Constant((int)DebugMode.FullyEnabled)),
                            (_pushFrame != null) ? _pushFrame : Ast.Empty(),
                            Ast.Call(
                                typeof(RuntimeOps).GetMethod("OnTraceEvent"),
                                thread,
                                debugMarker,
                                exceptionVar
                                )
                            )
                        );

                    newHandlers.Add(Ast.MakeCatchBlock(
                                        catchBlock.Test,
                                        exceptionVar,
                                        Ast.Block(
                                            exceptionEvent,
                                            catchBlock.Body
                                            ),
                                        catchBlock.Filter
                                        ));
                }
            }

            if (!_transformToGenerator && node.Finally != null)
            {
                // Prevent the user finally block from running if the frame is currently remapping to generator
                newFinally = AstUtils.If(
                    Ast.Not(
                        Ast.Call(
                            typeof(RuntimeOps).GetMethod("IsCurrentLeafFrameRemappingToGenerator"),
                            _thread
                            )
                        ),
                    node.Finally
                    );
            }

            if (newHandlers != null || newFinally != null)
            {
                node = Ast.MakeTry(
                    node.Type,
                    node.Body,
                    newFinally != null ? newFinally : node.Finally,
                    node.Fault,
                    newHandlers != null ? newHandlers : newHandlers
                    );
            }

            return(node);
        }
        private static Expression Expand(TryExpression expression)
        {
            var res = expression.Body;

            var handlers = default(List<CatchBlock>);

            foreach (var handler in expression.Handlers)
            {
                if (handler.Filter != null)
                {
                    if (handlers != null)
                    {
                        res = Expression.TryCatch(res, handlers.ToArray());
                        handlers = null;
                    }

                    res = Expression.TryCatch(res, handler);
                }
                else
                {
                    if (handlers == null)
                    {
                        handlers = new List<CatchBlock>();
                    }

                    handlers.Add(handler);
                }
            }

            if (handlers != null)
            {
                res = Expression.TryCatch(res, handlers.ToArray());
            }

            if (expression.Finally != null)
            {
                res = Expression.TryFinally(res, expression.Finally);
            }

            return res;
        }
 protected override Expression VisitTry(TryExpression node)
 {
     throw new NotSupportedException();
 }
예제 #39
0
 protected virtual Expression VisitTry(TryExpression node)
 {
     throw new NotImplementedException();
 }
예제 #40
0
 private static string VisitTry(TryExpression node)
 {
     throw new NotImplementedException();
 }
예제 #41
0
 protected internal override Expression VisitTry(TryExpression node)
 {
     Expressions.Add(node);
     return(base.VisitTry(node));
 }
 protected internal override Expression VisitTry(TryExpression node)
 {
     this.Out("try { ... }");
     return(node);
 }
예제 #43
0
 public TryExpressionProxy(TryExpression node)
 {
     ArgumentNullException.ThrowIfNull(node);
     _node = node;
 }