示例#1
0
        // Just splat the args and dispatch through a nested site
        public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel) {
            Debug.Assert(args.Length == 2);

            int count = ((object[])args[1]).Length;
            ParameterExpression array = parameters[1];

            var nestedArgs = new ReadOnlyCollectionBuilder<Expression>(count + 1);
            var delegateArgs = new Type[count + 3]; // args + target + returnType + CallSite
            nestedArgs.Add(parameters[0]);
            delegateArgs[0] = typeof(CallSite);
            delegateArgs[1] = typeof(object);
            for (int i = 0; i < count; i++) {
                nestedArgs.Add(Expression.ArrayAccess(array, Expression.Constant(i)));
                delegateArgs[i + 2] = typeof(object).MakeByRefType();
            }
            delegateArgs[delegateArgs.Length - 1] = typeof(object);

            return Expression.IfThen(
                Expression.Equal(Expression.ArrayLength(array), Expression.Constant(count)),
                Expression.Return(
                    returnLabel,
                    Expression.MakeDynamic(
                        Expression.GetDelegateType(delegateArgs),
                        new ComInvokeAction(new CallInfo(count)),
                        nestedArgs
                    )
                )
            );
        }
示例#2
0
 public override Expression Bind(object[] args, System.Collections.ObjectModel.ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel) {
     //For this sample, we just always return a constant.
     return Expression.Return(
         returnLabel,
         Expression.Constant((int)args[0] + (int)args[1])
     );
 }
 private LabelInfo EnsureLabel(LabelTarget node) {
     LabelInfo result;
     if (!_labelInfo.TryGetValue(node, out result)) {
         _labelInfo.Add(node, result = new LabelInfo(_ilg, node, false));
     }
     return result;
 }
 private LabelInfo DefineLabel(LabelTarget node) {
     if (node == null) {
         return new LabelInfo(_ilg, null, false);
     }
     LabelInfo result = EnsureLabel(node);
     result.Define(_ilg, _labelBlock);
     return result;
 }
示例#5
0
        internal LabelInfo(ILGen il, LabelTarget node, bool canReturn) {
            _ilg = il;
            Node = node;
            Label = il.DefineLabel();
            _canReturn = canReturn;
            if (node != null && node.Type != typeof(void)) {
                Value = il.DeclareLocal(node.Type);
            }

            // Until we have more information, default to a leave instruction, which always works
            _opCode = OpCodes.Leave;
        }
示例#6
0
        public LambdaExpression Generate(Subroutine sub, bool is_main)
        {
            IsMain = is_main;
            SubLabel = Expression.Label(typeof(IP5Any));

            for (int i = 0; i < sub.BasicBlocks.Count; ++i)
                if (sub.BasicBlocks[i] != null)
                    BlockLabels[sub.BasicBlocks[i]] = Expression.Label("L" + i.ToString());

            var scopes = GenerateScopes(sub);

            var vars = new List<ParameterExpression>();
            AddVars(vars, Variables);
            AddVars(vars, Lexicals);
            AddVars(vars, Temporaries);
            AddVars(vars, LexStates);
            AddVars(vars, RxStates);

            var block = Expression.Block(typeof(IP5Any), vars, scopes);
            var args = new ParameterExpression[] { Runtime, Context, Pad, Arguments };
            return Expression.Lambda<P5Code.Sub>(Expression.Label(SubLabel, block), args);
        }
 /// <summary>
 /// Creates a <see cref="GotoExpression"/> representing a break statement with the specified type.
 /// </summary>
 /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
 /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
 /// <returns>
 /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break, 
 /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>, 
 /// and the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>.
 /// </returns>
 public static GotoExpression Break(LabelTarget target, Type type) {
     return MakeGoto(GotoExpressionKind.Break, target, null, type);
 }
 private static void AddFuncHandlerExpressions(PredicateAndHandler handler, List <Expression> body, Expression argumentExpression, LabelTarget returnTarget)
 {
     //Add this code to the body:
     //    if(func(castedValue))
     //    {
     //      return true;
     //    }
     body.Add(
         Expression.IfThen(
             Expression.Invoke(handler.ActionOrFuncExpression, argumentExpression),
             Expression.Return(returnTarget, Expression.Constant(true))
             ));
 }
示例#9
0
 internal LabelInfo(ILGenerator il, LabelTarget node, bool canReturn) {
     _ilg = il;
     _node = node;
     _canReturn = canReturn;
 }
 /// <summary>
 /// Creates a new expression that is like this one, but using the
 /// supplied children. If all of the children are the same, it will
 /// return this expression.
 /// </summary>
 /// <param name="target">The <see cref="Target" /> property of the result.</param>
 /// <param name="defaultValue">The <see cref="DefaultValue" /> property of the result.</param>
 /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
 public LabelExpression Update(LabelTarget target, Expression defaultValue) {
     if (target == Target && defaultValue == DefaultValue) {
         return this;
     }
     return Expression.Label(target, defaultValue);
 }
 /// <summary>
 /// Creates a new expression that is like this one, but using the
 /// supplied children. If all of the children are the same, it will
 /// return this expression.
 /// </summary>
 /// <param name="breakLabel">The <see cref="BreakLabel" /> property of the result.</param>
 /// <param name="continueLabel">The <see cref="ContinueLabel" /> property of the result.</param>
 /// <param name="body">The <see cref="Body" /> property of the result.</param>
 /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
 public LoopExpression Update(LabelTarget breakLabel, LabelTarget continueLabel, Expression body) {
     if (breakLabel == BreakLabel && continueLabel == ContinueLabel && body == Body) {
         return this;
     }
     return Expression.Loop(body, breakLabel, continueLabel);
 }
 /// <summary>
 /// Creates a <see cref="LoopExpression"/> with the given body.
 /// </summary>
 /// <param name="body">The body of the loop.</param>
 /// <param name="break">The break target used by the loop body.</param>
 /// <param name="continue">The continue target used by the loop body.</param>
 /// <returns>The created <see cref="LoopExpression"/>.</returns>
 public static LoopExpression Loop(Expression body, LabelTarget @break, LabelTarget @continue) {
     RequiresCanRead(body, "body");
     ContractUtils.Requires(@continue == null || @continue.Type == typeof(void), "continue", Strings.LabelTypeMustBeVoid);
     return new LoopExpression(body, @break, @continue);
 }
 /// <summary>
 /// Creates a <see cref="GotoExpression"/> representing a jump of the specified <see cref="GotoExpressionKind"/>.
 /// The value passed to the label upon jumping can also be specified.
 /// </summary>
 /// <param name="kind">The <see cref="GotoExpressionKind"/> of the <see cref="GotoExpression"/>.</param>
 /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
 /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
 /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
 /// <returns>
 /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to <paramref name="kind"/>, 
 /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>, 
 /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
 /// and <paramref name="value"/> to be passed to the target label upon jumping.
 /// </returns>
 public static GotoExpression MakeGoto(GotoExpressionKind kind, LabelTarget target, Expression value, Type type) {
     ValidateGoto(target, ref value, "target", "value");
     return new GotoExpression(kind, target, value, type);
 }
示例#14
0
 protected override LabelTarget VisitLabelTarget(LabelTarget node)
 {
     return(GiveUp(node));
 }
示例#15
0
 private static ConditionalExpression IfNullThenReturnExpression(ParameterExpression inputParameter, LabelTarget endLabel)
 {
     //// Expression output:
     ////
     //// if (input == null)
     //// {
     ////     return null;
     //// }
     return
         (Expression.IfThen(
              Expression.Equal(
                  inputParameter,
                  Expression.Constant(null, ObjectType)),
              Expression.Return(endLabel)));
 }
示例#16
0
        private bool TryPushLabelBlock(Expression node)
        {
            // Anything that is "statement-like" -- e.g. has no associated
            // stack state can be jumped into, with the exception of try-blocks
            // We indicate this by a "Block"
            //
            // Otherwise, we push an "Expression" to indicate that it can't be
            // jumped into
            switch (node.NodeType)
            {
            default:
                if (_labelBlock.Kind != LabelScopeKind.Expression)
                {
                    PushLabelBlock(LabelScopeKind.Expression);
                    return(true);
                }
                return(false);

            case ExpressionType.Label:
                // LabelExpression is a bit special, if it's directly in a
                // block it becomes associate with the block's scope. Same
                // thing if it's in a switch case body.
                if (_labelBlock.Kind == LabelScopeKind.Block)
                {
                    LabelTarget label = ((LabelExpression)node).Target;
                    if (_labelBlock.ContainsTarget(label))
                    {
                        return(false);
                    }
                    if (_labelBlock.Parent !.Kind == LabelScopeKind.Switch &&
                        _labelBlock.Parent.ContainsTarget(label))
                    {
                        return(false);
                    }
                }
                PushLabelBlock(LabelScopeKind.Statement);
                return(true);

            case ExpressionType.Block:
                if (node is SpilledExpressionBlock)
                {
                    // treat it as an expression
                    goto default;
                }

                PushLabelBlock(LabelScopeKind.Block);
                // Labels defined immediately in the block are valid for
                // the whole block.
                if (_labelBlock.Parent !.Kind != LabelScopeKind.Switch)
                {
                    DefineBlockLabels(node);
                }
                return(true);

            case ExpressionType.Switch:
                PushLabelBlock(LabelScopeKind.Switch);
                // Define labels inside of the switch cases so they are in
                // scope for the whole switch. This allows "goto case" and
                // "goto default" to be considered as local jumps.
                var @switch = (SwitchExpression)node;
                foreach (SwitchCase c in @switch.Cases)
                {
                    DefineBlockLabels(c.Body);
                }
                DefineBlockLabels(@switch.DefaultBody);
                return(true);

            // Remove this when Convert(Void) goes away.
            case ExpressionType.Convert:
                if (node.Type != typeof(void))
                {
                    // treat it as an expression
                    goto default;
                }
                PushLabelBlock(LabelScopeKind.Statement);
                return(true);

            case ExpressionType.Conditional:
            case ExpressionType.Loop:
            case ExpressionType.Goto:
                PushLabelBlock(LabelScopeKind.Statement);
                return(true);
            }
        }
示例#17
0
        internal override Expression GetExpression(List <ParameterExpression> parameters, Dictionary <string, ConstantExpression> locals, List <DataContainer> dataContainers, Type dynamicContext, LabelTarget label)
        {
            Expression exp;

            if (ConstructorType != null)
            {
                if (Constructor != null)
                {
                    ParameterInfo[]   info = Constructor.GetParameters();
                    List <Expression> args = new List <Expression>();
                    for (int i = 0; i < info.Length; ++i)
                    {
                        args.Add(Expression.Dynamic(Binder.Convert(CSharpBinderFlags.None, info[i].ParameterType, dynamicContext ?? typeof(object)), info[i].ParameterType, Arguments.Arguments[i].GetExpression(parameters, locals, dataContainers, dynamicContext, label)));
                    }
                    exp = Expression.New(Constructor, args);
                }
                else
                {
                    exp = Expression.New(ConstructorType);
                }
                if (Initializers != null)
                {
                    if (Initializers.Arguments.Any(token => token is AssignmentToken))
                    {
                        Func <MemberInfo, Type> getType = mem => mem is FieldInfo ? (mem as FieldInfo).FieldType : (mem as PropertyInfo).PropertyType;
                        var inits = Initializers.Arguments.Cast <AssignmentToken>().Select(token => new Tuple <MemberInfo, Expression>(token.Member, Expression.Dynamic(Binder.Convert(CSharpBinderFlags.None, getType(token.Member), dynamicContext ?? typeof(object)), getType(token.Member), token.Value.GetExpression(parameters, locals, dataContainers, dynamicContext, label))));
                        exp = Expression.MemberInit(exp as NewExpression, inits.Select(init => (MemberBinding)Expression.Bind(init.Item1, init.Item2)));
                    }
                    else
                    {
                        exp = Expression.ListInit(exp as NewExpression, ConvertInitializers(Initializers, parameters, locals, dataContainers, dynamicContext, null, label).Cast <ElementInit>());
                    }
                }
            }
            else
            {
                if (Initializers != null)
                {
                    CallSiteBinder binder = Binder.Convert(CSharpBinderFlags.None, ArrayType, dynamicContext ?? typeof(object));
                    exp = Expression.NewArrayInit(ArrayType, Initializers.Arguments.Select(token => Expression.Dynamic(binder, ArrayType, token.GetExpression(parameters, locals, dataContainers, dynamicContext, label))));
                }
                else
                {
                    CallSiteBinder binder = Binder.Convert(CSharpBinderFlags.None, typeof(int), dynamicContext ?? typeof(object));
                    exp = Expression.NewArrayBounds(ArrayType, Arguments.Arguments.Select(token => Expression.Dynamic(binder, typeof(int), token.GetExpression(parameters, locals, dataContainers, dynamicContext, label))));
                }
            }
            return(Expression.Convert(exp, typeof(object)));
        }
示例#18
0
 private IEnumerable <object> ConvertInitializers(ArgumentListToken arguments, List <ParameterExpression> parameters, Dictionary <string, ConstantExpression> locals, List <DataContainer> dataContainers, Type dynamicContext, Type[] expectedTypes, LabelTarget label)
 {
     foreach (TokenBase token in arguments.Arguments)
     {
         if (token is ArgumentListToken)
         {
             MethodInfo   add  = Constructor.DeclaringType.GetMethods(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(m => m.Name == "Add" && m.GetParameters().Length == (token as ArgumentListToken).Arguments.Length);
             int          i    = 0;
             Expression[] exps = new Expression[add.GetParameters().Length];
             foreach (ParameterInfo info in add.GetParameters())
             {
                 CallSiteBinder binder = Binder.Convert(CSharpBinderFlags.None, info.ParameterType, dynamicContext);
                 exps[i] = Expression.Dynamic(binder, info.ParameterType, (token as ArgumentListToken).Arguments[i++].GetExpression(parameters, locals, dataContainers, dynamicContext, label));
             }
             yield return(Expression.ElementInit(add, exps));
         }
         else
         {
             MethodInfo     add    = Constructor.DeclaringType.GetMethods(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(m => m.Name == "Add" && m.GetParameters().Length == 1);
             CallSiteBinder binder = Binder.Convert(CSharpBinderFlags.None, add.GetParameters()[0].ParameterType, dynamicContext);
             yield return(Expression.ElementInit(add, Expression.Dynamic(binder, add.GetParameters()[0].ParameterType, token.GetExpression(parameters, locals, dataContainers, dynamicContext, label))));
         }
     }
 }
示例#19
0
        private static void IfNullThenReturnNullExpression(ParameterExpression inputParameter, LabelTarget endLabel, List <Expression> expressions)
        {
            ///// Intended code:
            /////
            ///// if (input == null)
            ///// {
            /////     return null;
            ///// }

            var ifNullThenReturnNullExpression =
                Expression.IfThen(
                    Expression.Equal(
                        inputParameter,
                        Expression.Constant(null, ObjectType)),
                    Expression.Return(endLabel));

            expressions.Add(ifNullThenReturnNullExpression);
        }
 /// <summary>
 /// Creates a <see cref="GotoExpression"/> representing a return statement with the specified type.
 /// </summary>
 /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
 /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
 /// <returns>
 /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Return, 
 /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>, 
 /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
 /// and a null value to be passed to the target label upon jumping.
 /// </returns>
 public static GotoExpression Return(LabelTarget target, Type type) {
     return MakeGoto(GotoExpressionKind.Return, target, null, type);
 }
 /// <summary>
 /// Creates a <see cref="GotoExpression"/> representing a goto.
 /// </summary>
 /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
 /// <returns>
 /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto, 
 /// the <see cref="P:GotoExpression.Target"/> property set to the specified value, 
 /// and a null value to be passed to the target label upon jumping.
 /// </returns>
 public static GotoExpression Goto(LabelTarget target) {
     return MakeGoto(GotoExpressionKind.Goto, target, null, typeof(void));
 }
示例#22
0
        public static WhileExpression While(Expression test, Expression body, LabelTarget breakTarget, LabelTarget continueTarget)
        {
            if (test == null)
            {
                throw new ArgumentNullException("test");
            }
            if (body == null)
            {
                throw new ArgumentNullException("body");
            }

            if (test.Type != typeof(bool))
            {
                throw new ArgumentException("Test must be a boolean expression", "test");
            }

            if (continueTarget != null && continueTarget.Type != typeof(void))
            {
                throw new ArgumentException("Continue label target must be void", "continueTarget");
            }

            return(new WhileExpression(test, body, breakTarget, continueTarget));
        }
 internal GotoExpression(GotoExpressionKind kind, LabelTarget target, Expression value, Type type) {
     _kind = kind;
     _value = value;
     _target = target;
     _type = type;
 }
示例#24
0
 internal WhileExpression(Expression test, Expression body, LabelTarget breakTarget, LabelTarget continueTarget)
 {
     this.test            = test;
     this.body            = body;
     this.break_target    = breakTarget;
     this.continue_target = continueTarget;
 }
 /// <summary>
 /// Creates a <see cref="LoopExpression"/> with the given body.
 /// </summary>
 /// <param name="body">The body of the loop.</param>
 /// <param name="break">The break target used by the loop body.</param>
 /// <param name="continue">The continue target used by the loop body.</param>
 /// <returns>The created <see cref="LoopExpression"/>.</returns>
 public static LoopExpression Loop(Expression body, LabelTarget @break, LabelTarget @continue) {
     RequiresCanRead(body, "body");
     if (@continue != null && @continue.Type != typeof(void)) throw Error.LabelTypeMustBeVoid();
     return new LoopExpression(body, @break, @continue);
 }
示例#26
0
        public WhileExpression Update(Expression test, Expression body, LabelTarget breakTarget, LabelTarget continueTarget)
        {
            if (this.test == test && this.body == body && this.break_target == breakTarget && this.continue_target == continueTarget)
            {
                return(this);
            }

            return(CustomExpression.While(test, body, breakTarget, continueTarget));
        }
 /// <summary>
 /// Creates a <see cref="LabelExpression"/> representing a label with the given default value.
 /// </summary>
 /// <param name="target">The <see cref="LabelTarget"/> which this <see cref="LabelExpression"/> will be associated with.</param>
 /// <param name="defaultValue">The value of this <see cref="LabelExpression"/> when the label is reached through normal control flow.</param>
 /// <returns>A <see cref="LabelExpression"/> with the given default value.</returns>
 public static LabelExpression Label(LabelTarget target, Expression defaultValue) {
     ValidateGoto(target, ref defaultValue, "label", "defaultValue");
     return new LabelExpression(target, defaultValue);
 }
示例#28
0
 bool IEvaluatableExpressionFilter.IsEvaluatableLabelTarget(LabelTarget node) => true;
示例#29
0
        internal bool TryGetLabelInfo(LabelTarget target, out LabelInfo info) {
            if (Labels == null) {
                info = null;
                return false;
            }

            return Labels.TryGetValue(target, out info);
        }
示例#30
0
 /// <summary>
 /// Performs the runtime binding of the dynamic operation on a set of arguments.
 /// </summary>
 /// <param name="args">An array of arguments to the dynamic operation.</param>
 /// <param name="parameters">The array of <see cref="ParameterExpression"/> instances that represent the parameters of the call site in the binding process.</param>
 /// <param name="returnLabel">A LabelTarget used to return the result of the dynamic binding.</param>
 /// <returns>
 /// An Expression that performs tests on the dynamic operation arguments, and
 /// performs the dynamic operation if hte tests are valid. If the tests fail on
 /// subsequent occurrences of the dynamic operation, Bind will be called again
 /// to produce a new <see cref="Expression"/> for the new argument types.
 /// </returns>
 public abstract Expression Bind(object[] args, ReadOnlyCollection <ParameterExpression> parameters, LabelTarget returnLabel);
 private LabelInfo ReferenceLabel(LabelTarget node) {
     LabelInfo result = EnsureLabel(node);
     result.Reference(_labelBlock);
     return result;
 }
示例#32
0
    private static Action <object, TextWriter> CreateDumper(Type type)
    {
        MethodInfo writeLine1Obj        = typeof(TextWriter).GetMethod("WriteLine", new[] { typeof(object) });
        MethodInfo writeLine1String2Obj = typeof(TextWriter).GetMethod("WriteLine", new[] { typeof(string), typeof(object), typeof(object) });

        ParameterExpression objParam        = Expression.Parameter(typeof(object), "o");
        ParameterExpression outputParam     = Expression.Parameter(typeof(TextWriter), "output");
        ParameterExpression objVariable     = Expression.Variable(type, "o2");
        LabelTarget         returnTarget    = Expression.Label();
        List <Expression>   bodyExpressions = new List <Expression>();

        bodyExpressions.Add(
            // o2 = (<type>)o
            Expression.Assign(objVariable, Expression.Convert(objParam, type)));

        bodyExpressions.Add(
            // output.WriteLine(o)
            Expression.Call(outputParam, writeLine1Obj, objParam));

        var properties =
            from prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
            where prop.CanRead &&
            !prop.GetIndexParameters().Any()        // exclude indexed properties to keep things simple
            select prop;

        foreach (var prop in properties)
        {
            bool isNullable =
                !prop.PropertyType.IsValueType ||
                prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>);
            // (object)o2.<property> (cast to object to be passed to WriteLine)
            Expression propValue =
                Expression.Convert(
                    Expression.Property(objVariable, prop),
                    typeof(object));

            if (isNullable)
            {
                // (<propertyValue> ?? "null")
                propValue =
                    Expression.Coalesce(
                        propValue,
                        Expression.Constant("null", typeof(object)));
            }

            bodyExpressions.Add(
                // output.WriteLine("\t{0}: {1}", "<propertyName>", <propertyValue>)
                Expression.Call(
                    outputParam,
                    writeLine1String2Obj,
                    Expression.Constant("\t{0}: {1}", typeof(string)),
                    Expression.Constant(prop.Name, typeof(string)),
                    propValue));
        }

        bodyExpressions.Add(Expression.Label(returnTarget));

        Expression <Action <object, TextWriter> > dumperExpr =
            Expression.Lambda <Action <object, TextWriter> >(
                Expression.Block(new[] { objVariable }, bodyExpressions),
                objParam,
                outputParam);

        return(dumperExpr.Compile());
    }
        // Generates code for predicateAndHandlers and adds it to bodyExpressions
        private static void AddCodeForHandlers(List <PredicateAndHandler> predicateAndHandlers, List <Expression> bodyExpressions, Expression castedValueExpression, LabelTarget returnTarget, Expression inputValueExpression)
        {
            foreach (var predicateAndHandler in predicateAndHandlers)
            {
                var valueExpression = predicateAndHandler.HandlerFirstArgumentShouldBeBaseType ? inputValueExpression : castedValueExpression;
                switch (predicateAndHandler.HandlerKind)
                {
                case HandlerKind.Action:
                    AddActionHandlerExpressions(predicateAndHandler, bodyExpressions, valueExpression, returnTarget);
                    break;

                case HandlerKind.ActionWithPredicate:
                    AddActionHandlerWithPredicateExpressions(predicateAndHandler, bodyExpressions, valueExpression, returnTarget);
                    break;

                case HandlerKind.Func:
                    AddFuncHandlerExpressions(predicateAndHandler, bodyExpressions, valueExpression, returnTarget);
                    break;

                default:
                    throw new ArgumentOutOfRangeException(
                              $"This should not happen. The value {typeof(HandlerKind)}.{predicateAndHandler.HandlerKind} is a new enum value that has been added without updating the code in this method.");
                }
            }
        }
示例#34
0
        public void NonVoidTargetReturnHasNoValueTypeExplicit(Type type)
        {
            LabelTarget target = Expression.Label(type);

            AssertExtensions.Throws <ArgumentException>("target", () => Expression.Return(target, type));
        }
 /// <summary>
 /// Creates a <see cref="GotoExpression"/> representing a continue statement with the specified type.
 /// </summary>
 /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
 /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
 /// <returns>
 /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue, 
 /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>, 
 /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
 /// and a null value to be passed to the target label upon jumping.
 /// </returns>
 public static GotoExpression Continue(LabelTarget target, Type type) {
     return MakeGoto(GotoExpressionKind.Continue, target, null, type);
 }
示例#36
0
 protected override LabelTarget VisitLabelTarget(LabelTarget node)
 {
     return(base.VisitLabelTarget(node));
 }
 /// <summary>
 /// Creates a <see cref="GotoExpression"/> representing a return statement. The value passed to the label upon jumping can be specified.
 /// </summary>
 /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
 /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
 /// <returns>
 /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue, 
 /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>, 
 /// and <paramref name="value"/> to be passed to the target label upon jumping.
 /// </returns>
 public static GotoExpression Return(LabelTarget target, Expression value) {
     return MakeGoto(GotoExpressionKind.Return, target, value, typeof(void));
 }
示例#38
0
 public LightExceptionRewrittenCode(LabelTarget target, Expression body)
 {
     _returnLabel = target;
     _body        = body;
 }
 /// <summary>
 /// Creates a <see cref="GotoExpression"/> representing a goto with the specified type.
 /// The value passed to the label upon jumping can be specified.
 /// </summary>
 /// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
 /// <param name="value">The value that will be passed to the associated label upon jumping.</param>
 /// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
 /// <returns>
 /// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto, 
 /// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>, 
 /// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
 /// and <paramref name="value"/> to be passed to the target label upon jumping.
 /// </returns>
 public static GotoExpression Goto(LabelTarget target, Expression value, Type type) {
     return MakeGoto(GotoExpressionKind.Goto, target, value, type);
 }
示例#40
0
 protected override LabelTarget VisitLabelTarget(LabelTarget node)
 {
     Console.WriteLine($"call {MethodBase.GetCurrentMethod().Name} : {node}");
     return(base.VisitLabelTarget(node));
 }
 private static void ValidateGoto(LabelTarget target, ref Expression value, string targetParameter, string valueParameter) {
     ContractUtils.RequiresNotNull(target, targetParameter);
     if (value == null) {
         if (target.Type != typeof(void)) throw Error.LabelMustBeVoidOrHaveExpression();
     } else {
         ValidateGotoType(target.Type, ref value, valueParameter);
     }
 }
 public static WhileExpression While(Expression test, Expression body, LabelTarget breakTarget) =>
 While(test, body, breakTarget, null);
        /// <summary>
        /// Performs the runtime binding of the dynamic operation on a set of arguments.
        /// </summary>
        /// <param name="args">An array of arguments to the dynamic operation.</param>
        /// <param name="parameters">The array of <see cref="ParameterExpression"/> instances that represent the parameters of the call site in the binding process.</param>
        /// <param name="returnLabel">A LabelTarget used to return the result of the dynamic binding.</param>
        /// <returns>
        /// An Expression that performs tests on the dynamic operation arguments, and
        /// performs the dynamic operation if hte tests are valid. If the tests fail on
        /// subsequent occurrences of the dynamic operation, Bind will be called again
        /// to produce a new <see cref="Expression"/> for the new argument types.
        /// </returns>
        public sealed override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel) {
            ContractUtils.RequiresNotNull(args, "args");
            ContractUtils.RequiresNotNull(parameters, "parameters");
            ContractUtils.RequiresNotNull(returnLabel, "returnLabel");
            if (args.Length == 0) {
                throw Error.OutOfRange("args.Length", 1);
            }
            if (parameters.Count == 0) {
                throw Error.OutOfRange("parameters.Count", 1);
            }
            if (args.Length != parameters.Count) {
                throw new ArgumentOutOfRangeException("args");
            }

            // Ensure that the binder's ReturnType matches CallSite's return
            // type. We do this so meta objects and language binders can
            // compose trees together without needing to insert converts.
            Type expectedResult;
            if (IsStandardBinder) {
                expectedResult = ReturnType;

                if (returnLabel.Type != typeof(void) &&
                    !TypeUtils.AreReferenceAssignable(returnLabel.Type, expectedResult)) {
                    throw Error.BinderNotCompatibleWithCallSite(expectedResult, this, returnLabel.Type);
                }
            } else {
                // Even for non-standard binders, we have to at least make sure
                // it works with the CallSite's type to build the return.
                expectedResult = returnLabel.Type;
            }

            DynamicMetaObject target = DynamicMetaObject.Create(args[0], parameters[0]);
            DynamicMetaObject[] metaArgs = CreateArgumentMetaObjects(args, parameters);

            DynamicMetaObject binding = Bind(target, metaArgs);

            if (binding == null) {
                throw Error.BindingCannotBeNull();
            }

            Expression body = binding.Expression;
            BindingRestrictions restrictions = binding.Restrictions;

            // Ensure the result matches the expected result type.
            if (expectedResult != typeof(void) &&
                !TypeUtils.AreReferenceAssignable(expectedResult, body.Type)) {

                //
                // Blame the last person that handled the result: assume it's
                // the dynamic object (if any), otherwise blame the language.
                //
                if (target.Value is IDynamicMetaObjectProvider) {
                    throw Error.DynamicObjectResultNotAssignable(body.Type, target.Value.GetType(), this, expectedResult);
                } else {
                    throw Error.DynamicBinderResultNotAssignable(body.Type, this, expectedResult);
                }
            }

            // if the target is IDO, standard binders ask it to bind the rule so we may have a target-specific binding. 
            // it makes sense to restrict on the target's type in such cases.
            // ideally IDO metaobjects should do this, but they often miss that type of "this" is significant.
            if (IsStandardBinder && args[0] as IDynamicMetaObjectProvider != null) {
                if (restrictions == BindingRestrictions.Empty) {
                    throw Error.DynamicBindingNeedsRestrictions(target.Value.GetType(), this);
                }
            }

            restrictions = AddRemoteObjectRestrictions(restrictions, args, parameters);

            // Add the return
            if (body.NodeType != ExpressionType.Goto) {
                body = Expression.Return(returnLabel, body);
            }

            // Finally, add restrictions
            if (restrictions != BindingRestrictions.Empty) {
                body = Expression.IfThen(restrictions.ToExpression(), body);
            }

            return body;
        }
 internal WhileExpression(Expression test, Expression body, LabelTarget breakTarget, LabelTarget continueTarget)
 {
     Test           = test;
     Body           = body;
     BreakTarget    = breakTarget;
     ContinueTarget = continueTarget;
 }
 /// <summary>
 /// Creates a <see cref="LoopExpression"/> with the given body and break target.
 /// </summary>
 /// <param name="body">The body of the loop.</param>
 /// <param name="break">The break target used by the loop body.</param>
 /// <returns>The created <see cref="LoopExpression"/>.</returns>
 public static LoopExpression Loop(Expression body, LabelTarget @break) {
     return Loop(body, @break, null);
 }
示例#46
0
 /// <summary>
 /// Visits the children of <see cref="System.Linq.Expressions.LabelTarget"/>.
 /// </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 override LabelTarget VisitLabelTarget(LabelTarget node)
 {
     throw new NotSupportedException(string.Format(Resources.EX_PROCESS_NODE_NOT_SUPPORT, node.GetType().Name));
 }
 internal LoopExpression(Expression body, LabelTarget @break, LabelTarget @continue) {
     _body = body;
     _break = @break;
     _continue = @continue;
 }
示例#48
0
        // Just splat the args and dispatch through a nested site
        public override Expression Bind(object[] args, ReadOnlyCollection <ParameterExpression> parameters, LabelTarget returnLabel)
        {
            Debug.Assert(args.Length == 2);

            int count = ((object[])args[1]).Length;
            ParameterExpression array = parameters[1];

            var nestedArgs   = new ReadOnlyCollectionBuilder <Expression>(count + 1);
            var delegateArgs = new Type[count + 3]; // args + target + returnType + CallSite

            nestedArgs.Add(parameters[0]);
            delegateArgs[0] = typeof(CallSite);
            delegateArgs[1] = typeof(object);
            for (int i = 0; i < count; i++)
            {
                nestedArgs.Add(Expression.ArrayAccess(array, Expression.Constant(i)));
                delegateArgs[i + 2] = typeof(object).MakeByRefType();
            }
            delegateArgs[delegateArgs.Length - 1] = typeof(object);

            return(Expression.IfThen(
                       Expression.Equal(Expression.ArrayLength(array), Expression.Constant(count)),
                       Expression.Return(
                           returnLabel,
                           Expression.MakeDynamic(
                               Expression.GetDelegateType(delegateArgs),
                               new ComInvokeAction(new CallInfo(count)),
                               nestedArgs
                               )
                           )
                       ));
        }
 /// <summary>
 /// Creates a <see cref="LabelExpression"/> representing a label with no default value.
 /// </summary>
 /// <param name="target">The <see cref="LabelTarget"/> which this <see cref="LabelExpression"/> will be associated with.</param>
 /// <returns>A <see cref="LabelExpression"/> with no default value.</returns>
 public static LabelExpression Label(LabelTarget target) {
     return Label(target, null);
 }
 internal LabelInfo(LabelTarget node)
 {
     _node = node;
 }
 internal LabelExpression(LabelTarget label, Expression defaultValue) {
     _target = label;
     _defaultValue = defaultValue;
 }
示例#52
0
        public TemplatedForeachExpression(Expression enumerable, Expression loopVariable, Expression beforeAll, Expression before, Expression odd, Expression even, Expression between, Expression after, Expression afterAll, Expression each, Expression noData, LabelTarget breakLabel, Expression loopIndex)
        {
            if (enumerable == null)
            {
                throw new ArgumentNullException(nameof(enumerable));
            }
            if (!typeof(IEnumerable).IsAssignableFrom(enumerable.Type))
            {
                throw new ArgumentOutOfRangeException(nameof(enumerable));
            }

            if (loopVariable == null)
            {
                throw new ArgumentNullException(nameof(loopVariable));
            }
            if (loopIndex == null)
            {
                throw new ArgumentNullException(nameof(loopIndex));
            }
            if (breakLabel == null)
            {
                throw new ArgumentNullException(nameof(breakLabel));
            }

            Enumerable   = enumerable;
            LoopVariable = loopVariable;
            LoopIndex    = loopIndex;
            BeforeAll    = beforeAll;
            Before       = before;
            Odd          = odd;
            Even         = even;
            Between      = between;
            After        = after;
            AfterAll     = afterAll;
            Each         = each;
            NoData       = noData;
            _break       = breakLabel;
        }
示例#53
0
        internal bool ContainsTarget(LabelTarget target) {
            if (Labels == null) {
                return false;
            }

            return Labels.ContainsKey(target);
        }
示例#54
0
        public void NonVoidTargetContinueHasNoValueTypeExplicit(Type type)
        {
            LabelTarget target = Expression.Label(type);

            Assert.Throws <ArgumentException>("target", () => Expression.Continue(target, type));
        }
示例#55
0
        internal void AddLabelInfo(LabelTarget target, LabelInfo info) {
            Debug.Assert(CanJumpInto);

            if (Labels == null) {
                Labels = new Dictionary<LabelTarget, LabelInfo>();
            }

            Labels.Add(target, info);
        }
示例#56
0
        protected override Expression VisitTry(TryExpression node)
        {
            // Visit finally/fault block first
            BlockInfo block = new BlockInfo {
                InFinally = true
            };

            _blocks.Push(block);
            Expression @finally = Visit(node.Finally);
            Expression fault    = Visit(node.Fault);

            block.InFinally = false;

            LabelTarget finallyEnd = block.FlowLabel;

            if (finallyEnd != null)
            {
                if (@finally != null)
                {
                    @finally = Expression.Label(finallyEnd, @finally);
                }
                if (fault != null)
                {
                    fault = Expression.Label(finallyEnd, fault);
                }
                // Make a new target, which will be emitted after the try
                block.FlowLabel = Expression.Label();
            }

            Expression         @try     = Visit(node.Body);
            IList <CatchBlock> handlers = Visit(node.Handlers, VisitCatchBlock);

            _blocks.Pop();

            if (@try == node.Body &&
                handlers == node.Handlers &&
                @finally == node.Finally &&
                fault == node.Fault)
            {
                return(node);
            }

            if (!block.HasFlow)
            {
                return(Expression.MakeTry(@try, @finally, fault, handlers));
            }

            //  If there is a control flow in finally, emit outer:
            //  try {
            //      // try block body and all catch handling
            //  } catch (Exception all) {
            //      saved = all;
            //  } finally {
            //      finally_body
            //      if (saved != null) {
            //          throw saved;
            //      }
            //  }
            //
            //  If we have a fault handler we turn this into the better:
            //  try {
            //      // try block body and all catch handling
            //  } catch (Exception all) {
            //      saved = all;
            //      fault_body
            //      throw saved
            //  }

            if (handlers.Count > 0)
            {
                @try = Expression.MakeTry(@try, null, null, handlers);
            }

            var all = Expression.Variable(typeof(Exception), "$exception");

            if (@finally != null)
            {
                handlers = new[] { Expression.Catch(all.Type, Expression.Empty()) };
                @finally = Expression.Block(
                    @finally,
                    Expression.Condition(
                        Expression.NotEqual(all, Expression.Constant(null, all.Type)),
                        Expression.Throw(all),
                        Expression.Empty()
                        )
                    );
            }
            else
            {
                handlers = new[] {
                    Expression.Catch(
                        all.Type,
                        Expression.Block(fault, Expression.Throw(all))
                        )
                };
                fault = null;
            }

            // Emit flow control
            return(Expression.Block(
                       new ParameterExpression[] { all },
                       Expression.MakeTry(@try, @finally, fault, handlers),
                       Expression.Label(block.FlowLabel),
                       MakeFlowControlSwitch(block)
                       ));
        }
示例#57
0
        public void NonVoidTargetGotoHasNoValueTypeExplicit(Type type)
        {
            LabelTarget target = Expression.Label(type);

            Assert.Throws <ArgumentException>(() => Expression.Goto(target, type));
        }
        private static void AddActionHandlerExpressions(PredicateAndHandler handler, List <Expression> body, Expression argumentExpression, LabelTarget returnTarget)
        {
            //Add the action as an argument, and get the expression for retrieving it

            //Adds this code to the body:
            //    action(arg);
            //    return true;
            body.Add(Expression.Invoke(handler.ActionOrFuncExpression, argumentExpression));
            body.Add(Expression.Return(returnTarget, Expression.Constant(true)));
        }
示例#59
0
 public override Expression Compile(ParameterExpression stateParameterExpression, LabelTarget returnTarget)
 {
     return(this.AssignmentTarget.Compile(stateParameterExpression, returnTarget, this.Expression));
 }
 private static void AddActionHandlerWithPredicateExpressions(PredicateAndHandler handler, List <Expression> body, Expression argumentExpression, LabelTarget returnTarget)
 {
     //Add this code to the body:
     //    if(predicate(arg))
     //    {
     //      action(arg);
     //      return true;
     //    }
     body.Add(
         Expression.IfThen(
             Expression.Invoke(handler.PredicateExpression, argumentExpression),
             Expression.Block(
                 Expression.Invoke(handler.ActionOrFuncExpression, argumentExpression),
                 Expression.Return(returnTarget, Expression.Constant(true))
                 )));
 }