Exemplo n.º 1
0
        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);
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 8
0
        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;
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        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)));
            }
        }
Exemplo n.º 11
0
        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);
        }
Exemplo n.º 12
0
        // 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));
        }
Exemplo n.º 13
0
        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);
        }
Exemplo n.º 14
0
        /// <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));
        }
Exemplo n.º 15
0
        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);
        }
Exemplo n.º 16
0
        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;
                    }
                }
Exemplo n.º 17
0
        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);
        }
Exemplo n.º 18
0
        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;
                    }
                }
Exemplo n.º 19
0
        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);
        }
Exemplo n.º 20
0
        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);
        }