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)); }
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)); } }
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); }
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; }