BindDefault() public static méthode

public static BindDefault ( Type t ) : Expression
t System.Type
Résultat System.Linq.Expressions.Expression
Exemple #1
0
                public override Expression BindArgument(int srcarg, ParameterInfo targetparam = null)
                {
                    Debug.Assert(srcarg >= 0);

                    if (TryBindArgument(srcarg, targetparam?.ParameterType, out var expr))
                    {
                        return(expr);
                    }
                    else
                    {
                        if (targetparam != null)
                        {
                            if (targetparam.HasDefaultValue)
                            {
                                return(ConvertExpression.Bind(Expression.Constant(targetparam.DefaultValue), targetparam.ParameterType, _ctx));
                            }
                            else
                            {
                                var defaultValueAttr = targetparam.GetCustomAttribute <DefaultValueAttribute>();
                                if (defaultValueAttr != null)
                                {
                                    return(ConvertExpression.Bind(BindDefaultValue(targetparam.Member.DeclaringType, defaultValueAttr), targetparam.ParameterType, _ctx));
                                }
                            }

                            //
                            return(ConvertExpression.BindDefault(targetparam.ParameterType));
                        }

                        return(Expression.Constant(null, typeof(object)));
                    }
                }
Exemple #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();
        }
Exemple #3
0
        protected override Expression BindMissingMethod(CallSiteContext bound)
        {
            if (bound.TargetType == null)   // already reported - class cannot be found
            {
                return(ConvertExpression.BindDefault(this.ReturnType));
            }

            var call = BinderHelpers.FindMagicMethod(bound.TargetType, (bound.TargetInstance == null) ? TypeMethods.MagicMethods.__callstatic : TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName;

                // T.__callStatic(name, array)
                var call_args = new Expression[]
                {
                    name_expr,
                    BinderHelpers.NewPhpArray(bound.Arguments),
                };
                return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, true, lateStaticType: bound.TargetType));
            }

            //
            return(base.BindMissingMethod(bound));
        }
Exemple #4
0
        protected override Expression BindMissingMethod(CallSiteContext bound)
        {
            var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName;

            // resolve target expression:
            var isobject = bound.TargetType != null;

            if (isobject == false)
            {
                /* Template:
                 * PhpException.MethodOnNonObject(name_expr); // aka PhpException.Throw(Error, method_called_on_non_object, name_expr)
                 * return NULL;
                 */
                var throwcall = Expression.Call(typeof(PhpException), "MethodOnNonObject", Array.Empty <Type>(), ConvertExpression.Bind(name_expr, typeof(string), bound.Context));
                return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
            }

            var call = BinderHelpers.FindMagicMethod(bound.TargetType, TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                // target.__call(name, array)
                var call_args = new Expression[]
                {
                    name_expr,
                    BinderHelpers.NewPhpArray(bound.Arguments),
                };
                return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, false));
            }

            return(base.BindMissingMethod(bound));
        }
                public override Expression BindArgument(int srcarg, ParameterInfo targetparam = null)
                {
                    Debug.Assert(srcarg >= 0);

                    if (srcarg < _args.Length)
                    {
                        var expr = _args[srcarg];

                        return((targetparam != null)
                            ? ConvertExpression.Bind(expr, targetparam.ParameterType, _ctx)
                            : expr);
                    }
                    else
                    {
                        if (targetparam != null)
                        {
                            if (targetparam.HasDefaultValue)
                            {
                                return(ConvertExpression.Bind(Expression.Constant(targetparam.DefaultValue), targetparam.ParameterType, _ctx));
                            }
                            else if (targetparam.GetCustomAttribute <DefaultValueAttribute>() != null)
                            {
                                // TODO: DefaultValueAttribute
                                //Debug.Fail("default value lost");
                            }

                            return(ConvertExpression.BindDefault(targetparam.ParameterType));
                        }

                        return(Expression.Constant(null, typeof(object)));
                    }
                }
Exemple #6
0
                public override Expression BindArgument(int srcarg, ParameterInfo targetparam = null)
                {
                    Debug.Assert(srcarg >= 0);

                    if (srcarg < _args.Length)
                    {
                        var expr = _args[srcarg];

                        return((targetparam != null)
                            ? ConvertExpression.Bind(expr, targetparam.ParameterType, _ctx)
                            : expr);
                    }
                    else
                    {
                        if (targetparam != null)
                        {
                            if (targetparam.HasDefaultValue)
                            {
                                return(ConvertExpression.Bind(Expression.Constant(targetparam.DefaultValue), targetparam.ParameterType, _ctx));
                            }

                            return(ConvertExpression.BindDefault(targetparam.ParameterType));
                        }

                        return(Expression.Constant(null, typeof(object)));
                    }
                }
Exemple #7
0
                public override Expression BindArgument(int srcarg, ParameterInfo targetparam = null)
                {
                    Debug.Assert(srcarg >= 0);

                    // cache the argument value

                    var key = new TmpVarKey()
                    {
                        Priority = 0 /*first*/, ArgIndex = srcarg, Prefix = "arg"
                    };
                    TmpVarValue value;

                    if (!_tmpvars.TryGetValue(key, out value))
                    {
                        value = new TmpVarValue();

                        value.TrueInitializer  = Expression.ArrayIndex(_argsarray, Expression.Constant(srcarg));
                        value.FalseInitializer = ConvertExpression.BindDefault(value.TrueInitializer.Type); // ~ default(_argsarray.Type.GetElementType())
                        value.Expression       = Expression.Variable(value.TrueInitializer.Type, "arg_" + srcarg);

                        //
                        _tmpvars[key] = value;
                    }

                    if (targetparam != null)
                    {
                        // create specialized variable with default value
                        if (targetparam.HasDefaultValue)
                        {
                            var @default         = targetparam.DefaultValue;
                            var defaultValueExpr = Expression.Constant(@default);
                            var defaultValueStr  = (@default != null) ? @default.ToString() : "NULL";

                            //
                            var key2 = new TmpVarKey()
                            {
                                Priority = 1 /*after key*/, ArgIndex = srcarg, Prefix = "arg(" + defaultValueStr + ")"
                            };
                            TmpVarValue value2;
                            if (!_tmpvars.TryGetValue(key2, out value2))
                            {
                                value2 = new TmpVarValue();

                                value2.TrueInitializer  = ConvertExpression.Bind(value.Expression, targetparam.ParameterType, _ctx);   // reuse the value already obtained from argv
                                value2.FalseInitializer = ConvertExpression.Bind(defaultValueExpr, value2.TrueInitializer.Type, _ctx); // ~ default(targetparam)
                                value2.Expression       = Expression.Variable(value2.TrueInitializer.Type, "arg_" + srcarg + "_" + defaultValueStr);

                                //
                                _tmpvars[key2] = value2;
                            }

                            return(value2.Expression);   // already converted to targetparam.ParameterType
                        }
                    }

                    return((targetparam == null)
                        ? value.Expression
                        : ConvertExpression.Bind(value.Expression, targetparam.ParameterType, _ctx));
                }
Exemple #8
0
        protected virtual Expression BindMissingMethod(CallSiteContext bound)
        {
            /* Template:
             * PhpException.UndefinedFunctionCalled(name); // aka PhpException.Throw(Error, undefined_function_called, name)
             * return NULL;
             */
            var throwcall = Expression.Call(typeof(PhpException), "UndefinedFunctionCalled", Array.Empty <Type>(), bound.IndirectName ?? Expression.Constant(bound.Name));

            return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
        }
Exemple #9
0
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            bool hasTargetInstance = (target.LimitType != typeof(TargetTypeParam));

            var bound = new CallSiteContext(!hasTargetInstance)
            {
                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 = BinderHelpers.VariableMisusedAsObject(target.Expression, _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);
            }

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

            if (IsClassConst)
            {
                // error: constant not defined
                // ...
            }

            // unreachable: property not found
            throw new InvalidOperationException($"{bound.TargetType.Name}::{bound.Name} could not be resolved.");
        }
Exemple #10
0
        protected virtual Expression BindMissingMethod(CallSiteContext bound)
        {
            /* Template:
             * PhpException.UndefinedFunctionCalled(name);
             * return NULL;
             */
            var throwcall = bound.TargetType != null
                ? Expression.Call(typeof(PhpException), "UndefinedMethodCalled", Array.Empty <Type>(), Expression.Constant(bound.TargetType.Name), bound.IndirectName ?? Expression.Constant(bound.Name))
                : Expression.Call(typeof(PhpException), "UndefinedFunctionCalled", Array.Empty <Type>(), bound.IndirectName ?? Expression.Constant(bound.Name));

            return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
        }
        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();
        }
Exemple #12
0
        protected override Expression BindMissingMethod(CallSiteContext bound)
        {
            var type = bound.TargetType;

            if (type == null)   // already reported - class cannot be found
            {
                return(ConvertExpression.BindDefault(this.ReturnType));
            }

            if (bound.TargetInstance != null && bound.CurrentTargetInstance != null) // it has been checked it is a subclass of TargetType
            {
                // ensure current scope's __call() is favoured over the specified class
                type = bound.CurrentTargetInstance.GetPhpTypeInfo();
            }

            var call = BinderHelpers.FindMagicMethod(type, (bound.TargetInstance == null) ? TypeMethods.MagicMethods.__callstatic : TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                Expression[] call_args;

                var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName;

                if (call.Methods.All(IsClrMagicCallWithParams))
                {
                    // Template: target.__call(name, arg1, arg2, ...)
                    // flatterns the arguments:
                    call_args = ArrayUtils.AppendRange(name_expr, bound.Arguments);
                }
                else
                {
                    // Template: target.__call(name, array)
                    // regular PHP behavior:
                    call_args = new Expression[]
                    {
                        name_expr,
                        BinderHelpers.NewPhpArray(bound.Arguments, bound.Context, bound.ClassContext),
                    };
                }

                return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args,
                                                       isStaticCallSyntax: true,
                                                       lateStaticType: bound.TargetType,
                                                       classContext: bound.ClassContext));
            }

            //
            return(base.BindMissingMethod(bound));
        }
Exemple #13
0
        protected override Expression BindMissingMethod(CallSiteContext bound)
        {
            var name_expr = (_name != null) ? Expression.Constant(_name) : bound.IndirectName;

            // resolve target expression:
            var isobject = bound.TargetType != null;

            if (isobject == false)
            {
                /* Template:
                 * PhpException.MethodOnNonObject(name_expr);
                 * return NULL;
                 */
                var throwcall = Expression.Call(typeof(PhpException), "MethodOnNonObject", Array.Empty <Type>(), ConvertExpression.Bind(name_expr, typeof(string), bound.Context));
                return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
            }

            var call = BinderHelpers.FindMagicMethod(bound.TargetType, TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                Expression[] call_args;

                if (call.Methods.All(IsClrMagicCallWithParams))
                {
                    // Template: target.__call(name, arg1, arg2, ...)
                    // flatterns the arguments:
                    call_args = ArrayUtils.AppendRange(name_expr, bound.Arguments);
                }
                else
                {
                    // Template: target.__call(name, array)
                    // regular PHP behavior:
                    call_args = new Expression[]
                    {
                        name_expr,
                        BinderHelpers.NewPhpArray(bound.Arguments, bound.Context, bound.ClassContext),
                    };
                }

                return(OverloadBinder.BindOverloadCall(_returnType, bound.TargetInstance, call.Methods, bound.Context, call_args, false));
            }

            return(base.BindMissingMethod(bound));
        }
Exemple #14
0
        protected override Expression BindMissingMethod(DynamicMetaObject ctx, PhpTypeInfo tinfo, DynamicMetaObject nameMeta, DynamicMetaObject target, IList <DynamicMetaObject> args, ref BindingRestrictions restrictions)
        {
            var name_expr = (_name != null) ? Expression.Constant(_name) : nameMeta?.Expression;

            // resolve target expression:
            Expression target_expr;
            object     target_value;

            BinderHelpers.TargetAsObject(target, out target_expr, out target_value, ref restrictions);

            if (target_value == null)
            {
                /* Template:
                 * PhpException.MethodOnNonObject(name_expr); // aka PhpException.Throw(Error, method_called_on_non_object, name_expr)
                 * return NULL;
                 */
                var throwcall = Expression.Call(typeof(PhpException), "MethodOnNonObject", Array.Empty <Type>(), ConvertExpression.Bind(name_expr, typeof(string), ctx.Expression));
                return(Expression.Block(throwcall, ConvertExpression.BindDefault(this.ReturnType)));
            }

            Debug.Assert(ReflectionUtils.IsClassType(target_value.GetType().GetTypeInfo()));

            tinfo = target_value.GetPhpTypeInfo();

            var call = BinderHelpers.FindMagicMethod(tinfo, TypeMethods.MagicMethods.__call);

            if (call != null)
            {
                // target.__call(name, array)
                var call_args = new Expression[]
                {
                    name_expr,
                    BinderHelpers.NewPhpArray(ctx.Expression, args.Select(a => a.Expression)),
                };
                return(OverloadBinder.BindOverloadCall(_returnType, target.Expression, call.Methods, ctx.Expression, call_args));
            }

            return(base.BindMissingMethod(ctx, tinfo, nameMeta, target, args, ref restrictions));
        }
Exemple #15
0
                public override Expression BindArgument(int srcarg, ParameterInfo targetparam = null)
                {
                    Debug.Assert(srcarg >= 0);

                    // cache the argument value

                    var key = new TmpVarKey()
                    {
                        Priority = 0 /*first*/, ArgIndex = srcarg, Prefix = "arg"
                    };
                    TmpVarValue value;

                    if (!_tmpvars.TryGetValue(key, out value))
                    {
                        value = new TmpVarValue();

                        value.TrueInitializer  = Expression.ArrayIndex(_argsarray, Expression.Constant(srcarg));
                        value.FalseInitializer = ConvertExpression.BindDefault(value.TrueInitializer.Type); // ~ default(_argsarray.Type.GetElementType())
                        value.Expression       = Expression.Variable(value.TrueInitializer.Type, "arg_" + srcarg);

                        //
                        _tmpvars[key] = value;
                    }

                    if (targetparam != null)
                    {
                        DefaultValueAttribute defaultValueAttr = null;

                        // create specialized variable with default value
                        if (targetparam.HasDefaultValue || (defaultValueAttr = targetparam.GetCustomAttribute <DefaultValueAttribute>()) != null)
                        {
                            Debug.Assert(!targetparam.ParameterType.IsByRef);   // parameter with a default value cannot be byref (at least we don't expect it)

                            // just for debugging purposes:
                            var defaultValueStr = defaultValueAttr != null
                                ? defaultValueAttr.FieldName
                                : targetparam.DefaultValue?.ToString() ?? "NULL";

                            // the default value expression
                            var defaultValueExpr = defaultValueAttr != null
                                ? BindDefaultValue(targetparam.Member.DeclaringType, defaultValueAttr)
                                : Expression.Constant(targetparam.DefaultValue);

                            //
                            var key2 = new TmpVarKey()
                            {
                                Priority = 1 /*after key*/, ArgIndex = srcarg, Prefix = "default(" + defaultValueStr + ")"
                            };
                            TmpVarValue value2;
                            if (!_tmpvars.TryGetValue(key2, out value2))
                            {
                                value2 = new TmpVarValue();

                                value2.TrueInitializer  = ConvertExpression.Bind(value.Expression, targetparam.ParameterType, _ctx);   // reuse the value already obtained from argv
                                value2.FalseInitializer = ConvertExpression.Bind(defaultValueExpr, value2.TrueInitializer.Type, _ctx); // ~ default(targetparam)
                                value2.Expression       = Expression.Variable(value2.TrueInitializer.Type, "default_" + srcarg + "_" + defaultValueStr);

                                //
                                _tmpvars[key2] = value2;
                            }

                            return(value2.Expression);   // already converted to targetparam.ParameterType
                        }
                    }

                    if (targetparam == null)
                    {
                        return(value.Expression);
                    }
                    else
                    {
                        var ptype = targetparam.ParameterType;

                        // TODO: ptype.IsByRef -> implement write-back after the invocation
                        if (ptype.IsByRef)
                        {
                            ptype = ptype.GetElementType(); // LINQ will create a local variable for it implicitly
                        }

                        return(ConvertExpression.Bind(value.Expression, ptype, _ctx));
                    }
                }
Exemple #16
0
        static Expression BindAccess(Expression expr, Expression ctx, AccessMask access, Expression rvalue)
        {
            if (access.EnsureObject())
            {
                if (expr.Type == typeof(PhpAlias))
                {
                    // ((PhpAlias)fld).EnsureObject()
                    expr = Expression.Call(expr, Cache.Operators.PhpAlias_EnsureObject);
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // ((PhpValue)fld).EnsureObject()
                    expr = Expression.Call(expr, Cache.Operators.PhpValue_EnsureObject);
                }
                else
                {
                    // getter // TODO: ensure it is not null
                    Debug.Assert(!expr.Type.GetTypeInfo().IsValueType);
                }
            }
            else if (access.EnsureArray())
            {
                if (expr.Type == typeof(PhpAlias))
                {
                    // ((PhpAlias)fld).EnsureArray()
                    expr = Expression.Call(expr, Cache.Operators.PhpAlias_EnsureArray);
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // ((PhpValue)fld).EnsureArray()
                    expr = Expression.Call(expr, Cache.Operators.PhpValue_EnsureArray);
                }
                else if (expr.Type == typeof(PhpArray))
                {
                    // (PhpArray)fld // TODO: ensure it is not null
                }
                else
                {
                    // getter
                }
            }
            else if (access.EnsureAlias())
            {
                if (expr.Type == typeof(PhpAlias))
                {
                    // (PhpAlias)getter
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // ((PhpValue)fld).EnsureAlias()
                    expr = Expression.Call(expr, Cache.Operators.PhpValue_EnsureAlias);
                }
                else
                {
                    // getter // cannot read as reference
                }
            }
            else if (access.WriteAlias())
            {
                // write alias

                Debug.Assert(rvalue.Type == typeof(PhpAlias));
                rvalue = ConvertExpression.Bind(rvalue, typeof(PhpAlias), ctx);

                if (expr.Type == typeof(PhpAlias))
                {
                    // ok
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // fld = PhpValue.Create(alias)
                    rvalue = Expression.Call(typeof(PhpValue).GetMethod("Create", Cache.Types.PhpAlias), rvalue);
                }
                else
                {
                    // fld is not aliasable
                    Debug.Assert(false, "Cannot assign aliased value to field of type " + expr.Type.ToString());
                    rvalue = ConvertExpression.Bind(rvalue, expr.Type, ctx);
                }

                expr = Expression.Assign(expr, rvalue);
            }
            else if (access.Unset())
            {
                Debug.Assert(rvalue == null);

                expr = Expression.Assign(expr, ConvertExpression.BindDefault(expr.Type));
            }
            else if (access.Write())
            {
                // write by value

                if (expr.Type == typeof(PhpAlias))
                {
                    // Template: fld.Value = (PhpValue)value
                    expr = Expression.Assign(Expression.PropertyOrField(expr, "Value"), ConvertExpression.Bind(rvalue, typeof(PhpValue), ctx));
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // Template: Operators.SetValue(ref fld, (PhpValue)value)
                    expr = Expression.Call(Cache.Operators.SetValue_PhpValueRef_PhpValue, expr, ConvertExpression.Bind(rvalue, typeof(PhpValue), ctx));
                }
                else
                {
                    // Template: fld = value
                    // default behaviour by value to value
                    expr = Expression.Assign(expr, ConvertExpression.Bind(rvalue, expr.Type, ctx));
                }
            }
            else if (access.ReadCopy())
            {
                // dereference & copy
                if (expr.Type == typeof(PhpValue))
                {
                    // Template: value.GetValue().DeepCopy()
                    expr = Expression.Call(Expression.Call(expr, Cache.Operators.PhpValue_GetValue), Cache.Operators.PhpValue_DeepCopy);
                }
                else if (expr.Type == typeof(PhpAlias))
                {
                }
            }

            //
            return(expr);
        }
Exemple #17
0
        static Expression BindAccess(Expression expr, Expression ctx, AccessMask access, Expression rvalue)
        {
            if (access.EnsureObject())
            {
                if (expr.Type == typeof(PhpAlias))
                {
                    // ((PhpAlias)fld).EnsureObject()
                    expr = Expression.Call(expr, Cache.Operators.PhpAlias_EnsureObject);
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // ((PhpValue)fld).EnsureObject()
                    expr = Expression.Call(expr, Cache.Operators.PhpValue_EnsureObject);
                }
                else
                {
                    // getter // TODO: ensure it is not null
                    Debug.Assert(!expr.Type.GetTypeInfo().IsValueType);
                }
            }
            else if (access.EnsureArray())
            {
                if (expr.Type == typeof(PhpAlias))
                {
                    // ((PhpAlias)fld).EnsureArray()
                    expr = Expression.Call(expr, Cache.Operators.PhpAlias_EnsureArray);
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // ((PhpValue)fld).EnsureArray()
                    expr = Expression.Call(expr, Cache.Operators.PhpValue_EnsureArray);
                }
                else if (expr.Type == typeof(PhpArray))
                {
                    // (PhpArray)fld // TODO: ensure it is not null
                }
                else
                {
                    // Operators.EnsureArray( fld )
                    // TODO: string
                    expr = Expression.Call(Cache.Operators.Object_EnsureArray, expr);
                }
            }
            else if (access.EnsureAlias())
            {
                if (expr.Type == typeof(PhpAlias))
                {
                    // (PhpAlias)getter
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // ((PhpValue)fld).EnsureAlias()
                    expr = Expression.Call(expr, Cache.Operators.PhpValue_EnsureAlias);
                }
                else
                {
                    // getter // cannot read as reference
                }
            }
            else if (access.WriteAlias())
            {
                // write alias

                Debug.Assert(rvalue.Type == typeof(PhpAlias));
                rvalue = ConvertExpression.Bind(rvalue, typeof(PhpAlias), ctx);

                if (expr.Type == typeof(PhpAlias))
                {
                    // ok
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // fld = PhpValue.Create(alias)
                    rvalue = Expression.Call(typeof(PhpValue).GetMethod("Create", Cache.Types.PhpAlias), rvalue);
                }
                else
                {
                    // fld is not aliasable
                    Debug.Assert(false, "Cannot assign aliased value to field of type " + expr.Type.ToString());
                    rvalue = ConvertExpression.Bind(rvalue, expr.Type, ctx);
                }

                expr = Expression.Assign(expr, rvalue);
            }
            else if (access.Unset())
            {
                Debug.Assert(rvalue == null);

                expr = Expression.Assign(expr, ConvertExpression.BindDefault(expr.Type));
            }
            else if (access.Write())
            {
                // write by value

                if (expr.Type == typeof(PhpAlias))
                {
                    // Template: fld.Value = (PhpValue)value
                    expr = Expression.Assign(Expression.Field(expr, Cache.PhpAlias.Value), ConvertExpression.Bind(rvalue, typeof(PhpValue), ctx));
                }
                else if (expr.Type == typeof(PhpValue))
                {
                    // Template: Operators.SetValue(ref fld, (PhpValue)value)
                    expr = Expression.Call(Cache.Operators.SetValue_PhpValueRef_PhpValue, expr, ConvertExpression.Bind(rvalue, typeof(PhpValue), ctx));
                }
                else
                {
                    // Template: fld = value
                    // default behaviour by value to value
                    expr = Expression.Assign(expr, ConvertExpression.Bind(rvalue, expr.Type, ctx));
                }
            }
            else if (access.ReadValue())
            {
                // dereference
                if (expr.Type == typeof(PhpValue))
                {
                    // Template: value.GetValue().DeepCopy()
                    expr = Expression.Call(expr, Cache.Operators.PhpValue_GetValue);
                }
                else if (expr.Type == typeof(PhpAlias))
                {
                    // Template: alias.Value // expecting alias cannot be null ref
                    expr = Expression.Field(expr, Cache.PhpAlias.Value);
                }
            }
            else if (access.ReadValueCopy())
            {
                // dereference & copy
                if (expr.Type == typeof(PhpValue))
                {
                    // Template: value.GetValue().DeepCopy()
                    expr = Expression.Call(Expression.Call(expr, Cache.Operators.PhpValue_GetValue), Cache.Operators.PhpValue_DeepCopy);
                }
                else if (expr.Type == typeof(PhpAlias))
                {
                    // TODO: specify - ReadCopy | ReadValue | ReadValueCopy - currently not consistent
                }
            }
            else if (access.Isset())
            {
                if (expr.Type == typeof(PhpAlias))
                {
                    expr = Expression.Field(expr, Cache.PhpAlias.Value);
                }

                //
                if (expr.Type == typeof(PhpValue))
                {
                    // Template: Operators.IsSet( value )
                    expr = Expression.Call(Cache.Operators.IsSet_PhpValue, expr);
                }
                else if (!expr.Type.GetTypeInfo().IsValueType)
                {
                    // Template: value != null
                    expr = Expression.ReferenceNotEqual(expr, Expression.Constant(null, typeof(object)));
                }
                else
                {
                    // if there is bound typed symbol, it is always set:
                    expr = Expression.Constant(true, typeof(bool));
                }
            }

            // Read, IsSet
            return(expr);
        }