public static Expression[] VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block) { Expression[] newNodes = null; for (int i = 0, n = block.ExpressionCount; i < n; i++) { var curNode = block.GetExpression(i); var node = visitor.Visit(curNode); if (newNodes != null) { newNodes[i] = node; } else if (node != curNode) { newNodes = new Expression[n]; for (var j = 0; j < i; j++) { newNodes[j] = block.GetExpression(j); } newNodes[i] = node; } } return(newNodes); }
private void Emit(BlockExpression node, EmitAs emitAs) { EnterScope(node); int count = node.ExpressionCount; for (int index = 0; index < count - 1; index++) { var e = node.GetExpression(index); if (_emitDebugSymbols) { //No need to emit a clearance if the next expression in the block is also a //DebugInfoExprssion. var debugInfo = e as DebugInfoExpression; if (debugInfo != null && debugInfo.IsClear && node.GetExpression(index + 1) is DebugInfoExpression) { continue; } } EmitExpressionAsVoid(e); } // if the type of Block it means this is not a Comma // so we will force the last expression to emit as void. if (emitAs == EmitAs.Void || node.Type == typeof(void)) { EmitExpressionAsVoid(node.GetExpression(count - 1)); } else { EmitExpressionAsType(node.GetExpression(count - 1), node.Type); } ExitScope(node); }
private void Emit(BlockExpression node, EmitAs emitAs) { int count = node.ExpressionCount; // Labels defined immediately in the block are valid for the whole block for(int i = 0; i < count; i++) { Expression e = node.GetExpression(i); var label = e as LabelExpression; if (label != null) { DefineLabel(label.Label); } } EnterScope(node); for (int index = 0; index < count - 1; index++) { EmitExpressionAsVoid(node.GetExpression(index)); } // if the type of Block it means this is not a Comma // so we will force the last expression to emit as void. if (emitAs == EmitAs.Void || node.Type == typeof(void)) { EmitExpressionAsVoid(node.GetExpression(count - 1)); } else { EmitExpression(node.GetExpression(count - 1)); } ExitScope(node); }
private void EmitBranchBlock(bool branch, BlockExpression node, Label label) { var innerScopeInfo = GetInnerScope(node, _scope); if (innerScopeInfo.HasValue) { _scope = innerScopeInfo.Value.child.Enter(this, innerScopeInfo.Value.parent); } var count = node.ExpressionCount; for (var i = 0; i < count - 1; i++) { EmitExpressionAsVoid(node.GetExpression(i)); } EmitExpressionAndBranch(branch, node.GetExpression(count - 1), label); if (!innerScopeInfo.HasValue) { return; } innerScopeInfo.Value.child.Exit(); _scope = innerScopeInfo.Value.parent; }
private void Emit(BlockExpression node, CompilationFlags flags) { int count = node.ExpressionCount; if (count == 0) { return; } EnterScope(node); CompilationFlags emitAs = flags & CompilationFlags.EmitAsTypeMask; CompilationFlags tailCall = flags & CompilationFlags.EmitAsTailCallMask; for (int index = 0; index < count - 1; index++) { var e = node.GetExpression(index); var next = node.GetExpression(index + 1); CompilationFlags tailCallFlag; if (tailCall != CompilationFlags.EmitAsNoTail) { var g = next as GotoExpression; if (g != null && (g.Value == null || !Significant(g.Value)) && ReferenceLabel(g.Target).CanReturn) { // Since tail call flags are not passed into EmitTryExpression, CanReturn means the goto will be emitted // as Ret. Therefore we can emit the current expression with tail call. tailCallFlag = CompilationFlags.EmitAsTail; } else { // In the middle of the block. // We may do better here by marking it as Tail if the following expressions are not going to emit any IL. tailCallFlag = CompilationFlags.EmitAsMiddle; } } else { tailCallFlag = CompilationFlags.EmitAsNoTail; } flags = UpdateEmitAsTailCallFlag(flags, tailCallFlag); EmitExpressionAsVoid(e, flags); } // if the type of Block it means this is not a Comma // so we will force the last expression to emit as void. // We don't need EmitAsType flag anymore, should only pass // the EmitTailCall field in flags to emitting the last expression. if (emitAs == CompilationFlags.EmitAsVoidType || node.Type == typeof(void)) { EmitExpressionAsVoid(node.GetExpression(count - 1), tailCall); } else { EmitExpressionAsType(node.GetExpression(count - 1), node.Type, tailCall); } ExitScope(node); }
private void Emit(BlockExpression node, CompilationFlags flags) { EnterScope(node); CompilationFlags emitAs = flags & CompilationFlags.EmitAsTypeMask; int count = node.ExpressionCount; CompilationFlags tailCall = flags & CompilationFlags.EmitAsTailCallMask; CompilationFlags middleTailCall = tailCall == CompilationFlags.EmitAsNoTail ? CompilationFlags.EmitAsNoTail : CompilationFlags.EmitAsMiddle; for (int index = 0; index < count - 1; index++) { var e = node.GetExpression(index); var next = node.GetExpression(index + 1); if (EmitDebugSymbols) { // No need to emit a clearance if the next expression in the block is also a // DebugInfoExprssion. var debugInfo = e as DebugInfoExpression; if (debugInfo != null && debugInfo.IsClear && next is DebugInfoExpression) { continue; } } // In the middle of the block. // We may do better here by marking it as Tail if the following expressions are not going to emit any IL. var tailCallFlag = middleTailCall; var g = next as GotoExpression; if (g != null && (g.Value == null || !Significant(g.Value))) { var labelInfo = ReferenceLabel(g.Target); if (labelInfo.CanReturn) { // Since tail call flags are not passed into EmitTryExpression, CanReturn means the goto will be emitted // as Ret. Therefore we can emit the current expression with tail call. tailCallFlag = CompilationFlags.EmitAsTail; } } flags = UpdateEmitAsTailCallFlag(flags, tailCallFlag); EmitExpressionAsVoid(e, flags); } // if the type of Block it means this is not a Comma // so we will force the last expression to emit as void. // We don't need EmitAsType flag anymore, should only pass // the EmitTailCall field in flags to emitting the last expression. if (emitAs == CompilationFlags.EmitAsVoidType || node.Type == typeof(void)) { EmitExpressionAsVoid(node.GetExpression(count - 1), tailCall); } else { EmitExpressionAsType(node.GetExpression(count - 1), node.Type, tailCall); } ExitScope(node); }
private void Emit(BlockExpression node, CompilationFlags flags) { EnterScope(node); var emitAs = flags & CompilationFlags.EmitAsTypeMask; var count = node.ExpressionCount; var tailCall = flags & CompilationFlags.EmitAsTailCallMask; for (var index = 0; index < count - 1; index++) { var e = node.GetExpression(index); var next = node.GetExpression(index + 1); CompilationFlags tailCallFlag; if (tailCall != CompilationFlags.EmitAsNoTail) { var g = next as GotoExpression; if (g != null && (g.Value == null || !Significant(g.Value)) && ReferenceLabel(g.Target).CanReturn) { // Since tail call flags are not passed into EmitTryExpression, CanReturn means the goto will be emitted // as Ret. Therefore we can emit the current expression with tail call. tailCallFlag = CompilationFlags.EmitAsTail; } else { // In the middle of the block. // We may do better here by marking it as Tail if the following expressions are not going to emit any IL. tailCallFlag = CompilationFlags.EmitAsMiddle; } } else { tailCallFlag = CompilationFlags.EmitAsNoTail; } flags = UpdateEmitAsTailCallFlag(flags, tailCallFlag); EmitExpressionAsVoid(e, flags); } // if the type of Block it means this is not a Comma // so we will force the last expression to emit as void. // We don't need EmitAsType flag anymore, should only pass // the EmitTailCall field in flags to emitting the last expression. if (emitAs == CompilationFlags.EmitAsVoidType || node.Type == typeof(void)) { EmitExpressionAsVoid(node.GetExpression(count - 1), tailCall); } else { EmitExpressionAsType(node.GetExpression(count - 1), node.Type, tailCall); } ExitScope(node); }
private void Emit(BlockExpression node, CompilationFlags flags) { var count = node.ExpressionCount; if (count == 0) { return; } var innerScopeInfo = GetInnerScope(node, _scope); if (innerScopeInfo.HasValue) { _scope = innerScopeInfo.Value.child.Enter(this, innerScopeInfo.Value.parent); } var emitAs = flags & CompilationFlags.EmitAsTypeMask; var tailCall = flags & CompilationFlags.EmitAsTailCallMask; for (var index = 0; index < count - 1; index++) { var e = node.GetExpression(index); var next = node.GetExpression(index + 1); var tailCallFlag = tailCall != CompilationFlags.EmitAsNoTail ? next is GotoExpression g && (g.Value == null || !Significant(g.Value)) && ReferenceLabel(g.Target).CanReturn ? CompilationFlags.EmitAsTail : CompilationFlags.EmitAsMiddle : CompilationFlags.EmitAsNoTail; flags = UpdateEmitAsTailCallFlag(flags, tailCallFlag); EmitExpressionAsVoid(e, flags); } // if the type of Block it means this is not a Comma // so we will force the last expression to emit as void. // We don't need EmitAsType flag anymore, should only pass // the EmitTailCall field in flags to emitting the last expression. if (emitAs == CompilationFlags.EmitAsVoidType || node.Type == typeof(void)) { EmitExpressionAsVoid(node.GetExpression(count - 1), tailCall); } else { EmitExpressionAsType(node.GetExpression(count - 1), node.Type, tailCall); } if (!innerScopeInfo.HasValue) { return; } innerScopeInfo.Value.child.Exit(); _scope = innerScopeInfo.Value.parent; }
private void EmitBranchBlock(bool branch, BlockExpression node, Label label) { EnterScope(node); int count = node.ExpressionCount; for (int i = 0; i < count - 1; i++) { EmitExpressionAsVoid(node.GetExpression(i)); } EmitExpressionAndBranch(branch, node.GetExpression(count - 1), label); ExitScope(node); }
private Expression AddReturn(Expression body, LabelTarget @return) { switch (body.NodeType) { case ExpressionType.Conditional: ConditionalExpression conditional = (ConditionalExpression)body; if (IsDeferExpression(conditional.IfTrue)) { return(Expression.Condition( Expression.Not(conditional.Test), Expression.Return(@return, Helpers.Convert(conditional.IfFalse, @return.Type)), Expression.Empty() )); } else if (IsDeferExpression(conditional.IfFalse)) { return(Expression.Condition( conditional.Test, Expression.Return(@return, Helpers.Convert(conditional.IfTrue, @return.Type)), Expression.Empty() )); } return(Expression.Condition( conditional.Test, AddReturn(conditional.IfTrue, @return), AddReturn(conditional.IfFalse, @return) )); case ExpressionType.Throw: return(body); case ExpressionType.Block: // block could have a throw which we need to run through to avoid // trying to convert it BlockExpression block = (BlockExpression)body; int count = block.ExpressionCount; Expression[] nodes = new Expression[count]; for (int i = 0; i < nodes.Length - 1; i++) { nodes[i] = block.GetExpression(i); } nodes[nodes.Length - 1] = AddReturn(block.GetExpression(count - 1), @return); return(Expression.Block(block.Variables, nodes)); default: return(Expression.Return(@return, Helpers.Convert(body, @return.Type))); } }
// Block private Result RewriteBlockExpression(Expression expr, Stack stack) { BlockExpression node = (BlockExpression)expr; int count = node.ExpressionCount; RewriteAction action = RewriteAction.None; Expression[] clone = null; for (int i = 0; i < count; i++) { Expression expression = node.GetExpression(i); // All statements within the block execute at the // same stack state. Result rewritten = RewriteExpression(expression, stack); action |= rewritten.Action; if (clone == null && rewritten.Action != RewriteAction.None) { clone = Clone(node.Expressions, i); } if (clone != null) { clone[i] = rewritten.Node; } } if (action != RewriteAction.None) { // okay to wrap since we know no one can mutate the clone array expr = node.Rewrite(null, clone); } return(new Result(action, expr)); }
public int IndexOf(Expression item) { if (_arg0 == item) { return(0); } for (int i = 1; i < _block.ExpressionCount; i++) { if (_block.GetExpression(i) == item) { return(i); } } return(-1); }
/// <summary> /// Visits the children of the <see cref="BlockExpression" />. /// </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 VisitBlock(BlockExpression node) { int count = node.ExpressionCount; Expression[] nodes = null; for (int i = 0; i < count; i++) { Expression oldNode = node.GetExpression(i); Expression newNode = Visit(oldNode); if (oldNode != newNode) { if (nodes == null) { nodes = new Expression[count]; } nodes[i] = newNode; } } var v = VisitAndConvert(node.Variables, "VisitBlock"); if (v == node.Variables && nodes == null) { return(node); } else { for (int i = 0; i < count; i++) { if (nodes[i] == null) { nodes[i] = node.GetExpression(i); } } } return(node.Rewrite(v, nodes)); }
private void Emit(BlockExpression node, EmitAs emitAs) { int count = node.ExpressionCount; // Labels defined immediately in the block are valid for the whole block for (int i = 0; i < count; i++) { Expression e = node.GetExpression(i); var label = e as LabelExpression; if (label != null) { DefineLabel(label.Label); } } EnterScope(node); for (int index = 0; index < count - 1; index++) { EmitExpressionAsVoid(node.GetExpression(index)); } // if the type of Block it means this is not a Comma // so we will force the last expression to emit as void. if (emitAs == EmitAs.Void || node.Type == typeof(void)) { EmitExpressionAsVoid(node.GetExpression(count - 1)); } else { EmitExpression(node.GetExpression(count - 1)); } ExitScope(node); }
private void Emit(BlockExpression node, CompilationFlags flags) { int count = node.ExpressionCount; if (count == 0) { return; } EnterScope(node); CompilationFlags emitAs = flags & CompilationFlags.EmitAsTypeMask; CompilationFlags tailCall = flags & CompilationFlags.EmitAsTailCallMask; for (int index = 0; index < count - 1; index++) { Expression e = node.GetExpression(index); Expression next = node.GetExpression(index + 1); CompilationFlags tailCallFlag; if (tailCall != CompilationFlags.EmitAsNoTail) { if (next is GotoExpression g && (g.Value == null || !Significant(g.Value)) && ReferenceLabel(g.Target).CanReturn) { // Since tail call flags are not passed into EmitTryExpression, CanReturn means the goto will be emitted // as Ret. Therefore we can emit the current expression with tail call. tailCallFlag = CompilationFlags.EmitAsTail; } else { // In the middle of the block. // We may do better here by marking it as Tail if the following expressions are not going to emit any IL. tailCallFlag = CompilationFlags.EmitAsMiddle; } }
public static Expression[] VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block) { Expression[] newNodes = null; for (int i = 0, n = block.ExpressionCount; i < n; i++) { Expression curNode = block.GetExpression(i); Expression node = visitor.Visit(curNode); if (newNodes != null) { newNodes[i] = node; } else if (!object.ReferenceEquals(node, curNode)) { newNodes = new Expression[n]; for (int j = 0; j < i; j++) { newNodes[j] = block.GetExpression(j); } newNodes[i] = node; } } return(newNodes); }
private void Emit(BlockExpression node, CompilationFlags flags) { var count = node.ExpressionCount; if (count == 0) { return; } var innerScopeInfo = GetInnerScope(node, _scope); if (innerScopeInfo.HasValue) { _scope = innerScopeInfo.Value.child.Enter(this, innerScopeInfo.Value.parent); } var emitAs = flags & CompilationFlags.EmitAsTypeMask; var tailCall = flags & CompilationFlags.EmitAsTailCallMask; for (var index = 0; index < count - 1; index++) { var e = node.GetExpression(index); var next = node.GetExpression(index + 1); CompilationFlags tailCallFlag; if (tailCall != CompilationFlags.EmitAsNoTail) { if (next is GotoExpression g && (g.Value == null || !Significant(g.Value)) && ReferenceLabel(g.Target).CanReturn) { tailCallFlag = CompilationFlags.EmitAsTail; } else { tailCallFlag = CompilationFlags.EmitAsMiddle; } }
protected internal override Expression VisitBlock(BlockExpression node) { Out(".Block"); // Display <type> if the type of the BlockExpression is different from the // last expression's type in the block. if (node.Type != node.GetExpression(node.ExpressionCount - 1).Type) { Out(String.Format(CultureInfo.CurrentCulture, "<{0}>", node.Type.ToString())); } VisitDeclarations(node.Variables); Out(" "); // Use ; to separate expressions in the block VisitExpressions('{', ';', node.Expressions); return(node); }