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)); }
/// <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)); }
/// <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) )); }
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); }
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)); }
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))); }
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; }
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)); }
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)); }
public TryExpressionProxy(TryExpression node) { _node = node; }
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); }
private Variable VisitTry(TryExpression node) { throw new NotSupportedException("Expression of type " + node.NodeType + " is not supported"); //this.Out("try { ... }"); }
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; }
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(); }
protected virtual Expression VisitTry(TryExpression node) { throw new NotImplementedException(); }
private static string VisitTry(TryExpression node) { throw new NotImplementedException(); }
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); }
public TryExpressionProxy(TryExpression node) { ArgumentNullException.ThrowIfNull(node); _node = node; }