BindToValue() private static method

private static BindToValue ( Expression expr ) : Expression
expr System.Linq.Expressions.Expression
return System.Linq.Expressions.Expression
示例#1
0
        public static Expression NewPhpArray(Expression[] values)
        {
            Expression arr;

            if (values.Length == 0)
            {
                // PhpArray.NewEmpty()
                return(Expression.Call(typeof(PhpArray), "NewEmpty", Cache.Types.Empty)); // CONSIDER: just PhpArray.Empty
            }
            else if (values.Any(IsArgumentUnpacking))
            {
                // TODO: values.Length == 1 && values[0] is PhpArray => return values[0], AddRestriction

                // unpacking
                arr = UnpackArgumentsToArray(null, values);
            }
            else
            {
                // 1:1
                arr = Expression.NewArrayInit(typeof(PhpValue), values.Select(x => ConvertExpression.BindToValue(x)));
            }

            // PhpArray.New( values[] )
            return(Expression.Call(typeof(PhpArray), "New", Cache.Types.Empty, arr));
        }
示例#2
0
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            var restrictions = BindingRestrictions.Empty;

            PhpTypeInfo phptype;
            Expression  target_expr;

            //
            var ctx     = args[0];
            var fldName = ResolveName(args, ref restrictions);

            //
            if (target.LimitType == typeof(PhpTypeInfo))    // static field
            {
                target_expr = null;
                phptype     = (PhpTypeInfo)target.Value;

                //
                restrictions = restrictions.Merge(BindingRestrictions.GetInstanceRestriction(target.Expression, phptype));
            }
            else
            {
                var isobject = BinderHelpers.TryTargetAsObject(target, out DynamicMetaObject instance);
                restrictions = restrictions.Merge(instance.Restrictions);

                if (isobject == false)
                {
                    var defaultexpr = ConvertExpression.BindDefault(_returnType);

                    if (!_access.Quiet())
                    {
                        // PhpException.VariableMisusedAsObject(target, _access.ReadRef)
                        var throwcall = Expression.Call(typeof(PhpException), "VariableMisusedAsObject", Array.Empty <Type>(),
                                                        ConvertExpression.BindToValue(target.Expression), Expression.Constant(_access.EnsureAlias()));
                        defaultexpr = Expression.Block(throwcall, defaultexpr);
                    }

                    return(new DynamicMetaObject(defaultexpr, restrictions));
                }

                phptype     = instance.RuntimeType.GetPhpTypeInfo();
                target_expr = target_expr = Expression.Convert(instance.Expression, instance.RuntimeType);
            }

            Debug.Assert(IsClassConst == (target_expr == null));

            //
            var getter = IsClassConst
                ? BinderHelpers.BindClassConstant(phptype, _classContext, fldName, ctx.Expression)
                : BinderHelpers.BindField(phptype, _classContext, target_expr, fldName, ctx.Expression, _access, null);

            if (getter != null)
            {
                //
                return(new DynamicMetaObject(ConvertExpression.Bind(getter, _returnType, ctx.Expression), restrictions));
            }

            // field not found
            throw new NotImplementedException();
        }
示例#3
0
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            bool hasTargetInstance = (target.LimitType != typeof(TargetTypeParam));

            var bound = new CallSiteContext()
            {
                ClassContext = _classContext,
                Name         = _name
            }
            .ProcessArgs(target, args, hasTargetInstance);

            if (hasTargetInstance)
            {
                var isobject = bound.TargetType != null;
                if (isobject == false)
                {
                    var defaultexpr = ConvertExpression.BindDefault(_returnType);

                    if (!_access.Quiet())
                    {
                        // PhpException.VariableMisusedAsObject(target, _access.ReadRef)
                        var throwcall = Expression.Call(typeof(PhpException), "VariableMisusedAsObject", Array.Empty <Type>(),
                                                        ConvertExpression.BindToValue(target.Expression), Expression.Constant(_access.EnsureAlias()));
                        defaultexpr = Expression.Block(throwcall, defaultexpr);
                    }

                    return(new DynamicMetaObject(defaultexpr, bound.Restrictions));
                }

                // instance := (T)instance
                bound.TargetInstance = Expression.Convert(bound.TargetInstance, bound.TargetType.Type.AsType());
            }

            Debug.Assert(IsClassConst ? (bound.TargetInstance == null) : true);

            //
            var getter = IsClassConst
                ? BinderHelpers.BindClassConstant(bound.TargetType, bound.ClassContext, bound.Name, bound.Context)
                : BinderHelpers.BindField(bound.TargetType, bound.ClassContext, bound.TargetInstance, bound.Name, bound.Context, _access, null);

            if (getter != null)
            {
                //
                return(new DynamicMetaObject(ConvertExpression.Bind(getter, _returnType, bound.Context), bound.Restrictions));
            }

            // field not found
            throw new NotImplementedException();
        }
示例#4
0
        /// <summary>
        /// In case the method has [return: CastToFalse],
        /// the return value -1 or null is converted to false.
        /// </summary>
        static Expression BindCastToFalse(Expression expr, bool hasCastToFalse)
        {
            if (hasCastToFalse)
            {
                var        x      = Expression.Variable(expr.Type);
                var        assign = Expression.Assign(x, expr); // x = <expr>
                Expression test;

                if (expr.Type == typeof(int) || expr.Type == typeof(long))
                {
                    // Template: test = x >= 0
                    test = Expression.GreaterThanOrEqual(assign, Expression.Constant(0));
                }
                else if (expr.Type == typeof(double))
                {
                    // Template: test = x >= 0.0
                    test = Expression.GreaterThanOrEqual(assign, Expression.Constant(0.0));
                }
                else if (expr.Type == typeof(PhpString))
                {
                    // Template: test = !x.IsDefault
                    test = Expression.Not(Expression.Property(assign, Cache.PhpString.IsDefault));
                }
                else if (expr.Type.GetTypeInfo().IsValueType == false)  // reference type
                {
                    // Template: test = x != null
                    test = Expression.ReferenceNotEqual(assign, Expression.Constant(null, assign.Type));
                }
                else
                {
                    Debug.Fail($"[CastToFalse] for an unexpected type {expr.Type.ToString()}.");
                    return(expr);
                }

                // Template: test ? (PhpValue)x : PhpValue.False
                expr = Expression.Condition(
                    test,
                    ConvertExpression.BindToValue(x),
                    Expression.Property(null, Cache.Properties.PhpValue_False));

                //
                return(Expression.Block(
                           expr.Type,
                           new[] { x },
                           new[] { expr }));
            }

            return(expr);
        }
示例#5
0
        /// <summary>
        /// In case the method has [return: CastToFalse],
        /// the return value -1 or null is converted to false.
        /// </summary>
        static Expression BindCastToFalse(Expression expr, bool hasCastToFalse)
        {
            if (hasCastToFalse)
            {
                var        x      = Expression.Variable(expr.Type);
                var        assign = Expression.Assign(x, expr); // x = <expr>
                Expression test;

                if (expr.Type == typeof(int) || expr.Type == typeof(long))
                {
                    // Template: test = x >= 0
                    test = Expression.GreaterThanOrEqual(assign, Expression.Constant(0));
                }
                else if (expr.Type == typeof(double))
                {
                    // Template: test = x >= 0.0
                    test = Expression.GreaterThanOrEqual(assign, Expression.Constant(0.0));
                }
                else if (expr.Type == typeof(PhpString))
                {
                    // Template: test = !x.IsDefault
                    test = Expression.Not(Expression.Property(assign, Cache.PhpString.IsDefault));
                }
                else if (expr.Type.GetTypeInfo().IsValueType == false)  // reference type
                {
                    // Template: test = x != null
                    test = Expression.ReferenceNotEqual(assign, Expression.Constant(null, assign.Type));
                }
                else
                {
                    Debug.Fail($"[CastToFalse] for an unexpected type {expr.Type.ToString()}.");
                    return(expr);
                }

                // Template: test ? (PhpValue)x : PhpValue.False
                expr = Expression.Condition(
                    test,
                    ConvertExpression.BindToValue(x),
                    Expression.Property(null, Cache.Properties.PhpValue_False));

                //
                return(Expression.Block(
                           expr.Type,
                           new[] { x },
                           new[] { expr }));
            }
            //else if (expr.Type.IsNullable_T(out var t)) // Nullable -> Value | False
            //{
            //    // Template:
            //    //   tmp = expr
            //    //   tmp.HasValue ? tmp.GetValueOrDefault() : FALSE

            //    var tmp = Expression.Variable(expr.Type);
            //    var assign = Expression.Assign(tmp, expr);    // tmp = <expr>
            //    var test = Expression.Property(assign, "HasValue");

            //    expr = Expression.Condition(
            //        test,
            //        ifTrue: ConvertExpression.BindToValue(Expression.Call(tmp, expr.Type.GetMethod("GetValueOrDefault", Array.Empty<Type>()))),
            //        ifFalse: Expression.Property(null, Cache.Properties.PhpValue_False));

            //    //
            //    return Expression.Block(
            //        expr.Type,
            //        new[] { tmp },
            //        new[] { expr });
            //}

            return(expr);
        }
示例#6
0
        public static Expression UnpackArgumentsToArray(MethodBase[] methods, Expression[] arguments)
        {
            //if (arguments.Length == 1 && IsArgumentUnpacking(arguments[0]))
            //{
            //    // Template: (...$arg0)
            //    // TODO: if (arg0 is PhpArray) return arg0.ToArray();
            //}

            // create byrefs mask: (but mask of parameters passed by ref)
            ulong byrefs = 0uL;

            if (methods != null)
            {
                foreach (var m in methods)
                {
                    var ps   = m.GetParameters();
                    var skip = ps.TakeWhile(IsImplicitParameter).Count();

                    for (int i = skip; i < ps.Length; i++)
                    {
                        if (ps[i].ParameterType == typeof(PhpAlias))
                        {
                            byrefs |= (1uL << (i - skip));
                        }
                    }
                }
            }

            // List<PhpValue> list;
            var list_var    = Expression.Variable(typeof(List <PhpValue>), "list");
            var exprs       = new List <Expression>();
            var byrefs_expr = Expression.Constant(byrefs);

            // list = new List<PhpValue>( LENGTH )
            exprs.Add(Expression.Assign(list_var, Expression.New(list_var.Type.GetConstructor(Cache.Types.Int), Expression.Constant(arguments.Length))));

            // arguments.foreach(  Unpack(list, arg_i)  );
            foreach (var arg in arguments)
            {
                if (IsArgumentUnpacking(arg))
                {
                    Expression unpackexpr;

                    // Template: Operators.Unpack(list, arg, byrefs)

                    // Unpack(List<PhpValue> stack, PhpValue|PhpArray|Traversable argument, ulong byrefs)

                    var arg_value = Expression.Field(arg, "Value"); // UnpackingParam<>.Value

                    //if (typeof(PhpArray).IsAssignableFrom(arg_value.Type)) // TODO
                    //{

                    //}
                    //else if (typeof(Traversable).IsAssignableFrom(arg_value.Type)) // TODO
                    //{

                    //}
                    //else // PhpValue
                    {
                        unpackexpr = Expression.Call(
                            typeof(Operators), "Unpack", Cache.Types.Empty,
                            list_var, ConvertExpression.BindToValue(arg_value), byrefs_expr);
                    }

                    exprs.Add(unpackexpr);
                }
                else
                {
                    // list.Add((PhpValue)arg)
                    exprs.Add(Expression.Call(list_var, "Add", Cache.Types.Empty, ConvertExpression.BindToValue(arg)));
                }
            }

            // return list.ToArray()
            exprs.Add(Expression.Call(list_var, "ToArray", Cache.Types.Empty));

            //
            return(Expression.Block(new[] { list_var }, exprs));
        }